diff options
Diffstat (limited to 'Example/Database/Tests/Integration/FOrder.m')
-rw-r--r-- | Example/Database/Tests/Integration/FOrder.m | 646 |
1 files changed, 646 insertions, 0 deletions
diff --git a/Example/Database/Tests/Integration/FOrder.m b/Example/Database/Tests/Integration/FOrder.m new file mode 100644 index 0000000..e8c628b --- /dev/null +++ b/Example/Database/Tests/Integration/FOrder.m @@ -0,0 +1,646 @@ +/* + * 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 "FOrder.h" +#import "FIRDatabaseReference.h" +#import "FTypedefs_Private.h" +#import "FTupleFirebase.h" +#import "FTestHelpers.h" +#import "FEventTester.h" +#import "FTupleEventTypeString.h" + +@implementation FOrder + +- (void) testPushEnumerateAndCheckCorrectOrder { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + for(int i = 0; i < 10; i++) { + [[node childByAutoId] setValue:[NSNumber numberWithInt:i]]; + } + + [super snapWaiter:node withBlock:^(FIRDataSnapshot * snapshot) { + int expected = 0; + for (FIRDataSnapshot * child in snapshot.children) { + XCTAssertEqualObjects([NSNumber numberWithInt:expected], [child value], @"Expects values match."); + expected = expected + 1; + } + XCTAssertTrue(expected == 10, @"Should get all of the children"); + XCTAssertTrue(expected == snapshot.childrenCount, @"Snapshot should report correct count"); + }]; +} + +- (void) testPushEnumerateManyPathsWriteAndCheckOrder { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + NSMutableArray* paths = [[NSMutableArray alloc] init]; + + for(int i = 0; i < 20; i++) { + [paths addObject:[node childByAutoId]]; + } + + for(int i = 0; i < 20; i++) { + [(FIRDatabaseReference *)[paths objectAtIndex:i] setValue:[NSNumber numberWithInt:i]]; + } + + [super snapWaiter:node withBlock:^(FIRDataSnapshot *snap) { + int expected = 0; + for (FIRDataSnapshot * child in snap.children) { + XCTAssertEqualObjects([NSNumber numberWithInt:expected], [child value], @"Expects values match."); + expected = expected + 1; + } + XCTAssertTrue(expected == 20, @"Should get all of the children"); + XCTAssertTrue(expected == snap.childrenCount, @"Snapshot should report correct count"); + }]; +} + +- (void) testPushDataReconnectReadBackAndVerifyOrder { + + FTupleFirebase* tuple = [FTestHelpers getRandomNodePair]; + + __block int expected = 0; + __block int nodesSet = 0; + FIRDatabaseReference * node = tuple.one; + for(int i = 0; i < 10; i++) { + [[node childByAutoId] setValue:[NSNumber numberWithInt:i] withCompletionBlock:^(NSError* err, FIRDatabaseReference * ref) { + nodesSet++; + }]; + } + + [self waitUntil:^BOOL{ + return nodesSet == 10; + }]; + + __block BOOL done = NO; + [super snapWaiter:node withBlock:^(FIRDataSnapshot *snap) { + expected = 0; + //[snap forEach:^BOOL(FIRDataSnapshot *child) { + for (FIRDataSnapshot * child in snap.children) { + XCTAssertEqualObjects([NSNumber numberWithInt:expected], [child value], @"Expected child value"); + expected = expected + 1; + //return NO; + } + done = YES; + }]; + + [self waitUntil:^BOOL{ + return done; + }]; + + done = NO; + + XCTAssertTrue(nodesSet == 10, @"All of the nodes have been set"); + + [super snapWaiter:tuple.two withBlock:^(FIRDataSnapshot *snap) { + expected = 0; + for (FIRDataSnapshot * child in snap.children) { + XCTAssertEqualObjects([NSNumber numberWithInt:expected], [child value], @"Expected child value"); + expected = expected + 1; + } + done = YES; + XCTAssertTrue(expected == 10, @"Saw the expected number of children %d == 10", expected); + }]; + +} + +- (void) testPushDataWithPrioritiesReconnectReadBackAndVerifyOrder { + FTupleFirebase* tuple = [FTestHelpers getRandomNodePair]; + + __block int expected = 0; + __block int nodesSet = 0; + FIRDatabaseReference * node = tuple.one; + for(int i = 0; i < 10; i++) { + [[node childByAutoId] setValue:[NSNumber numberWithInt:i] andPriority:[NSNumber numberWithInt:(10 - i)] withCompletionBlock:^(NSError* error, FIRDatabaseReference * ref) { + nodesSet = nodesSet + 1; + }]; + } + + [super snapWaiter:node withBlock:^(FIRDataSnapshot *snap) { + expected = 9; + + for (FIRDataSnapshot * child in snap.children) { + XCTAssertEqualObjects([child value], [NSNumber numberWithInt:expected], @"Expected child value as per priority"); + expected = expected - 1; + } + XCTAssertTrue(expected == -1, @"Saw the expected number of children"); + }]; + + [self waitUntil:^BOOL{ + return nodesSet == 10; + }]; + + XCTAssertTrue(nodesSet == 10, @"All of the nodes have been set"); + + [super snapWaiter:tuple.two withBlock:^(FIRDataSnapshot *snap) { + expected = 9; + for (FIRDataSnapshot * child in snap.children) { + XCTAssertEqualObjects([child value], [NSNumber numberWithInt:expected], @"Expected child value as per priority"); + expected = expected - 1; + } + XCTAssertTrue(expected == -1, @"Saw the expected number of children"); + }]; +} + +- (void) testPushDataWithExponentialPrioritiesReconnectReadBackAndVerifyOrder { + FTupleFirebase* tuple = [FTestHelpers getRandomNodePair]; + + __block int expected = 0; + __block int nodesSet = 0; + FIRDatabaseReference * node = tuple.one; + for(int i = 0; i < 10; i++) { + [[node childByAutoId] setValue:[NSNumber numberWithInt:i] andPriority:[NSNumber numberWithDouble:(111111111111111111111111111111.0 / pow(10, i))] withCompletionBlock:^(NSError* error, FIRDatabaseReference * ref) { + nodesSet = nodesSet + 1; + }]; + } + + [super snapWaiter:node withBlock:^(FIRDataSnapshot *snap) { + expected = 9; + + for (FIRDataSnapshot * child in snap.children) { + XCTAssertEqualObjects([child value], [NSNumber numberWithInt:expected], @"Expected child value as per priority"); + expected = expected - 1; + } + XCTAssertTrue(expected == -1, @"Saw the expected number of children"); + }]; + + WAIT_FOR(nodesSet == 10); + + [super snapWaiter:tuple.two withBlock:^(FIRDataSnapshot *snap) { + expected = 9; + for (FIRDataSnapshot * child in snap.children) { + XCTAssertEqualObjects([child value], [NSNumber numberWithInt:expected], @"Expected child value as per priority"); + expected = expected - 1; + } + XCTAssertTrue(expected == -1, @"Saw the expected number of children"); + }]; +} + +- (void) testThatNodesWithoutValuesAreNotEnumerated { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + [node child:@"foo"]; + [[node child:@"bar"] setValue:@"test"]; + + __block int items = 0; + [super snapWaiter:node withBlock:^(FIRDataSnapshot *snap) { + + for (FIRDataSnapshot * child in snap.children) { + items = items + 1; + XCTAssertEqualObjects([child key], @"bar", @"Saw the child which had a value set and not the empty one"); + } + + XCTAssertTrue(items == 1, @"Saw only the one that was actually set."); + }]; +} + +- (void) testChildMovedEventWhenPriorityChanges { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + FEventTester* et = [[FEventTester alloc] initFrom:self]; + + NSArray* expect = @[ + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeChildAdded withString:@"a"], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeValue withString:nil], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeChildAdded withString:@"b"], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeValue withString:nil], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeChildAdded withString:@"c"], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeValue withString:nil], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeChildMoved withString:@"a"], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeChildChanged withString:@"a"], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeValue withString:nil] + ]; + + [et addLookingFor:expect]; + + [et waitForInitialization]; + + [[node child:@"a"] setValue:@"first" andPriority:@1]; + [[node child:@"b"] setValue:@"second" andPriority:@2]; + [[node child:@"c"] setValue:@"third" andPriority:@3]; + + [[node child:@"a"] setPriority:@15]; + + [et wait]; +} + + +- (void) testCanResetPriorityToNull { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + [[node child:@"a"] setValue:@"a" andPriority:@1]; + [[node child:@"b"] setValue:@"b" andPriority:@2]; + + FEventTester* et = [[FEventTester alloc] initFrom:self]; + NSArray* expect = @[ + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeChildAdded withString:@"a"], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeChildAdded withString:@"b"], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeValue withString:nil] + ]; + + [et addLookingFor:expect]; + + [et wait]; + + expect = @[ + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeChildMoved withString:@"b"], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeChildChanged withString:@"b"], + [[FTupleEventTypeString alloc] initWithFirebase:node withEvent:FIRDataEventTypeValue withString:nil] + ]; + + [et addLookingFor:expect]; + + [[node child:@"b"] setPriority:nil]; + + [et wait]; + + __block BOOL ready = NO; + [[node child:@"b"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { + XCTAssertTrue([snapshot priority] == [NSNull null], @"Should be null"); + ready = YES; + }]; + + [self waitUntil:^BOOL{ + return ready; + }]; +} + +- (void) testInsertingANodeUnderALeafPreservesItsPriority { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + __block FIRDataSnapshot * snap; + [node observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *s) { + snap = s; + }]; + + [node setValue:@"a" andPriority:@10]; + [[node child:@"deeper"] setValue:@"deeper"]; + + [self waitUntil:^BOOL{ + id result = [snap value]; + NSDictionary* expected = @{@"deeper": @"deeper"}; + return snap != nil && [result isKindOfClass:[NSDictionary class]] && [result isEqualToDictionary:expected]; + }]; + + XCTAssertEqualObjects([snap priority], @10, @"Proper value"); +} + +- (void) testVerifyOrderOfMixedNumbersStringNoPriorities { + FTupleFirebase* tuple = [FTestHelpers getRandomNodePair]; + + NSArray* nodeAndPriorities = @[ + @"alpha42", @"zed", + @"noPriorityC", [NSNull null], + @"num41", @500, + @"noPriorityB", [NSNull null], + @"num80", @4000.1, + @"num50", @4000, + @"num10", @24, + @"alpha41", @"zed", + @"alpha20", @"horse", + @"num20", @123, + @"num70", @4000.01, + @"noPriorityA", [NSNull null], + @"alpha30", @"tree", + @"num30", @300, + @"num60", @4000.001, + @"alpha10", @"0horse", + @"num42", @500, + @"alpha40", @"zed", + @"num40", @500 + ]; + + __block int setsCompleted = 0; + + for (int i = 0; i < [nodeAndPriorities count]; i++) { + FIRDatabaseReference * n = [tuple.one child:[nodeAndPriorities objectAtIndex:i++]]; + [n setValue:@1 andPriority:[nodeAndPriorities objectAtIndex:i] withCompletionBlock:^(NSError* error, FIRDatabaseReference * ref) { + setsCompleted = setsCompleted + 1; + }]; + } + + NSString* expected = @"noPriorityA, noPriorityB, noPriorityC, num10, num20, num30, num40, num41, num42, num50, num60, num70, num80, alpha10, alpha20, alpha30, alpha40, alpha41, alpha42, "; + + [super snapWaiter:tuple.one withBlock:^(FIRDataSnapshot *snap) { + NSMutableString* output = [[NSMutableString alloc] init]; + for (FIRDataSnapshot * n in snap.children) { + [output appendFormat:@"%@, ", [n key]]; + } + + XCTAssertTrue([expected isEqualToString:output], @"Proper order"); + }]; + + WAIT_FOR(setsCompleted == [nodeAndPriorities count] / 2); + + [super snapWaiter:tuple.two withBlock:^(FIRDataSnapshot *snap) { + NSMutableString* output = [[NSMutableString alloc] init]; + for (FIRDataSnapshot * n in snap.children) { + [output appendFormat:@"%@, ", [n key]]; + } + + XCTAssertTrue([expected isEqualToString:output], @"Proper order"); + }]; +} + +- (void) testVerifyOrderOfIntegerNames { + FIRDatabaseReference * ref = [FTestHelpers getRandomNode]; + + NSArray* keys = @[ + @"foo", + @"bar", + @"03", + @"0", + @"100", + @"20", + @"5", + @"3", + @"003", + @"9" + ]; + + __block int setsCompleted = 0; + + for (int i = 0; i < [keys count]; i++) { + FIRDatabaseReference * n = [ref child:[keys objectAtIndex:i]]; + [n setValue:@1 withCompletionBlock:^(NSError* error, FIRDatabaseReference * ref) { + setsCompleted = setsCompleted + 1; + }]; + } + + NSString* expected = @"0, 3, 03, 003, 5, 9, 20, 100, bar, foo, "; + + [super snapWaiter:ref withBlock:^(FIRDataSnapshot *snap) { + NSMutableString* output = [[NSMutableString alloc] init]; + for (FIRDataSnapshot * n in snap.children) { + [output appendFormat:@"%@, ", [n key]]; + } + + XCTAssertTrue([expected isEqualToString:output], @"Proper order"); + }]; +} + +- (void) testPrevNameIsCorrectOnChildAddedEvent { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + [node setValue:@{@"a": @1, @"b": @2, @"c": @3}]; + + + NSMutableString* added = [[NSMutableString alloc] init]; + + __block int count = 0; + [node observeEventType:FIRDataEventTypeChildAdded andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snap, NSString *prevName) { + [added appendFormat:@"%@ %@, ", [snap key], prevName]; + count++; + }]; + + [self waitUntil:^BOOL{ + return count == 3; + }]; + + XCTAssertTrue([added isEqualToString:@"a (null), b a, c b, "], @"Proper order and prevname"); + +} + +- (void) testPrevNameIsCorrectWhenAddingNewNodes { + + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + [node setValue:@{@"b": @2, @"c": @3, @"d": @4}]; + + NSMutableString* added = [[NSMutableString alloc] init]; + + __block int count = 0; + [node observeEventType:FIRDataEventTypeChildAdded andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snap, NSString *prevName) { + [added appendFormat:@"%@ %@, ", [snap key], prevName]; + count++; + }]; + + [self waitUntil:^BOOL{ + return count == 3; + }]; + + XCTAssertTrue([added isEqualToString:@"b (null), c b, d c, "], @"Proper order and prevname"); + + [added setString:@""]; + [[node child:@"a"] setValue:@1]; + [self waitUntil:^BOOL{ + return count == 4; + }]; + + XCTAssertTrue([added isEqualToString:@"a (null), "], @"Proper insertion of new node"); + + [added setString:@""]; + [[node child:@"e"] setValue:@5]; + [self waitUntil:^BOOL{ + return count == 5; + }]; + XCTAssertTrue([added isEqualToString:@"e d, "], @"Proper insertion of new node"); +} + +- (void) testPrevNameIsCorrectWhenAddingNewNodesWithJSON { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + [node setValue:@{@"b": @2, @"c": @3, @"d": @4}]; + + NSMutableString* added = [[NSMutableString alloc] init]; + __block int count = 0; + [node observeEventType:FIRDataEventTypeChildAdded andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snap, NSString *prevName) { + [added appendFormat:@"%@ %@, ", [snap key], prevName]; + count++; + }]; + + [self waitUntil:^BOOL{ + return count == 3; + }]; + + XCTAssertTrue([added isEqualToString:@"b (null), c b, d c, "], @"Proper order and prevname"); + + [added setString:@""]; + [node setValue:@{@"a": @1, @"b": @2, @"c": @3, @"d": @4}]; + [self waitUntil:^BOOL{ + return count == 4; + }]; + + XCTAssertTrue([added isEqualToString:@"a (null), "], @"Proper insertion of new node"); + + [added setString:@""]; + [node setValue:@{@"a": @1, @"b": @2, @"c": @3, @"d": @4, @"e": @5}]; + [self waitUntil:^BOOL{ + return count == 5; + }]; + + XCTAssertTrue([added isEqualToString:@"e d, "], @"Proper insertion of new node"); +} + +- (void) testPrevNameIsCorrectWhenMovingNodes { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + NSMutableString* moved = [[NSMutableString alloc] init]; + + __block int count = 0; + [node observeEventType:FIRDataEventTypeChildMoved andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, NSString *prevName) { + [moved appendFormat:@"%@ %@, ", snapshot.key, prevName]; + count++; + }]; + + [[node child:@"a"] setValue:@"a" andPriority:@1]; + [[node child:@"b"] setValue:@"a" andPriority:@2]; + [[node child:@"c"] setValue:@"a" andPriority:@3]; + [[node child:@"d"] setValue:@"a" andPriority:@4]; + + [[node child:@"d"] setPriority:@0]; + [self waitUntil:^BOOL{ + return count == 1; + }]; + + XCTAssertTrue([moved isEqualToString:@"d (null), "], @"Got first move"); + + [moved setString:@""]; + [[node child:@"a"] setPriority:@4]; + [self waitUntil:^BOOL{ + return count == 2; + }]; + + XCTAssertTrue([moved isEqualToString:@"a c, "], @"Got second move"); + + [moved setString:@""]; + [[node child:@"c"] setPriority:@0.5]; + [self waitUntil:^BOOL{ + return count == 3; + }]; + + XCTAssertTrue([moved isEqualToString:@"c d, "], @"Got third move"); +} + + +- (void) testPrevNameIsCorrectWhenSettingWholeJsonDict { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + NSMutableString* moved = [[NSMutableString alloc] init]; + + __block int count = 0; + [node observeEventType:FIRDataEventTypeChildMoved andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, NSString *prevName) { + [moved appendFormat:@"%@ %@, ", snapshot.key, prevName]; + count++; + }]; + + [node setValue:@{ + @"a": @{@".value": @"a", @".priority": @1}, + @"b": @{@".value": @"b", @".priority": @2}, + @"c": @{@".value": @"c", @".priority": @3}, + @"d": @{@".value": @"d", @".priority": @4} + }]; + + [node setValue:@{ + @"d": @{@".value": @"d", @".priority": @0}, + @"a": @{@".value": @"a", @".priority": @1}, + @"b": @{@".value": @"b", @".priority": @2}, + @"c": @{@".value": @"c", @".priority": @3} + }]; + [self waitUntil:^BOOL{ + return count == 1; + }]; + + XCTAssertTrue([moved isEqualToString:@"d (null), "], @"Got move"); + + [moved setString:@""]; + + [node setValue:@{ + @"d": @{@".value": @"d", @".priority": @0}, + @"b": @{@".value": @"b", @".priority": @2}, + @"c": @{@".value": @"c", @".priority": @3}, + @"a": @{@".value": @"a", @".priority": @4} + }]; + + [self waitUntil:^BOOL{ + return count == 2; + }]; + + XCTAssertTrue([moved isEqualToString:@"a c, "], @"Got move"); + + [moved setString:@""]; + + [node setValue:@{ + @"d": @{@".value": @"d", @".priority": @0}, + @"c": @{@".value": @"c", @".priority": @0.5}, + @"b": @{@".value": @"b", @".priority": @2}, + @"a": @{@".value": @"a", @".priority": @4} + }]; + + [self waitUntil:^BOOL{ + return count == 3; + }]; + + XCTAssertTrue([moved isEqualToString:@"c d, "], @"Got move"); +} + +- (void) testCase595NoChildMovedEventWhenDeletingPrioritizedGrandchild { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + __block int moves = 0; + [node observeEventType:FIRDataEventTypeChildMoved withBlock:^(FIRDataSnapshot *snapshot) { + moves++; + }]; + + __block BOOL ready = NO; + [[node child:@"test/foo"] setValue:@42 andPriority:@"5"]; + [[node child:@"test/foo2"] setValue:@42 andPriority:@"10"]; + [[node child:@"test/foo"] removeValue]; + [[node child:@"test/foo"] removeValueWithCompletionBlock:^(NSError *error, FIRDatabaseReference * ref) { + ready = YES; + }]; + + [self waitUntil:^BOOL{ + return ready; + }]; + + XCTAssertTrue(moves == 0, @"Nothing should have moved"); + +} + +- (void) testCanSetAValueWithPriZero { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + __block FIRDataSnapshot * snap = nil; + [node observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *s) { + snap = s; + }]; + + [node setValue:@"test" andPriority:@0]; + + [self waitUntil:^BOOL{ + return snap != nil; + }]; + + XCTAssertEqualObjects([snap value], @"test", @"Proper value"); + XCTAssertEqualObjects([snap priority], @0, @"Proper value"); +} + +- (void) testCanSetObjectWithPriZero { + FIRDatabaseReference * node = [FTestHelpers getRandomNode]; + + __block FIRDataSnapshot * snap = nil; + [node observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *s) { + snap = s; + }]; + + [node setValue:@{@"x": @"test", @"y": @7} andPriority:@0]; + + [self waitUntil:^BOOL{ + return snap != nil; + }]; + + XCTAssertEqualObjects([[snap value] objectForKey:@"x"], @"test", @"Proper value"); + XCTAssertEqualObjects([[snap value] objectForKey:@"y"], @7, @"Proper value"); + XCTAssertEqualObjects([snap priority], @0, @"Proper value"); +} + +@end |