Skip to content

Commit

Permalink
Merge 2699116 into 3aff190
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-andersen committed Jun 19, 2024
2 parents 3aff190 + 2699116 commit d2e31d6
Show file tree
Hide file tree
Showing 23 changed files with 327 additions and 291 deletions.
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 @@ -26,9 +26,11 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import androidx.annotation.NonNull;
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.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 +111,7 @@ 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(),
testQueue,
new EmptyCredentialsProvider(),
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
null);
Datastore datastore = createTestDatastore(testQueue, null);
final WriteStream writeStream = datastore.createWriteStream(callback);
waitForWriteStreamOpen(testQueue, writeStream, callback);
return writeStream;
Expand All @@ -131,18 +126,25 @@ private void waitForWriteStreamOpen(
waitFor(callback.handshakeSemaphore);
}

@NonNull
private static Datastore createTestDatastore(AsyncQueue testQueue, GrpcMetadataProvider metadataProvider) {
DatabaseInfo databaseInfo = IntegrationTestUtil.testEnvDatabaseInfo();
RemoteSerializer remoteSerializer = new RemoteSerializer(databaseInfo.getDatabaseId());
FirestoreChannel firestoreChannel = new FirestoreChannel(
testQueue,
ApplicationProvider.getApplicationContext(),
new EmptyCredentialsProvider(),
new EmptyAppCheckTokenProvider(),
databaseInfo,
metadataProvider);
return new Datastore(testQueue, remoteSerializer, firestoreChannel);
}

@Test
public void testWatchStreamStopBeforeHandshake() throws Exception {
AsyncQueue testQueue = new AsyncQueue();
GrpcMetadataProvider mockGrpcProvider = mock(GrpcMetadataProvider.class);
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
testQueue,
new EmptyCredentialsProvider(),
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
mockGrpcProvider);
Datastore datastore = createTestDatastore(testQueue, mockGrpcProvider);
StreamStatusCallback streamCallback = new StreamStatusCallback() {};
final WatchStream watchStream = datastore.createWatchStream(streamCallback);

Expand All @@ -158,14 +160,7 @@ public void testWatchStreamStopBeforeHandshake() throws Exception {
@Test
public void testWriteStreamStopAfterHandshake() throws Exception {
AsyncQueue testQueue = new AsyncQueue();
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
testQueue,
new EmptyCredentialsProvider(),
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
null);
Datastore datastore = createTestDatastore(testQueue, null);
final WriteStream[] writeStreamWrapper = new WriteStream[1];
StreamStatusCallback streamCallback =
new StreamStatusCallback() {
Expand Down Expand Up @@ -206,14 +201,7 @@ public void onWriteResponse(
@Test
public void testWriteStreamStopPartial() throws Exception {
AsyncQueue testQueue = new AsyncQueue();
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
testQueue,
new EmptyCredentialsProvider(),
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
null);
Datastore datastore = createTestDatastore(testQueue, null);
StreamStatusCallback streamCallback = new StreamStatusCallback() {};
final WriteStream writeStream = datastore.createWriteStream(streamCallback);

Expand Down Expand Up @@ -287,14 +275,7 @@ public void testStreamStaysIdle() throws Exception {
public void testStreamRefreshesTokenUponExpiration() throws Exception {
AsyncQueue testQueue = new AsyncQueue();
MockCredentialsProvider mockCredentialsProvider = new MockCredentialsProvider();
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
testQueue,
mockCredentialsProvider,
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
null);
Datastore datastore = createTestDatastore(testQueue, null);
StreamStatusCallback callback = new StreamStatusCallback();
WriteStream writeStream = datastore.createWriteStream(callback);
waitForWriteStreamOpen(testQueue, writeStream, callback);
Expand All @@ -317,14 +298,7 @@ public void testStreamRefreshesTokenUponExpiration() throws Exception {
public void testTokenIsNotInvalidatedOnceStreamIsHealthy() throws Exception {
AsyncQueue testQueue = new AsyncQueue();
MockCredentialsProvider mockCredentialsProvider = new MockCredentialsProvider();
Datastore datastore =
new Datastore(
IntegrationTestUtil.testEnvDatabaseInfo(),
testQueue,
mockCredentialsProvider,
new EmptyAppCheckTokenProvider(),
ApplicationProvider.getApplicationContext(),
null);
Datastore datastore = createTestDatastore(testQueue, null);
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

0 comments on commit d2e31d6

Please sign in to comment.