From f53c306da3838f5259b3ad296f33352eb53307d2 Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Thu, 6 Oct 2022 15:27:43 -0400 Subject: [PATCH 1/4] Initial checkin --- firestore/CONTRIBUTING.md | 83 ++++++++++++++++ firestore/README.md | 90 ------------------ firestore/architecture.png | Bin 0 -> 108396 bytes .../integration_test_internal/CMakeLists.txt | 1 + .../src/firestore_integration_test.cc | 34 +------ .../src/integration_test.cc | 3 + .../src/util/locate_emulator.cc | 61 ++++++++++++ .../src/util/locate_emulator.h | 30 ++++++ 8 files changed, 180 insertions(+), 122 deletions(-) create mode 100644 firestore/CONTRIBUTING.md delete mode 100644 firestore/README.md create mode 100644 firestore/architecture.png create mode 100644 firestore/integration_test_internal/src/util/locate_emulator.cc create mode 100644 firestore/integration_test_internal/src/util/locate_emulator.h diff --git a/firestore/CONTRIBUTING.md b/firestore/CONTRIBUTING.md new file mode 100644 index 0000000000..de95d78f08 --- /dev/null +++ b/firestore/CONTRIBUTING.md @@ -0,0 +1,83 @@ +# Overview + +This describes how to Firestore CPP SDK works on supported platforms, and how to +contribute this Firestore CPP SDK. + +Please read `README.md` and `CONTRIBUTING.md` from the repository root first. + +# Prerequisites + +There is no specific prerequisites for Firestore, `README.md` from the root directory +should have everything you need. + +One slight enhancement is to use [https://github.com/pyenv/pyenv][pyenv] to manage +your python versions, if you work on multiple projects with different python +requirements. + +For CPP SDK to compile, you generally need your `pyenv which python` to point to +a Python3 installation. + +# Architecture + +It is easier to work this Firestore CPP SDK by keeping a high level archetecture in mind: + +![architecture.png](architecture.png) + +To summarize, the C++ Code in this directory is an adapting layer on top of the underlying +SDKs: Firestore Android SDK for Android, and C++ Core SDK for everything else. + +These dependencies live within different github repos, so understanding where and which versions +of the dependencies being used is critical to troubleshooting, should the issues stem from +those dependencies or the interop layer. + +# Desktop building and testing + +Desktop builds of the Firestore SDK uses `CMAKE` to build and test. The complete set +of tests lives under `${REPO_ROOT}/firestore/integration_test_internal`. To build +the Firestore CPP SDK and its test suites: + +```shell +# from ${REPO_ROOT}/firestore/integration_test_internal +mkdir cmake-build-debug +cd cmake-build-debug + +# Generate build files +cmake .. # Or OPENSSL_ROOT_DIR=${PATH_TO_OPENSSL} cmake .. +# Build SDK and tests +cmake --build . -j +``` + +Once above steps are successful, there should be a `integration_test` under the current directory: +```shell +./integration_test # Run all tests against Firestore Prod Backend + +USE_FIRESTORE_EMULATOR=yes ./integration_test # Run all tests against Firestore Emulator + +# Run all tests against Firestore Emulator on a custom port +USE_FIRESTORE_EMULATOR=yes FIRESTORE_EMULATOR_PORT=9999 ./integration_test + +./integration_test --gtest_filter="*Query*" # Run a subset of tests +``` + +It is also possible to change where we get the underlying C++ Core SDK living under +`firebase-ios-sdk` by providing a custom cmake flag `FIRESTORE_DEP_SOURCE`: +```shell +# Default behavior when not specified, getting the Core SDK the last C++ SDK release +# was released with. +cmake -DFIRESTORE_DEP_SOURCE=RELEASED .. + +# Clones the origin/master branch of `firebase-ios-sdk` to get the Core SDK. +cmake -DFIRESTORE_DEP_SOURCE=TIP .. + +# Clones the origin/master branch of `firebase-ios-sdk` to get the Core SDK. +cmake -DFIRESTORE_DEP_SOURCE=origin/master .. + +# Clones commit '555555' of `firebase-ios-sdk`. +cmake -DFIRESTORE_DEP_SOURCE=555555 .. +``` + +## IDE Integration + +# Android building and testing +# iOS building and testing + diff --git a/firestore/README.md b/firestore/README.md deleted file mode 100644 index a99f9ef35b..0000000000 --- a/firestore/README.md +++ /dev/null @@ -1,90 +0,0 @@ -# Overview - -(TODO: Describe C++ SDK and its scope) - -## Integration with FPL - -(TODO: Describe how this is integrated with FPL, architecture overview and -useful commands) - -## Copybara process - -(TODO: Describe how github C++ code is copied here, what is not copied, and how -to run the copybara) - -## Running integration tests - -Given the C++ SDK runs on a lot of platforms, there are many different setups we -can use to run its integration tests. Below are instructions on how to run them -with all possible setups. - -### Against Firestore emulator - -This is the preferred way to run integration tests. The way it is configured is -we have a controlling `sh_test` (`integration_test_emulator.sh`), which will -pull Firestore emulator as a `data` dependency and set it up before it finds and -runs the actual integration tests in separate processes. - -Note this means on mobile platforms, the integration tests are run within -simulation, as there is no way to setup Firestore emulator if they are run on -real devices. - -#### Linux: - -```bash -blaze test //firebase/firestore/client/cpp:cc_emulator_tests -``` - -#### iOS (running within iOS simulator on forge-on-mac, hence `darwin_x86_64`): - -(TODO: When tests fail, the messages are not properly formatted, especially -newline is turned into '\n'.) - -```bash -blaze test --config=darwin_x86_64 //firebase/firestore/client/cpp:ios_integration_tests -``` - -#### Android (running within Android emulator, requires kvm to run on google3): - -(TODO: When tests fail, the messages only tell you the test failed, because of -the JUnit test wrapping. Ideally we should fix that.) - -```bash -blaze --blazerc=//google/src/head/depot/google3/java/com/google/android/gmscore/blaze/blazerc \ - test --define=firebase_build=head --config=gmscore_x86 \ - //firebase/firestore/client/cpp:android_integration_tests \ - --experimental_one_version_enforcement=warning -``` - -Support for other platforms is not available yet. - -### Against Firestore prod backend - -Running against the actual Firestore backend takes much longer and sometimes our -tests might get to run in an environment where external network connection is -impossible (such as Forge). - -It is useful still, for example, to run it before a release or to debug issues -that only happen with real backend. - -#### Linux: - -```bash -# Run the tests locally (`--test_output=streamed`) so they have network access. -blaze test --test_output=streamed //firebase/firestore/client/cpp:cc_tests -``` - -#### iOS (Runs on real devices via MobileHarness): - -```bash -blaze test --config=ios_fat --notest_loasd //firebase/firestore/client/cpp:ios_integration_tests_mh -``` - -#### Android: - -```bash -blaze --blazerc=//google/src/head/depot/google3/java/com/google/android/gmscore/blaze/blazerc \ -test --define=firebase_build=head --config=gmscore_x86 \ -//firebase/firestore/client/cpp:android_integration_tests_prod \ ---experimental_one_version_enforcement=warning -``` diff --git a/firestore/architecture.png b/firestore/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..b818babb05eebc61da94bc270dcdc61a8b3bee8e GIT binary patch literal 108396 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 literal 0 HcmV?d00001 diff --git a/firestore/integration_test_internal/CMakeLists.txt b/firestore/integration_test_internal/CMakeLists.txt index 75667cb60d..cb3f2e8461 100644 --- a/firestore/integration_test_internal/CMakeLists.txt +++ b/firestore/integration_test_internal/CMakeLists.txt @@ -140,6 +140,7 @@ set(FIREBASE_INTEGRATION_TEST_PORTABLE_SUPPORT_SRCS src/firestore_integration_test.cc src/util/bundle_builder.cc src/util/future_test_util.cc + src/util/locate_emulator.cc src/util/integration_test_util.cc ) diff --git a/firestore/integration_test_internal/src/firestore_integration_test.cc b/firestore/integration_test_internal/src/firestore_integration_test.cc index 81f27d7e77..ed6f2df358 100644 --- a/firestore/integration_test_internal/src/firestore_integration_test.cc +++ b/firestore/integration_test_internal/src/firestore_integration_test.cc @@ -29,6 +29,7 @@ #include "android/util_autoid.h" #endif // !defined(__ANDROID__) #include "app_framework.h" +#include "util/locate_emulator.h" namespace firebase { namespace firestore { @@ -38,37 +39,6 @@ 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 via USE_FIRESTORE_EMULATOR -void LocateEmulator(Firestore* db) { - // Use emulator as long as this env variable is set, regardless its value. - if (std::getenv("USE_FIRESTORE_EMULATOR") == nullptr) { - LogDebug("Using Firestore Prod for testing."); - return; - } - -#if defined(__ANDROID__) - // Special IP to access the hosting OS from Android Emulator. - std::string local_host = "10.0.2.2"; -#else - std::string local_host = "localhost"; -#endif // defined(__ANDROID__) - - // Use FIRESTORE_EMULATOR_PORT if it is set to non empty string, - // otherwise use the default port. - std::string port = std::getenv("FIRESTORE_EMULATOR_PORT") - ? std::getenv("FIRESTORE_EMULATOR_PORT") - : "8080"; - std::string address = - port.empty() ? (local_host + ":8080") : (local_host + ":" + port); - - LogInfo("Using Firestore Emulator (%s) for testing.", address.c_str()); - auto settings = db->settings(); - settings.set_host(address); - // Emulator does not support ssl yet. - settings.set_ssl_enabled(false); - db->set_settings(settings); -} - } // namespace std::string ToFirestoreErrorCodeName(int error_code) { @@ -163,7 +133,7 @@ Firestore* FirestoreIntegrationTest::TestFirestoreWithProjectId( Firestore* db = new Firestore(CreateTestFirestoreInternal(app)); firestores_[db] = FirestoreInfo(name, std::unique_ptr(db)); - LocateEmulator(db); + firestore::LocateEmulator(db); return db; } diff --git a/firestore/integration_test_internal/src/integration_test.cc b/firestore/integration_test_internal/src/integration_test.cc index a660c68677..13b36d59f6 100644 --- a/firestore/integration_test_internal/src/integration_test.cc +++ b/firestore/integration_test_internal/src/integration_test.cc @@ -43,6 +43,7 @@ #include "firebase/auth.h" #include "firebase/firestore.h" #include "firebase_test_framework.h" // NOLINT +#include "util/locate_emulator.h" // The TO_STRING macro is useful for command line defined strings as the quotes // get stripped. @@ -253,6 +254,8 @@ void FirebaseFirestoreBasicTest::InitializeFirestore() { ASSERT_EQ(initializer.InitializeLastResult().error(), 0) << initializer.InitializeLastResult().error_message(); + LocateEmulator(firestore_); + LogDebug("Successfully initialized Firebase Firestore."); initialized_ = true; diff --git a/firestore/integration_test_internal/src/util/locate_emulator.cc b/firestore/integration_test_internal/src/util/locate_emulator.cc new file mode 100644 index 0000000000..499c876b22 --- /dev/null +++ b/firestore/integration_test_internal/src/util/locate_emulator.cc @@ -0,0 +1,61 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "app/meta/move.h" +#include "app/src/assert.h" +#include "app/src/include/firebase/internal/common.h" +#include "firestore/src/include/firebase/firestore.h" + +namespace firebase { +namespace firestore { + +// Set Firestore up to use Firestore Emulator via USE_FIRESTORE_EMULATOR +void LocateEmulator(Firestore* db) { + // Use emulator as long as this env variable is set, regardless its value. + if (std::getenv("USE_FIRESTORE_EMULATOR") == nullptr) { + LogDebug("Using Firestore Prod for testing."); + return; + } + +#if defined(__ANDROID__) + // Special IP to access the hosting OS from Android Emulator. + std::string local_host = "10.0.2.2"; +#else + std::string local_host = "localhost"; +#endif // defined(__ANDROID__) + + // Use FIRESTORE_EMULATOR_PORT if it is set to non empty string, + // otherwise use the default port. + std::string port = std::getenv("FIRESTORE_EMULATOR_PORT") + ? std::getenv("FIRESTORE_EMULATOR_PORT") + : "8080"; + std::string address = + port.empty() ? (local_host + ":8080") : (local_host + ":" + port); + + LogInfo("Using Firestore Emulator (%s) for testing.", address.c_str()); + auto settings = db->settings(); + settings.set_host(address); + // Emulator does not support ssl yet. + settings.set_ssl_enabled(false); + db->set_settings(settings); +} + +} // namespace firestore +} // namespace firebase + diff --git a/firestore/integration_test_internal/src/util/locate_emulator.h b/firestore/integration_test_internal/src/util/locate_emulator.h new file mode 100644 index 0000000000..893b14ef17 --- /dev/null +++ b/firestore/integration_test_internal/src/util/locate_emulator.h @@ -0,0 +1,30 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef FIREBASE_FIRESTORE_INTEGRATION_TEST_INTERNAL_SRC_UTIL_LOCATE_EMULATOR_H_ +#define FIREBASE_FIRESTORE_INTEGRATION_TEST_INTERNAL_SRC_UTIL_LOCATE_EMULATOR_H_ + +#include "firestore/src/include/firebase/firestore.h" + +namespace firebase { +namespace firestore { + +// Set Firestore up to use Firestore Emulator via USE_FIRESTORE_EMULATOR +void LocateEmulator(Firestore* db); + +} // namespace firestore +} // namespace firebase + +#endif // FIREBASE_FIRESTORE_INTEGRATION_TEST_INTERNAL_SRC_UTIL_LOCATE_EMULATOR_H_ From 87a7da169316fcc3cfe97c2ec36ab391ac5d7050 Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Thu, 6 Oct 2022 15:29:00 -0400 Subject: [PATCH 2/4] Format --- .../integration_test_internal/src/util/locate_emulator.cc | 5 ++--- .../integration_test_internal/src/util/locate_emulator.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/firestore/integration_test_internal/src/util/locate_emulator.cc b/firestore/integration_test_internal/src/util/locate_emulator.cc index 499c876b22..3930deba8e 100644 --- a/firestore/integration_test_internal/src/util/locate_emulator.cc +++ b/firestore/integration_test_internal/src/util/locate_emulator.cc @@ -56,6 +56,5 @@ void LocateEmulator(Firestore* db) { db->set_settings(settings); } -} // namespace firestore -} // namespace firebase - +} // namespace firestore +} // namespace firebase diff --git a/firestore/integration_test_internal/src/util/locate_emulator.h b/firestore/integration_test_internal/src/util/locate_emulator.h index 893b14ef17..99225985db 100644 --- a/firestore/integration_test_internal/src/util/locate_emulator.h +++ b/firestore/integration_test_internal/src/util/locate_emulator.h @@ -24,7 +24,7 @@ namespace firestore { // Set Firestore up to use Firestore Emulator via USE_FIRESTORE_EMULATOR void LocateEmulator(Firestore* db); -} // namespace firestore -} // namespace firebase +} // namespace firestore +} // namespace firebase #endif // FIREBASE_FIRESTORE_INTEGRATION_TEST_INTERNAL_SRC_UTIL_LOCATE_EMULATOR_H_ From f9d5f37bfbb9808b48660b803fab0ec0eee50afc Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Thu, 6 Oct 2022 15:33:00 -0400 Subject: [PATCH 3/4] Lint --- .../integration_test_internal/src/util/locate_emulator.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/firestore/integration_test_internal/src/util/locate_emulator.cc b/firestore/integration_test_internal/src/util/locate_emulator.cc index 3930deba8e..89f7470e1d 100644 --- a/firestore/integration_test_internal/src/util/locate_emulator.cc +++ b/firestore/integration_test_internal/src/util/locate_emulator.cc @@ -13,14 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "util/locate_emulator.h" -#include #include -#include "app/meta/move.h" #include "app/src/assert.h" -#include "app/src/include/firebase/internal/common.h" -#include "firestore/src/include/firebase/firestore.h" namespace firebase { namespace firestore { From d35bab3d090628c6ad039f2913a4337282a83544 Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Wed, 12 Oct 2022 10:08:30 -0400 Subject: [PATCH 4/4] Add IDE integration. --- firestore/CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/firestore/CONTRIBUTING.md b/firestore/CONTRIBUTING.md index de95d78f08..1adf865d46 100644 --- a/firestore/CONTRIBUTING.md +++ b/firestore/CONTRIBUTING.md @@ -78,6 +78,11 @@ cmake -DFIRESTORE_DEP_SOURCE=555555 .. ## IDE Integration +Open up the repo root directory from `CLion` should load all symbols for the SDK itsel should +load all symbols for the SDK itself. Once loaded, you can right load on +`firestore/integration_test_internal/CMakeLists.txt` and `load project` to load the tests into +the IDE. + # Android building and testing # iOS building and testing