19
19
import static com .google .firebase .firestore .testutil .IntegrationTestUtil .testCollectionWithDocsOnNightly ;
20
20
import static com .google .firebase .firestore .testutil .IntegrationTestUtil .waitFor ;
21
21
import static com .google .firebase .firestore .testutil .TestUtil .map ;
22
+ import static java .lang .Double .NaN ;
23
+ import static java .lang .Double .POSITIVE_INFINITY ;
22
24
import static org .junit .Assert .assertEquals ;
23
25
import static org .junit .Assert .assertNotNull ;
24
26
import static org .junit .Assert .assertNull ;
@@ -54,6 +56,7 @@ public void writeAndReadBsonTypes() throws ExecutionException, InterruptedExcept
54
56
"bsonTimestamp" , new BsonTimestamp (1 , 2 ),
55
57
"bsonBinary" , BsonBinaryData .fromBytes (1 , new byte [] {1 , 2 , 3 }),
56
58
"int32" , new Int32Value (1 ),
59
+ "decimal128" , new Decimal128Value ("1.2e3" ),
57
60
"minKey" , MinKey .instance (),
58
61
"maxKey" , MaxKey .instance ())));
59
62
@@ -75,6 +78,7 @@ public void writeAndReadBsonTypes() throws ExecutionException, InterruptedExcept
75
78
expected .put ("bsonTimestamp" , new BsonTimestamp (1 , 3 ));
76
79
expected .put ("bsonBinary" , BsonBinaryData .fromBytes (1 , new byte [] {1 , 2 , 3 }));
77
80
expected .put ("int32" , new Int32Value (2 ));
81
+ expected .put ("decimal128" , new Decimal128Value ("1.2e3" ));
78
82
expected .put ("minKey" , MinKey .instance ());
79
83
expected .put ("maxKey" , MaxKey .instance ());
80
84
@@ -85,6 +89,7 @@ public void writeAndReadBsonTypes() throws ExecutionException, InterruptedExcept
85
89
assertTrue (actual .get ("bsonTimestamp" ) instanceof BsonTimestamp );
86
90
assertTrue (actual .get ("bsonBinary" ) instanceof BsonBinaryData );
87
91
assertTrue (actual .get ("int32" ) instanceof Int32Value );
92
+ assertTrue (actual .get ("decimal128" ) instanceof Decimal128Value );
88
93
assertTrue (actual .get ("minKey" ) instanceof MinKey );
89
94
assertTrue (actual .get ("maxKey" ) instanceof MaxKey );
90
95
assertEquals (expected , actual .getData ());
@@ -101,13 +106,22 @@ public void writeAndReadBsonTypeOffline() throws ExecutionException, Interrupted
101
106
Map <String , Object > expected = new HashMap <>();
102
107
docRef .set (
103
108
map (
104
- "bsonObjectId" , new BsonObjectId ("507f191e810c19729de860ea" ),
105
- "regex" , new RegexValue ("^foo" , "i" ),
106
- "bsonTimestamp" , new BsonTimestamp (1 , 2 ),
107
- "bsonBinary" , BsonBinaryData .fromBytes (1 , new byte [] {1 , 2 , 3 }),
108
- "int32" , new Int32Value (1 ),
109
- "minKey" , MinKey .instance (),
110
- "maxKey" , MaxKey .instance ()));
109
+ "bsonObjectId" ,
110
+ new BsonObjectId ("507f191e810c19729de860ea" ),
111
+ "regex" ,
112
+ new RegexValue ("^foo" , "i" ),
113
+ "bsonTimestamp" ,
114
+ new BsonTimestamp (1 , 2 ),
115
+ "bsonBinary" ,
116
+ BsonBinaryData .fromBytes (1 , new byte [] {1 , 2 , 3 }),
117
+ "int32" ,
118
+ new Int32Value (1 ),
119
+ "decimal128" ,
120
+ new Decimal128Value ("1.2e3" ),
121
+ "minKey" ,
122
+ MinKey .instance (),
123
+ "maxKey" ,
124
+ MaxKey .instance ()));
111
125
112
126
docRef .update (
113
127
map (
@@ -123,6 +137,7 @@ public void writeAndReadBsonTypeOffline() throws ExecutionException, Interrupted
123
137
expected .put ("bsonTimestamp" , new BsonTimestamp (1 , 3 ));
124
138
expected .put ("bsonBinary" , BsonBinaryData .fromBytes (1 , new byte [] {1 , 2 , 3 }));
125
139
expected .put ("int32" , new Int32Value (1 ));
140
+ expected .put ("decimal128" , new Decimal128Value ("1.2e3" ));
126
141
expected .put ("minKey" , MinKey .instance ());
127
142
expected .put ("maxKey" , MaxKey .instance ());
128
143
@@ -133,6 +148,7 @@ public void writeAndReadBsonTypeOffline() throws ExecutionException, Interrupted
133
148
assertTrue (actual .get ("bsonTimestamp" ) instanceof BsonTimestamp );
134
149
assertTrue (actual .get ("bsonBinary" ) instanceof BsonBinaryData );
135
150
assertTrue (actual .get ("int32" ) instanceof Int32Value );
151
+ assertTrue (actual .get ("decimal128" ) instanceof Decimal128Value );
136
152
assertTrue (actual .get ("minKey" ) instanceof MinKey );
137
153
assertTrue (actual .get ("maxKey" ) instanceof MaxKey );
138
154
assertEquals (expected , actual .getData ());
@@ -174,6 +190,8 @@ public void listenToDocumentsWithBsonTypes() throws Throwable {
174
190
BsonBinaryData .fromBytes (1 , new byte [] {1 , 2 , 3 }),
175
191
"int32" ,
176
192
new Int32Value (1 ),
193
+ "decimal128" ,
194
+ new Decimal128Value ("1.2e3" ),
177
195
"minKey" ,
178
196
MinKey .instance (),
179
197
"maxKey" ,
@@ -192,6 +210,9 @@ public void listenToDocumentsWithBsonTypes() throws Throwable {
192
210
assertEquals (
193
211
docSnap .getBsonTimestamp ("bsonTimestamp" ), new BsonTimestamp (1 , 2 ));
194
212
assertEquals (docSnap .getInt32Value ("int32" ), new Int32Value (1 ));
213
+ assertEquals (
214
+ docSnap .getDecimal128Value ("decimal128" ),
215
+ new Decimal128Value ("1.2e3" ));
195
216
assertEquals (docSnap .getMinKey ("minKey" ), MinKey .instance ());
196
217
assertEquals (docSnap .getMaxKey ("maxKey" ), MaxKey .instance ());
197
218
@@ -266,15 +287,13 @@ public void filterAndOrderBsonObjectIds() throws Exception {
266
287
randomColl
267
288
.orderBy ("key" , Direction .DESCENDING )
268
289
.whereGreaterThan ("key" , new BsonObjectId ("507f191e810c19729de860ea" ));
269
-
270
290
assertSDKQueryResultsConsistentWithBackend (
271
291
randomColl , orderedQuery , docs , Arrays .asList ("c" , "b" ));
272
292
273
293
orderedQuery =
274
294
randomColl
275
295
.orderBy ("key" , Direction .DESCENDING )
276
296
.whereNotEqualTo ("key" , new BsonObjectId ("507f191e810c19729de860eb" ));
277
-
278
297
assertSDKQueryResultsConsistentWithBackend (
279
298
randomColl , orderedQuery , docs , Arrays .asList ("c" , "a" ));
280
299
}
@@ -385,6 +404,77 @@ public void filterAndOrderInt32() throws Exception {
385
404
randomColl , orderedQuery , docs , Arrays .asList ("c" , "a" ));
386
405
}
387
406
407
+ @ Test
408
+ public void filterAndOrderDecimal128 () throws Exception {
409
+ Map <String , Map <String , Object >> docs =
410
+ map (
411
+ "a" ,
412
+ map ("key" , new Decimal128Value ("-1.2e3" )),
413
+ "b" ,
414
+ map ("key" , new Decimal128Value ("0" )),
415
+ "c" ,
416
+ map ("key" , new Decimal128Value ("1.2e3" )),
417
+ "d" ,
418
+ map ("key" , new Decimal128Value ("NaN" )),
419
+ "e" ,
420
+ map ("key" , new Decimal128Value ("-Infinity" )),
421
+ "f" ,
422
+ map ("key" , new Decimal128Value ("Infinity" )));
423
+ CollectionReference randomColl = testCollectionWithDocsOnNightly (docs );
424
+
425
+ Query orderedQuery =
426
+ randomColl
427
+ .orderBy ("key" , Direction .DESCENDING )
428
+ .whereGreaterThan ("key" , new Decimal128Value ("-1.2e3" ));
429
+ assertSDKQueryResultsConsistentWithBackend (
430
+ randomColl , orderedQuery , docs , Arrays .asList ("f" , "c" , "b" ));
431
+
432
+ orderedQuery =
433
+ randomColl
434
+ .orderBy ("key" , Direction .DESCENDING )
435
+ .whereGreaterThan ("key" , new Decimal128Value ("-1.2e-3" ));
436
+ assertSDKQueryResultsConsistentWithBackend (
437
+ randomColl , orderedQuery , docs , Arrays .asList ("f" , "c" , "b" ));
438
+
439
+ orderedQuery =
440
+ randomColl
441
+ .orderBy ("key" , Direction .DESCENDING )
442
+ .whereNotEqualTo ("key" , new Decimal128Value ("0.0" ));
443
+ assertSDKQueryResultsConsistentWithBackend (
444
+ randomColl , orderedQuery , docs , Arrays .asList ("f" , "c" , "a" , "e" , "d" ));
445
+
446
+ orderedQuery = randomColl .whereNotEqualTo ("key" , new Decimal128Value ("NaN" ));
447
+ assertSDKQueryResultsConsistentWithBackend (
448
+ randomColl , orderedQuery , docs , Arrays .asList ("e" , "a" , "b" , "c" , "f" ));
449
+
450
+ orderedQuery =
451
+ randomColl
452
+ .orderBy ("key" , Direction .DESCENDING )
453
+ .whereEqualTo ("key" , new Decimal128Value ("1.2e3" ));
454
+ assertSDKQueryResultsConsistentWithBackend (randomColl , orderedQuery , docs , Arrays .asList ("c" ));
455
+
456
+ orderedQuery =
457
+ randomColl
458
+ .orderBy ("key" , Direction .DESCENDING )
459
+ .whereNotEqualTo ("key" , new Decimal128Value ("1.2e3" ));
460
+ assertSDKQueryResultsConsistentWithBackend (
461
+ randomColl , orderedQuery , docs , Arrays .asList ("f" , "b" , "a" , "e" , "d" ));
462
+
463
+ // Note: server is sending NaN incorrectly, but the SDK NotInFilter.matches gracefully handles
464
+ // it and removes the incorrect doc "d".
465
+ orderedQuery =
466
+ randomColl
467
+ .orderBy ("key" , Direction .DESCENDING )
468
+ .whereNotIn (
469
+ "key" ,
470
+ Arrays .asList (
471
+ new Decimal128Value ("1.2e3" ),
472
+ new Decimal128Value ("Infinity" ),
473
+ new Decimal128Value ("NaN" )));
474
+ assertSDKQueryResultsConsistentWithBackend (
475
+ randomColl , orderedQuery , docs , Arrays .asList ("b" , "a" , "e" ));
476
+ }
477
+
388
478
@ Test
389
479
public void filterAndOrderMinKey () throws Exception {
390
480
Map <String , Map <String , Object >> docs =
@@ -478,6 +568,102 @@ public void filterNullValueWithBsonTypes() throws Exception {
478
568
randomColl , query , docs , Arrays .asList ("a" , "d" , "e" ));
479
569
}
480
570
571
+ @ Test
572
+ public void filterAndOrderNumericalValues () throws Exception {
573
+ Map <String , Map <String , Object >> docs =
574
+ map (
575
+ "a" ,
576
+ map ("key" , new Decimal128Value ("-1.2e3" )), // -1200
577
+ "b" ,
578
+ map ("key" , new Int32Value (0 )),
579
+ "c" ,
580
+ map ("key" , new Decimal128Value ("1" )),
581
+ "d" ,
582
+ map ("key" , new Int32Value (1 )),
583
+ "e" ,
584
+ map ("key" , 1L ),
585
+ "f" ,
586
+ map ("key" , 1.0 ),
587
+ "g" ,
588
+ map ("key" , new Decimal128Value ("1.2e-3" )), // 0.0012
589
+ "h" ,
590
+ map ("key" , new Int32Value (2 )),
591
+ "i" ,
592
+ map ("key" , new Decimal128Value ("NaN" )),
593
+ "j" ,
594
+ map ("key" , new Decimal128Value ("-Infinity" )),
595
+ "k" ,
596
+ map ("key" , NaN ),
597
+ "l" ,
598
+ map ("key" , POSITIVE_INFINITY ));
599
+ CollectionReference randomColl = testCollectionWithDocsOnNightly (docs );
600
+
601
+ Query orderedQuery = randomColl .orderBy ("key" , Direction .DESCENDING );
602
+ assertSDKQueryResultsConsistentWithBackend (
603
+ randomColl ,
604
+ orderedQuery ,
605
+ docs ,
606
+ Arrays .asList (
607
+ "l" , // Infinity
608
+ "h" , // 2
609
+ "f" , // 1.0
610
+ "e" , // 1
611
+ "d" , // 1
612
+ "c" , // 1
613
+ "g" , // 0.0012
614
+ "b" , // 0
615
+ "a" , // -1200
616
+ "j" , // -Infinity
617
+ "k" , // NaN
618
+ "i" // NaN
619
+ ));
620
+
621
+ orderedQuery =
622
+ randomColl
623
+ .orderBy ("key" , Direction .DESCENDING )
624
+ .whereNotEqualTo ("key" , new Decimal128Value ("1.0" ));
625
+ assertSDKQueryResultsConsistentWithBackend (
626
+ randomColl , orderedQuery , docs , Arrays .asList ("l" , "h" , "g" , "b" , "a" , "j" , "k" , "i" ));
627
+
628
+ orderedQuery = randomColl .orderBy ("key" , Direction .DESCENDING ).whereEqualTo ("key" , 1 );
629
+ assertSDKQueryResultsConsistentWithBackend (
630
+ randomColl , orderedQuery , docs , Arrays .asList ("f" , "e" , "d" , "c" ));
631
+ }
632
+
633
+ @ Test
634
+ public void decimal128ValuesWithNo2sComplementRepresentation () throws Exception {
635
+ // For decimal128 values with no 2's complement representation, it is considered not equal to
636
+ // a double with the same value, e.g, 1.1.
637
+ Map <String , Map <String , Object >> docs =
638
+ map (
639
+ "a" ,
640
+ map ("key" , new Decimal128Value ("-1.1e-3" )), // -0.0011
641
+ "b" ,
642
+ map ("key" , new Decimal128Value ("1.1" )),
643
+ "c" ,
644
+ map ("key" , 1.1 ),
645
+ "d" ,
646
+ map ("key" , 1.0 ),
647
+ "e" ,
648
+ map ("key" , new Decimal128Value ("1.1e-3" )) // 0.0011
649
+ );
650
+ CollectionReference randomColl = testCollectionWithDocsOnNightly (docs );
651
+
652
+ Query orderedQuery = randomColl .whereEqualTo ("key" , new Decimal128Value ("1.1" ));
653
+ assertSDKQueryResultsConsistentWithBackend (randomColl , orderedQuery , docs , Arrays .asList ("b" ));
654
+
655
+ orderedQuery = randomColl .whereNotEqualTo ("key" , new Decimal128Value ("1.1" ));
656
+ assertSDKQueryResultsConsistentWithBackend (
657
+ randomColl , orderedQuery , docs , Arrays .asList ("a" , "e" , "d" , "c" ));
658
+
659
+ orderedQuery = randomColl .whereEqualTo ("key" , 1.1 );
660
+ assertSDKQueryResultsConsistentWithBackend (randomColl , orderedQuery , docs , Arrays .asList ("c" ));
661
+
662
+ orderedQuery = randomColl .whereNotEqualTo ("key" , 1.1 );
663
+ assertSDKQueryResultsConsistentWithBackend (
664
+ randomColl , orderedQuery , docs , Arrays .asList ("a" , "e" , "d" , "b" ));
665
+ }
666
+
481
667
@ Test
482
668
public void orderBsonTypesTogether () throws Exception {
483
669
Map <String , Map <String , Object >> docs =
@@ -512,6 +698,12 @@ public void orderBsonTypesTogether() throws Exception {
512
698
map ("key" , new Int32Value (1 )),
513
699
"int32Value3" ,
514
700
map ("key" , new Int32Value (0 )),
701
+ "decimal128Value1" ,
702
+ map ("key" , new Decimal128Value ("-1.2e3" )),
703
+ "decimal128Value2" ,
704
+ map ("key" , new Decimal128Value ("-0.0" )),
705
+ "decimal128Value3" ,
706
+ map ("key" , new Decimal128Value ("1.2e3" )),
515
707
"minKey1" ,
516
708
map ("key" , MinKey .instance ()),
517
709
"minKey2" ,
@@ -539,9 +731,15 @@ public void orderBsonTypesTogether() throws Exception {
539
731
"bsonTimestamp1" ,
540
732
"bsonTimestamp2" ,
541
733
"bsonTimestamp3" ,
734
+ // Int32Value and Decimal128Value are sorted together
735
+ "decimal128Value3" ,
542
736
"int32Value2" ,
737
+ // Int32Value of 0 equals to Decimal128Value of 0, and falls to document key as second
738
+ // order
543
739
"int32Value3" ,
740
+ "decimal128Value2" ,
544
741
"int32Value1" ,
742
+ "decimal128Value1" ,
545
743
"minKey2" ,
546
744
"minKey1" );
547
745
0 commit comments