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

Test Harness for gRPC Integration Test of full Firestore stack #6043

Merged
merged 54 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
830d631
dbToken Persistence
tom-andersen May 8, 2024
37b97be
Copyright
tom-andersen May 8, 2024
d9cf32e
Remove user from globals cache.
tom-andersen May 14, 2024
88919eb
Merge branch 'master' into tomandersen/dbToken
tom-andersen May 14, 2024
a1ff6d6
Merge branch 'master' into tomandersen/dbToken
tom-andersen May 17, 2024
297d2c4
Fix
tom-andersen May 17, 2024
09def37
Merge branch 'master' into tomandersen/dbToken
tom-andersen May 17, 2024
e80b843
Merge branch 'master' into tomandersen/dbToken
tom-andersen May 22, 2024
cb08356
Fix from review comments
tom-andersen May 27, 2024
f79a0a2
Merge branch 'master' into tomandersen/dbToken
tom-andersen May 27, 2024
686e19c
Rename
tom-andersen Jun 5, 2024
b5f66a0
Merge branch 'master' into tomandersen/dbToken
tom-andersen Jun 5, 2024
be8097f
AbstractStream refactor
tom-andersen Jun 5, 2024
b61a395
AbstractStream refactor
tom-andersen Jun 5, 2024
0d25982
Whitespace
tom-andersen Jun 5, 2024
6d0f288
Merge branch 'tomandersen/dbToken' into tomandersen/streamRefactor
tom-andersen Jun 5, 2024
f2c309f
Merge branch 'master' into tomandersen/dbToken
tom-andersen Jun 11, 2024
906acc5
Merge branch 'tomandersen/dbToken' into tomandersen/streamRefactor
tom-andersen Jun 11, 2024
b9f339a
Merge branch 'master' into tomandersen/dbToken
tom-andersen Jun 12, 2024
c65331b
Merge branch 'tomandersen/dbToken' into tomandersen/streamRefactor
tom-andersen Jun 12, 2024
01f424c
Merge branch 'main' into tomandersen/dbToken
tom-andersen Jun 14, 2024
2c4d4d1
Merge branch 'tomandersen/dbToken' into tomandersen/streamRefactor
tom-andersen Jun 14, 2024
3113171
Refactor ComponentProvider
tom-andersen Jun 14, 2024
a3be1e6
Remove dead code
tom-andersen Jun 17, 2024
c61a40c
Fix
tom-andersen Jun 17, 2024
93fd42f
Merge branch 'tomandersen/streamRefactor' into tomandersen/componentP…
tom-andersen Jun 17, 2024
4808d45
Comments and cleanup
tom-andersen Jun 17, 2024
103f775
Merge remote-tracking branch 'origin/tomandersen/componentProviderRef…
tom-andersen Jun 17, 2024
5d8d687
Merge branch 'main' into tomandersen/dbToken
tom-andersen Jun 17, 2024
0beca8a
Merge branch 'tomandersen/dbToken' into tomandersen/streamRefactor
tom-andersen Jun 17, 2024
22a97f3
Merge branch 'tomandersen/streamRefactor' into tomandersen/componentP…
tom-andersen Jun 17, 2024
b749f5c
Whitespace
tom-andersen Jun 17, 2024
89991ef
Merge remote-tracking branch 'origin/tomandersen/componentProviderRef…
tom-andersen Jun 17, 2024
29b2ef9
gRPC integration test of write handshake
tom-andersen Jun 17, 2024
fbc7ad9
PR feedback
tom-andersen Jun 17, 2024
90db84e
Merge branch 'tomandersen/dbToken' into tomandersen/streamRefactor
tom-andersen Jun 17, 2024
2b09c74
Merge branch 'tomandersen/streamRefactor' into tomandersen/componentP…
tom-andersen Jun 17, 2024
6f48bc3
Merge branch 'tomandersen/componentProviderRefactor' into tomandersen…
tom-andersen Jun 17, 2024
3aff190
Merge branch 'main' into tomandersen/streamRefactor
tom-andersen Jun 18, 2024
2699116
Merge branch 'tomandersen/streamRefactor' into tomandersen/componentP…
tom-andersen Jun 19, 2024
1cbaac1
Merge branch 'tomandersen/componentProviderRefactor' into tomandersen…
tom-andersen Jun 19, 2024
7a8b052
Fix
tom-andersen Jun 21, 2024
66676d4
Merge remote-tracking branch 'origin/tomandersen/componentProviderRef…
tom-andersen Jun 21, 2024
ec7c414
Merge branch 'tomandersen/componentProviderRefactor' into tomandersen…
tom-andersen Jun 21, 2024
3865cd3
Review feedback
tom-andersen Jul 3, 2024
f114692
Merge remote-tracking branch 'origin/main' into tomandersen/handshake…
tom-andersen Jul 3, 2024
1795ed4
Merge branch 'main' into tomandersen/handshakeTest
tom-andersen Jul 3, 2024
86e3992
Speedup tests
tom-andersen Jul 3, 2024
72d5ed6
Merge remote-tracking branch 'origin/main' into tomandersen/handshake…
tom-andersen Jul 3, 2024
60fab11
Merge remote-tracking branch 'origin/tomandersen/handshakeTest' into …
tom-andersen Jul 3, 2024
6efb195
Speedup tests
tom-andersen Jul 3, 2024
3f1421c
Speedup tests ?
tom-andersen Jul 3, 2024
b1d7299
Allow tests to run longer.
tom-andersen Jul 3, 2024
17859fa
Merge branch 'main' into tomandersen/handshakeTest
tom-andersen Jul 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
import com.google.firebase.FirebaseApp;
import com.google.firebase.firestore.auth.CredentialsProvider;
import com.google.firebase.firestore.auth.User;
import com.google.firebase.firestore.core.ComponentProvider;
import com.google.firebase.firestore.model.DatabaseId;
import com.google.firebase.firestore.util.AsyncQueue;
import com.google.firebase.firestore.util.Function;

/** Gives access to package private methods in integration tests. */
public final class AccessHelper {
Expand All @@ -32,6 +34,7 @@ public static FirebaseFirestore newFirebaseFirestore(
CredentialsProvider<User> authProvider,
CredentialsProvider<String> appCheckProvider,
AsyncQueue asyncQueue,
Function<FirebaseFirestoreSettings, ComponentProvider> componentProviderFactory,
FirebaseApp firebaseApp,
FirebaseFirestore.InstanceRegistry instanceRegistry) {
return new FirebaseFirestore(
Expand All @@ -41,6 +44,7 @@ public static FirebaseFirestore newFirebaseFirestore(
authProvider,
appCheckProvider,
asyncQueue,
componentProviderFactory,
firebaseApp,
instanceRegistry,
null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.firebase.database.collection.ImmutableSortedSet;
import com.google.firebase.firestore.auth.User;
import com.google.firebase.firestore.core.DatabaseInfo;
import com.google.firebase.firestore.core.OnlineState;
import com.google.firebase.firestore.local.LocalStore;
import com.google.firebase.firestore.local.MemoryPersistence;
Expand All @@ -40,14 +41,8 @@ public class RemoteStoreTest {
@Test
public void testRemoteStoreStreamStopsWhenNetworkUnreachable() {
AsyncQueue testQueue = new AsyncQueue();
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
testQueue,
null,
null,
ApplicationProvider.getApplicationContext(),
null);
RemoteSerializer serializer = new RemoteSerializer(IntegrationTestUtil.testEnvDatabaseId());
Datastore datastore = new Datastore(testQueue, serializer, null);
Semaphore networkChangeSemaphore = new Semaphore(0);
RemoteStore.RemoteStoreCallback callback =
new RemoteStore.RemoteStoreCallback() {
Expand Down Expand Up @@ -75,12 +70,11 @@ public ImmutableSortedSet<DocumentKey> getRemoteKeysForTarget(int targetId) {
};

FakeConnectivityMonitor connectivityMonitor = new FakeConnectivityMonitor();
QueryEngine queryEngine = new QueryEngine();
Persistence persistence = MemoryPersistence.createEagerGcMemoryPersistence();
persistence.start();
LocalStore localStore = new LocalStore(persistence, queryEngine, User.UNAUTHENTICATED);
LocalStore localStore = new LocalStore(persistence, new QueryEngine(), User.UNAUTHENTICATED);
RemoteStore remoteStore =
new RemoteStore(callback, localStore, datastore, testQueue, connectivityMonitor);
new RemoteStore(IntegrationTestUtil.testEnvDatabaseId(), callback, localStore, datastore, testQueue, connectivityMonitor);

waitFor(testQueue.enqueue(remoteStore::forceEnableNetwork));
drain(testQueue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.auth.CredentialsProvider;
import com.google.firebase.firestore.auth.User;
import com.google.firebase.firestore.core.DatabaseInfo;
import com.google.firebase.firestore.model.SnapshotVersion;
import com.google.firebase.firestore.model.mutation.Mutation;
import com.google.firebase.firestore.model.mutation.MutationResult;
Expand Down Expand Up @@ -109,14 +112,16 @@ public void onWriteResponse(
/** Creates a WriteStream and gets it in a state that accepts mutations. */
private WriteStream createAndOpenWriteStream(
AsyncQueue testQueue, StreamStatusCallback callback) {
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
DatabaseInfo databaseInfo = IntegrationTestUtil.testEnvDatabaseInfo();
RemoteSerializer remoteSerializer = new RemoteSerializer(databaseInfo.getDatabaseId());
FirestoreChannel firestoreChannel = new FirestoreChannel(
testQueue,
new EmptyCredentialsProvider(),
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
null);
null == null ? new EmptyCredentialsProvider() : null,
new EmptyAppCheckTokenProvider(),
databaseInfo,
(GrpcMetadataProvider) null);
Datastore datastore = new Datastore(testQueue, remoteSerializer, firestoreChannel);
final WriteStream writeStream = datastore.createWriteStream(callback);
waitForWriteStreamOpen(testQueue, writeStream, callback);
return writeStream;
Expand All @@ -135,14 +140,16 @@ private void waitForWriteStreamOpen(
public void testWatchStreamStopBeforeHandshake() throws Exception {
AsyncQueue testQueue = new AsyncQueue();
GrpcMetadataProvider mockGrpcProvider = mock(GrpcMetadataProvider.class);
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
DatabaseInfo databaseInfo = IntegrationTestUtil.testEnvDatabaseInfo();
RemoteSerializer remoteSerializer = new RemoteSerializer(databaseInfo.getDatabaseId());
FirestoreChannel firestoreChannel = new FirestoreChannel(
testQueue,
ApplicationProvider.getApplicationContext(),
new EmptyCredentialsProvider(),
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
databaseInfo,
mockGrpcProvider);
Datastore datastore = new Datastore(testQueue, remoteSerializer, firestoreChannel);
StreamStatusCallback streamCallback = new StreamStatusCallback() {};
final WatchStream watchStream = datastore.createWatchStream(streamCallback);

Expand All @@ -158,14 +165,16 @@ public void testWatchStreamStopBeforeHandshake() throws Exception {
@Test
public void testWriteStreamStopAfterHandshake() throws Exception {
AsyncQueue testQueue = new AsyncQueue();
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
DatabaseInfo databaseInfo = IntegrationTestUtil.testEnvDatabaseInfo();
RemoteSerializer remoteSerializer = new RemoteSerializer(databaseInfo.getDatabaseId());
FirestoreChannel firestoreChannel = new FirestoreChannel(
testQueue,
ApplicationProvider.getApplicationContext(),
new EmptyCredentialsProvider(),
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
null);
databaseInfo,
(GrpcMetadataProvider) null);
Datastore datastore = new Datastore(testQueue, remoteSerializer, firestoreChannel);
final WriteStream[] writeStreamWrapper = new WriteStream[1];
StreamStatusCallback streamCallback =
new StreamStatusCallback() {
Expand Down Expand Up @@ -206,14 +215,16 @@ public void onWriteResponse(
@Test
public void testWriteStreamStopPartial() throws Exception {
AsyncQueue testQueue = new AsyncQueue();
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
DatabaseInfo databaseInfo = IntegrationTestUtil.testEnvDatabaseInfo();
RemoteSerializer remoteSerializer = new RemoteSerializer(databaseInfo.getDatabaseId());
FirestoreChannel firestoreChannel = new FirestoreChannel(
testQueue,
ApplicationProvider.getApplicationContext(),
new EmptyCredentialsProvider(),
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
null);
databaseInfo,
(GrpcMetadataProvider) null);
Datastore datastore = new Datastore(testQueue, remoteSerializer, firestoreChannel);
StreamStatusCallback streamCallback = new StreamStatusCallback() {};
final WriteStream writeStream = datastore.createWriteStream(streamCallback);

Expand Down Expand Up @@ -287,14 +298,16 @@ public void testStreamStaysIdle() throws Exception {
public void testStreamRefreshesTokenUponExpiration() throws Exception {
AsyncQueue testQueue = new AsyncQueue();
MockCredentialsProvider mockCredentialsProvider = new MockCredentialsProvider();
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
DatabaseInfo databaseInfo = IntegrationTestUtil.testEnvDatabaseInfo();
RemoteSerializer remoteSerializer = new RemoteSerializer(databaseInfo.getDatabaseId());
FirestoreChannel firestoreChannel = new FirestoreChannel(
testQueue,
ApplicationProvider.getApplicationContext(),
mockCredentialsProvider,
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
null);
databaseInfo,
(GrpcMetadataProvider) null);
Datastore datastore = new Datastore(testQueue, remoteSerializer, firestoreChannel);
StreamStatusCallback callback = new StreamStatusCallback();
WriteStream writeStream = datastore.createWriteStream(callback);
waitForWriteStreamOpen(testQueue, writeStream, callback);
Expand All @@ -317,14 +330,16 @@ public void testStreamRefreshesTokenUponExpiration() throws Exception {
public void testTokenIsNotInvalidatedOnceStreamIsHealthy() throws Exception {
AsyncQueue testQueue = new AsyncQueue();
MockCredentialsProvider mockCredentialsProvider = new MockCredentialsProvider();
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
DatabaseInfo databaseInfo = IntegrationTestUtil.testEnvDatabaseInfo();
RemoteSerializer remoteSerializer = new RemoteSerializer(databaseInfo.getDatabaseId());
FirestoreChannel firestoreChannel = new FirestoreChannel(
testQueue,
ApplicationProvider.getApplicationContext(),
mockCredentialsProvider,
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
null);
databaseInfo,
(GrpcMetadataProvider) null);
Datastore datastore = new Datastore(testQueue, remoteSerializer, firestoreChannel);
StreamStatusCallback callback = new StreamStatusCallback();
WriteStream writeStream = datastore.createWriteStream(callback);
waitForWriteStreamOpen(testQueue, writeStream, callback);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

import android.content.Context;
import android.os.StrictMode;

import androidx.annotation.NonNull;
import androidx.test.core.app.ApplicationProvider;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.TaskCompletionSource;
Expand All @@ -42,6 +44,7 @@
import com.google.firebase.firestore.Source;
import com.google.firebase.firestore.WriteBatch;
import com.google.firebase.firestore.auth.User;
import com.google.firebase.firestore.core.ComponentProvider;
import com.google.firebase.firestore.core.DatabaseInfo;
import com.google.firebase.firestore.model.DatabaseId;
import com.google.firebase.firestore.testutil.provider.FirestoreProvider;
Expand Down Expand Up @@ -170,14 +173,20 @@ public static TargetBackend getTargetBackend() {
}
}

@NonNull
public static DatabaseInfo testEnvDatabaseInfo() {
return new DatabaseInfo(
DatabaseId.forProject(provider.projectId()),
testEnvDatabaseId(),
"test-persistenceKey",
getFirestoreHost(),
getSslEnabled());
}

@NonNull
public static DatabaseId testEnvDatabaseId() {
return DatabaseId.forProject(provider.projectId());
}

public static FirebaseFirestoreSettings newTestSettings() {
Logger.debug("IntegrationTestUtil", "target backend is: %s", backend.name());
FirebaseFirestoreSettings.Builder settings = new FirebaseFirestoreSettings.Builder();
Expand Down Expand Up @@ -315,6 +324,7 @@ public static FirebaseFirestore testFirestore(
MockCredentialsProvider.instance(),
new EmptyAppCheckTokenProvider(),
asyncQueue,
ComponentProvider::defaultFactory,
/*firebaseApp=*/ null,
/*instanceRegistry=*/ (dbId) -> {});
waitFor(firestore.clearPersistence());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.google.firebase.firestore.auth.User;
import com.google.firebase.firestore.core.ActivityScope;
import com.google.firebase.firestore.core.AsyncEventListener;
import com.google.firebase.firestore.core.ComponentProvider;
import com.google.firebase.firestore.core.DatabaseInfo;
import com.google.firebase.firestore.core.FirestoreClient;
import com.google.firebase.firestore.local.SQLitePersistence;
Expand Down Expand Up @@ -75,6 +76,8 @@
*/
public class FirebaseFirestore {

private final Function<FirebaseFirestoreSettings, ComponentProvider> componentProviderFactory;

/**
* Provides a registry management interface for {@code FirebaseFirestore} instances.
*
Expand Down Expand Up @@ -205,18 +208,17 @@ static FirebaseFirestore newInstance(
// so there is no need to include it in the persistence key.
String persistenceKey = app.getName();

FirebaseFirestore firestore =
new FirebaseFirestore(
context,
databaseId,
persistenceKey,
authProvider,
appCheckProvider,
queue,
app,
instanceRegistry,
metadataProvider);
return firestore;
return new FirebaseFirestore(
context,
databaseId,
persistenceKey,
authProvider,
appCheckProvider,
queue,
ComponentProvider::defaultFactory,
app,
instanceRegistry,
metadataProvider);
}

@VisibleForTesting
Expand All @@ -227,6 +229,7 @@ static FirebaseFirestore newInstance(
CredentialsProvider<User> authProvider,
CredentialsProvider<String> appCheckProvider,
AsyncQueue asyncQueue,
@NonNull Function<FirebaseFirestoreSettings, ComponentProvider> componentProviderFactory,
@Nullable FirebaseApp firebaseApp,
InstanceRegistry instanceRegistry,
@Nullable GrpcMetadataProvider metadataProvider) {
Expand All @@ -237,6 +240,7 @@ static FirebaseFirestore newInstance(
this.authProvider = checkNotNull(authProvider);
this.appCheckProvider = checkNotNull(appCheckProvider);
this.asyncQueue = checkNotNull(asyncQueue);
this.componentProviderFactory = checkNotNull(componentProviderFactory);
// NOTE: We allow firebaseApp to be null in tests only.
this.firebaseApp = firebaseApp;
this.instanceRegistry = instanceRegistry;
Expand All @@ -256,10 +260,9 @@ public FirebaseFirestoreSettings getFirestoreSettings() {
* can only be called before calling any other methods on this object.
*/
public void setFirestoreSettings(@NonNull FirebaseFirestoreSettings settings) {
settings = mergeEmulatorSettings(settings, this.emulatorSettings);

checkNotNull(settings, "Provided settings must not be null.");
synchronized (databaseId) {
checkNotNull(settings, "Provided settings must not be null.");
settings = mergeEmulatorSettings(settings, emulatorSettings);

// As a special exception, don't throw if the same settings are passed repeatedly. This
// should make it simpler to get a Firestore instance in an activity.
Expand Down Expand Up @@ -288,8 +291,8 @@ public void useEmulator(@NonNull String host, int port) {
"Cannot call useEmulator() after instance has already been initialized.");
}

this.emulatorSettings = new EmulatedServiceSettings(host, port);
this.settings = mergeEmulatorSettings(this.settings, this.emulatorSettings);
emulatorSettings = new EmulatedServiceSettings(host, port);
settings = mergeEmulatorSettings(settings, emulatorSettings);
}

private void ensureClientConfigured() {
Expand All @@ -312,7 +315,8 @@ private void ensureClientConfigured() {
authProvider,
appCheckProvider,
asyncQueue,
metadataProvider);
metadataProvider,
componentProviderFactory.apply(settings));
}
}

Expand Down
Loading
Loading