FIRFirestoreSourceTests.mm 29 KB

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