Skip to content

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

Merged
merged 5 commits into from
Jul 1, 2021

Conversation

wu-hui
Copy link
Contributor

@wu-hui wu-hui commented Jun 23, 2021

Android: via extra adb shell start ... -e USE_FIRESTORE_EMULATOR true.

Desktop/iOS: set env var USE_FIRESTORE_EMULATOR.

@google-cla google-cla bot added the cla: yes label Jun 23, 2021
@wu-hui wu-hui added the tests-requested: quick Trigger a quick set of integration tests. label Jun 23, 2021
@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. and removed tests-requested: quick Trigger a quick set of integration tests. labels Jun 23, 2021
@github-actions
Copy link

github-actions bot commented Jun 23, 2021

❌  Integration test FAILED

Requested by @wu-hui on commit dea10eb
Last updated: Wed Jun 30 20:12 PDT 2021
View integration test log & download artifacts

Failures Configs
firestore [TEST] [FAILURE] [iOS] [macos] [ios_target]
(1 failed tests)  LoadInvalidBundlesShouldFail

@github-actions github-actions bot added the tests: failed This PR's integration tests failed. label Jun 23, 2021
@wu-hui wu-hui requested review from alexames and dconeybe June 23, 2021 18:15
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Jun 23, 2021
void SetEnvironmentVariableFromExtra(const char* extra_name, JNIEnv* env,
jobject intent,
jmethodID get_string_extra) {
jstring extra_value_jstring = (jstring)env->CallObjectMethod(
Copy link
Contributor

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?

Copy link
Contributor Author

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);
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@wu-hui wu-hui added tests-requested: quick Trigger a quick set of integration tests. and removed tests: failed This PR's integration tests failed. labels Jun 24, 2021
@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. and removed tests-requested: quick Trigger a quick set of integration tests. labels Jun 24, 2021
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...");
Copy link
Contributor

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.

Copy link
Contributor Author

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";
Copy link
Contributor

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?

Copy link
Contributor Author

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";
Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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:

  1. If USE_FIRESTORE_EMULATOR is unset, empty, or 0 then use prod; otherwise, use the emulator.
  2. If FIRESTORE_EMULATOR_PORT is unset or empty, then use port 8080; otherwise, use the port specified in the environment variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. It can also be set to false, no, etc. I think it is reasonable to not stress too much on this.

  2. Done.


if (!port.empty()) {
std::string address = local_host + ":" + port;
std::string message = "Using emulator (" + address + ") for testing...";
Copy link
Contributor

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());

Copy link
Contributor Author

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,
Copy link
Contributor

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.

Copy link
Contributor

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).

Copy link
Contributor Author

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));
Copy link
Contributor

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).

Copy link
Contributor Author

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;
Copy link
Contributor

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().

Copy link
Contributor Author

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);
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@dconeybe dconeybe assigned wu-hui and unassigned dconeybe Jun 24, 2021
@github-actions github-actions bot added the tests: failed This PR's integration tests failed. label Jun 24, 2021
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Jun 24, 2021
@wu-hui wu-hui assigned dconeybe and unassigned wu-hui Jun 24, 2021
dconeybe
dconeybe previously approved these changes Jun 24, 2021
Copy link
Contributor

@dconeybe dconeybe left a 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>
Copy link
Contributor

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>?

Copy link
Contributor Author

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);
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@dconeybe dconeybe assigned wu-hui and unassigned dconeybe Jun 24, 2021
@github-actions github-actions bot added the tests: failed This PR's integration tests failed. label Jun 26, 2021
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Jun 26, 2021
@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. tests: failed This PR's integration tests failed. and removed tests: failed This PR's integration tests failed. labels Jun 29, 2021
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Jun 29, 2021
@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. tests: failed This PR's integration tests failed. and removed tests: failed This PR's integration tests failed. labels Jun 29, 2021
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Jun 29, 2021
@wu-hui wu-hui enabled auto-merge (squash) June 30, 2021 13:19
@wu-hui wu-hui added tests-requested: quick Trigger a quick set of integration tests. and removed tests: failed This PR's integration tests failed. labels Jun 30, 2021
@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. tests: failed This PR's integration tests failed. and removed tests-requested: quick Trigger a quick set of integration tests. labels Jun 30, 2021
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Jun 30, 2021
@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. tests: failed This PR's integration tests failed. and removed tests: failed This PR's integration tests failed. labels Jun 30, 2021
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Jun 30, 2021
@wu-hui wu-hui removed the tests: failed This PR's integration tests failed. label Jul 1, 2021
@wu-hui wu-hui merged commit dea10eb into main Jul 1, 2021
@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. tests: failed This PR's integration tests failed. labels Jul 1, 2021
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Jul 1, 2021
jonsimantov pushed a commit that referenced this pull request Jul 1, 2021
* Desktop and Android works with env variable and extra

* Format and remove GTEST_FILTER for now

* Add deletelocalref

* Feedback.

* More tweaks.
@jonsimantov jonsimantov deleted the wuandy/FirestoreEmulator branch July 12, 2021 22:49
@firebase firebase locked and limited conversation to collaborators Jul 31, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla: yes tests: failed This PR's integration tests failed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants