FIRCountTests.mm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. * Copyright 2022 Google LLC
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <FirebaseFirestore/FirebaseFirestore.h>
  17. #import <XCTest/XCTest.h>
  18. #import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h"
  19. @interface FIRCountTests : FSTIntegrationTestCase
  20. @end
  21. @implementation FIRCountTests
  22. - (void)testAggregateQueryEquals {
  23. FIRCollectionReference* coll1 = [self collectionRefWithDocuments:@{}];
  24. FIRCollectionReference* coll1Same = [[coll1 firestore] collectionWithPath:[coll1 path]];
  25. FIRAggregateQuery* query1 = [coll1 count];
  26. FIRAggregateQuery* query1Same = [coll1Same count];
  27. FIRCollectionReference* sub = [[coll1 documentWithPath:@"bar"] collectionWithPath:@"baz"];
  28. FIRAggregateQuery* query2 = [[[sub queryWhereField:@"a" isEqualTo:@1] queryLimitedTo:100] count];
  29. FIRAggregateQuery* query2Same = [[[sub queryWhereField:@"a"
  30. isEqualTo:@1] queryLimitedTo:100] count];
  31. FIRAggregateQuery* query3 = [[[sub queryWhereField:@"b"
  32. isEqualTo:@1] queryOrderedByField:@"c"] count];
  33. FIRAggregateQuery* query3Same = [[[sub queryWhereField:@"b"
  34. isEqualTo:@1] queryOrderedByField:@"c"] count];
  35. XCTAssertEqualObjects(query1, query1Same);
  36. XCTAssertEqualObjects(query2, query2Same);
  37. XCTAssertEqualObjects(query3, query3Same);
  38. XCTAssertEqual([query1 hash], [query1Same hash]);
  39. XCTAssertEqual([query2 hash], [query2Same hash]);
  40. XCTAssertEqual([query3 hash], [query3Same hash]);
  41. XCTAssertFalse([query1 isEqual:nil]);
  42. XCTAssertFalse([query1 isEqual:@"string"]);
  43. XCTAssertFalse([query1 isEqual:query2]);
  44. XCTAssertFalse([query2 isEqual:query3]);
  45. XCTAssertNotEqual([query1 hash], [query2 hash]);
  46. XCTAssertNotEqual([query2 hash], [query3 hash]);
  47. }
  48. - (void)testCanRunCountQuery {
  49. FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
  50. @"a" : @{@"k" : @"a"},
  51. @"b" : @{@"k" : @"b"},
  52. @"c" : @{@"k" : @"c"}
  53. }];
  54. FIRAggregateQuerySnapshot* snapshot = [self readSnapshotForAggregate:[testCollection count]];
  55. XCTAssertEqual(snapshot.count, [NSNumber numberWithLong:3L]);
  56. }
  57. - (void)testCanRunCountWithFilters {
  58. FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
  59. @"a" : @{@"k" : @"a"},
  60. @"b" : @{@"k" : @"b"},
  61. @"c" : @{@"k" : @"c"}
  62. }];
  63. FIRAggregateQuerySnapshot* snapshot =
  64. [self readSnapshotForAggregate:[[testCollection queryWhereField:@"k" isEqualTo:@"b"] count]];
  65. XCTAssertEqual(snapshot.count, [NSNumber numberWithLong:1L]);
  66. }
  67. - (void)testCanRunCountWithOrderBys {
  68. FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
  69. @"a" : @{@"k" : @"a"},
  70. @"b" : @{@"k" : @"b"},
  71. @"c" : @{@"k" : @"c"},
  72. @"d" : @{@"absent" : @"d"},
  73. }];
  74. FIRAggregateQuerySnapshot* snapshot =
  75. [self readSnapshotForAggregate:[[testCollection queryOrderedByField:@"k"] count]];
  76. XCTAssertEqual(snapshot.count, [NSNumber numberWithLong:3L]);
  77. }
  78. - (void)testSnapshotEquals {
  79. FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
  80. @"a" : @{@"k" : @"a"},
  81. @"b" : @{@"k" : @"b"},
  82. @"c" : @{@"k" : @"c"}
  83. }];
  84. FIRAggregateQuerySnapshot* snapshot1 =
  85. [self readSnapshotForAggregate:[[testCollection queryWhereField:@"k" isEqualTo:@"b"] count]];
  86. FIRAggregateQuerySnapshot* snapshot1Same =
  87. [self readSnapshotForAggregate:[[testCollection queryWhereField:@"k" isEqualTo:@"b"] count]];
  88. FIRAggregateQuerySnapshot* snapshot2 =
  89. [self readSnapshotForAggregate:[[testCollection queryWhereField:@"k" isEqualTo:@"a"] count]];
  90. [self writeDocumentRef:[testCollection documentWithPath:@"d"] data:@{@"k" : @"a"}];
  91. FIRAggregateQuerySnapshot* snapshot2Different =
  92. [self readSnapshotForAggregate:[[testCollection queryWhereField:@"k" isEqualTo:@"a"] count]];
  93. FIRAggregateQuerySnapshot* snapshot3 =
  94. [self readSnapshotForAggregate:[[testCollection queryWhereField:@"k" isEqualTo:@"b"] count]];
  95. FIRAggregateQuerySnapshot* snapshot3Different =
  96. [self readSnapshotForAggregate:[[testCollection queryWhereField:@"k" isEqualTo:@"c"] count]];
  97. XCTAssertEqualObjects(snapshot1, snapshot1Same);
  98. XCTAssertEqual([snapshot1 hash], [snapshot1Same hash]);
  99. XCTAssertEqualObjects([snapshot1 query], [[testCollection queryWhereField:@"k"
  100. isEqualTo:@"b"] count]);
  101. XCTAssertNotEqualObjects(snapshot1, nil);
  102. XCTAssertNotEqualObjects(snapshot1, @"string");
  103. XCTAssertNotEqualObjects(snapshot1, snapshot2);
  104. XCTAssertNotEqual([snapshot1 hash], [snapshot2 hash]);
  105. XCTAssertNotEqualObjects(snapshot2, snapshot2Different);
  106. XCTAssertNotEqual([snapshot2 hash], [snapshot2Different hash]);
  107. XCTAssertNotEqualObjects(snapshot3, snapshot3Different);
  108. XCTAssertNotEqual([snapshot3 hash], [snapshot3Different hash]);
  109. }
  110. - (void)testTerminateDoesNotCrashWithFlyingCountQuery {
  111. FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
  112. @"a" : @{@"k" : @"a"},
  113. @"b" : @{@"k" : @"b"},
  114. @"c" : @{@"k" : @"c"},
  115. }];
  116. [[testCollection count]
  117. aggregationWithSource:FIRAggregateSourceServer
  118. completion:^(FIRAggregateQuerySnapshot* snapshot, NSError* error) {
  119. (void)snapshot;
  120. (void)error;
  121. }];
  122. [self terminateFirestore:testCollection.firestore];
  123. }
  124. - (void)testCanRunCollectionGroupCountQuery {
  125. NSString* collectionGroup =
  126. [NSString stringWithFormat:@"%@%@", @"b",
  127. [self.db collectionWithPath:@"foo"].documentWithAutoID.documentID];
  128. NSArray* docPathFormats = @[
  129. @"abc/123/%@/cg-doc1", @"abc/123/%@/cg-doc2", @"%@/cg-doc3", @"%@/cg-doc4",
  130. @"def/456/%@/cg-doc5", @"%@/virtual-doc/nested-coll/not-cg-doc", @"x%@/not-cg-doc",
  131. @"%@x/not-cg-doc", @"abc/123/%@x/not-cg-doc", @"abc/123/x%@/not-cg-doc", @"abc/%@"
  132. ];
  133. FIRWriteBatch* batch = self.db.batch;
  134. for (NSString* format in docPathFormats) {
  135. NSString* path = [NSString stringWithFormat:format, collectionGroup];
  136. [batch setData:@{@"x" : @"a"} forDocument:[self.db documentWithPath:path]];
  137. }
  138. [self commitWriteBatch:batch];
  139. FIRAggregateQuerySnapshot* snapshot =
  140. [self readSnapshotForAggregate:[[self.db collectionGroupWithID:collectionGroup] count]];
  141. // "cg-doc1", "cg-doc2", "cg-doc3", "cg-doc4", "cg-doc5",
  142. XCTAssertEqual(snapshot.count, [NSNumber numberWithLong:5L]);
  143. }
  144. - (void)testCanRunCountWithFiltersAndLimits {
  145. FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
  146. @"a" : @{@"k" : @"a"},
  147. @"b" : @{@"k" : @"a"},
  148. @"c" : @{@"k" : @"a"},
  149. @"d" : @{@"k" : @"d"},
  150. }];
  151. FIRAggregateQuerySnapshot* snapshot = [self
  152. readSnapshotForAggregate:[[[testCollection queryLimitedTo:2] queryWhereField:@"k"
  153. isEqualTo:@"a"] count]];
  154. XCTAssertEqual(snapshot.count, [NSNumber numberWithLong:2L]);
  155. snapshot = [self readSnapshotForAggregate:[[[testCollection queryLimitedToLast:2]
  156. queryWhereField:@"k"
  157. isEqualTo:@"a"] count]];
  158. XCTAssertEqual(snapshot.count, [NSNumber numberWithLong:2L]);
  159. snapshot = [self readSnapshotForAggregate:[[[testCollection queryLimitedToLast:1000]
  160. queryWhereField:@"k"
  161. isEqualTo:@"d"] count]];
  162. XCTAssertEqual(snapshot.count, [NSNumber numberWithLong:1L]);
  163. }
  164. - (void)testCanRunCountOnNonExistentCollection {
  165. FIRCollectionReference* testCollection = [self collectionRef];
  166. FIRAggregateQuerySnapshot* snapshot = [self readSnapshotForAggregate:[testCollection count]];
  167. XCTAssertEqual(snapshot.count, [NSNumber numberWithLong:0L]);
  168. snapshot = [self readSnapshotForAggregate:[[testCollection queryWhereField:@"k"
  169. isEqualTo:@"a"] count]];
  170. XCTAssertEqual(snapshot.count, [NSNumber numberWithLong:0L]);
  171. }
  172. - (void)testFailWithoutNetwork {
  173. FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
  174. @"a" : @{@"k" : @"a"},
  175. @"b" : @{@"k" : @"b"},
  176. @"c" : @{@"k" : @"c"}
  177. }];
  178. [self disableNetwork];
  179. [[testCollection count]
  180. aggregationWithSource:FIRAggregateSourceServer
  181. completion:^(FIRAggregateQuerySnapshot* snapshot, NSError* error) {
  182. (void)snapshot;
  183. XCTAssertNotNil(error);
  184. }];
  185. [self enableNetwork];
  186. FIRAggregateQuerySnapshot* snapshot = [self readSnapshotForAggregate:[testCollection count]];
  187. XCTAssertEqual(snapshot.count, [NSNumber numberWithLong:3L]);
  188. }
  189. - (void)testFailWithMessageWithConsoleLinkIfMissingIndex {
  190. XCTSkipIf([FSTIntegrationTestCase isRunningAgainstEmulator],
  191. "Skip this test when running against the Firestore emulator because the Firestore "
  192. "emulator does not use indexes and never fails with a 'missing index' error.");
  193. FIRCollectionReference* testCollection = [self collectionRef];
  194. FIRQuery* compositeIndexQuery = [[testCollection queryWhereField:@"field1"
  195. isEqualTo:@42] queryWhereField:@"field2"
  196. isLessThan:@99];
  197. FIRAggregateQuery* compositeIndexCountQuery = [compositeIndexQuery count];
  198. XCTestExpectation* queryCompletion = [self expectationWithDescription:@"query"];
  199. [compositeIndexCountQuery
  200. aggregationWithSource:FIRAggregateSourceServer
  201. completion:^(FIRAggregateQuerySnapshot* snapshot, NSError* error) {
  202. XCTAssertNotNil(error);
  203. if (error) {
  204. NSString* errorDescription = [error localizedDescription];
  205. XCTAssertTrue([errorDescription.lowercaseString containsString:@"index"],
  206. "The NSError should have contained the word 'index' "
  207. "(case-insensitive), but got: %@",
  208. errorDescription);
  209. // TODO(b/316359394) Remove this check for the default databases once
  210. // cl/582465034 is rolled out to production.
  211. if ([[FSTIntegrationTestCase databaseID] isEqualToString:@"(default)"]) {
  212. XCTAssertTrue(
  213. [errorDescription containsString:@"https://console.firebase.google.com"],
  214. "The NSError should have contained the string "
  215. "'https://console.firebase.google.com', but got: %@",
  216. errorDescription);
  217. }
  218. }
  219. XCTAssertNil(snapshot);
  220. [queryCompletion fulfill];
  221. }];
  222. [self awaitExpectations];
  223. }
  224. @end