- Notifications
You must be signed in to change notification settings - Fork 125
Make it possible to run firestore tests against emulator #488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
❌ Integration test FAILEDRequested by @wu-hui on commit dea10eb
|
| void SetEnvironmentVariableFromExtra(const char* extra_name, JNIEnv* env, | ||
| jobject intent, | ||
| jmethodID get_string_extra) { | ||
| jstring extra_value_jstring = (jstring)env->CallObjectMethod( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forget the jni rules for object ownership lifetimes. I see that you called ReleaseStringUTFChars below, but do you also have to call DeleteLocalRef on this as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| jclass activity_clazz = env->GetObjectClass(activity); | ||
| jmethodID get_intent = env->GetMethodID(activity_clazz, "getIntent", | ||
| "()Landroid/content/Intent;"); | ||
| jobject intent = env->CallObjectMethod(activity, get_intent); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, I think you should be calling DeleteLocalRef at the end of the function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| address = std::getenv("FIRESTORE_EMULATOR_HOST"); | ||
| // Use prod backend as long as this env variable is unset. | ||
| if (std::getenv("USE_FIRESTORE_EMULATOR") == nullptr) { | ||
| LogDebug("Using prod backend for testing..."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: The "..." is not really meaningful here. A single period is all that is needed. Also on line 45.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| #endif // !defined(__ANDROID__) | ||
| if (!address.empty()) { | ||
| #if defined(__ANDROID__) | ||
| std::string local_host = "10.0.2.2"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does "10.0.2.2" come from? Could you add an inline comment to document this magic value and/or provide a link to where this number is documented?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| std::string local_host = "localhost"; | ||
| #endif // defined(__ANDROID__) | ||
| | ||
| std::string port = "8080"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Avoid assign-and-mutate for local variables, port in this case. Instead, assign to the variable exactly once in any given code flow. This improves readability by reducing the cognitive energy required to understand the code and is therefore also less error-prone. This advice comes from Python, but is equally applicable to C++: go/python-tips/026.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| static const char* kBootstrapAppName = "bootstrap"; | ||
| | ||
| // Set Firestore up to use Firestore Emulator if it can be found. | ||
| // Set Firestore up to use Firestore Emulator via USE_FIRESTORE_EMULATOR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears that based on the logic in this method, as long as USE_FIRESTORE_EMULATOR is defined, to any value (even 0 or empty), then the emulator will be used, unless FIRESTORE_EMULATOR_PORT is set to the empty string. This logic seems a bit complex.
How do you feel about coding it like this:
- If
USE_FIRESTORE_EMULATORis unset, empty, or0then use prod; otherwise, use the emulator. - If
FIRESTORE_EMULATOR_PORTis unset or empty, then use port 8080; otherwise, use the port specified in the environment variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
It can also be set to
false,no, etc. I think it is reasonable to not stress too much on this. -
Done.
| | ||
| if (!port.empty()) { | ||
| std::string address = local_host + ":" + port; | ||
| std::string message = "Using emulator (" + address + ") for testing..."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of creating the temporary variable message, how about just use the string formatting built into LogDebug.
e.g. LogDebug("Using emulator (%s) for testing.", address.c_str());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| return g_text_entry_field_data->ReadText(title, message, placeholder); | ||
| } | ||
| | ||
| void SetEnvironmentVariableFromExtra(const char* extra_name, JNIEnv* env, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: It is conventional for the JNIEnv pointer to be the first argument; please re-order the env argument to be the first argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider renaming SetEnvironmentVariableFromExtra to SetEnvironmentVariableFromStringExtra, to clearly identify that it is only concerned with string extras (not int extras, long extras, etc).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| jobject intent, | ||
| jmethodID get_string_extra) { | ||
| jstring extra_value_jstring = (jstring)env->CallObjectMethod( | ||
| intent, get_string_extra, env->NewStringUTF(extra_name)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should call DeleteLocalRef on the jstring returned from env->NewStringUTF(extra_name).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fun!
| | ||
| void SetExtrasAsEnvironmentVariables() { | ||
| JNIEnv* env = app_framework::GetJniEnv(); | ||
| jobject activity = g_app_state->activity->clazz; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that g_app_state->activity->clazz can be replaced by app_framework::GetActivity().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| JNIEnv* env = app_framework::GetJniEnv(); | ||
| jobject activity = g_app_state->activity->clazz; | ||
| | ||
| jclass activity_clazz = env->GetObjectClass(activity); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should call DeleteLocalRef(activity_clazz) once you're done with activity_clazz.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rename activity_clazz to activity_class, and intent_clazz to intent_class below. The "ss" -> "zz" is only needed because class is a reserved word, unlike activity_class and intent_class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| "()Landroid/content/Intent;"); | ||
| jobject intent = env->CallObjectMethod(activity, get_intent); | ||
| | ||
| jclass intent_clazz = env->GetObjectClass(intent); // class pointer of Intent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the comment "// class pointer of Intent"; it is explaining what the code is clearly doing. Moreover, above online 502 you do the same thing without commenting about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should call DeleteLocalRef(intent_clazz) once you're done with intent_clazz.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO This logic to get the jmethodID for getStringExtra() belongs in SetEnvironmentVariableFromExtra(), not here. It appears that you're trying to avoid retrieving the jmethodID twice, but the costs of this is inconsequential and leaks implementation details of SetEnvironmentVariableFromExtra() to its callers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a few minor nits. Thanks for doing this!
| #include <cstdlib> | ||
| #include <cstring> | ||
| #include <ctime> | ||
| #include <iostream> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you still need #include <iostream>?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleted.
| env->GetStringUTFChars(extra_value_jstring, nullptr); | ||
| setenv(extra_name, extra_value == nullptr ? "" : extra_value, | ||
| /*overwrite=*/1); | ||
| env->ReleaseStringUTFChars(extra_value_jstring, extra_value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since extra_value is potentially nullptr, I think you should conditionally invoke ReleaseStringUTFChars() only if it is not null. Alternately, just assume that GetStringUTFChars() returns non-null and get rid of the extra_value == nullptr check above. It would be some incredibly rare situation where it would return null and it would indicate a much larger problem anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
* Desktop and Android works with env variable and extra * Format and remove GTEST_FILTER for now * Add deletelocalref * Feedback. * More tweaks.
Android: via extra
adb shell start ... -e USE_FIRESTORE_EMULATOR true.Desktop/iOS: set env var
USE_FIRESTORE_EMULATOR.