| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589 |
- /*
- * 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 "FEventTests.h"
- #import "FEventTester.h"
- #import "FTestHelpers.h"
- #import "FTupleEventTypeString.h"
- @implementation FEventTests
- - (void)testInvalidEventType {
- FIRDatabaseReference* f = [FTestHelpers getRandomNode];
- XCTAssertThrows([f observeEventType:-4
- withBlock:^(FIRDataSnapshot* s){
- }],
- @"Invalid event type properly throws an error");
- }
- - (void)testWriteLeafExpectValueChanged {
- FTupleFirebase* tuple = [FTestHelpers getRandomNodePair];
- FIRDatabaseReference* writeNode = tuple.one;
- FIRDatabaseReference* readNode = tuple.two;
- __block BOOL done = NO;
- [writeNode setValue:@1234
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- [super snapWaiter:readNode
- withBlock:^(FIRDataSnapshot* s) {
- XCTAssertEqualObjects([s value], @1234, @"Proper value in snapshot");
- }];
- }
- - (void)testWRiteLeafNodeThenExpectValueEvent {
- FIRDatabaseReference* writeNode = [FTestHelpers getRandomNode];
- [writeNode setValue:@42];
- [super snapWaiter:writeNode
- withBlock:^(FIRDataSnapshot* s) {
- XCTAssertEqualObjects([s value], @42, @"Proper value in snapshot");
- }];
- }
- - (void)testWriteLeafNodeThenExpectChildAddedEventThenValueEvent {
- FIRDatabaseReference* writeNode = [FTestHelpers getRandomNode];
- [[writeNode child:@"foo"] setValue:@878787];
- NSArray* lookingFor = @[
- [[FTupleEventTypeString alloc] initWithFirebase:writeNode
- withEvent:FIRDataEventTypeChildAdded
- withString:@"foo"],
- [[FTupleEventTypeString alloc] initWithFirebase:writeNode
- withEvent:FIRDataEventTypeValue
- withString:nil],
- ];
- FEventTester* et = [[FEventTester alloc] initFrom:self];
- [et addLookingFor:lookingFor];
- [et wait];
- [super snapWaiter:writeNode
- withBlock:^(FIRDataSnapshot* s) {
- XCTAssertEqualObjects([[s childSnapshotForPath:@"foo"] value], @878787,
- @"Got proper value");
- }];
- }
- - (void)testSetMultipleEventListenersOnSameNode {
- FTupleFirebase* tuple = [FTestHelpers getRandomNodePair];
- FIRDatabaseReference* writeNode = tuple.one;
- FIRDatabaseReference* readNode = tuple.two;
- [writeNode setValue:@42];
- // two write nodes
- FEventTester* et = [[FEventTester alloc] initFrom:self];
- [et addLookingFor:@[ [[FTupleEventTypeString alloc] initWithFirebase:writeNode
- withEvent:FIRDataEventTypeValue
- withString:nil] ]];
- [et wait];
- et = [[FEventTester alloc] initFrom:self];
- [et addLookingFor:@[ [[FTupleEventTypeString alloc] initWithFirebase:writeNode
- withEvent:FIRDataEventTypeValue
- withString:nil] ]];
- [et wait];
- // two read nodes
- et = [[FEventTester alloc] initFrom:self];
- [et addLookingFor:@[ [[FTupleEventTypeString alloc] initWithFirebase:readNode
- withEvent:FIRDataEventTypeValue
- withString:nil] ]];
- [et wait];
- et = [[FEventTester alloc] initFrom:self];
- [et addLookingFor:@[ [[FTupleEventTypeString alloc] initWithFirebase:readNode
- withEvent:FIRDataEventTypeValue
- withString:nil] ]];
- [et wait];
- }
- - (void)testUnsubscribeEventsAndConfirmThatEventsNoLongerFire {
- FIRDatabaseReference* node = [FTestHelpers getRandomNode];
- __block int numValueCB = 0;
- FIRDatabaseHandle handle = [node observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot* s) {
- numValueCB = numValueCB + 1;
- }];
- // Set
- for (int i = 0; i < 3; i++) {
- [node setValue:[NSNumber numberWithInt:i]];
- }
- // bye
- [node removeObserverWithHandle:handle];
- // set again
- for (int i = 10; i < 15; i++) {
- [node setValue:[NSNumber numberWithInt:i]];
- }
- for (int i = 20; i < 25; i++) {
- [node setValue:[NSNumber numberWithInt:i]];
- }
- // Should just be 3
- [self waitUntil:^BOOL {
- return numValueCB == 3;
- }];
- }
- - (void)testCanWriteACompoundObjectAndGetMoreGranularEventsForIndividualChanges {
- FTupleFirebase* tuple = [FTestHelpers getRandomNodePair];
- FIRDatabaseReference* writeNode = tuple.one;
- FIRDatabaseReference* readNode = tuple.two;
- __block BOOL done = NO;
- [writeNode setValue:@{@"a" : @10, @"b" : @20}
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- NSArray* lookingForW = @[
- [[FTupleEventTypeString alloc] initWithFirebase:[writeNode child:@"a"]
- withEvent:FIRDataEventTypeValue
- withString:nil],
- [[FTupleEventTypeString alloc] initWithFirebase:[writeNode child:@"b"]
- withEvent:FIRDataEventTypeValue
- withString:nil],
- ];
- NSArray* lookingForR = @[
- [[FTupleEventTypeString alloc] initWithFirebase:[readNode child:@"a"]
- withEvent:FIRDataEventTypeValue
- withString:nil],
- [[FTupleEventTypeString alloc] initWithFirebase:[readNode child:@"b"]
- withEvent:FIRDataEventTypeValue
- withString:nil],
- ];
- FEventTester* etW = [[FEventTester alloc] initFrom:self];
- [etW addLookingFor:lookingForW];
- [etW wait];
- FEventTester* etR = [[FEventTester alloc] initFrom:self];
- [etR addLookingFor:lookingForR];
- [etR wait];
- // Modify compound but just change one of them
- lookingForW = @[ [[FTupleEventTypeString alloc] initWithFirebase:[writeNode child:@"b"]
- withEvent:FIRDataEventTypeValue
- withString:nil] ];
- lookingForR = @[ [[FTupleEventTypeString alloc] initWithFirebase:[readNode child:@"b"]
- withEvent:FIRDataEventTypeValue
- withString:nil] ];
- [etW addLookingFor:lookingForW];
- [etR addLookingFor:lookingForR];
- [writeNode setValue:@{@"a" : @10, @"b" : @30}];
- [etW wait];
- [etR wait];
- }
- - (void)testValueEventIsFiredForEmptyNode {
- FIRDatabaseReference* node = [FTestHelpers getRandomNode];
- __block BOOL valueFired = NO;
- [node observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot* s) {
- XCTAssertTrue([[s value] isEqual:[NSNull null]], @"Value is properly nil");
- valueFired = YES;
- }];
- [self waitUntil:^BOOL {
- return valueFired;
- }];
- }
- - (void)testCorrectEventsRaisedWhenLeafTurnsIntoInternalNode {
- FIRDatabaseReference* node = [FTestHelpers getRandomNode];
- NSMutableString* eventString = [[NSMutableString alloc] init];
- [node observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot* s) {
- if ([s hasChildren]) {
- [eventString appendString:@", got children"];
- } else {
- [eventString appendFormat:@", value %@", [s value]];
- }
- }];
- [node observeEventType:FIRDataEventTypeChildAdded
- withBlock:^(FIRDataSnapshot* s) {
- [eventString appendFormat:@", child_added %@", [s key]];
- }];
- [node setValue:@42];
- [node setValue:@{@"a" : @2}];
- [node setValue:@84];
- __block BOOL done = NO;
- [node setValue:nil
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- XCTAssertEqualObjects(@", value 42, child_added a, got children, value 84, value <null>",
- eventString, @"Proper order seen");
- }
- - (void)testRegisteringCallbackMultipleTimesAndUnregistering {
- FIRDatabaseReference* node = [FTestHelpers getRandomNode];
- __block int changes = 0;
- fbt_void_datasnapshot cb = ^(FIRDataSnapshot* snapshot) {
- changes = changes + 1;
- };
- FIRDatabaseHandle handle1 = [node observeEventType:FIRDataEventTypeValue withBlock:cb];
- FIRDatabaseHandle handle2 = [node observeEventType:FIRDataEventTypeValue withBlock:cb];
- FIRDatabaseHandle handle3 = [node observeEventType:FIRDataEventTypeValue withBlock:cb];
- __block BOOL done = NO;
- [node setValue:@42
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- done = NO;
- XCTAssertTrue(changes == 3, @"Saw 3 callback events %d", changes);
- [node removeObserverWithHandle:handle1];
- [node setValue:@84
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- done = NO;
- XCTAssertTrue(changes == 5, @"Saw 5 callback events %d", changes);
- [node removeObserverWithHandle:handle2];
- [node setValue:@168
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- done = NO;
- XCTAssertTrue(changes == 6, @"Saw 6 callback events %d", changes);
- [node removeObserverWithHandle:handle3];
- [node setValue:@376
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- done = NO;
- XCTAssertTrue(changes == 6, @"Saw 6 callback events %d", changes);
- NSLog(@"callbacks: %d", changes);
- }
- - (void)testUnregisteringTheSameCallbackTooManyTimesDoesNothing {
- FIRDatabaseReference* node = [FTestHelpers getRandomNode];
- fbt_void_datasnapshot cb = ^(FIRDataSnapshot* snapshot) {
- };
- FIRDatabaseHandle handle1 = [node observeEventType:FIRDataEventTypeValue withBlock:cb];
- [node removeObserverWithHandle:handle1];
- [node removeObserverWithHandle:handle1];
- XCTAssertTrue(YES, @"Properly reached end of test without throwing errors.");
- }
- - (void)testOnceValueFiresExactlyOnce {
- FIRDatabaseReference* path = [FTestHelpers getRandomNode];
- __block BOOL firstCall = YES;
- [path observeSingleEventOfType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot* snapshot) {
- XCTAssertTrue(firstCall, @"Properly saw first call");
- firstCall = NO;
- XCTAssertEqualObjects(@42, [snapshot value], @"Properly saw node value");
- }];
- [path setValue:@42];
- [path setValue:@84];
- __block BOOL done = NO;
- [path setValue:nil
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- }
- - (void)testOnceChildAddedFiresExaclyOnce {
- __block int badCount = 0;
- // for(int i = 0; i < 100; i++) {
- FIRDatabaseReference* path = [FTestHelpers getRandomNode];
- __block BOOL firstCall = YES;
- __block BOOL done = NO;
- [path observeSingleEventOfType:FIRDataEventTypeChildAdded
- withBlock:^(FIRDataSnapshot* snapshot) {
- XCTAssertTrue(firstCall, @"Properly saw first call");
- firstCall = NO;
- XCTAssertEqualObjects(@42, [snapshot value], @"Properly saw node value");
- XCTAssertEqualObjects(@"foo", [snapshot key],
- @"Properly saw the first node");
- if (![[snapshot value] isEqual:@42]) {
- exit(-1);
- badCount = badCount + 1;
- }
- done = YES;
- }];
- [[path child:@"foo"] setValue:@42];
- [[path child:@"bar"] setValue:@84]; // XXX FIXME sometimes this event fires first
- [[path child:@"foo"] setValue:@168];
- // [path setValue:nil withCompletionBlock:^(BOOL status) { done = YES; }];
- [self waitUntil:^BOOL {
- return done;
- }];
- // }
- NSLog(@"BADCOUNT: %d", badCount);
- }
- - (void)testOnceValueFiresExacltyOnceEvenIfThereIsASetInsideCallback {
- FIRDatabaseReference* path = [FTestHelpers getRandomNode];
- __block BOOL firstCall = YES;
- __block BOOL done = NO;
- [path observeSingleEventOfType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot* snapshot) {
- XCTAssertTrue(firstCall, @"Properly saw first call");
- if (firstCall) {
- firstCall = NO;
- XCTAssertEqualObjects(@42, [snapshot value], @"Properly saw node value");
- [path setValue:@43];
- done = YES;
- } else {
- XCTFail(@"Callback got called more than once.");
- }
- }];
- [path setValue:@42];
- [path setValue:@84];
- [self waitUntil:^BOOL {
- return done;
- }];
- }
- - (void)testOnceChildAddedFiresOnceEvenWithCompoundObject {
- FIRDatabaseReference* path = [FTestHelpers getRandomNode];
- __block BOOL firstCall = YES;
- [path observeSingleEventOfType:FIRDataEventTypeChildAdded
- withBlock:^(FIRDataSnapshot* snapshot) {
- XCTAssertTrue(firstCall, @"Properly saw first call");
- firstCall = NO;
- XCTAssertEqualObjects(@84, [snapshot value], @"Properly saw node value");
- XCTAssertEqualObjects(@"bar", [snapshot key],
- @"Properly saw the first node");
- }];
- [path setValue:@{@"foo" : @42, @"bar" : @84}];
- __block BOOL done = NO;
- [path setValue:nil
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- }
- - (void)testOnEmptyChildFires {
- FIRDatabaseReference* node = [FTestHelpers getRandomNode];
- __block BOOL done = NO;
- [node observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot* snapshot){
- }];
- [[node child:@"test"] observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot* snapshot) {
- XCTAssertTrue([[snapshot value] isEqual:[NSNull null]],
- @"Properly saw nil child node");
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- }
- - (void)testOnEmptyChildEvenAfterParentIsSynched {
- FIRDatabaseReference* node = [FTestHelpers getRandomNode];
- __block BOOL parentDone = NO;
- __block BOOL done = NO;
- [node observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot* snapshot) {
- parentDone = YES;
- }];
- [self waitUntil:^BOOL {
- return parentDone;
- }];
- [[node child:@"test"]
- observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot* snapshot) {
- XCTAssertTrue([[snapshot value] isEqual:[NSNull null]], @"Child is properly nil");
- done = YES;
- }];
- // This test really isn't in the same spirit as the JS test; we can't currently make sure that the
- // test fires right away since the ON and callback are async
- [self waitUntil:^BOOL {
- return done;
- }];
- XCTAssertTrue(done, @"Done fired.");
- }
- - (void)testEventsAreRaisedChildRemovedChildAddedChildMoved {
- FIRDatabaseReference* node = [FTestHelpers getRandomNode];
- NSMutableArray* events = [[NSMutableArray alloc] init];
- [node observeEventType:FIRDataEventTypeChildAdded
- withBlock:^(FIRDataSnapshot* snap) {
- [events addObject:[NSString stringWithFormat:@"added %@", [snap key]]];
- }];
- [node observeEventType:FIRDataEventTypeChildRemoved
- withBlock:^(FIRDataSnapshot* snap) {
- [events addObject:[NSString stringWithFormat:@"removed %@", [snap key]]];
- }];
- [node observeEventType:FIRDataEventTypeChildMoved
- withBlock:^(FIRDataSnapshot* snap) {
- [events addObject:[NSString stringWithFormat:@"moved %@", [snap key]]];
- }];
- __block BOOL done = NO;
- [node setValue:@{
- @"a" : @{@".value" : @1, @".priority" : @0},
- @"b" : @{@".value" : @1, @".priority" : @1},
- @"c" : @{@".value" : @1, @".priority" : @2},
- @"d" : @{@".value" : @1, @".priority" : @3},
- @"e" : @{@".value" : @1, @".priority" : @4},
- @"f" : @{@".value" : @1, @".priority" : @5},
- }
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- [events removeAllObjects];
- done = NO;
- [node setValue:@{
- @"a" : @{@".value" : @1, @".priority" : @5},
- @"aa" : @{@".value" : @1, @".priority" : @0},
- @"b" : @{@".value" : @1, @".priority" : @1},
- @"bb" : @{@".value" : @1, @".priority" : @2},
- @"d" : @{@".value" : @1, @".priority" : @3},
- @"e" : @{@".value" : @1, @".priority" : @6},
- }
- withCompletionBlock:^(NSError* error, FIRDatabaseReference* ref) {
- done = YES;
- }];
- [self waitUntil:^BOOL {
- return done;
- }];
- XCTAssertEqualObjects(@"removed c, removed f, added aa, added bb, moved a, moved e",
- [events componentsJoinedByString:@", "], @"Got expected results");
- }
- - (void)testIntegerToDoubleConversions {
- FIRDatabaseReference* node = [FTestHelpers getRandomNode];
- NSMutableArray<NSString*>* events = [[NSMutableArray alloc] init];
- [node observeEventType:FIRDataEventTypeValue
- withBlock:^(FIRDataSnapshot* snap) {
- [events addObject:[NSString stringWithFormat:@"value %@", [snap value]]];
- }];
- for (NSNumber* number in @[ @1, @1.0, @1, @1.1 ]) {
- [self waitForCompletionOf:node setValue:number];
- }
- XCTAssertEqualObjects(@"value 1, value 1.1", [events componentsJoinedByString:@", "],
- @"Got expected results");
- }
- - (void)testEventsAreRaisedProperlyWithOnQueryLimits {
- // xxx impl query
- }
- @end
|