Skip to content

Commit 45fe72b

Browse files
committed
Expose Multi-DB, and add tests.
1 parent 58c1677 commit 45fe72b

File tree

7 files changed

+146
-6
lines changed

7 files changed

+146
-6
lines changed

firebase-firestore/firebase-firestore.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ dependencies {
179179
androidTestImplementation 'androidx.test:runner:1.2.0'
180180
androidTestImplementation 'androidx.test:rules:1.2.0'
181181
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
182+
183+
//testImplementation project(':firebase-firestore')
184+
androidTestImplementation project(':firebase-firestore')
182185
}
183186

184187
gradle.projectsEvaluated {

firebase-firestore/ktx/src/main/kotlin/com/google/firebase/firestore/ktx/Firestore.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@ val Firebase.firestore: FirebaseFirestore
4343
/** Returns the [FirebaseFirestore] instance of a given [FirebaseApp]. */
4444
fun Firebase.firestore(app: FirebaseApp): FirebaseFirestore = FirebaseFirestore.getInstance(app)
4545

46+
/** Returns the [FirebaseFirestore] instance of a given [FirebaseApp] and database name. */
47+
fun Firebase.firestore(
48+
app: FirebaseApp,
49+
database: String
50+
): FirebaseFirestore = FirebaseFirestore.getInstance(app, database)
51+
52+
/**
53+
* Returns the [FirebaseFirestore] instance of the default [FirebaseApp], given the database name.
54+
*/
55+
fun Firebase.firestore(
56+
database: String
57+
): FirebaseFirestore = FirebaseFirestore.getInstance(database)
58+
4659
/**
4760
* Returns the contents of the document converted to a POJO or null if the document doesn't exist.
4861
*

firebase-firestore/ktx/src/test/kotlin/com/google/firebase/firestore/ktx/FirestoreTests.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,23 @@ class FirestoreTests : BaseTestCase() {
7878
assertThat(Firebase.firestore).isSameInstanceAs(FirebaseFirestore.getInstance())
7979
}
8080

81+
@Test
82+
fun `Database#firestore should delegate to FirebaseFirestore#getInstance(Database)`() {
83+
assertThat(Firebase.firestore("name")).isSameInstanceAs(FirebaseFirestore.getInstance("name"))
84+
}
85+
8186
@Test
8287
fun `FirebaseApp#firestore should delegate to FirebaseFirestore#getInstance(FirebaseApp)`() {
8388
val app = Firebase.app(EXISTING_APP)
8489
assertThat(Firebase.firestore(app)).isSameInstanceAs(FirebaseFirestore.getInstance(app))
8590
}
8691

92+
@Test
93+
fun `FirebaseApp#Database#firestore should delegate to FirebaseFirestore#getInstance(FirebaseApp,Database)`() {
94+
val app = Firebase.app(EXISTING_APP)
95+
assertThat(Firebase.firestore(app, "name")).isSameInstanceAs(FirebaseFirestore.getInstance(app, "name"))
96+
}
97+
8798
@Test
8899
fun `FirebaseFirestoreSettings builder works`() {
89100
val host = "http://10.0.2.2:8080"

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/FirestoreTest.java

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package com.google.firebase.firestore;
1616

1717
import static com.google.firebase.firestore.AccessHelper.getAsyncQueue;
18+
import static com.google.firebase.firestore.testutil.IntegrationTestUtil.isRunningAgainstEmulator;
1819
import static com.google.firebase.firestore.testutil.IntegrationTestUtil.newTestSettings;
1920
import static com.google.firebase.firestore.testutil.IntegrationTestUtil.provider;
2021
import static com.google.firebase.firestore.testutil.IntegrationTestUtil.testChangeUserTo;
@@ -46,6 +47,7 @@
4647
import com.google.firebase.firestore.FirebaseFirestoreException.Code;
4748
import com.google.firebase.firestore.Query.Direction;
4849
import com.google.firebase.firestore.auth.User;
50+
import com.google.firebase.firestore.model.DatabaseId;
4951
import com.google.firebase.firestore.testutil.EventAccumulator;
5052
import com.google.firebase.firestore.testutil.IntegrationTestUtil;
5153
import com.google.firebase.firestore.util.AsyncQueue.TimerId;
@@ -57,7 +59,9 @@
5759
import java.util.List;
5860
import java.util.Map;
5961
import java.util.concurrent.CountDownLatch;
62+
import java.util.concurrent.ExecutionException;
6063
import java.util.concurrent.Semaphore;
64+
import java.util.concurrent.TimeoutException;
6165
import org.junit.After;
6266
import org.junit.Test;
6367
import org.junit.runner.RunWith;
@@ -1131,6 +1135,87 @@ public void testAppDeleteLeadsToFirestoreTerminate() {
11311135
assertTrue(instance.getClient().isTerminated());
11321136
}
11331137

1138+
@Test
1139+
public void testDefaultNamedDbIsSame() {
1140+
FirebaseApp app = FirebaseApp.getInstance();
1141+
FirebaseFirestore db1 = FirebaseFirestore.getInstance();
1142+
FirebaseFirestore db2 = FirebaseFirestore.getInstance(app);
1143+
FirebaseFirestore db3 = FirebaseFirestore.getInstance(app, "(default)");
1144+
FirebaseFirestore db4 = FirebaseFirestore.getInstance("(default)");
1145+
1146+
assertSame(db1, db2);
1147+
assertSame(db1, db3);
1148+
assertSame(db1, db4);
1149+
}
1150+
1151+
@Test
1152+
public void testSameNamedDbIsSame() {
1153+
FirebaseApp app = FirebaseApp.getInstance();
1154+
FirebaseFirestore db1 = FirebaseFirestore.getInstance(app, "myDb");
1155+
FirebaseFirestore db2 = FirebaseFirestore.getInstance("myDb");
1156+
1157+
assertSame(db1, db2);
1158+
}
1159+
1160+
@Test
1161+
public void testDifferentDbNamesAreDifferent() {
1162+
FirebaseFirestore db1 = FirebaseFirestore.getInstance();
1163+
FirebaseFirestore db2 = FirebaseFirestore.getInstance("db1");
1164+
FirebaseFirestore db3 = FirebaseFirestore.getInstance("db2");
1165+
1166+
assertNotSame(db1, db2);
1167+
assertNotSame(db1, db3);
1168+
assertNotSame(db2, db3);
1169+
}
1170+
1171+
@Test
1172+
public void testNamedDbHaveDifferentPersistence()
1173+
throws ExecutionException, InterruptedException, TimeoutException {
1174+
// TODO: Have backend with named databases created beforehand.
1175+
// Emulator doesn't care if database was created beforehand.
1176+
if (!isRunningAgainstEmulator()) {
1177+
return;
1178+
}
1179+
// FirebaseFirestore db1 = FirebaseFirestore.getInstance();
1180+
String projectId = provider().projectId();
1181+
FirebaseFirestore db1 =
1182+
testFirestore(
1183+
DatabaseId.forDatabase(projectId, "db1"),
1184+
Level.DEBUG,
1185+
newTestSettings(),
1186+
"dbPersistenceKey");
1187+
FirebaseFirestore db2 =
1188+
testFirestore(
1189+
DatabaseId.forDatabase(projectId, "db2"),
1190+
Level.DEBUG,
1191+
newTestSettings(),
1192+
"dbPersistenceKey");
1193+
1194+
DocumentReference docRef = db1.collection("col1").document("doc1");
1195+
waitFor(docRef.set(Collections.singletonMap("foo", "bar")));
1196+
assertEquals(waitFor(docRef.get(Source.SERVER)).get("foo"), "bar");
1197+
1198+
String path = docRef.getPath();
1199+
DocumentReference docRef2 = db2.document(path);
1200+
1201+
{
1202+
Exception e = waitForException(docRef2.get(Source.CACHE));
1203+
assertEquals(Code.UNAVAILABLE, ((FirebaseFirestoreException) e).getCode());
1204+
}
1205+
1206+
{
1207+
Task<DocumentSnapshot> task = docRef2.get(Source.SERVER);
1208+
DocumentSnapshot result = waitFor(task);
1209+
assertNull(result.getDocument());
1210+
}
1211+
1212+
{
1213+
Task<DocumentSnapshot> task = docRef2.get(Source.DEFAULT);
1214+
DocumentSnapshot result = waitFor(task);
1215+
assertNull(result.getDocument());
1216+
}
1217+
}
1218+
11341219
@Test
11351220
public void testNewOperationThrowsAfterFirestoreTerminate() {
11361221
FirebaseFirestore instance = testFirestore();

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/ValidationTest.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,15 @@ public void disableSslWithoutSettingHostFails() {
9595
@Test
9696
public void firestoreGetInstanceWithNullAppFails() {
9797
expectError(
98-
() -> FirebaseFirestore.getInstance(null), "Provided FirebaseApp must not be null.");
98+
() -> FirebaseFirestore.getInstance((FirebaseApp) null),
99+
"Provided FirebaseApp must not be null.");
100+
}
101+
102+
@Test
103+
public void firestoreGetInstanceWithNullDbNamepFails() {
104+
expectError(
105+
() -> FirebaseFirestore.getInstance((String) null),
106+
"Provided database name must not be null.");
99107
}
100108

101109
@Test

firebase-firestore/src/androidTest/java/com/google/firebase/firestore/testutil/IntegrationTestUtil.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,11 +251,22 @@ public static FirebaseFirestore testFirestore(
251251
Logger.Level logLevel,
252252
FirebaseFirestoreSettings settings,
253253
String persistenceKey) {
254+
return testFirestore(
255+
DatabaseId.forDatabase(projectId, DatabaseId.DEFAULT_DATABASE_ID),
256+
logLevel,
257+
settings,
258+
persistenceKey);
259+
}
260+
261+
public static FirebaseFirestore testFirestore(
262+
DatabaseId databaseId,
263+
Logger.Level logLevel,
264+
FirebaseFirestoreSettings settings,
265+
String persistenceKey) {
254266
// This unfortunately is a global setting that affects existing Firestore clients.
255267
Logger.setLogLevel(logLevel);
256268

257269
Context context = ApplicationProvider.getApplicationContext();
258-
DatabaseId databaseId = DatabaseId.forDatabase(projectId, DatabaseId.DEFAULT_DATABASE_ID);
259270

260271
ensureStrictMode();
261272

firebase-firestore/src/main/java/com/google/firebase/firestore/FirebaseFirestore.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,22 +104,31 @@ public interface InstanceRegistry {
104104
private final GrpcMetadataProvider metadataProvider;
105105

106106
@NonNull
107-
public static FirebaseFirestore getInstance() {
107+
private static FirebaseApp getDefaultFirebaseApp() {
108108
FirebaseApp app = FirebaseApp.getInstance();
109109
if (app == null) {
110110
throw new IllegalStateException("You must call FirebaseApp.initializeApp first.");
111111
}
112-
return getInstance(app, DatabaseId.DEFAULT_DATABASE_ID);
112+
return app;
113+
}
114+
115+
@NonNull
116+
public static FirebaseFirestore getInstance() {
117+
return getInstance(getDefaultFirebaseApp(), DatabaseId.DEFAULT_DATABASE_ID);
113118
}
114119

115120
@NonNull
116121
public static FirebaseFirestore getInstance(@NonNull FirebaseApp app) {
117122
return getInstance(app, DatabaseId.DEFAULT_DATABASE_ID);
118123
}
119124

120-
// TODO: make this public
121125
@NonNull
122-
private static FirebaseFirestore getInstance(@NonNull FirebaseApp app, @NonNull String database) {
126+
public static FirebaseFirestore getInstance(@NonNull String database) {
127+
return getInstance(getDefaultFirebaseApp(), database);
128+
}
129+
130+
@NonNull
131+
public static FirebaseFirestore getInstance(@NonNull FirebaseApp app, @NonNull String database) {
123132
checkNotNull(app, "Provided FirebaseApp must not be null.");
124133
FirestoreMultiDbComponent component = app.get(FirestoreMultiDbComponent.class);
125134
checkNotNull(component, "Firestore component is not present.");

0 commit comments

Comments
 (0)