| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
- /*
- * Copyright 2017 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #import "FRealtime.h"
- #import "FIRDatabaseConfig_Private.h"
- #import "FParsedUrl.h"
- #import "FRepoManager.h"
- #import "FTestHelpers.h"
- #import "FTupleFirebase.h"
- #import "FUtilities.h"
- @implementation FRealtime
- - (void)testUrlParsing {
- FParsedUrl *parsed = [FUtilities parseUrl:@"http://www.example.com:9000"];
- XCTAssertTrue([[parsed.path description] isEqualToString:@"/"], @"Got correct path");
- XCTAssertTrue([parsed.repoInfo.host isEqualToString:@"www.example.com:9000"],
- @"Got correct host");
- XCTAssertTrue([parsed.repoInfo.internalHost isEqualToString:@"www.example.com:9000"],
- @"Got correct host");
- XCTAssertFalse(parsed.repoInfo.secure, @"Should not be secure, there's a port");
- parsed = [FUtilities parseUrl:@"http://www.firebaseio.com/foo/bar"];
- XCTAssertTrue([[parsed.path description] isEqualToString:@"/foo/bar"], @"Got correct path");
- XCTAssertTrue([parsed.repoInfo.host isEqualToString:@"www.firebaseio.com"], @"Got correct host");
- XCTAssertTrue([parsed.repoInfo.internalHost isEqualToString:@"www.firebaseio.com"],
- @"Got correct host");
- XCTAssertTrue(parsed.repoInfo.secure, @"Should be secure, there's no port");
- }
- - (void)testCachingRedirects {
- NSString *host = @"host.example.com";
- NSString *host2 = @"host2.example.com";
- NSString *internalHost = @"internal.example.com";
- NSString *internalHost2 = @"internal2.example.com";
- // Set host on first repo info
- FRepoInfo *repoInfo = [[FRepoInfo alloc] initWithHost:host isSecure:YES withNamespace:host];
- XCTAssertTrue([repoInfo.host isEqualToString:host], @"Got correct host");
- XCTAssertTrue([repoInfo.internalHost isEqualToString:host], @"Got correct host");
- // Set internal host on first repo info
- repoInfo.internalHost = internalHost;
- XCTAssertTrue([repoInfo.host isEqualToString:host], @"Got correct host");
- XCTAssertTrue([repoInfo.internalHost isEqualToString:internalHost], @"Got correct host");
- // Set up a second unrelated repo info to make sure caching is keyspaced properly
- FRepoInfo *repoInfo2 = [[FRepoInfo alloc] initWithHost:host2 isSecure:YES withNamespace:host2];
- XCTAssertTrue([repoInfo2.host isEqualToString:host2], @"Got correct host");
- XCTAssertTrue([repoInfo2.internalHost isEqualToString:host2], @"Got correct host");
- repoInfo2.internalHost = internalHost2;
- XCTAssertTrue([repoInfo2.internalHost isEqualToString:internalHost2], @"Got correct host");
- // Setting host on this repo info should also set the right internal host
- FRepoInfo *repoInfoCached = [[FRepoInfo alloc] initWithHost:host isSecure:YES withNamespace:host];
- XCTAssertTrue([repoInfoCached.host isEqualToString:host], @"Got correct host");
- XCTAssertTrue([repoInfoCached.internalHost isEqualToString:internalHost], @"Got correct host");
- [repoInfo clearInternalHostCache];
- [repoInfo2 clearInternalHostCache];
- [repoInfoCached clearInternalHostCache];
- XCTAssertTrue([repoInfo.internalHost isEqualToString:host], @"Got correct host");
- XCTAssertTrue([repoInfo2.internalHost isEqualToString:host2], @"Got correct host");
- XCTAssertTrue([repoInfoCached.internalHost isEqualToString:host], @"Got correct host");
- }
- - (void)testOnDisconnectSetWorks {
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseConfig *readerCfg = [FTestHelpers configForName:@"reader"];
- FIRDatabaseReference *writer =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] childByAutoId];
- FIRDatabaseReference *reader =
- [[[FIRDatabaseReference alloc] initWithConfig:readerCfg] child:writer.key];
- __block NSNumber *readValue = @0;
- __block NSNumber *writeValue = @0;
- [[reader child:@"disconnected"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- NSNumber *val = [snapshot value];
- if (![val isEqual:[NSNull null]]) {
- readValue = val;
- }
- }];
- [[writer child:@"disconnected"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- id val = [snapshot value];
- if (val != [NSNull null]) {
- writeValue = val;
- }
- }];
- [writer child:@"hello"];
- __block BOOL ready = NO;
- [[writer child:@"disconnected"]
- onDisconnectSetValue:@1
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- ready = YES;
- }];
- [self waitUntil:^BOOL {
- return ready;
- }];
- [writer child:@"s"];
- ready = NO;
- [[writer child:@"disconnected"]
- onDisconnectSetValue:@2
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- ready = YES;
- }];
- [self waitUntil:^BOOL {
- return ready;
- }];
- [FRepoManager interrupt:writerCfg];
- [self waitUntil:^BOOL {
- return [@2 isEqualToNumber:readValue] && [@2 isEqualToNumber:writeValue];
- }];
- [FRepoManager interrupt:readerCfg];
- // cleanup
- [FRepoManager disposeRepos:writerCfg];
- [FRepoManager disposeRepos:readerCfg];
- }
- - (void)testOnDisconnectSetWithPriorityWorks {
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseConfig *readerCfg = [FTestHelpers configForName:@"reader"];
- FIRDatabaseReference *writer =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] childByAutoId];
- FIRDatabaseReference *reader =
- [[[FIRDatabaseReference alloc] initWithConfig:readerCfg] child:writer.key];
- __block BOOL sawNewValue = NO;
- __block BOOL writerSawNewValue = NO;
- [[reader child:@"disconnected"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- id val = snapshot.value;
- id pri = snapshot.priority;
- if (val != [NSNull null] && pri != [NSNull null]) {
- sawNewValue = [(NSNumber *)val boolValue] &&
- [pri isEqualToString:@"abcd"];
- }
- }];
- [[writer child:@"disconnected"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- id val = [snapshot value];
- id pri = snapshot.priority;
- if (val != [NSNull null] && pri != [NSNull null]) {
- writerSawNewValue = [(NSNumber *)val boolValue] &&
- [pri isEqualToString:@"abcd"];
- }
- }];
- __block BOOL ready = NO;
- [[writer child:@"disconnected"]
- onDisconnectSetValue:@YES
- andPriority:@"abcd"
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- ready = YES;
- }];
- [self waitUntil:^BOOL {
- return ready;
- }];
- [FRepoManager interrupt:writerCfg];
- [self waitUntil:^BOOL {
- return sawNewValue && writerSawNewValue;
- }];
- [FRepoManager interrupt:readerCfg];
- // cleanup
- [FRepoManager disposeRepos:writerCfg];
- [FRepoManager disposeRepos:readerCfg];
- }
- - (void)testOnDisconnectRemoveWorks {
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseConfig *readerCfg = [FTestHelpers configForName:@"reader"];
- FIRDatabaseReference *writer =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] childByAutoId];
- FIRDatabaseReference *reader =
- [[[FIRDatabaseReference alloc] initWithConfig:readerCfg] child:writer.key];
- __block BOOL ready = NO;
- [[writer child:@"foo"] setValue:@"bar"
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- ready = YES;
- }];
- [self waitUntil:^BOOL {
- return ready;
- }];
- __block BOOL sawRemove = NO;
- __block BOOL writerSawRemove = NO;
- [[reader child:@"foo"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- sawRemove = [[NSNull null] isEqual:snapshot.value];
- }];
- [[writer child:@"foo"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- writerSawRemove = [[NSNull null] isEqual:snapshot.value];
- }];
- ready = NO;
- [[writer child:@"foo"]
- onDisconnectRemoveValueWithCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- ready = YES;
- }];
- [self waitUntil:^BOOL {
- return ready;
- }];
- [FRepoManager interrupt:writerCfg];
- [self waitUntil:^BOOL {
- return sawRemove && writerSawRemove;
- }];
- [FRepoManager interrupt:readerCfg];
- // cleanup
- [FRepoManager disposeRepos:writerCfg];
- [FRepoManager disposeRepos:readerCfg];
- }
- - (void)testOnDisconnectUpdateWorks {
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseConfig *readerCfg = [FTestHelpers configForName:@"reader"];
- FIRDatabaseReference *writer =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] childByAutoId];
- FIRDatabaseReference *reader =
- [[[FIRDatabaseReference alloc] initWithConfig:readerCfg] child:writer.key];
- [self waitForCompletionOf:[writer child:@"foo"] setValue:@{@"bar" : @"a", @"baz" : @"b"}];
- __block BOOL sawNewValue = NO;
- __block BOOL writerSawNewValue = NO;
- [[reader child:@"foo"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- NSDictionary *val = [snapshot value];
- if (val) {
- sawNewValue = [@{@"bar" : @"a", @"baz" : @"c", @"bat" : @"d"}
- isEqualToDictionary:val];
- }
- }];
- [[writer child:@"foo"]
- observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- NSDictionary *val = [snapshot value];
- if (val) {
- writerSawNewValue =
- [@{@"bar" : @"a", @"baz" : @"c", @"bat" : @"d"} isEqualToDictionary:val];
- }
- }];
- __block BOOL ready = NO;
- [[writer child:@"foo"]
- onDisconnectUpdateChildValues:@{@"baz" : @"c", @"bat" : @"d"}
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- ready = YES;
- }];
- [self waitUntil:^BOOL {
- return ready;
- }];
- [FRepoManager interrupt:writerCfg];
- [self waitUntil:^BOOL {
- return sawNewValue && writerSawNewValue;
- }];
- [FRepoManager interrupt:readerCfg];
- // cleanup
- [FRepoManager disposeRepos:writerCfg];
- [FRepoManager disposeRepos:readerCfg];
- }
- - (void)testOnDisconnectTriggersSingleLocalValueEventForWriter {
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseReference *writer =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] childByAutoId];
- __block int calls = 0;
- [writer observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- calls++;
- if (calls == 2) {
- // second call, verify the data
- NSDictionary *val = [snapshot value];
- NSDictionary *expected = @{@"foo" : @{@"bar" : @"a", @"bam" : @"c"}};
- XCTAssertTrue([val isEqualToDictionary:expected],
- @"Got all of the updates in one");
- } else if (calls > 2) {
- XCTFail(@"Extra calls");
- }
- }];
- [self waitUntil:^BOOL {
- return calls == 1;
- }];
- __block BOOL done = NO;
- FIRDatabaseReference *child = [writer child:@"foo"];
- [child onDisconnectSetValue:@{@"bar" : @"a", @"baz" : @"b"}];
- [child onDisconnectUpdateChildValues:@{@"bam" : @"c"}];
- [[child child:@"baz"]
- onDisconnectRemoveValueWithCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- [FRepoManager interrupt:writerCfg];
- [self waitUntil:^BOOL {
- return calls == 2;
- }];
- // cleanup
- [FRepoManager disposeRepos:writerCfg];
- }
- - (void)testOnDisconnectTriggersSingleLocalValueEventForReader {
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseReference *reader = [FTestHelpers getRandomNode];
- FIRDatabaseReference *writer =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] child:reader.key];
- __block int calls = 0;
- [reader observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- calls++;
- if (calls == 2) {
- // second call, verify the data
- NSDictionary *val = [snapshot value];
- NSDictionary *expected = @{@"foo" : @{@"bar" : @"a", @"bam" : @"c"}};
- XCTAssertTrue([val isEqualToDictionary:expected],
- @"Got all of the updates in one");
- } else if (calls > 2) {
- XCTFail(@"Extra calls");
- }
- }];
- [self waitUntil:^BOOL {
- return calls == 1;
- }];
- __block BOOL done = NO;
- FIRDatabaseReference *child = [writer child:@"foo"];
- [child onDisconnectSetValue:@{@"bar" : @"a", @"baz" : @"b"}];
- [child onDisconnectUpdateChildValues:@{@"bam" : @"c"}];
- [[child child:@"baz"]
- onDisconnectRemoveValueWithCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- [FRepoManager interrupt:writerCfg];
- [self waitUntil:^BOOL {
- return calls == 2;
- }];
- // cleanup
- [FRepoManager disposeRepos:writerCfg];
- }
- - (void)testOnDisconnectTriggersSingleLocalValueEventForWriterWithQuery {
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseReference *writer =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] childByAutoId];
- __block int calls = 0;
- [[[writer child:@"foo"] queryLimitedToLast:2]
- observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- calls++;
- if (calls == 2) {
- // second call, verify the data
- NSDictionary *val = [snapshot value];
- NSDictionary *expected = @{@"bar" : @"a", @"bam" : @"c"};
- XCTAssertTrue([val isEqualToDictionary:expected],
- @"Got all of the updates in one");
- } else if (calls > 2) {
- XCTFail(@"Extra calls");
- }
- }];
- [self waitUntil:^BOOL {
- return calls == 1;
- }];
- __block BOOL done = NO;
- FIRDatabaseReference *child = [writer child:@"foo"];
- [child onDisconnectSetValue:@{@"bar" : @"a", @"baz" : @"b"}];
- [child onDisconnectUpdateChildValues:@{@"bam" : @"c"}];
- [[child child:@"baz"]
- onDisconnectRemoveValueWithCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- [FRepoManager interrupt:writerCfg];
- [self waitUntil:^BOOL {
- return calls == 2;
- }];
- // cleanup
- [FRepoManager disposeRepos:writerCfg];
- }
- - (void)testOnDisconnectTriggersSingleLocalValueEventForReaderWithQuery {
- FIRDatabaseReference *reader = [FTestHelpers getRandomNode];
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseReference *writer =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] child:reader.key];
- __block int calls = 0;
- [[[reader child:@"foo"] queryLimitedToLast:2]
- observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- calls++;
- XCTAssertTrue([snapshot.key isEqualToString:@"foo"], @"Got the right snapshot");
- if (calls == 2) {
- // second call, verify the data
- NSDictionary *val = [snapshot value];
- NSDictionary *expected = @{@"bar" : @"a", @"bam" : @"c"};
- XCTAssertTrue([val isEqualToDictionary:expected],
- @"Got all of the updates in one");
- } else if (calls > 2) {
- XCTFail(@"Extra calls");
- }
- }];
- [self waitUntil:^BOOL {
- return calls == 1;
- }];
- __block BOOL done = NO;
- FIRDatabaseReference *child = [writer child:@"foo"];
- [child onDisconnectSetValue:@{@"bar" : @"a", @"baz" : @"b"}];
- [child onDisconnectUpdateChildValues:@{@"bam" : @"c"}];
- [[child child:@"baz"]
- onDisconnectRemoveValueWithCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- [FRepoManager interrupt:writerCfg];
- [self waitUntil:^BOOL {
- return calls == 2;
- }];
- // cleanup
- [FRepoManager disposeRepos:writerCfg];
- }
- - (void)testOnDisconnectDeepMergeTriggersOnlyOneValueEventForReaderWithQuery {
- FIRDatabaseReference *reader = [FTestHelpers getRandomNode];
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseReference *writer =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] childByAutoId];
- __block BOOL done = NO;
- NSDictionary *toSet =
- @{@"a" : @1, @"b" : @{@"c" : @YES, @"d" : @"scalar", @"e" : @{@"f" : @"hooray"}}};
- [writer setValue:toSet];
- [[writer child:@"a"] onDisconnectSetValue:@2];
- [[writer child:@"b/d"]
- onDisconnectRemoveValueWithCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- done = YES;
- }];
- WAIT_FOR(done);
- __block int count = 2;
- [[reader queryLimitedToLast:3]
- observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- count++;
- if (count == 1) {
- // Loaded the data, kill the writer connection
- [FRepoManager interrupt:writerCfg];
- } else if (count == 2) {
- NSDictionary *expected =
- @{@"a" : @2,
- @"b" : @{@"c" : @YES, @"e" : @{@"f" : @"hooray"}}};
- XCTAssertTrue([snapshot.value isEqualToDictionary:expected],
- @"Should see complete new snapshot");
- } else {
- XCTFail(@"Too many calls");
- }
- }];
- WAIT_FOR(count == 2);
- // cleanup
- [reader removeAllObservers];
- [FRepoManager disposeRepos:writerCfg];
- }
- - (void)testOnDisconnectCancelWorks {
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseConfig *readerCfg = [FTestHelpers configForName:@"reader"];
- FIRDatabaseReference *writer =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] childByAutoId];
- FIRDatabaseReference *reader =
- [[[FIRDatabaseReference alloc] initWithConfig:readerCfg] child:writer.key];
- __block BOOL ready = NO;
- [[writer child:@"foo"] setValue:@{@"bar" : @"a", @"baz" : @"b"}
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- ready = YES;
- }];
- [self waitUntil:^BOOL {
- return ready;
- }];
- __block BOOL sawNewValue = NO;
- __block BOOL writerSawNewValue = NO;
- [[reader child:@"foo"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- NSDictionary *val = [snapshot value];
- if (val) {
- sawNewValue = [@{@"bar" : @"a", @"baz" : @"b", @"bat" : @"d"}
- isEqualToDictionary:val];
- }
- }];
- [[writer child:@"foo"]
- observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- NSDictionary *val = [snapshot value];
- if (val) {
- writerSawNewValue =
- [@{@"bar" : @"a", @"baz" : @"b", @"bat" : @"d"} isEqualToDictionary:val];
- }
- }];
- ready = NO;
- [[writer child:@"foo"] onDisconnectUpdateChildValues:@{@"baz" : @"c", @"bat" : @"d"}];
- [[writer child:@"foo/baz"]
- cancelDisconnectOperationsWithCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- ready = YES;
- }];
- [self waitUntil:^BOOL {
- return ready;
- }];
- [FRepoManager interrupt:writerCfg];
- [self waitUntil:^BOOL {
- return sawNewValue && writerSawNewValue;
- }];
- [FRepoManager interrupt:readerCfg];
- // cleanup
- [FRepoManager disposeRepos:writerCfg];
- [FRepoManager disposeRepos:readerCfg];
- }
- - (void)testOnDisconnectWithServerValuesWithLocalEvents {
- FIRDatabaseConfig *writerCfg = [FTestHelpers configForName:@"writer"];
- FIRDatabaseReference *node =
- [[[FIRDatabaseReference alloc] initWithConfig:writerCfg] childByAutoId];
- __block FIRDataSnapshot *snap = nil;
- [node observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot *snapshot) {
- snap = snapshot;
- }];
- NSDictionary *data = @{
- @"a" : @1,
- @"b" : @{@".value" : [FIRServerValue timestamp], @".priority" : [FIRServerValue timestamp]}
- };
- __block BOOL done = NO;
- [node onDisconnectSetValue:data
- andPriority:[FIRServerValue timestamp]
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- done = NO;
- [node onDisconnectUpdateChildValues:@{
- @"a" : [FIRServerValue timestamp],
- @"c" : [FIRServerValue timestamp]
- }
- withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- done = NO;
- [FRepoManager interrupt:writerCfg];
- [self waitUntil:^BOOL {
- if ([snap value] != [NSNull null]) {
- NSDictionary *val = [snap value];
- done = (val[@"a"] && val[@"b"] && val[@"c"]);
- }
- return done;
- }];
- NSDictionary *value = [snap value];
- NSNumber *now = [NSNumber numberWithDouble:round([[NSDate date] timeIntervalSince1970] * 1000)];
- NSNumber *timestamp = [snap priority];
- XCTAssertTrue([[snap priority] isKindOfClass:[NSNumber class]], @"Should get back number");
- XCTAssertTrue([now doubleValue] - [timestamp doubleValue] < 2000,
- @"Number should be no more than 2 seconds ago");
- XCTAssertEqualObjects([snap priority], [value objectForKey:@"a"],
- @"Should get back matching ServerValue.TIMESTAMP");
- XCTAssertEqualObjects([snap priority], [value objectForKey:@"b"],
- @"Should get back matching ServerValue.TIMESTAMP");
- XCTAssertEqualObjects([snap priority], [[snap childSnapshotForPath:@"b"] priority],
- @"Should get back matching ServerValue.TIMESTAMP");
- XCTAssertEqualObjects([NSNull null], [[snap childSnapshotForPath:@"d"] value],
- @"Should get null for cancelled child");
- // cleanup
- [FRepoManager disposeRepos:writerCfg];
- }
- @end
|