FIRFirestoreSourceTests.mm 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. /*
  2. * Copyright 2018 Google
  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. #import "Firestore/Source/API/FIRFirestore+Internal.h"
  20. #import "Firestore/Source/Core/FSTFirestoreClient.h"
  21. @interface FIRFirestoreSourceTests : FSTIntegrationTestCase
  22. @end
  23. @implementation FIRFirestoreSourceTests
  24. - (void)testGetDocumentWhileOnlineWithDefaultSource {
  25. FIRDocumentReference *doc = [self documentRef];
  26. // set document to a known value
  27. NSDictionary<NSString *, id> *initialData = @{@"key" : @"value"};
  28. [self writeDocumentRef:doc data:initialData];
  29. // get doc and ensure that it exists, is *not* from the cache, and matches
  30. // the initialData.
  31. FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
  32. XCTAssertTrue(result.exists);
  33. XCTAssertFalse(result.metadata.fromCache);
  34. XCTAssertFalse(result.metadata.hasPendingWrites);
  35. XCTAssertEqualObjects(result.data, initialData);
  36. }
  37. - (void)testGetCollectionWhileOnlineWithDefaultSource {
  38. FIRCollectionReference *col = [self collectionRef];
  39. // set a few documents to known values
  40. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
  41. @"doc1" : @{@"key1" : @"value1"},
  42. @"doc2" : @{@"key2" : @"value2"},
  43. @"doc3" : @{@"key3" : @"value3"}
  44. };
  45. [self writeAllDocuments:initialDocs toCollection:col];
  46. // get docs and ensure they are *not* from the cache, and match the
  47. // initialDocs.
  48. FIRQuerySnapshot *result = [self readDocumentSetForRef:col];
  49. XCTAssertFalse(result.metadata.fromCache);
  50. XCTAssertFalse(result.metadata.hasPendingWrites);
  51. XCTAssertEqualObjects(
  52. FIRQuerySnapshotGetData(result),
  53. (@[ @{@"key1" : @"value1"}, @{@"key2" : @"value2"}, @{@"key3" : @"value3"} ]));
  54. XCTAssertEqualObjects(FIRQuerySnapshotGetDocChangesData(result), (@[
  55. @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
  56. @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2"} ],
  57. @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3" : @"value3"} ]
  58. ]));
  59. }
  60. - (void)testGetDocumentError {
  61. FIRDocumentReference *doc = [self.db documentWithPath:@"foo/__invalid__"];
  62. XCTestExpectation *completed = [self expectationWithDescription:@"get completed"];
  63. [doc getDocumentWithCompletion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
  64. XCTAssertNotNil(error);
  65. [completed fulfill];
  66. }];
  67. [self awaitExpectations];
  68. }
  69. - (void)testGetCollectionError {
  70. FIRCollectionReference *col = [self.db collectionWithPath:@"__invalid__"];
  71. XCTestExpectation *completed = [self expectationWithDescription:@"get completed"];
  72. [col getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) {
  73. XCTAssertNotNil(error);
  74. [completed fulfill];
  75. }];
  76. [self awaitExpectations];
  77. }
  78. - (void)testGetDocumentWhileOfflineWithDefaultSource {
  79. FIRDocumentReference *doc = [self documentRef];
  80. // set document to a known value
  81. NSDictionary<NSString *, id> *initialData = @{@"key1" : @"value1"};
  82. [self writeDocumentRef:doc data:initialData];
  83. // go offline for the rest of this test
  84. [self disableNetwork];
  85. // update the doc (though don't wait for a server response. We're offline; so
  86. // that ain't happening!). This allows us to further distinguished cached vs
  87. // server responses below.
  88. NSDictionary<NSString *, id> *newData = @{@"key2" : @"value2"};
  89. [doc setData:newData
  90. completion:^(NSError *_Nullable error) {
  91. XCTAssertTrue(false, "Because we're offline, this should never occur.");
  92. }];
  93. // get doc and ensure it exists, *is* from the cache, and matches the
  94. // newData.
  95. FIRDocumentSnapshot *result = [self readDocumentForRef:doc];
  96. XCTAssertTrue(result.exists);
  97. XCTAssertTrue(result.metadata.fromCache);
  98. XCTAssertTrue(result.metadata.hasPendingWrites);
  99. XCTAssertEqualObjects(result.data, newData);
  100. }
  101. - (void)testGetCollectionWhileOfflineWithDefaultSource {
  102. FIRCollectionReference *col = [self collectionRef];
  103. // set a few documents to known values
  104. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
  105. @"doc1" : @{@"key1" : @"value1"},
  106. @"doc2" : @{@"key2" : @"value2"},
  107. @"doc3" : @{@"key3" : @"value3"}
  108. };
  109. [self writeAllDocuments:initialDocs toCollection:col];
  110. // go offline for the rest of this test
  111. [self disableNetwork];
  112. // update the docs (though don't wait for a server response. We're offline; so
  113. // that ain't happening!). This allows us to further distinguished cached vs
  114. // server responses below.
  115. [[col documentWithPath:@"doc2"] setData:@{@"key2b" : @"value2b"} merge:YES];
  116. [[col documentWithPath:@"doc3"] setData:@{@"key3b" : @"value3b"}];
  117. [[col documentWithPath:@"doc4"] setData:@{@"key4" : @"value4"}];
  118. // get docs and ensure they *are* from the cache, and matches the updated data.
  119. FIRQuerySnapshot *result = [self readDocumentSetForRef:col];
  120. XCTAssertTrue(result.metadata.fromCache);
  121. XCTAssertTrue(result.metadata.hasPendingWrites);
  122. XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
  123. @{@"key1" : @"value1"}, @{@"key2" : @"value2", @"key2b" : @"value2b"},
  124. @{@"key3b" : @"value3b"}, @{@"key4" : @"value4"}
  125. ]));
  126. XCTAssertEqualObjects(
  127. FIRQuerySnapshotGetDocChangesData(result), (@[
  128. @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
  129. @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2", @"key2b" : @"value2b"} ],
  130. @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3b" : @"value3b"} ],
  131. @[ @(FIRDocumentChangeTypeAdded), @"doc4", @{@"key4" : @"value4"} ]
  132. ]));
  133. }
  134. - (void)testGetDocumentWhileOnlineCacheOnly {
  135. FIRDocumentReference *doc = [self documentRef];
  136. // set document to a known value
  137. NSDictionary<NSString *, id> *initialData = @{@"key" : @"value"};
  138. [self writeDocumentRef:doc data:initialData];
  139. // get doc and ensure that it exists, *is* from the cache, and matches
  140. // the initialData.
  141. FIRDocumentSnapshot *result = [self readDocumentForRef:doc source:FIRFirestoreSourceCache];
  142. XCTAssertTrue(result.exists);
  143. XCTAssertTrue(result.metadata.fromCache);
  144. XCTAssertFalse(result.metadata.hasPendingWrites);
  145. XCTAssertEqualObjects(result.data, initialData);
  146. }
  147. - (void)testGetCollectionWhileOnlineCacheOnly {
  148. FIRCollectionReference *col = [self collectionRef];
  149. // set a few documents to a known value
  150. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
  151. @"doc1" : @{@"key1" : @"value1"},
  152. @"doc2" : @{@"key2" : @"value2"},
  153. @"doc3" : @{@"key3" : @"value3"},
  154. };
  155. [self writeAllDocuments:initialDocs toCollection:col];
  156. // get docs and ensure they *are* from the cache, and matches the
  157. // initialDocs.
  158. FIRQuerySnapshot *result = [self readDocumentSetForRef:col source:FIRFirestoreSourceCache];
  159. XCTAssertTrue(result.metadata.fromCache);
  160. XCTAssertFalse(result.metadata.hasPendingWrites);
  161. XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
  162. @{@"key1" : @"value1"},
  163. @{@"key2" : @"value2"},
  164. @{@"key3" : @"value3"},
  165. ]));
  166. XCTAssertEqualObjects(FIRQuerySnapshotGetDocChangesData(result), (@[
  167. @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
  168. @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2"} ],
  169. @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3" : @"value3"} ]
  170. ]));
  171. }
  172. - (void)testGetDocumentWhileOfflineCacheOnly {
  173. FIRDocumentReference *doc = [self documentRef];
  174. // set document to a known value
  175. NSDictionary<NSString *, id> *initialData = @{@"key1" : @"value1"};
  176. [self writeDocumentRef:doc data:initialData];
  177. // go offline for the rest of this test
  178. [self disableNetwork];
  179. // update the doc (though don't wait for a server response. We're offline; so
  180. // that ain't happening!). This allows us to further distinguished cached vs
  181. // server responses below.
  182. NSDictionary<NSString *, id> *newData = @{@"key2" : @"value2"};
  183. [doc setData:newData
  184. completion:^(NSError *_Nullable error) {
  185. XCTFail("Because we're offline, this should never occur.");
  186. }];
  187. // get doc and ensure it exists, *is* from the cache, and matches the
  188. // newData.
  189. FIRDocumentSnapshot *result = [self readDocumentForRef:doc source:FIRFirestoreSourceCache];
  190. XCTAssertTrue(result.exists);
  191. XCTAssertTrue(result.metadata.fromCache);
  192. XCTAssertTrue(result.metadata.hasPendingWrites);
  193. XCTAssertEqualObjects(result.data, newData);
  194. }
  195. - (void)testGetCollectionWhileOfflineCacheOnly {
  196. FIRCollectionReference *col = [self collectionRef];
  197. // set a few documents to a known value
  198. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
  199. @"doc1" : @{@"key1" : @"value1"},
  200. @"doc2" : @{@"key2" : @"value2"},
  201. @"doc3" : @{@"key3" : @"value3"},
  202. };
  203. [self writeAllDocuments:initialDocs toCollection:col];
  204. // go offline for the rest of this test
  205. [self disableNetwork];
  206. // update the docs (though don't wait for a server response. We're offline; so
  207. // that ain't happening!). This allows us to further distinguished cached vs
  208. // server responses below.
  209. [[col documentWithPath:@"doc2"] setData:@{@"key2b" : @"value2b"} merge:YES];
  210. [[col documentWithPath:@"doc3"] setData:@{@"key3b" : @"value3b"}];
  211. [[col documentWithPath:@"doc4"] setData:@{@"key4" : @"value4"}];
  212. // get docs and ensure they *are* from the cache, and matches the updated
  213. // data.
  214. FIRQuerySnapshot *result = [self readDocumentSetForRef:col source:FIRFirestoreSourceCache];
  215. XCTAssertTrue(result.metadata.fromCache);
  216. XCTAssertTrue(result.metadata.hasPendingWrites);
  217. XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
  218. @{@"key1" : @"value1"}, @{@"key2" : @"value2", @"key2b" : @"value2b"},
  219. @{@"key3b" : @"value3b"}, @{@"key4" : @"value4"}
  220. ]));
  221. XCTAssertEqualObjects(
  222. FIRQuerySnapshotGetDocChangesData(result), (@[
  223. @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
  224. @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2", @"key2b" : @"value2b"} ],
  225. @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3b" : @"value3b"} ],
  226. @[ @(FIRDocumentChangeTypeAdded), @"doc4", @{@"key4" : @"value4"} ]
  227. ]));
  228. }
  229. - (void)testGetDocumentWhileOnlineServerOnly {
  230. FIRDocumentReference *doc = [self documentRef];
  231. // set document to a known value
  232. NSDictionary<NSString *, id> *initialData = @{@"key" : @"value"};
  233. [self writeDocumentRef:doc data:initialData];
  234. // get doc and ensure that it exists, is *not* from the cache, and matches
  235. // the initialData.
  236. FIRDocumentSnapshot *result = [self readDocumentForRef:doc source:FIRFirestoreSourceServer];
  237. XCTAssertTrue(result.exists);
  238. XCTAssertFalse(result.metadata.fromCache);
  239. XCTAssertFalse(result.metadata.hasPendingWrites);
  240. XCTAssertEqualObjects(result.data, initialData);
  241. }
  242. - (void)testGetCollectionWhileOnlineServerOnly {
  243. FIRCollectionReference *col = [self collectionRef];
  244. // set a few documents to a known value
  245. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
  246. @"doc1" : @{@"key1" : @"value1"},
  247. @"doc2" : @{@"key2" : @"value2"},
  248. @"doc3" : @{@"key3" : @"value3"},
  249. };
  250. [self writeAllDocuments:initialDocs toCollection:col];
  251. // get docs and ensure they are *not* from the cache, and matches the
  252. // initialData.
  253. FIRQuerySnapshot *result = [self readDocumentSetForRef:col source:FIRFirestoreSourceServer];
  254. XCTAssertFalse(result.metadata.fromCache);
  255. XCTAssertFalse(result.metadata.hasPendingWrites);
  256. XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
  257. @{@"key1" : @"value1"},
  258. @{@"key2" : @"value2"},
  259. @{@"key3" : @"value3"},
  260. ]));
  261. XCTAssertEqualObjects(FIRQuerySnapshotGetDocChangesData(result), (@[
  262. @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
  263. @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2"} ],
  264. @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3" : @"value3"} ]
  265. ]));
  266. }
  267. - (void)testGetDocumentWhileOfflineServerOnly {
  268. FIRDocumentReference *doc = [self documentRef];
  269. // set document to a known value
  270. NSDictionary<NSString *, id> *initialData = @{@"key1" : @"value1"};
  271. [self writeDocumentRef:doc data:initialData];
  272. // go offline for the rest of this test
  273. [self disableNetwork];
  274. // attempt to get doc and ensure it cannot be retreived
  275. XCTestExpectation *failedGetDocCompletion = [self expectationWithDescription:@"failedGetDoc"];
  276. [doc getDocumentWithSource:FIRFirestoreSourceServer
  277. completion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
  278. XCTAssertNotNil(error);
  279. XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
  280. XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
  281. [failedGetDocCompletion fulfill];
  282. }];
  283. [self awaitExpectations];
  284. }
  285. - (void)testGetCollectionWhileOfflineServerOnly {
  286. FIRCollectionReference *col = [self collectionRef];
  287. // set a few documents to a known value
  288. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
  289. @"doc1" : @{@"key1" : @"value1"},
  290. @"doc2" : @{@"key2" : @"value2"},
  291. @"doc3" : @{@"key3" : @"value3"},
  292. };
  293. [self writeAllDocuments:initialDocs toCollection:col];
  294. // go offline for the rest of this test
  295. [self disableNetwork];
  296. // attempt to get docs and ensure they cannot be retreived
  297. XCTestExpectation *failedGetDocsCompletion = [self expectationWithDescription:@"failedGetDocs"];
  298. [col getDocumentsWithSource:FIRFirestoreSourceServer
  299. completion:^(FIRQuerySnapshot *snapshot, NSError *error) {
  300. XCTAssertNotNil(error);
  301. XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
  302. XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
  303. [failedGetDocsCompletion fulfill];
  304. }];
  305. [self awaitExpectations];
  306. }
  307. - (void)testGetDocumentWhileOfflineWithDifferentSource {
  308. FIRDocumentReference *doc = [self documentRef];
  309. // set document to a known value
  310. NSDictionary<NSString *, id> *initialData = @{@"key1" : @"value1"};
  311. [self writeDocumentRef:doc data:initialData];
  312. // go offline for the rest of this test
  313. [self disableNetwork];
  314. // update the doc (though don't wait for a server response. We're offline; so
  315. // that ain't happening!). This allows us to further distinguished cached vs
  316. // server responses below.
  317. NSDictionary<NSString *, id> *newData = @{@"key2" : @"value2"};
  318. [doc setData:newData
  319. completion:^(NSError *_Nullable error) {
  320. XCTAssertTrue(false, "Because we're offline, this should never occur.");
  321. }];
  322. // Create an initial listener for this query (to attempt to disrupt the gets below) and wait for
  323. // the listener to deliver its initial snapshot before continuing.
  324. XCTestExpectation *listenerReady = [self expectationWithDescription:@"listenerReady"];
  325. [doc addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *error) {
  326. [listenerReady fulfill];
  327. }];
  328. [self awaitExpectations];
  329. // get doc (from cache) and ensure it exists, *is* from the cache, and
  330. // matches the newData.
  331. FIRDocumentSnapshot *result = [self readDocumentForRef:doc source:FIRFirestoreSourceCache];
  332. XCTAssertTrue(result.exists);
  333. XCTAssertTrue(result.metadata.fromCache);
  334. XCTAssertTrue(result.metadata.hasPendingWrites);
  335. XCTAssertEqualObjects(result.data, newData);
  336. // attempt to get doc (with default get source)
  337. result = [self readDocumentForRef:doc source:FIRFirestoreSourceDefault];
  338. XCTAssertTrue(result.exists);
  339. XCTAssertTrue(result.metadata.fromCache);
  340. XCTAssertTrue(result.metadata.hasPendingWrites);
  341. XCTAssertEqualObjects(result.data, newData);
  342. // attempt to get doc (from the server) and ensure it cannot be retreived
  343. XCTestExpectation *failedGetDocCompletion = [self expectationWithDescription:@"failedGetDoc"];
  344. [doc getDocumentWithSource:FIRFirestoreSourceServer
  345. completion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
  346. XCTAssertNotNil(error);
  347. XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
  348. XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
  349. [failedGetDocCompletion fulfill];
  350. }];
  351. [self awaitExpectations];
  352. }
  353. - (void)testGetCollectionWhileOfflineWithDifferentSource {
  354. FIRCollectionReference *col = [self collectionRef];
  355. // set a few documents to a known value
  356. NSDictionary<NSString *, NSDictionary<NSString *, id> *> *initialDocs = @{
  357. @"doc1" : @{@"key1" : @"value1"},
  358. @"doc2" : @{@"key2" : @"value2"},
  359. @"doc3" : @{@"key3" : @"value3"},
  360. };
  361. [self writeAllDocuments:initialDocs toCollection:col];
  362. // go offline for the rest of this test
  363. [self disableNetwork];
  364. // update the docs (though don't wait for a server response. We're offline; so
  365. // that ain't happening!). This allows us to further distinguished cached vs
  366. // server responses below.
  367. [[col documentWithPath:@"doc2"] setData:@{@"key2b" : @"value2b"} merge:YES];
  368. [[col documentWithPath:@"doc3"] setData:@{@"key3b" : @"value3b"}];
  369. [[col documentWithPath:@"doc4"] setData:@{@"key4" : @"value4"}];
  370. // Create an initial listener for this query (to attempt to disrupt the gets
  371. // below) and wait for the listener to deliver its initial snapshot before
  372. // continuing.
  373. XCTestExpectation *listenerReady = [self expectationWithDescription:@"listenerReady"];
  374. [col addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) {
  375. [listenerReady fulfill];
  376. }];
  377. [self awaitExpectations];
  378. // get docs (from cache) and ensure they *are* from the cache, and
  379. // matches the updated data.
  380. FIRQuerySnapshot *result = [self readDocumentSetForRef:col source:FIRFirestoreSourceCache];
  381. XCTAssertTrue(result.metadata.fromCache);
  382. XCTAssertTrue(result.metadata.hasPendingWrites);
  383. XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
  384. @{@"key1" : @"value1"}, @{@"key2" : @"value2", @"key2b" : @"value2b"},
  385. @{@"key3b" : @"value3b"}, @{@"key4" : @"value4"}
  386. ]));
  387. XCTAssertEqualObjects(
  388. FIRQuerySnapshotGetDocChangesData(result), (@[
  389. @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
  390. @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2", @"key2b" : @"value2b"} ],
  391. @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3b" : @"value3b"} ],
  392. @[ @(FIRDocumentChangeTypeAdded), @"doc4", @{@"key4" : @"value4"} ]
  393. ]));
  394. // attempt to get docs (with default get source)
  395. result = [self readDocumentSetForRef:col source:FIRFirestoreSourceDefault];
  396. XCTAssertTrue(result.metadata.fromCache);
  397. XCTAssertEqualObjects(FIRQuerySnapshotGetData(result), (@[
  398. @{@"key1" : @"value1"}, @{@"key2" : @"value2", @"key2b" : @"value2b"},
  399. @{@"key3b" : @"value3b"}, @{@"key4" : @"value4"}
  400. ]));
  401. XCTAssertEqualObjects(
  402. FIRQuerySnapshotGetDocChangesData(result), (@[
  403. @[ @(FIRDocumentChangeTypeAdded), @"doc1", @{@"key1" : @"value1"} ],
  404. @[ @(FIRDocumentChangeTypeAdded), @"doc2", @{@"key2" : @"value2", @"key2b" : @"value2b"} ],
  405. @[ @(FIRDocumentChangeTypeAdded), @"doc3", @{@"key3b" : @"value3b"} ],
  406. @[ @(FIRDocumentChangeTypeAdded), @"doc4", @{@"key4" : @"value4"} ]
  407. ]));
  408. // attempt to get docs (from the server) and ensure they cannot be retreived
  409. XCTestExpectation *failedGetDocsCompletion = [self expectationWithDescription:@"failedGetDocs"];
  410. [col getDocumentsWithSource:FIRFirestoreSourceServer
  411. completion:^(FIRQuerySnapshot *snapshot, NSError *error) {
  412. XCTAssertNotNil(error);
  413. XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
  414. XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
  415. [failedGetDocsCompletion fulfill];
  416. }];
  417. [self awaitExpectations];
  418. }
  419. - (void)testGetNonExistingDocWhileOnlineWithDefaultSource {
  420. FIRDocumentReference *doc = [self documentRef];
  421. // get doc and ensure that it does not exist and is *not* from the cache.
  422. FIRDocumentSnapshot *snapshot = [self readDocumentForRef:doc];
  423. XCTAssertFalse(snapshot.exists);
  424. XCTAssertFalse(snapshot.metadata.fromCache);
  425. XCTAssertFalse(snapshot.metadata.hasPendingWrites);
  426. }
  427. - (void)testGetNonExistingCollectionWhileOnlineWithDefaultSource {
  428. FIRCollectionReference *col = [self collectionRef];
  429. // get collection and ensure it's empty and that it's *not* from the cache.
  430. FIRQuerySnapshot *snapshot = [self readDocumentSetForRef:col];
  431. XCTAssertEqual(snapshot.count, 0);
  432. XCTAssertEqual(snapshot.documentChanges.count, 0);
  433. XCTAssertFalse(snapshot.metadata.fromCache);
  434. XCTAssertFalse(snapshot.metadata.hasPendingWrites);
  435. }
  436. - (void)testGetNonExistingDocWhileOfflineWithDefaultSource {
  437. FIRDocumentReference *doc = [self documentRef];
  438. // go offline for the rest of this test
  439. [self disableNetwork];
  440. // Attempt to get doc. This will fail since there's nothing in cache.
  441. XCTestExpectation *getNonExistingDocCompletion =
  442. [self expectationWithDescription:@"getNonExistingDoc"];
  443. [doc getDocumentWithCompletion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
  444. XCTAssertNotNil(error);
  445. XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
  446. XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
  447. [getNonExistingDocCompletion fulfill];
  448. }];
  449. [self awaitExpectations];
  450. }
  451. // TODO(b/112267729): We should raise a fromCache=true event with a nonexistent snapshot, but
  452. // because the default source goes through a normal listener, we do not.
  453. - (void)xtestGetDeletedDocWhileOfflineWithDefaultSource {
  454. FIRDocumentReference *doc = [self documentRef];
  455. // Delete the doc to get a deleted document into our cache.
  456. [self deleteDocumentRef:doc];
  457. // Go offline for the rest of this test
  458. [self disableNetwork];
  459. // Should get a FIRDocumentSnapshot with exists=false, fromCache=true
  460. FIRDocumentSnapshot *snapshot = [self readDocumentForRef:doc source:FIRFirestoreSourceDefault];
  461. XCTAssertNotNil(snapshot);
  462. XCTAssertFalse(snapshot.exists);
  463. XCTAssertNil(snapshot.data);
  464. XCTAssertTrue(snapshot.metadata.fromCache);
  465. XCTAssertFalse(snapshot.metadata.hasPendingWrites);
  466. }
  467. - (void)testGetNonExistingCollectionWhileOfflineWithDefaultSource {
  468. FIRCollectionReference *col = [self collectionRef];
  469. // go offline for the rest of this test
  470. [self disableNetwork];
  471. // get collection and ensure it's empty and that it *is* from the cache.
  472. FIRQuerySnapshot *snapshot = [self readDocumentSetForRef:col];
  473. XCTAssertEqual(snapshot.count, 0);
  474. XCTAssertEqual(snapshot.documentChanges.count, 0);
  475. XCTAssertTrue(snapshot.metadata.fromCache);
  476. XCTAssertFalse(snapshot.metadata.hasPendingWrites);
  477. }
  478. - (void)testGetNonExistingDocWhileOnlineCacheOnly {
  479. FIRDocumentReference *doc = [self documentRef];
  480. // Attempt to get doc. This will fail since there's nothing in cache.
  481. XCTestExpectation *getNonExistingDocCompletion =
  482. [self expectationWithDescription:@"getNonExistingDoc"];
  483. [doc getDocumentWithSource:FIRFirestoreSourceCache
  484. completion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
  485. XCTAssertNotNil(error);
  486. XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
  487. XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
  488. [getNonExistingDocCompletion fulfill];
  489. }];
  490. [self awaitExpectations];
  491. }
  492. - (void)testGetNonExistingCollectionWhileOnlineCacheOnly {
  493. FIRCollectionReference *col = [self collectionRef];
  494. // get collection and ensure it's empty and that it *is* from the cache.
  495. FIRQuerySnapshot *snapshot = [self readDocumentSetForRef:col source:FIRFirestoreSourceCache];
  496. XCTAssertEqual(snapshot.count, 0);
  497. XCTAssertEqual(snapshot.documentChanges.count, 0);
  498. XCTAssertTrue(snapshot.metadata.fromCache);
  499. XCTAssertFalse(snapshot.metadata.hasPendingWrites);
  500. }
  501. - (void)testGetNonExistingDocWhileOfflineCacheOnly {
  502. FIRDocumentReference *doc = [self documentRef];
  503. // go offline for the rest of this test
  504. [self disableNetwork];
  505. // Attempt to get doc. This will fail since there's nothing in cache.
  506. XCTestExpectation *getNonExistingDocCompletion =
  507. [self expectationWithDescription:@"getNonExistingDoc"];
  508. [doc getDocumentWithSource:FIRFirestoreSourceCache
  509. completion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
  510. XCTAssertNotNil(error);
  511. XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
  512. XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
  513. [getNonExistingDocCompletion fulfill];
  514. }];
  515. [self awaitExpectations];
  516. }
  517. - (void)testGetDeletedDocWhileOfflineCacheOnly {
  518. FIRDocumentReference *doc = [self documentRef];
  519. // Delete the doc to get a deleted document into our cache.
  520. [self deleteDocumentRef:doc];
  521. // Go offline for the rest of this test
  522. [self disableNetwork];
  523. // Should get a FIRDocumentSnapshot with exists=false, fromCache=true
  524. FIRDocumentSnapshot *snapshot = [self readDocumentForRef:doc source:FIRFirestoreSourceCache];
  525. XCTAssertNotNil(snapshot);
  526. XCTAssertFalse(snapshot.exists);
  527. XCTAssertNil(snapshot.data);
  528. XCTAssertTrue(snapshot.metadata.fromCache);
  529. XCTAssertFalse(snapshot.metadata.hasPendingWrites);
  530. }
  531. - (void)testGetNonExistingCollectionWhileOfflineCacheOnly {
  532. FIRCollectionReference *col = [self collectionRef];
  533. // go offline for the rest of this test
  534. [self disableNetwork];
  535. // get collection and ensure it's empty and that it *is* from the cache.
  536. FIRQuerySnapshot *snapshot = [self readDocumentSetForRef:col source:FIRFirestoreSourceCache];
  537. XCTAssertEqual(snapshot.count, 0);
  538. XCTAssertEqual(snapshot.documentChanges.count, 0);
  539. XCTAssertTrue(snapshot.metadata.fromCache);
  540. XCTAssertFalse(snapshot.metadata.hasPendingWrites);
  541. }
  542. - (void)testGetNonExistingDocWhileOnlineServerOnly {
  543. FIRDocumentReference *doc = [self documentRef];
  544. // get doc and ensure that it does not exist and is *not* from the cache.
  545. FIRDocumentSnapshot *snapshot = [self readDocumentForRef:doc source:FIRFirestoreSourceServer];
  546. XCTAssertFalse(snapshot.exists);
  547. XCTAssertFalse(snapshot.metadata.fromCache);
  548. XCTAssertFalse(snapshot.metadata.hasPendingWrites);
  549. }
  550. - (void)testGetNonExistingCollectionWhileOnlineServerOnly {
  551. FIRCollectionReference *col = [self collectionRef];
  552. // get collection and ensure that it's empty and that it's *not* from the cache.
  553. FIRQuerySnapshot *snapshot = [self readDocumentSetForRef:col source:FIRFirestoreSourceServer];
  554. XCTAssertEqual(snapshot.count, 0);
  555. XCTAssertEqual(snapshot.documentChanges.count, 0);
  556. XCTAssertFalse(snapshot.metadata.fromCache);
  557. XCTAssertFalse(snapshot.metadata.hasPendingWrites);
  558. }
  559. - (void)testGetNonExistingDocWhileOfflineServerOnly {
  560. FIRDocumentReference *doc = [self documentRef];
  561. // go offline for the rest of this test
  562. [self disableNetwork];
  563. // attempt to get doc. Currently, this is expected to fail. In the future, we
  564. // might consider adding support for negative cache hits so that we know
  565. // certain documents *don't* exist.
  566. XCTestExpectation *getNonExistingDocCompletion =
  567. [self expectationWithDescription:@"getNonExistingDoc"];
  568. [doc getDocumentWithSource:FIRFirestoreSourceServer
  569. completion:^(FIRDocumentSnapshot *snapshot, NSError *error) {
  570. XCTAssertNotNil(error);
  571. XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
  572. XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
  573. [getNonExistingDocCompletion fulfill];
  574. }];
  575. [self awaitExpectations];
  576. }
  577. - (void)testGetNonExistingCollectionWhileOfflineServerOnly {
  578. FIRCollectionReference *col = [self collectionRef];
  579. // go offline for the rest of this test
  580. [self disableNetwork];
  581. // attempt to get collection and ensure that it cannot be retreived
  582. XCTestExpectation *failedGetDocsCompletion = [self expectationWithDescription:@"failedGetDocs"];
  583. [col getDocumentsWithSource:FIRFirestoreSourceServer
  584. completion:^(FIRQuerySnapshot *snapshot, NSError *error) {
  585. XCTAssertNotNil(error);
  586. XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
  587. XCTAssertEqual(error.code, FIRFirestoreErrorCodeUnavailable);
  588. [failedGetDocsCompletion fulfill];
  589. }];
  590. [self awaitExpectations];
  591. }
  592. @end