diff --git a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/Order.java b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/Order.java index 65a92a1be..d7c39ebf4 100644 --- a/google-cloud-firestore/src/main/java/com/google/cloud/firestore/Order.java +++ b/google-cloud-firestore/src/main/java/com/google/cloud/firestore/Order.java @@ -135,13 +135,19 @@ public int compare(@Nonnull Value left, @Nonnull Value right) { } private int compareStrings(Value left, Value right) { - return left.getStringValue().compareTo(right.getStringValue()); + ByteString leftBytes = ByteString.copyFromUtf8(left.getStringValue()); + ByteString rightBytes = ByteString.copyFromUtf8(right.getStringValue()); +// return left.getStringValue().compareTo(right.getStringValue()); + return compareBytes(leftBytes, rightBytes); } private int compareBlobs(Value left, Value right) { ByteString leftBytes = left.getBytesValue(); ByteString rightBytes = right.getBytesValue(); + return compareBytes(leftBytes, rightBytes); + } + private int compareBytes(ByteString leftBytes, ByteString rightBytes){ int size = Math.min(leftBytes.size(), rightBytes.size()); for (int i = 0; i < size; i++) { // Make sure the bytes are unsigned diff --git a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/it/ITQueryTest.java b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/it/ITQueryTest.java index 6125d24f4..fc5fb9d7d 100644 --- a/google-cloud-firestore/src/test/java/com/google/cloud/firestore/it/ITQueryTest.java +++ b/google-cloud-firestore/src/test/java/com/google/cloud/firestore/it/ITQueryTest.java @@ -34,6 +34,8 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -1113,4 +1115,45 @@ public void testAggregateQueryProfile() throws Exception { assertThat(stats.getResultsReturned()).isEqualTo(1); assertThat(stats.getExecutionDuration()).isGreaterThan(Duration.ZERO); } + + @Test + public void snapshotListenerSortsUnicodesSameWayAsServer() throws Exception { + CollectionReference col = createEmptyCollection(); + + firestore + .batch() + .set(col.document("a"), map("value", "Łukasiewicz")) + .set(col.document("b"), map("value", "Sierpiński")) + .set(col.document("c"), map("value", "岩澤")) + .set(col.document("d"), map("value", "🄟")) + .set(col.document("e"), map("value", "P")) + .set(col.document("f"), map("value", "︒")) + .set(col.document("g"), map("value", "🐵")) + + .commit() + .get(); + + Query query = col.orderBy("value", Direction.ASCENDING); + + QuerySnapshot snapshot = query.get().get(); + List queryOrder = + snapshot.getDocuments().stream().map(doc -> doc.getId()).collect(Collectors.toList()); + + CountDownLatch latch = new CountDownLatch(1); + List listenerOrder = new ArrayList<>(); + ListenerRegistration registration = + query.addSnapshotListener( + (value, error) -> { + listenerOrder.addAll( + value.getDocuments().stream() + .map(doc -> doc.getId()) + .collect(Collectors.toList())); + latch.countDown(); + }); + latch.await(); + registration.remove(); + + assertEquals(queryOrder, Arrays.asList("b", "a", "c", "f", "e", "d", "g")); + assertEquals(queryOrder, listenerOrder); // Assert order in the SDK + } }