Skip to content

Commit f00700c

Browse files
authored
Merge branch 'master' into releases/M133.mergeback
2 parents cd5f5c2 + f76f697 commit f00700c

File tree

10 files changed

+182
-7
lines changed

10 files changed

+182
-7
lines changed

firebase-firestore/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Unreleased
2+
* [feature] Expose MultiDb support in API. [#4015](//github.com/firebase/firebase-android-sdk/issues/4015)
23

34
# 24.6.1
45
* [feature] Implemented an optimization in the local cache synchronization logic that reduces the number of billed document reads when documents were deleted on the server while the client was not actively listening to the query (e.g. while the client was offline). (GitHub [#4982](//github.com/firebase/firebase-android-sdk/pull/4982){: .external})

firebase-firestore/api.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ package com.google.firebase.firestore {
186186
method @NonNull public com.google.firebase.firestore.FirebaseFirestoreSettings getFirestoreSettings();
187187
method @NonNull public static com.google.firebase.firestore.FirebaseFirestore getInstance();
188188
method @NonNull public static com.google.firebase.firestore.FirebaseFirestore getInstance(@NonNull com.google.firebase.FirebaseApp);
189+
method @NonNull public static com.google.firebase.firestore.FirebaseFirestore getInstance(@NonNull String);
190+
method @NonNull public static com.google.firebase.firestore.FirebaseFirestore getInstance(@NonNull com.google.firebase.FirebaseApp, @NonNull String);
189191
method @NonNull public com.google.android.gms.tasks.Task<com.google.firebase.firestore.Query> getNamedQuery(@NonNull String);
190192
method @NonNull public com.google.firebase.firestore.LoadBundleTask loadBundle(@NonNull java.io.InputStream);
191193
method @NonNull public com.google.firebase.firestore.LoadBundleTask loadBundle(@NonNull byte[]);

firebase-firestore/ktx/api.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ package com.google.firebase.firestore.ktx {
55
method public static inline <reified T> kotlinx.coroutines.flow.Flow<? extends java.util.List<? extends T>> dataObjects(@NonNull com.google.firebase.firestore.Query, @NonNull com.google.firebase.firestore.MetadataChanges metadataChanges = com.google.firebase.firestore.MetadataChanges.EXCLUDE);
66
method public static inline <reified T> kotlinx.coroutines.flow.Flow<? extends T> dataObjects(@NonNull com.google.firebase.firestore.DocumentReference, @NonNull com.google.firebase.firestore.MetadataChanges metadataChanges = com.google.firebase.firestore.MetadataChanges.EXCLUDE);
77
method @NonNull public static com.google.firebase.firestore.FirebaseFirestore firestore(@NonNull com.google.firebase.ktx.Firebase, @NonNull com.google.firebase.FirebaseApp app);
8+
method @NonNull public static com.google.firebase.firestore.FirebaseFirestore firestore(@NonNull com.google.firebase.ktx.Firebase, @NonNull com.google.firebase.FirebaseApp app, @NonNull String database);
9+
method @NonNull public static com.google.firebase.firestore.FirebaseFirestore firestore(@NonNull com.google.firebase.ktx.Firebase, @NonNull String database);
810
method @NonNull public static com.google.firebase.firestore.FirebaseFirestoreSettings firestoreSettings(@NonNull kotlin.jvm.functions.Function1<? super com.google.firebase.firestore.FirebaseFirestoreSettings.Builder,kotlin.Unit> init);
911
method public static inline <reified T> T getField(@NonNull com.google.firebase.firestore.DocumentSnapshot, @NonNull String field);
1012
method public static inline <reified T> T getField(@NonNull com.google.firebase.firestore.DocumentSnapshot, @NonNull String field, @NonNull com.google.firebase.firestore.DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior);

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ val Firebase.firestore: FirebaseFirestore
3636
/** Returns the [FirebaseFirestore] instance of a given [FirebaseApp]. */
3737
fun Firebase.firestore(app: FirebaseApp): FirebaseFirestore = FirebaseFirestore.getInstance(app)
3838

39+
/** Returns the [FirebaseFirestore] instance of a given [FirebaseApp] and database name. */
40+
fun Firebase.firestore(app: FirebaseApp, database: String): FirebaseFirestore =
41+
FirebaseFirestore.getInstance(app, database)
42+
43+
/**
44+
* Returns the [FirebaseFirestore] instance of the default [FirebaseApp], given the database name.
45+
*/
46+
fun Firebase.firestore(database: String): FirebaseFirestore =
47+
FirebaseFirestore.getInstance(database)
48+
3949
/**
4050
* Returns the contents of the document converted to a POJO or null if the document doesn't exist.
4151
*

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

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

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

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

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

Lines changed: 82 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;
@@ -38,6 +39,7 @@
3839
import static org.junit.Assert.assertThrows;
3940
import static org.junit.Assert.assertTrue;
4041
import static org.junit.Assert.fail;
42+
import static org.junit.Assume.assumeTrue;
4143

4244
import androidx.test.ext.junit.runners.AndroidJUnit4;
4345
import com.google.android.gms.tasks.Task;
@@ -47,6 +49,7 @@
4749
import com.google.firebase.firestore.FirebaseFirestoreException.Code;
4850
import com.google.firebase.firestore.Query.Direction;
4951
import com.google.firebase.firestore.auth.User;
52+
import com.google.firebase.firestore.model.DatabaseId;
5053
import com.google.firebase.firestore.testutil.EventAccumulator;
5154
import com.google.firebase.firestore.testutil.IntegrationTestUtil;
5255
import com.google.firebase.firestore.util.AsyncQueue.TimerId;
@@ -1132,6 +1135,85 @@ public void testAppDeleteLeadsToFirestoreTerminate() {
11321135
assertTrue(instance.getClient().isTerminated());
11331136
}
11341137

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+
// TODO: Have backend with named databases created beforehand.
1174+
// Emulator doesn't care if database was created beforehand.
1175+
assumeTrue(isRunningAgainstEmulator());
1176+
1177+
// FirebaseFirestore db1 = FirebaseFirestore.getInstance();
1178+
String projectId = provider().projectId();
1179+
FirebaseFirestore db1 =
1180+
testFirestore(
1181+
DatabaseId.forDatabase(projectId, "db1"),
1182+
Level.DEBUG,
1183+
newTestSettings(),
1184+
"dbPersistenceKey");
1185+
FirebaseFirestore db2 =
1186+
testFirestore(
1187+
DatabaseId.forDatabase(projectId, "db2"),
1188+
Level.DEBUG,
1189+
newTestSettings(),
1190+
"dbPersistenceKey");
1191+
1192+
DocumentReference docRef = db1.collection("col1").document("doc1");
1193+
waitFor(docRef.set(Collections.singletonMap("foo", "bar")));
1194+
assertEquals(waitFor(docRef.get(Source.SERVER)).get("foo"), "bar");
1195+
1196+
String path = docRef.getPath();
1197+
DocumentReference docRef2 = db2.document(path);
1198+
1199+
{
1200+
Exception e = waitForException(docRef2.get(Source.CACHE));
1201+
assertEquals(Code.UNAVAILABLE, ((FirebaseFirestoreException) e).getCode());
1202+
}
1203+
1204+
{
1205+
Task<DocumentSnapshot> task = docRef2.get(Source.SERVER);
1206+
DocumentSnapshot result = waitFor(task);
1207+
assertNull(result.getDocument());
1208+
}
1209+
1210+
{
1211+
Task<DocumentSnapshot> task = docRef2.get(Source.DEFAULT);
1212+
DocumentSnapshot result = waitFor(task);
1213+
assertNull(result.getDocument());
1214+
}
1215+
}
1216+
11351217
@Test
11361218
public void testNewOperationThrowsAfterFirestoreTerminate() {
11371219
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
@@ -282,11 +282,22 @@ public static FirebaseFirestore testFirestore(
282282
Logger.Level logLevel,
283283
FirebaseFirestoreSettings settings,
284284
String persistenceKey) {
285+
return testFirestore(
286+
DatabaseId.forDatabase(projectId, DatabaseId.DEFAULT_DATABASE_ID),
287+
logLevel,
288+
settings,
289+
persistenceKey);
290+
}
291+
292+
public static FirebaseFirestore testFirestore(
293+
DatabaseId databaseId,
294+
Logger.Level logLevel,
295+
FirebaseFirestoreSettings settings,
296+
String persistenceKey) {
285297
// This unfortunately is a global setting that affects existing Firestore clients.
286298
Logger.setLogLevel(logLevel);
287299

288300
Context context = ApplicationProvider.getApplicationContext();
289-
DatabaseId databaseId = DatabaseId.forDatabase(projectId, DatabaseId.DEFAULT_DATABASE_ID);
290301

291302
ensureStrictMode();
292303

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

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,23 +105,68 @@ public interface InstanceRegistry {
105105
private final GrpcMetadataProvider metadataProvider;
106106

107107
@NonNull
108-
public static FirebaseFirestore getInstance() {
108+
private static FirebaseApp getDefaultFirebaseApp() {
109109
FirebaseApp app = FirebaseApp.getInstance();
110110
if (app == null) {
111111
throw new IllegalStateException("You must call FirebaseApp.initializeApp first.");
112112
}
113-
return getInstance(app, DatabaseId.DEFAULT_DATABASE_ID);
113+
return app;
114+
}
115+
116+
/**
117+
* Returns the default {@link FirebaseFirestore} instance associated with the default {@link
118+
* FirebaseApp}. Returns the same instance for all invocations. If no instance exists, initializes
119+
* a new instance with default settings.
120+
*
121+
* @returns The {@link FirebaseFirestore} instance.
122+
*/
123+
@NonNull
124+
public static FirebaseFirestore getInstance() {
125+
return getInstance(getDefaultFirebaseApp(), DatabaseId.DEFAULT_DATABASE_ID);
114126
}
115127

128+
/**
129+
* Returns the default {@link FirebaseFirestore} instance that is associated with the provided
130+
* {@link FirebaseApp}. For a given {@link FirebaseApp}, invocation always returns the same
131+
* instance. If no instance exists, initializes a new instance with default settings.
132+
*
133+
* @param app - The {@link FirebaseApp} instance that the returned {@link FirebaseFirestore}
134+
* instance is associated with.
135+
* @returns The {@link FirebaseFirestore} instance.
136+
*/
116137
@NonNull
117138
public static FirebaseFirestore getInstance(@NonNull FirebaseApp app) {
118139
return getInstance(app, DatabaseId.DEFAULT_DATABASE_ID);
119140
}
120141

121-
// TODO: make this public
142+
/**
143+
* Returns the {@link FirebaseFirestore} instance that is associated with the default {@link
144+
* FirebaseApp}. Returns the same instance for all invocations given the same database parameter.
145+
* If no instance exists, initializes a new instance with default settings.
146+
*
147+
* @param database - The name of database.
148+
* @returns The {@link FirebaseFirestore} instance.
149+
*/
150+
@NonNull
151+
public static FirebaseFirestore getInstance(@NonNull String database) {
152+
return getInstance(getDefaultFirebaseApp(), database);
153+
}
154+
155+
/**
156+
* Returns the {@link FirebaseFirestore} instance that is associated with the provided {@link
157+
* FirebaseApp}. Returns the same instance for all invocations given the same {@link FirebaseApp}
158+
* and database parameter. If no instance exists, initializes a new instance with default
159+
* settings.
160+
*
161+
* @param app - The {@link FirebaseApp} instance that the returned {@link FirebaseFirestore}
162+
* instance is associated with.
163+
* @param database - The name of database.
164+
* @returns The {@link FirebaseFirestore} instance.
165+
*/
122166
@NonNull
123-
private static FirebaseFirestore getInstance(@NonNull FirebaseApp app, @NonNull String database) {
167+
public static FirebaseFirestore getInstance(@NonNull FirebaseApp app, @NonNull String database) {
124168
checkNotNull(app, "Provided FirebaseApp must not be null.");
169+
checkNotNull(database, "Provided database name must not be null.");
125170
FirestoreMultiDbComponent component = app.get(FirestoreMultiDbComponent.class);
126171
checkNotNull(component, "Firestore component is not present.");
127172
return component.get(database);

firebase-messaging/src/test/java/com/google/firebase/messaging/FirebaseMessagingRoboTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
// limitations under the License.
1414
package com.google.firebase.messaging;
1515

16-
import static android.os.Looper.getMainLooper;
1716
import static com.google.common.truth.Truth.assertThat;
1817
import static com.google.firebase.messaging.FirebaseMessaging.GMS_PACKAGE;
1918
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -462,6 +461,8 @@ public void proxyNotificationEnabledIsFalseWhenUidIsWrong() throws Exception {
462461
assertThat(FirebaseMessaging.getInstance().isNotificationDelegationEnabled()).isFalse();
463462
}
464463

464+
/*
465+
TODO b/286544512
465466
@Test
466467
public void testSubscribeToTopic_withPrefix() {
467468
firebaseMessaging.subscribeToTopic(VALID_TOPIC);
@@ -491,6 +492,7 @@ public void testUnsubscribeFromTopic_invalid() {
491492
shadowOf(getMainLooper()).runToEndOfTasks();
492493
assertThat(task.getException()).isInstanceOf(IllegalArgumentException.class);
493494
}
495+
*/
494496

495497
@Test
496498
public void testLibraryVersionRegistration_valid() {

0 commit comments

Comments
 (0)