-
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.
@@ -20,26 +20,30 @@ namespace { | |||
// non-default app to avoid data ending up in the cache before tests run. | |||
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_EMULATOR
is unset, empty, or0
then use prod; otherwise, use the emulator. - If
FIRESTORE_EMULATOR_PORT
is 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.
@@ -478,6 +479,43 @@ std::string ReadTextInput(const char* title, const char* message, | |||
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!
@@ -23,6 +23,7 @@ | |||
#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
.