FIRDatabaseTests.m 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. /*
  2. * Copyright 2017 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 <XCTest/XCTest.h>
  17. #import <FirebaseCore/FIRApp.h>
  18. #import <FirebaseCore/FIROptions.h>
  19. #import "FIRDatabase.h"
  20. #import "FIRDatabaseConfig_Private.h"
  21. #import "FIRDatabaseReference.h"
  22. #import "FIRDatabaseReference_Private.h"
  23. #import "FIRFakeApp.h"
  24. #import "FMockStorageEngine.h"
  25. #import "FTestBase.h"
  26. #import "FTestHelpers.h"
  27. @interface FIRDatabaseTests : FTestBase
  28. @end
  29. static const NSInteger kFErrorCodeWriteCanceled = 3;
  30. static NSString *kFirebaseTestAltNamespace = @"https://foobar.firebaseio.com";
  31. @implementation FIRDatabaseTests
  32. - (void)testFIRDatabaseForNilApp {
  33. #pragma clang diagnostic push
  34. #pragma clang diagnostic ignored "-Wnonnull"
  35. XCTAssertThrowsSpecificNamed([FIRDatabase databaseForApp:nil], NSException, @"InvalidFIRApp");
  36. #pragma clang diagnostic pop
  37. }
  38. - (void)testDatabaseForApp {
  39. FIRDatabase *database = [self databaseForURL:self.databaseURL];
  40. XCTAssertEqualObjects(self.databaseURL, [database reference].URL);
  41. }
  42. - (void)testDatabaseForAppWithInvalidURLs {
  43. XCTAssertThrows([self databaseForURL:nil]);
  44. XCTAssertThrows([self databaseForURL:@"not-a-url"]);
  45. XCTAssertThrows([self databaseForURL:@"http://x.example.com/paths/are/bad"]);
  46. }
  47. - (void)testDatabaseForAppWithURL {
  48. id app = [[FIRFakeApp alloc] initWithName:@"testDatabaseForAppWithURL"
  49. URL:kFirebaseTestAltNamespace];
  50. FIRDatabase *database = [FIRDatabase databaseForApp:app URL:@"http://foo.bar.com"];
  51. XCTAssertEqualObjects(@"https://foo.bar.com", [database reference].URL);
  52. }
  53. - (void)testDatabaseForAppWithURLAndPort {
  54. id app = [[FIRFakeApp alloc] initWithName:@"testDatabaseForAppWithURLAndPort"
  55. URL:kFirebaseTestAltNamespace];
  56. FIRDatabase *database = [FIRDatabase databaseForApp:app URL:@"http://foo.bar.com:80"];
  57. XCTAssertEqualObjects(@"http://foo.bar.com:80", [database reference].URL);
  58. }
  59. - (void)testDatabaseForAppWithHttpsURL {
  60. id app = [[FIRFakeApp alloc] initWithName:@"testDatabaseForAppWithHttpsURL"
  61. URL:kFirebaseTestAltNamespace];
  62. FIRDatabase *database = [FIRDatabase databaseForApp:app URL:@"https://foo.bar.com"];
  63. XCTAssertEqualObjects(@"https://foo.bar.com", [database reference].URL);
  64. }
  65. - (void)testDifferentInstanceForAppWithURL {
  66. id app = [[FIRFakeApp alloc] initWithName:@"testDifferentInstanceForAppWithURL"
  67. URL:kFirebaseTestAltNamespace];
  68. FIRDatabase *database1 = [FIRDatabase databaseForApp:app URL:@"https://foo1.bar.com"];
  69. FIRDatabase *database2 = [FIRDatabase databaseForApp:app URL:@"https://foo1.bar.com/"];
  70. FIRDatabase *database3 = [FIRDatabase databaseForApp:app URL:@"https://foo2.bar.com"];
  71. XCTAssertEqual(database1, database2);
  72. XCTAssertNotEqual(database1, database3);
  73. }
  74. - (void)testDatabaseForAppWithInvalidCustomURLs {
  75. id app = [[FIRFakeApp alloc] initWithName:@"testDatabaseForAppWithInvalidCustomURLs"
  76. URL:kFirebaseTestAltNamespace];
  77. #pragma clang diagnostic push
  78. #pragma clang diagnostic ignored "-Wnonnull"
  79. XCTAssertThrows([FIRDatabase databaseForApp:app URL:nil]);
  80. #pragma clang diagnostic pop
  81. XCTAssertThrows([FIRDatabase databaseForApp:app URL:@"not-a-url"]);
  82. XCTAssertThrows([FIRDatabase databaseForApp:app URL:@"http://x.fblocal.com:9000/paths/are/bad"]);
  83. }
  84. - (void)testDeleteDatabase {
  85. // Set up a custom FIRApp with a custom database based on it.
  86. FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"1:123:ios:123abc"
  87. GCMSenderID:@"gcm_sender_id"];
  88. options.databaseURL = self.databaseURL;
  89. NSString *customAppName = @"MyCustomApp";
  90. [FIRApp configureWithName:customAppName options:options];
  91. FIRApp *customApp = [FIRApp appNamed:customAppName];
  92. FIRDatabase *customDatabase = [FIRDatabase databaseForApp:customApp];
  93. XCTAssertNotNil(customDatabase);
  94. // Delete the custom app and wait for it to be done.
  95. XCTestExpectation *customAppDeletedExpectation =
  96. [self expectationWithDescription:@"Deleting the custom app should be successful."];
  97. [customApp deleteApp:^(BOOL success) {
  98. // The app shouldn't exist anymore, ensure that the databaseForApp throws.
  99. XCTAssertThrows([FIRDatabase databaseForApp:[FIRApp appNamed:customAppName]]);
  100. [customAppDeletedExpectation fulfill];
  101. }];
  102. // Wait for the custom app to be deleted.
  103. [self waitForExpectations:@[ customAppDeletedExpectation ] timeout:2];
  104. // Configure the app again, then grab a reference to the database. Assert it's different.
  105. [FIRApp configureWithName:customAppName options:options];
  106. FIRApp *secondCustomApp = [FIRApp appNamed:customAppName];
  107. FIRDatabase *secondCustomDatabase = [FIRDatabase databaseForApp:secondCustomApp];
  108. XCTAssertNotNil(secondCustomDatabase);
  109. XCTAssertNotEqualObjects(customDatabase, secondCustomDatabase);
  110. }
  111. - (void)testReferenceWithPath {
  112. FIRDatabase *db = [self defaultDatabase];
  113. NSString *expectedURL = [NSString stringWithFormat:@"%@/foo", self.databaseURL];
  114. XCTAssertEqualObjects(expectedURL, [db referenceWithPath:@"foo"].URL);
  115. }
  116. - (void)testReferenceFromURLWithEmptyPath {
  117. FIRDatabaseReference *ref = [[self defaultDatabase] referenceFromURL:self.databaseURL];
  118. XCTAssertEqualObjects(self.databaseURL, ref.URL);
  119. }
  120. - (void)testReferenceFromURLWithPath {
  121. NSString *url = [NSString stringWithFormat:@"%@/foo/bar", self.databaseURL];
  122. FIRDatabaseReference *ref = [[self defaultDatabase] referenceFromURL:url];
  123. XCTAssertEqualObjects(url, ref.URL);
  124. }
  125. - (void)testReferenceFromURLWithWrongURL {
  126. NSString *url = [NSString stringWithFormat:@"%@/foo/bar", @"https://foobar.firebaseio.com"];
  127. XCTAssertThrows([[self defaultDatabase] referenceFromURL:url]);
  128. }
  129. - (void)testReferenceEqualityForFIRDatabase {
  130. FIRDatabase *db1 = [self databaseForURL:self.databaseURL name:@"db1"];
  131. FIRDatabase *db2 = [self databaseForURL:self.databaseURL name:@"db2"];
  132. FIRDatabase *altDb = [self databaseForURL:self.databaseURL name:@"altDb"];
  133. FIRDatabase *wrongHostDb = [self databaseForURL:@"http://tests.example.com"];
  134. FIRDatabaseReference *testRef1 = [db1 reference];
  135. FIRDatabaseReference *testRef2 = [db1 referenceWithPath:@"foo"];
  136. FIRDatabaseReference *testRef3 = [altDb reference];
  137. FIRDatabaseReference *testRef4 = [wrongHostDb reference];
  138. FIRDatabaseReference *testRef5 = [db2 reference];
  139. FIRDatabaseReference *testRef6 = [db2 reference];
  140. // Referential equality
  141. XCTAssertTrue(testRef1.database == testRef2.database);
  142. XCTAssertFalse(testRef1.database == testRef3.database);
  143. XCTAssertFalse(testRef1.database == testRef4.database);
  144. XCTAssertFalse(testRef1.database == testRef5.database);
  145. XCTAssertFalse(testRef1.database == testRef6.database);
  146. // references from same FIRDatabase same identical .database references.
  147. XCTAssertTrue(testRef5.database == testRef6.database);
  148. [db1 goOffline];
  149. [db2 goOffline];
  150. [altDb goOffline];
  151. [wrongHostDb goOffline];
  152. }
  153. - (FIRDatabaseReference *)rootRefWithEngine:(id<FStorageEngine>)engine name:(NSString *)name {
  154. FIRDatabaseConfig *config = [FTestHelpers configForName:name];
  155. config.persistenceEnabled = YES;
  156. config.forceStorageEngine = engine;
  157. return [[FIRDatabaseReference alloc] initWithConfig:config];
  158. }
  159. - (void)testPurgeWritesPurgesAllWrites {
  160. FMockStorageEngine *engine = [[FMockStorageEngine alloc] init];
  161. FIRDatabaseReference *ref = [self rootRefWithEngine:engine name:@"purgeWritesPurgesAllWrites"];
  162. FIRDatabase *database = ref.database;
  163. [database goOffline];
  164. [[ref childByAutoId] setValue:@"test-value-1"];
  165. [[ref childByAutoId] setValue:@"test-value-2"];
  166. [[ref childByAutoId] setValue:@"test-value-3"];
  167. [[ref childByAutoId] setValue:@"test-value-4"];
  168. [self waitForEvents:ref];
  169. XCTAssertEqual(engine.userWrites.count, (NSUInteger)4);
  170. [database purgeOutstandingWrites];
  171. [self waitForEvents:ref];
  172. XCTAssertEqual(engine.userWrites.count, (NSUInteger)0);
  173. [database goOnline];
  174. }
  175. - (void)testPurgeWritesAreCanceledInOrder {
  176. FMockStorageEngine *engine = [[FMockStorageEngine alloc] init];
  177. FIRDatabaseReference *ref = [self rootRefWithEngine:engine name:@"purgeWritesAndCanceledInOrder"];
  178. FIRDatabase *database = ref.database;
  179. [database goOffline];
  180. NSMutableArray *order = [NSMutableArray array];
  181. [[ref childByAutoId] setValue:@"test-value-1"
  182. withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  183. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  184. [order addObject:@"1"];
  185. }];
  186. [[ref childByAutoId] setValue:@"test-value-2"
  187. withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  188. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  189. [order addObject:@"2"];
  190. }];
  191. [[ref childByAutoId] setValue:@"test-value-3"
  192. withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  193. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  194. [order addObject:@"3"];
  195. }];
  196. [[ref childByAutoId] setValue:@"test-value-4"
  197. withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  198. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  199. [order addObject:@"4"];
  200. }];
  201. [self waitForEvents:ref];
  202. XCTAssertEqual(engine.userWrites.count, (NSUInteger)4);
  203. [database purgeOutstandingWrites];
  204. [self waitForEvents:ref];
  205. XCTAssertEqual(engine.userWrites.count, (NSUInteger)0);
  206. XCTAssertEqualObjects(order, (@[ @"1", @"2", @"3", @"4" ]));
  207. [database goOnline];
  208. }
  209. - (void)testPurgeWritesCancelsOnDisconnects {
  210. FMockStorageEngine *engine = [[FMockStorageEngine alloc] init];
  211. FIRDatabaseReference *ref = [self rootRefWithEngine:engine
  212. name:@"purgeWritesCancelsOnDisconnects"];
  213. FIRDatabase *database = ref.database;
  214. [database goOffline];
  215. NSMutableArray *events = [NSMutableArray array];
  216. [[ref childByAutoId] onDisconnectSetValue:@"test-value-1"
  217. withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  218. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  219. [events addObject:@"1"];
  220. }];
  221. [[ref childByAutoId] onDisconnectSetValue:@"test-value-2"
  222. withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  223. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  224. [events addObject:@"2"];
  225. }];
  226. [self waitForEvents:ref];
  227. [database purgeOutstandingWrites];
  228. [self waitForEvents:ref];
  229. XCTAssertEqualObjects(events, (@[ @"1", @"2" ]));
  230. }
  231. - (void)testPurgeWritesReraisesEvents {
  232. FMockStorageEngine *engine = [[FMockStorageEngine alloc] init];
  233. FIRDatabaseReference *ref = [[self rootRefWithEngine:engine
  234. name:@"purgeWritesReraiseEvents"] childByAutoId];
  235. FIRDatabase *database = ref.database;
  236. [self waitForCompletionOf:ref
  237. setValue:@{@"foo" : @"foo-value", @"bar" : @{@"qux" : @"qux-value"}}];
  238. NSMutableArray *fooValues = [NSMutableArray array];
  239. NSMutableArray *barQuuValues = [NSMutableArray array];
  240. NSMutableArray *barQuxValues = [NSMutableArray array];
  241. NSMutableArray *cancelOrder = [NSMutableArray array];
  242. [[ref child:@"foo"] observeEventType:FIRDataEventTypeValue
  243. withBlock:^(FIRDataSnapshot *snapshot) {
  244. [fooValues addObject:snapshot.value];
  245. }];
  246. [[ref child:@"bar/quu"] observeEventType:FIRDataEventTypeValue
  247. withBlock:^(FIRDataSnapshot *snapshot) {
  248. [barQuuValues addObject:snapshot.value];
  249. }];
  250. [[ref child:@"bar/qux"] observeEventType:FIRDataEventTypeValue
  251. withBlock:^(FIRDataSnapshot *snapshot) {
  252. [barQuxValues addObject:snapshot.value];
  253. }];
  254. [database goOffline];
  255. [[ref child:@"foo"] setValue:@"new-foo-value"
  256. withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  257. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  258. // This should be after we raised events
  259. XCTAssertEqualObjects(fooValues.lastObject, @"foo-value");
  260. [cancelOrder addObject:@"foo-1"];
  261. }];
  262. [[ref child:@"bar"] updateChildValues:@{@"quu" : @"quu-value", @"qux" : @"new-qux-value"}
  263. withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  264. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  265. // This should be after we raised events
  266. XCTAssertEqualObjects(barQuxValues.lastObject, @"qux-value");
  267. XCTAssertEqualObjects(barQuuValues.lastObject, [NSNull null]);
  268. [cancelOrder addObject:@"bar"];
  269. }];
  270. [[ref child:@"foo"] setValue:@"newest-foo-value"
  271. withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  272. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  273. // This should be after we raised events
  274. XCTAssertEqualObjects(fooValues.lastObject, @"foo-value");
  275. [cancelOrder addObject:@"foo-2"];
  276. }];
  277. [database purgeOutstandingWrites];
  278. [self waitForEvents:ref];
  279. XCTAssertEqualObjects(cancelOrder, (@[ @"foo-1", @"bar", @"foo-2" ]));
  280. XCTAssertEqualObjects(fooValues,
  281. (@[ @"foo-value", @"new-foo-value", @"newest-foo-value", @"foo-value" ]));
  282. XCTAssertEqualObjects(barQuuValues, (@[ [NSNull null], @"quu-value", [NSNull null] ]));
  283. XCTAssertEqualObjects(barQuxValues, (@[ @"qux-value", @"new-qux-value", @"qux-value" ]));
  284. [database goOnline];
  285. // Make sure we're back online and reconnected again
  286. [self waitForRoundTrip:ref];
  287. // No events should be reraised
  288. XCTAssertEqualObjects(cancelOrder, (@[ @"foo-1", @"bar", @"foo-2" ]));
  289. XCTAssertEqualObjects(fooValues,
  290. (@[ @"foo-value", @"new-foo-value", @"newest-foo-value", @"foo-value" ]));
  291. XCTAssertEqualObjects(barQuuValues, (@[ [NSNull null], @"quu-value", [NSNull null] ]));
  292. XCTAssertEqualObjects(barQuxValues, (@[ @"qux-value", @"new-qux-value", @"qux-value" ]));
  293. }
  294. - (void)testPurgeWritesCancelsTransactions {
  295. FMockStorageEngine *engine = [[FMockStorageEngine alloc] init];
  296. FIRDatabaseReference *ref =
  297. [[self rootRefWithEngine:engine name:@"purgeWritesCancelsTransactions"] childByAutoId];
  298. FIRDatabase *database = ref.database;
  299. NSMutableArray *events = [NSMutableArray array];
  300. [ref observeEventType:FIRDataEventTypeValue
  301. withBlock:^(FIRDataSnapshot *snapshot) {
  302. [events addObject:[NSString stringWithFormat:@"value-%@", snapshot.value]];
  303. }];
  304. // Make sure the first value event is fired
  305. [self waitForRoundTrip:ref];
  306. [database goOffline];
  307. [ref
  308. runTransactionBlock:^FIRTransactionResult *(FIRMutableData *currentData) {
  309. [currentData setValue:@"1"];
  310. return [FIRTransactionResult successWithValue:currentData];
  311. }
  312. andCompletionBlock:^(NSError *error, BOOL committed, FIRDataSnapshot *snapshot) {
  313. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  314. [events addObject:@"cancel-1"];
  315. }];
  316. [ref
  317. runTransactionBlock:^FIRTransactionResult *(FIRMutableData *currentData) {
  318. [currentData setValue:@"2"];
  319. return [FIRTransactionResult successWithValue:currentData];
  320. }
  321. andCompletionBlock:^(NSError *error, BOOL committed, FIRDataSnapshot *snapshot) {
  322. XCTAssertEqual(error.code, kFErrorCodeWriteCanceled);
  323. [events addObject:@"cancel-2"];
  324. }];
  325. [database purgeOutstandingWrites];
  326. [self waitForEvents:ref];
  327. // The order should really be cancel-1 then cancel-2, but meh, to difficult to implement
  328. // currently...
  329. XCTAssertEqualObjects(
  330. events,
  331. (@[ @"value-<null>", @"value-1", @"value-2", @"value-<null>", @"cancel-2", @"cancel-1" ]));
  332. }
  333. - (void)testPersistenceEnabled {
  334. id app = [[FIRFakeApp alloc] initWithName:@"testPersistenceEnabled" URL:self.databaseURL];
  335. FIRDatabase *database = [FIRDatabase databaseForApp:app];
  336. database.persistenceEnabled = YES;
  337. XCTAssertTrue(database.persistenceEnabled);
  338. // Just do a dummy observe that should get null added to the persistent cache.
  339. FIRDatabaseReference *ref = [[database reference] childByAutoId];
  340. [self waitForValueOf:ref toBe:[NSNull null]];
  341. // Now go offline and since null is cached offline, our observer should still complete.
  342. [database goOffline];
  343. [self waitForValueOf:ref toBe:[NSNull null]];
  344. }
  345. - (void)testPersistenceCacheSizeBytes {
  346. id app = [[FIRFakeApp alloc] initWithName:@"testPersistenceCacheSizeBytes" URL:self.databaseURL];
  347. FIRDatabase *database = [FIRDatabase databaseForApp:app];
  348. database.persistenceEnabled = YES;
  349. int oneMegabyte = 1 * 1024 * 1024;
  350. XCTAssertThrows([database setPersistenceCacheSizeBytes:1], @"Cache must be a least 1 MB.");
  351. XCTAssertThrows([database setPersistenceCacheSizeBytes:101 * oneMegabyte],
  352. @"Cache must be less than 100 MB.");
  353. database.persistenceCacheSizeBytes = 2 * oneMegabyte;
  354. XCTAssertEqual(2 * oneMegabyte, database.persistenceCacheSizeBytes);
  355. [database reference]; // Initialize database.
  356. XCTAssertThrows([database setPersistenceCacheSizeBytes:3 * oneMegabyte],
  357. @"Persistence can't be changed after initialization.");
  358. XCTAssertEqual(2 * oneMegabyte, database.persistenceCacheSizeBytes);
  359. }
  360. - (void)testCallbackQueue {
  361. id app = [[FIRFakeApp alloc] initWithName:@"testCallbackQueue" URL:self.databaseURL];
  362. FIRDatabase *database = [FIRDatabase databaseForApp:app];
  363. dispatch_queue_t callbackQueue = dispatch_queue_create("testCallbackQueue", NULL);
  364. database.callbackQueue = callbackQueue;
  365. XCTAssertEqual(callbackQueue, database.callbackQueue);
  366. __block BOOL done = NO;
  367. [database.reference.childByAutoId observeSingleEventOfType:FIRDataEventTypeValue
  368. withBlock:^(FIRDataSnapshot *snapshot) {
  369. if (@available(iOS 10.0, macOS 10.12, *)) {
  370. dispatch_assert_queue(callbackQueue);
  371. } else {
  372. NSAssert(YES, @"Test requires iOS 10");
  373. }
  374. done = YES;
  375. }];
  376. WAIT_FOR(done);
  377. [database goOffline];
  378. }
  379. - (FIRDatabase *)defaultDatabase {
  380. return [self databaseForURL:self.databaseURL];
  381. }
  382. - (FIRDatabase *)databaseForURL:(NSString *)url {
  383. NSString *name = [NSString stringWithFormat:@"url:%@", url];
  384. return [self databaseForURL:url name:name];
  385. }
  386. - (FIRDatabase *)databaseForURL:(NSString *)url name:(NSString *)name {
  387. id app = nil;
  388. NSString *defaultDatabaseURL = [NSString stringWithFormat:@"url:%@", self.databaseURL];
  389. if ([url isEqualToString:self.databaseURL] && [name isEqualToString:defaultDatabaseURL]) {
  390. // Use the default app for the default URL to avoid getting out of sync with FRepoManager
  391. // when calling ensureRepo during tests that don't create their own FIRFakeApp.
  392. app = [FIRApp defaultApp];
  393. } else {
  394. app = [[FIRFakeApp alloc] initWithName:name URL:url];
  395. }
  396. return [FIRDatabase databaseForApp:app];
  397. }
  398. @end