diff --git a/firestore/CONTRIBUTING.md b/firestore/CONTRIBUTING.md new file mode 100644 index 0000000000..1adf865d46 --- /dev/null +++ b/firestore/CONTRIBUTING.md @@ -0,0 +1,88 @@ +# 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 + +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 + 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 0000000000..b818babb05 Binary files /dev/null and b/firestore/architecture.png differ 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..89f7470e1d --- /dev/null +++ b/firestore/integration_test_internal/src/util/locate_emulator.cc @@ -0,0 +1,57 @@ +/* + * 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 "util/locate_emulator.h" + +#include + +#include "app/src/assert.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..99225985db --- /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_