diff options
author | Ryan Wilson <wilsonryan@google.com> | 2017-08-17 11:15:25 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-17 11:15:25 -0400 |
commit | 566665e3bbb47ed7e77f35f29c62bbc5c737a769 (patch) | |
tree | cc2501b7f63c73d3dfd040375d9925dfb5f3ce71 | |
parent | 55476604aabbb35be7ed7d871236644c1e1d395a (diff) |
Delete app from Database when deleted in Core. (#194)
* Delete an app from Database when deleted in Core.
When a FIRApp is deleted in Core, it should also be deleted from
the instances array in Database.
See #160 for more details.
* Add tests for deleting databases.
* Add call to clean up deleted FIRDatabase instance.
-rw-r--r-- | Example/Database/Tests/Integration/FIRDatabaseTests.m | 50 | ||||
-rw-r--r-- | Firebase/Database/Api/FIRDatabase.m | 20 |
2 files changed, 70 insertions, 0 deletions
diff --git a/Example/Database/Tests/Integration/FIRDatabaseTests.m b/Example/Database/Tests/Integration/FIRDatabaseTests.m index 3b20a46..4bdb773 100644 --- a/Example/Database/Tests/Integration/FIRDatabaseTests.m +++ b/Example/Database/Tests/Integration/FIRDatabaseTests.m @@ -53,6 +53,56 @@ static const NSInteger kFErrorCodeWriteCanceled = 3; XCTAssertThrows([self databaseForURL:@"http://x.example.com/paths/are/bad"]); } +- (void) testDeleteDatabase { + FIRDatabase *defaultDatabase = [FIRDatabase database]; + FIRApp *defaultApp = [FIRApp defaultApp]; + XCTAssertEqualObjects(defaultDatabase.app, defaultApp); + + // Set up expectation for the default app to be deleted. + XCTestExpectation *defaultAppDeletedExpectation = + [self expectationWithDescription:@"Deleting the default app should invalidate the default " + @"database."]; + [defaultApp deleteApp:^(BOOL success) { + // Deleting the default app should make the default database unavailable. + XCTAssertThrows([FIRDatabase database]); + + [defaultAppDeletedExpectation fulfill]; + }]; + + // Wait for the default app to be deleted. + [self waitForExpectations:@[defaultAppDeletedExpectation] timeout:2]; + + // Set up a custom FIRApp with a custom database based on it. + FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"1:123:ios:123abc" + GCMSenderID:@"gcm_sender_id"]; + options.databaseURL = self.databaseURL; + NSString *customAppName = @"MyCustomApp"; + [FIRApp configureWithName:customAppName options:options]; + FIRApp *customApp = [FIRApp appNamed:customAppName]; + FIRDatabase *customDatabase = [FIRDatabase databaseForApp:customApp]; + XCTAssertNotNil(customDatabase); + + // Delete the custom app and wait for it to be done. + XCTestExpectation *customAppDeletedExpectation = + [self expectationWithDescription:@"Deleting the custom app should be successful."]; + [customApp deleteApp:^(BOOL success) { + // The app shouldn't exist anymore, ensure that the databaseForApp throws. + XCTAssertThrows([FIRDatabase databaseForApp:[FIRApp appNamed:customAppName]]); + + [customAppDeletedExpectation fulfill]; + }]; + + // Wait for the custom app to be deleted. + [self waitForExpectations:@[customAppDeletedExpectation] timeout:2]; + + // Configure the app again, then grab a reference to the database. Assert it's different. + [FIRApp configureWithName:customAppName options:options]; + FIRApp *secondCustomApp = [FIRApp appNamed:customAppName]; + FIRDatabase *secondCustomDatabase = [FIRDatabase databaseForApp:secondCustomApp]; + XCTAssertNotNil(secondCustomDatabase); + XCTAssertNotEqualObjects(customDatabase, secondCustomDatabase); +} + - (void) testReferenceWithPath { FIRDatabase *db = [self defaultDatabase]; NSString *expectedURL = [NSString stringWithFormat:@"%@/foo", self.databaseURL]; diff --git a/Firebase/Database/Api/FIRDatabase.m b/Firebase/Database/Api/FIRDatabase.m index 38ccd54..6ee163f 100644 --- a/Firebase/Database/Api/FIRDatabase.m +++ b/Firebase/Database/Api/FIRDatabase.m @@ -42,6 +42,26 @@ #define STR_EXPAND(x) #x static const char *FIREBASE_SEMVER = (const char *)STR(FIRDatabase_VERSION); ++ (void)load { + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center addObserverForName:kFIRAppDeleteNotification + object:nil + queue:nil + usingBlock:^(NSNotification * _Nonnull note) { + NSString *appName = note.userInfo[kFIRAppNameKey]; + if (appName == nil) { return; } + + NSMutableDictionary *instances = [self instances]; + @synchronized (instances) { + FIRDatabase *deletedApp = instances[appName]; + // Clean up the deleted instance in an effort to remove any resources still in use. + // Note: Any leftover instances of this exact database will be invalid. + [FRepoManager disposeRepos:deletedApp.config]; + [instances removeObjectForKey:appName]; + } + }]; +} + /** * A static NSMutableDictionary of FirebaseApp names to FirebaseDatabase instance. To ensure thread- * safety, it should only be accessed in databaseForApp, which is synchronized. |