Skip to content

Commit 12de4c0

Browse files
authored
Merge branch 'master' into mila/multiple-inequality-support
2 parents 3b20dad + dff55b6 commit 12de4c0

File tree

18 files changed

+345
-45
lines changed

18 files changed

+345
-45
lines changed

.github/workflows/version-check.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Version Check
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
branches:
7+
- 'releases/**'
8+
9+
jobs:
10+
version-check:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/[email protected]
14+
15+
- name: Build
16+
run: |
17+
./gradlew gmavenVersionCheck

buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseJavaLibraryPlugin.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,17 @@ class FirebaseJavaLibraryPlugin : BaseFirebaseLibraryPlugin() {
5656
setupStaticAnalysis(project, firebaseLibrary)
5757
setupApiInformationAnalysis(project)
5858
getIsPomValidTask(project, firebaseLibrary)
59-
getSemverTaskJar(project, firebaseLibrary)
59+
setupVersionCheckTasks(project, firebaseLibrary)
6060
configurePublishing(project, firebaseLibrary)
6161
}
6262

63-
private fun getSemverTaskJar(project: Project, firebaseLibrary: FirebaseLibraryExtension) {
63+
private fun setupVersionCheckTasks(project: Project, firebaseLibrary: FirebaseLibraryExtension) {
64+
project.tasks.register<GmavenVersionChecker>("gmavenVersionCheck") {
65+
groupId.value(firebaseLibrary.groupId.get())
66+
artifactId.value(firebaseLibrary.artifactId.get())
67+
version.value(firebaseLibrary.version)
68+
latestReleasedVersion.value(firebaseLibrary.latestReleasedVersion.orElseGet { "" })
69+
}
6470
project.mkdir("semver")
6571
project.tasks.register<GmavenCopier>("copyPreviousArtifacts") {
6672
dependsOn("jar")

buildSrc/src/main/java/com/google/firebase/gradle/plugins/FirebaseLibraryPlugin.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import java.io.File
2727
import org.gradle.api.JavaVersion
2828
import org.gradle.api.Project
2929
import org.gradle.api.attributes.Attribute
30-
import org.gradle.api.publish.tasks.GenerateModuleMetadata
3130
import org.gradle.api.tasks.Copy
3231
import org.gradle.kotlin.dsl.apply
3332
import org.gradle.kotlin.dsl.create
@@ -85,11 +84,17 @@ class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() {
8584
android.testServer(FirebaseTestServer(project, firebaseLibrary.testLab, android))
8685
setupStaticAnalysis(project, firebaseLibrary)
8786
getIsPomValidTask(project, firebaseLibrary)
88-
getSemverTaskAar(project, firebaseLibrary)
87+
setupVersionCheckTasks(project, firebaseLibrary)
8988
configurePublishing(project, firebaseLibrary, android)
9089
}
9190

92-
private fun getSemverTaskAar(project: Project, firebaseLibrary: FirebaseLibraryExtension) {
91+
private fun setupVersionCheckTasks(project: Project, firebaseLibrary: FirebaseLibraryExtension) {
92+
project.tasks.register<GmavenVersionChecker>("gmavenVersionCheck") {
93+
groupId.value(firebaseLibrary.groupId.get())
94+
artifactId.value(firebaseLibrary.artifactId.get())
95+
version.value(firebaseLibrary.version)
96+
latestReleasedVersion.value(firebaseLibrary.latestReleasedVersion.orElseGet { "" })
97+
}
9398
project.mkdir("semver")
9499
project.mkdir("semver/previous-version")
95100
project.tasks.register<GmavenCopier>("copyPreviousArtifacts") {
@@ -173,7 +178,6 @@ class FirebaseLibraryPlugin : BaseFirebaseLibraryPlugin() {
173178
android: LibraryExtension
174179
) {
175180
android.publishing.singleVariant("release") { withSourcesJar() }
176-
project.tasks.withType<GenerateModuleMetadata> { isEnabled = false }
177181

178182
configurePublishing(project, firebaseLibrary)
179183
}

buildSrc/src/main/java/com/google/firebase/gradle/plugins/GmavenHelper.kt

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,35 @@ class GmavenHelper(val groupId: String, val artifactId: String) {
4848
return "${GMAVEN_ROOT}/${groupIdAsPath}/${artifactId}/${version}/${fileName}"
4949
}
5050

51+
fun hasReleasedVersion(version: String): Boolean {
52+
val doc: Document? = getMavenMetadata()
53+
if (doc != null) {
54+
val versions = doc.getElementsByTagName("version")
55+
for (i in 0..versions.length - 1) {
56+
if (versions.item(i).textContent == version) {
57+
return true
58+
}
59+
}
60+
}
61+
return false
62+
}
63+
5164
fun getLatestReleasedVersion(): String {
65+
val doc: Document? = getMavenMetadata()
66+
return doc?.getElementsByTagName("latest")?.item(0)?.getTextContent() ?: ""
67+
}
68+
69+
fun getMavenMetadata(): Document? {
70+
val groupIdAsPath = groupId.replace(".", "/")
71+
val mavenMetadataUrl = "${GMAVEN_ROOT}/${groupIdAsPath}/${artifactId}/maven-metadata.xml"
72+
val factory: DocumentBuilderFactory = DocumentBuilderFactory.newInstance()
73+
val builder: DocumentBuilder = factory.newDocumentBuilder()
5274
try {
53-
val groupIdAsPath = groupId.replace(".", "/")
54-
val mavenMetadataUrl = "${GMAVEN_ROOT}/${groupIdAsPath}/${artifactId}/maven-metadata.xml"
55-
val factory: DocumentBuilderFactory = DocumentBuilderFactory.newInstance()
56-
val builder: DocumentBuilder = factory.newDocumentBuilder()
5775
val doc: Document = builder.parse(URL(mavenMetadataUrl).openStream())
5876
doc.documentElement.normalize()
59-
return doc.getElementsByTagName("latest").item(0).getTextContent()
77+
return doc
6078
} catch (e: FileNotFoundException) {
61-
return ""
79+
return null
6280
}
6381
}
6482
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2023 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.gradle.plugins
16+
17+
import org.gradle.api.DefaultTask
18+
import org.gradle.api.GradleException
19+
import org.gradle.api.provider.Property
20+
import org.gradle.api.tasks.Input
21+
import org.gradle.api.tasks.TaskAction
22+
23+
abstract class GmavenVersionChecker : DefaultTask() {
24+
25+
@get:Input abstract val groupId: Property<String>
26+
27+
@get:Input abstract val artifactId: Property<String>
28+
29+
@get:Input abstract val latestReleasedVersion: Property<String>
30+
31+
@get:Input abstract val version: Property<String>
32+
33+
@TaskAction
34+
fun run() {
35+
val mavenHelper = GmavenHelper(groupId.get(), artifactId.get())
36+
val latestMavenVersion = mavenHelper.getLatestReleasedVersion()
37+
val info =
38+
"\n latestReleasedVersion in gradle.properties should match the latest release on GMaven (${latestMavenVersion})" +
39+
"\n version in gradle.properties should be a version bump above this, following SemVer, and should not be released on GMaven"
40+
// Either the Maven metadata does not exist, or the library hasn't been released
41+
if (latestMavenVersion.isEmpty()) {
42+
return
43+
}
44+
// TODO(b/285892320): Remove condition when bug fixed
45+
if (artifactId.get() == "protolite-well-known-types") {
46+
return
47+
}
48+
if (version.get() == latestReleasedVersion.get()) {
49+
throw GradleException(
50+
"version and latestReleasedVersion from gradle.properties are the same (${version.get()})" +
51+
info
52+
)
53+
}
54+
if (latestMavenVersion == version.get()) {
55+
throw GradleException(
56+
"version from gradle.properties (${version.get()}) is already the latest release on GMaven" +
57+
info
58+
)
59+
} else if (mavenHelper.hasReleasedVersion(version.get())) {
60+
throw GradleException(
61+
"version from gradle.properties (${version.get()}) has already been released on GMaven" +
62+
info
63+
)
64+
}
65+
if (latestMavenVersion != latestReleasedVersion.get()) {
66+
if (mavenHelper.hasReleasedVersion(latestReleasedVersion.get())) {
67+
throw GradleException(
68+
"latestReleasedVersion from gradle.properties (${latestReleasedVersion.get()}) has been released but is not the latest release on GMaven (${latestMavenVersion})"
69+
)
70+
} else {
71+
throw GradleException(
72+
"latestReleasedVersion from gradle.properties (${latestReleasedVersion.get()}) has not been released on GMaven" +
73+
info
74+
)
75+
}
76+
}
77+
}
78+
}

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

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,4 +1419,77 @@ public void testCannotGetDocumentWithMemoryEagerGcEnabled() {
14191419
assertTrue(e instanceof FirebaseFirestoreException);
14201420
assertEquals(((FirebaseFirestoreException) e).getCode(), Code.UNAVAILABLE);
14211421
}
1422+
1423+
@Test
1424+
public void testGetPersistentCacheIndexManager() {
1425+
// Use persistent disk cache (explicit)
1426+
FirebaseFirestore db1 = testFirestore();
1427+
FirebaseFirestoreSettings settings1 =
1428+
new FirebaseFirestoreSettings.Builder(db1.getFirestoreSettings())
1429+
.setLocalCacheSettings(PersistentCacheSettings.newBuilder().build())
1430+
.build();
1431+
db1.setFirestoreSettings(settings1);
1432+
assertNotNull(db1.getPersistentCacheIndexManager());
1433+
1434+
// Use persistent disk cache (default)
1435+
FirebaseFirestore db2 = testFirestore();
1436+
assertNotNull(db2.getPersistentCacheIndexManager());
1437+
1438+
// Disable persistent disk cache
1439+
FirebaseFirestore db3 = testFirestore();
1440+
FirebaseFirestoreSettings settings3 =
1441+
new FirebaseFirestoreSettings.Builder(db1.getFirestoreSettings())
1442+
.setLocalCacheSettings(MemoryCacheSettings.newBuilder().build())
1443+
.build();
1444+
db3.setFirestoreSettings(settings3);
1445+
assertNull(db3.getPersistentCacheIndexManager());
1446+
1447+
// Disable persistent disk cache (deprecated)
1448+
FirebaseFirestore db4 = testFirestore();
1449+
FirebaseFirestoreSettings settings4 =
1450+
new FirebaseFirestoreSettings.Builder(db4.getFirestoreSettings())
1451+
.setPersistenceEnabled(false)
1452+
.build();
1453+
db4.setFirestoreSettings(settings4);
1454+
assertNull(db4.getPersistentCacheIndexManager());
1455+
}
1456+
1457+
@Test
1458+
public void testCanGetSameOrDifferentPersistentCacheIndexManager() {
1459+
// Use persistent disk cache (explicit)
1460+
FirebaseFirestore db1 = testFirestore();
1461+
FirebaseFirestoreSettings settings1 =
1462+
new FirebaseFirestoreSettings.Builder(db1.getFirestoreSettings())
1463+
.setLocalCacheSettings(PersistentCacheSettings.newBuilder().build())
1464+
.build();
1465+
db1.setFirestoreSettings(settings1);
1466+
PersistentCacheIndexManager indexManager1 = db1.getPersistentCacheIndexManager();
1467+
PersistentCacheIndexManager indexManager2 = db1.getPersistentCacheIndexManager();
1468+
assertSame(indexManager1, indexManager2);
1469+
1470+
// Use persistent disk cache (default)
1471+
FirebaseFirestore db2 = testFirestore();
1472+
PersistentCacheIndexManager indexManager3 = db2.getPersistentCacheIndexManager();
1473+
PersistentCacheIndexManager indexManager4 = db2.getPersistentCacheIndexManager();
1474+
assertSame(indexManager3, indexManager4);
1475+
1476+
assertNotSame(indexManager1, indexManager3);
1477+
1478+
FirebaseFirestore db3 = testFirestore();
1479+
FirebaseFirestoreSettings settings3 =
1480+
new FirebaseFirestoreSettings.Builder(db3.getFirestoreSettings())
1481+
.setLocalCacheSettings(PersistentCacheSettings.newBuilder().build())
1482+
.build();
1483+
db3.setFirestoreSettings(settings3);
1484+
PersistentCacheIndexManager indexManager5 = db3.getPersistentCacheIndexManager();
1485+
assertNotSame(indexManager1, indexManager5);
1486+
assertNotSame(indexManager3, indexManager5);
1487+
1488+
// Use persistent disk cache (default)
1489+
FirebaseFirestore db4 = testFirestore();
1490+
PersistentCacheIndexManager indexManager6 = db4.getPersistentCacheIndexManager();
1491+
assertNotSame(indexManager1, indexManager6);
1492+
assertNotSame(indexManager3, indexManager6);
1493+
assertNotSame(indexManager5, indexManager6);
1494+
}
14221495
}

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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,13 @@ public void testBadIndexDoesNotCrashClient() {
108108
+ "}"));
109109
}
110110

111+
/**
112+
* After Auto Index Creation is enabled, through public API there is no way to state of indexes
113+
* sitting inside SDK. So this test only checks the API of auto index creation.
114+
*/
111115
@Test
112116
public void testAutoIndexCreationSetSuccessfully() {
113-
// Use persistent disk cache (default)
117+
// Use persistent disk cache (explicit)
114118
FirebaseFirestore db = testFirestore();
115119
FirebaseFirestoreSettings settings =
116120
new FirebaseFirestoreSettings.Builder(db.getFirestoreSettings())
@@ -128,19 +132,22 @@ public void testAutoIndexCreationSetSuccessfully() {
128132
assertEquals(1, results.size());
129133

130134
assertDoesNotThrow(() -> db.getPersistentCacheIndexManager().enableIndexAutoCreation());
131-
132-
results = waitFor(collection.whereEqualTo("match", true).get());
135+
results = waitFor(collection.whereEqualTo("match", true).get(Source.CACHE));
133136
assertEquals(1, results.size());
134137

135138
assertDoesNotThrow(() -> db.getPersistentCacheIndexManager().disableIndexAutoCreation());
136-
137-
results = waitFor(collection.whereEqualTo("match", true).get());
139+
results = waitFor(collection.whereEqualTo("match", true).get(Source.CACHE));
138140
assertEquals(1, results.size());
139141

140142
assertDoesNotThrow(() -> db.getPersistentCacheIndexManager().deleteAllIndexes());
143+
results = waitFor(collection.whereEqualTo("match", true).get(Source.CACHE));
141144
assertEquals(1, results.size());
142145
}
143146

147+
/**
148+
* After Auto Index Creation is enabled, through public API there is no way to state of indexes
149+
* sitting inside SDK. So this test only checks the API of auto index creation.
150+
*/
144151
@Test
145152
public void testAutoIndexCreationSetSuccessfullyUsingDefault() {
146153
// Use persistent disk cache (default)
@@ -156,16 +163,15 @@ public void testAutoIndexCreationSetSuccessfullyUsingDefault() {
156163
assertEquals(1, results.size());
157164

158165
assertDoesNotThrow(() -> db.getPersistentCacheIndexManager().enableIndexAutoCreation());
159-
160-
results = waitFor(collection.whereEqualTo("match", true).get());
166+
results = waitFor(collection.whereEqualTo("match", true).get(Source.CACHE));
161167
assertEquals(1, results.size());
162168

163169
assertDoesNotThrow(() -> db.getPersistentCacheIndexManager().disableIndexAutoCreation());
164-
165-
results = waitFor(collection.whereEqualTo("match", true).get());
170+
results = waitFor(collection.whereEqualTo("match", true).get(Source.CACHE));
166171
assertEquals(1, results.size());
167172

168173
assertDoesNotThrow(() -> db.getPersistentCacheIndexManager().deleteAllIndexes());
174+
results = waitFor(collection.whereEqualTo("match", true).get(Source.CACHE));
169175
assertEquals(1, results.size());
170176
}
171177

@@ -186,4 +192,6 @@ public void testAutoIndexCreationAfterFailsTermination() {
186192
() -> db.getPersistentCacheIndexManager().deleteAllIndexes(),
187193
"The client has already been terminated");
188194
}
195+
196+
// TODO(b/296100693) Add testing hooks to verify indexes are created as expected.
189197
}

firebase-firestore/src/main/java/com/google/firebase/firestore/local/QueryEngine.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ public ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingQuery(
120120
* Decides whether SDK should create a full matched field index for this query based on query
121121
* context and query result size.
122122
*/
123-
// TODO(csi): Auto experiment data.
124123
private void createCacheIndexes(Query query, QueryContext context, int resultSize) {
125124
if (context.getDocumentReadCount() < indexAutoCreationMinCollectionSize) {
126125
Logger.debug(

firebase-firestore/src/main/java/com/google/firebase/firestore/model/TargetIndexMatcher.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ public FieldIndex buildTargetIndex() {
230230
}
231231
}
232232

233+
// Note: We do not explicitly check `inequalityFilter` but rather rely on the target defining an
234+
// appropriate `orderBys` to ensure that the required index segment is added. The query engine
235+
// would reject a query with an inequality filter that lacks the required order-by clause.
233236
for (OrderBy orderBy : orderBys) {
234237
// Stop adding more segments if we see a order-by on key. Typically this is the default
235238
// implicit order-by which is covered in the index_entry table as a separate column.

0 commit comments

Comments
 (0)