|
20 | 20 | import static com.google.firebase.firestore.testutil.IntegrationTestUtil.testCollectionWithDocs;
|
21 | 21 | import static com.google.firebase.firestore.testutil.IntegrationTestUtil.testFirestore;
|
22 | 22 | import static com.google.firebase.firestore.testutil.IntegrationTestUtil.waitFor;
|
| 23 | +import static com.google.firebase.firestore.testutil.TestUtil.expectError; |
23 | 24 | import static com.google.firebase.firestore.testutil.TestUtil.map;
|
24 | 25 | import static java.util.Arrays.asList;
|
25 | 26 | import static java.util.Collections.singletonList;
|
@@ -80,6 +81,78 @@ public void testLimitQueriesUsingDescendingSortOrder() {
|
80 | 81 | assertEquals(asList(map("k", "d", "sort", 2L), map("k", "c", "sort", 1L)), data);
|
81 | 82 | }
|
82 | 83 |
|
| 84 | + @Test |
| 85 | + public void testLimitToLastMustAlsoHaveExplicitOrderBy() { |
| 86 | + CollectionReference collection = testCollectionWithDocs(map()); |
| 87 | + |
| 88 | + Query query = collection.limitToLast(2); |
| 89 | + expectError( |
| 90 | + () -> waitFor(query.get()), |
| 91 | + "limitToLast() queries require specifying at least one orderBy() clause"); |
| 92 | + } |
| 93 | + |
| 94 | + // Two queries that mapped to the same target ID are referred to as |
| 95 | + // "mirror queries". An example for a mirror query is a limitToLast() |
| 96 | + // query and a limit() query that share the same backend Target ID. |
| 97 | + // Since limitToLast() queries are sent to the backend with a modified |
| 98 | + // orderBy() clause, they can map to the same target representation as |
| 99 | + // limit() query, even if both queries appear separate to the user. |
| 100 | + @Test |
| 101 | + public void testListenUnlistenRelistenSequenceOfMirrorQueries() { |
| 102 | + CollectionReference collection = |
| 103 | + testCollectionWithDocs( |
| 104 | + map( |
| 105 | + "a", map("k", "a", "sort", 0), |
| 106 | + "b", map("k", "b", "sort", 1), |
| 107 | + "c", map("k", "c", "sort", 1), |
| 108 | + "d", map("k", "d", "sort", 2))); |
| 109 | + |
| 110 | + // Setup `limit` query. |
| 111 | + Query limit = collection.limit(2).orderBy("sort", Direction.ASCENDING); |
| 112 | + EventAccumulator<QuerySnapshot> limitAccumulator = new EventAccumulator<>(); |
| 113 | + ListenerRegistration limitRegistration = limit.addSnapshotListener(limitAccumulator.listener()); |
| 114 | + |
| 115 | + // Setup mirroring `limitToLast` query. |
| 116 | + Query limitToLast = collection.limitToLast(2).orderBy("sort", Direction.DESCENDING); |
| 117 | + EventAccumulator<QuerySnapshot> limitToLastAccumulator = new EventAccumulator<>(); |
| 118 | + ListenerRegistration limitToLastRegistration = |
| 119 | + limitToLast.addSnapshotListener(limitToLastAccumulator.listener()); |
| 120 | + |
| 121 | + // Verify both query get expected result. |
| 122 | + List<Map<String, Object>> data = querySnapshotToValues(limitAccumulator.await()); |
| 123 | + assertEquals(asList(map("k", "a", "sort", 0L), map("k", "b", "sort", 1L)), data); |
| 124 | + data = querySnapshotToValues(limitToLastAccumulator.await()); |
| 125 | + assertEquals(asList(map("k", "b", "sort", 1L), map("k", "a", "sort", 0L)), data); |
| 126 | + |
| 127 | + // Unlisten then re-listen limit query. |
| 128 | + limitRegistration.remove(); |
| 129 | + limit.addSnapshotListener(limitAccumulator.listener()); |
| 130 | + |
| 131 | + // Verify `limit` query still works. |
| 132 | + data = querySnapshotToValues(limitAccumulator.await()); |
| 133 | + assertEquals(asList(map("k", "a", "sort", 0L), map("k", "b", "sort", 1L)), data); |
| 134 | + |
| 135 | + // Add a document that would change the result set. |
| 136 | + waitFor(collection.add(map("k", "e", "sort", -1))); |
| 137 | + |
| 138 | + // Verify both query get expected result. |
| 139 | + data = querySnapshotToValues(limitAccumulator.await()); |
| 140 | + assertEquals(asList(map("k", "e", "sort", -1L), map("k", "a", "sort", 0L)), data); |
| 141 | + data = querySnapshotToValues(limitToLastAccumulator.await()); |
| 142 | + assertEquals(asList(map("k", "a", "sort", 0L), map("k", "e", "sort", -1L)), data); |
| 143 | + |
| 144 | + // Unlisten to limitToLast, update a doc, then relisten to limitToLast |
| 145 | + limitToLastRegistration.remove(); |
| 146 | + waitFor(collection.document("a").update(map("k", "a", "sort", -2))); |
| 147 | + limitToLast.addSnapshotListener(limitToLastAccumulator.listener()); |
| 148 | + |
| 149 | + // Verify both query get expected result. |
| 150 | + data = querySnapshotToValues(limitAccumulator.await()); |
| 151 | + assertEquals(asList(map("k", "a", "sort", -2L), map("k", "e", "sort", -1L)), data); |
| 152 | + data = querySnapshotToValues(limitToLastAccumulator.await()); |
| 153 | + assertEquals(asList(map("k", "e", "sort", -1L), map("k", "a", "sort", -2L)), data); |
| 154 | + } |
| 155 | + |
83 | 156 | @Test
|
84 | 157 | public void testKeyOrderIsDescendingForDescendingInequality() {
|
85 | 158 | CollectionReference collection =
|
|
0 commit comments