Skip to content
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

Firestore Android Development instructions #1106

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
131 changes: 131 additions & 0 deletions firestore/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# 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

Once Android NDK is installed and added to `local.properties`, and `google-services.json`,
is added to `integration_test_internal`, it should be possible to build the testing
Android App directly with `gradlew`:

```shell
# from within integration_test_internal, build and install the testapp to an emulator or
# device
./gradlew installDebug

# Start the testapp
adb shell am start com.google.firebase.cpp.firestore.testapp/android.app.NativeActivity
```

**Note Firestore Emulator support is currently broken, it falls back to using Production Backend for now.**
It is also possible to run the testapp against Firestore emulator, as long as the testapp
is run from an Android Emulator and the Firestore emulator is running from the same
host OS:

```shell
# Start the testapp, but run against Firestore emulator
adb shell am start com.google.firebase.cpp.firestore.testapp/android.app.NativeActivity -e USE_FIRESTORE_EMULATOR true
```

## IDE Integration

It is possible to simply open up the `integration_test_internal` directory from `Android Studio`
directly, Android Studio will configure gradle and load all the tasks. Once configured, there
should be a `integration_test_internal` testapp you can start/debug from Android Studio.

In case when you cannot start the testapp from Android Studio, you can start it via `adb`:

```shell
# Start the testapp but wait for a debug to attach
adb shell am start -D -N com.google.firebase.cpp.firestore.testapp/android.app.NativeActivity
```

Then attach the debugger from Android Studio to unblock the testapp.


# iOS building and testing




90 changes: 0 additions & 90 deletions firestore/README.md

This file was deleted.

Binary file added firestore/architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions firestore/integration_test_internal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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) {
Expand Down Expand Up @@ -163,7 +133,7 @@ Firestore* FirestoreIntegrationTest::TestFirestoreWithProjectId(
Firestore* db = new Firestore(CreateTestFirestoreInternal(app));
firestores_[db] = FirestoreInfo(name, std::unique_ptr<Firestore>(db));

LocateEmulator(db);
firestore::LocateEmulator(db);
return db;
}

Expand Down
3 changes: 3 additions & 0 deletions firestore/integration_test_internal/src/integration_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
57 changes: 57 additions & 0 deletions firestore/integration_test_internal/src/util/locate_emulator.cc
Original file line number Diff line number Diff line change
@@ -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 <string>

#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
30 changes: 30 additions & 0 deletions firestore/integration_test_internal/src/util/locate_emulator.h
Original file line number Diff line number Diff line change
@@ -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_