diff options
author | Benoit St-Pierre <ben@benoitstpierre.com> | 2018-04-19 15:56:11 -0400 |
---|---|---|
committer | Ryan Wilson <wilsonryan@google.com> | 2018-04-19 15:56:11 -0400 |
commit | 9eea8d4fc480f32d57cab344c32ebe631a083e9d (patch) | |
tree | dc8b95409edc50157a364c32121b489e6b40b9ca /Example/Core/Tests/FIRReachabilityCheckerTest.m | |
parent | 0df8378971553a203cc6982a298f342baecae543 (diff) |
Add unit tests for FirebaseCore (#751)
* Add unit tests for FIRMutableDictionary
Basic unit tests to increase overall code coverage.
* Add unit tests for FIRReachabilityChecker
Basic unit tests to increase overall test coverage.
* Add unit tests for FIRNetwork
Basic unit tests to increase overall test coverage.
This also includes a mock HTTP server to serve mock network responses
through the network stack.
* Remove +internal from imports
This was unnecessary.
* Move Example/Tests/Core/Utils files to Example/Tests/Core
This simplifies build files to include the correct dependencies
I had also missed some tvOS test fixes.
* PR Feedback
Fixed some style issues and updated GTMHTTPServer comments.
* Moved GTMHTTPServer.h into third_party directory
* Revert Firebase Xcode project for merging.
* Add tests to project file.
Diffstat (limited to 'Example/Core/Tests/FIRReachabilityCheckerTest.m')
-rw-r--r-- | Example/Core/Tests/FIRReachabilityCheckerTest.m | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/Example/Core/Tests/FIRReachabilityCheckerTest.m b/Example/Core/Tests/FIRReachabilityCheckerTest.m new file mode 100644 index 0000000..7b6b068 --- /dev/null +++ b/Example/Core/Tests/FIRReachabilityCheckerTest.m @@ -0,0 +1,365 @@ +// Copyright 2018 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 "FIRTestCase.h" + +#import <FirebaseCore/FIRReachabilityChecker+Internal.h> +#import <FirebaseCore/FIRReachabilityChecker.h> + +@interface FIRReachabilityCheckerTest : FIRTestCase <FIRReachabilityDelegate> { + @private + FIRReachabilityChecker *checker_; + NSMutableArray *statuses_; + BOOL createFail_; + BOOL setCallbackFail_; + BOOL scheduleUnscheduleFail_; +} + +- (void *)createReachabilityWithAllocator:(CFAllocatorRef)allocator withName:(const char *)hostname; +- (BOOL)reachability:(const void *)reachability + setCallback:(SCNetworkReachabilityCallBack)callback + withContext:(SCNetworkReachabilityContext *)context; +- (BOOL)scheduleReachability:(const void *)reachability + runLoop:(CFRunLoopRef)runLoop + runLoopMode:(CFStringRef)runLoopMode; +- (BOOL)unscheduleReachability:(const void *)reachability + runLoop:(CFRunLoopRef)runLoop + runLoopMode:(CFStringRef)runLoopMode; +- (void)releaseReachability:(const void *)reachability; +@end + +static NSString *const kHostname = @"www.google.com"; +static const void *kFakeReachabilityObject = (const void *)0x8badf00d; + +static FIRReachabilityCheckerTest *FakeReachabilityTest = nil; + +static struct { + int callsMade; + int createCall; + int setCallbackCall; + int scheduleCall; + int unscheduleCall; + int releaseCall; + void (*callback)(SCNetworkReachabilityRef, SCNetworkReachabilityFlags, void *info); + void *callbackInfo; +} FakeReachability; + +static SCNetworkReachabilityRef ReachabilityCreateWithName(CFAllocatorRef allocator, + const char *hostname) { + return (SCNetworkReachabilityRef) + [FakeReachabilityTest createReachabilityWithAllocator:allocator withName:hostname]; +} + +static Boolean ReachabilitySetCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityCallBack callback, + SCNetworkReachabilityContext *context) { + return [FakeReachabilityTest reachability:reachability setCallback:callback withContext:context]; +} + +static Boolean ReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef reachability, + CFRunLoopRef runLoop, + CFStringRef runLoopMode) { + return [FakeReachabilityTest scheduleReachability:reachability + runLoop:runLoop + runLoopMode:runLoopMode]; +} + +static Boolean ReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef reachability, + CFRunLoopRef runLoop, + CFStringRef runLoopMode) { + return [FakeReachabilityTest unscheduleReachability:reachability + runLoop:runLoop + runLoopMode:runLoopMode]; +} + +static void ReachabilityRelease(CFTypeRef reachability) { + [FakeReachabilityTest releaseReachability:reachability]; +} + +static const struct FIRReachabilityApi kTestReachabilityApi = { + ReachabilityCreateWithName, ReachabilitySetCallback, ReachabilityScheduleWithRunLoop, + ReachabilityUnscheduleFromRunLoop, ReachabilityRelease, +}; + +@implementation FIRReachabilityCheckerTest + +- (void)resetFakeReachability { + FakeReachabilityTest = self; + FakeReachability.callsMade = 0; + FakeReachability.createCall = -1; + FakeReachability.setCallbackCall = -1; + FakeReachability.scheduleCall = -1; + FakeReachability.unscheduleCall = -1; + FakeReachability.releaseCall = -1; + FakeReachability.callback = NULL; + FakeReachability.callbackInfo = NULL; +} + +- (void)setUp { + [super setUp]; + + [self resetFakeReachability]; + createFail_ = NO; + setCallbackFail_ = NO; + scheduleUnscheduleFail_ = NO; + + checker_ = [[FIRReachabilityChecker alloc] initWithReachabilityDelegate:self + loggerDelegate:nil + withHost:kHostname]; + statuses_ = [[NSMutableArray alloc] init]; +} + +- (void *)createReachabilityWithAllocator:(CFAllocatorRef)allocator + withName:(const char *)hostname { + XCTAssertTrue(allocator == kCFAllocatorDefault, @""); + XCTAssertEqual(strcmp(hostname, [kHostname UTF8String]), 0, @""); + XCTAssertEqual(FakeReachability.callsMade, 0, @"create call must always come first."); + XCTAssertEqual(FakeReachability.createCall, -1, @"create call must only be called once."); + FakeReachability.createCall = ++FakeReachability.callsMade; + return createFail_ ? NULL : (void *)kFakeReachabilityObject; +} + +- (BOOL)reachability:(const void *)reachability + setCallback:(SCNetworkReachabilityCallBack)callback + withContext:(SCNetworkReachabilityContext *)context { + XCTAssertEqual(reachability, kFakeReachabilityObject, @"got bad object"); + XCTAssertEqual((int)context->version, 0, @""); + XCTAssertEqual(context->info, (__bridge void *)checker_, @""); + XCTAssertEqual((void *)context->retain, NULL, @""); + XCTAssertEqual((void *)context->release, NULL, @""); + XCTAssertEqual((void *)context->copyDescription, NULL, @""); + XCTAssertEqual(FakeReachability.setCallbackCall, -1, @"setCallback should only be called once."); + FakeReachability.setCallbackCall = ++FakeReachability.callsMade; + XCTAssertTrue(callback != NULL, @""); + FakeReachability.callback = callback; + XCTAssertTrue(context->info != NULL, @""); + FakeReachability.callbackInfo = context->info; + return setCallbackFail_ ? NO : YES; +} + +- (BOOL)scheduleReachability:(const void *)reachability + runLoop:(CFRunLoopRef)runLoop + runLoopMode:(CFStringRef)runLoopMode { + XCTAssertEqual(reachability, kFakeReachabilityObject, @"got bad object"); + XCTAssertEqual(runLoop, CFRunLoopGetMain(), @"bad run loop"); + XCTAssertEqualObjects((__bridge NSString *)runLoopMode, + (__bridge NSString *)kCFRunLoopCommonModes, @"bad run loop mode"); + XCTAssertEqual(FakeReachability.scheduleCall, -1, + @"scheduleWithRunLoop should only be called once."); + FakeReachability.scheduleCall = ++FakeReachability.callsMade; + return scheduleUnscheduleFail_ ? NO : YES; +} + +- (BOOL)unscheduleReachability:(const void *)reachability + runLoop:(CFRunLoopRef)runLoop + runLoopMode:(CFStringRef)runLoopMode { + XCTAssertEqual(reachability, kFakeReachabilityObject, @"got bad object"); + XCTAssertEqual(runLoop, CFRunLoopGetMain(), @"bad run loop"); + XCTAssertEqualObjects((__bridge NSString *)runLoopMode, + (__bridge NSString *)kCFRunLoopCommonModes, @"bad run loop mode"); + XCTAssertEqual(FakeReachability.unscheduleCall, -1, + @"unscheduleFromRunLoop should only be called once."); + FakeReachability.unscheduleCall = ++FakeReachability.callsMade; + return scheduleUnscheduleFail_ ? NO : YES; +} + +- (void)releaseReachability:(const void *)reachability { + XCTAssertEqual(reachability, kFakeReachabilityObject, @"got bad object"); + XCTAssertEqual(FakeReachability.releaseCall, -1, @"release should only be called once."); + FakeReachability.releaseCall = ++FakeReachability.callsMade; +} + +- (void)reachability:(FIRReachabilityChecker *)reachability + statusChanged:(FIRReachabilityStatus)status { + [statuses_ addObject:[NSNumber numberWithInt:(int)status]]; +} + +#pragma mark - Test + +- (void)testApiHappyPath { + [checker_ setReachabilityApi:&kTestReachabilityApi]; + XCTAssertEqual([checker_ reachabilityApi], &kTestReachabilityApi, @""); + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + XCTAssertTrue([checker_ start], @""); + + XCTAssertTrue(checker_.isActive, @""); + XCTAssertEqual([statuses_ count], (NSUInteger)0, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + FakeReachability.callback(kFakeReachabilityObject, 0, FakeReachability.callbackInfo); + + XCTAssertEqual([statuses_ count], (NSUInteger)1, @""); + XCTAssertEqual([(NSNumber *)[statuses_ objectAtIndex:0] intValue], + (int)kFIRReachabilityNotReachable, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityNotReachable, @""); + + FakeReachability.callback(kFakeReachabilityObject, kSCNetworkReachabilityFlagsReachable, + FakeReachability.callbackInfo); + + XCTAssertEqual([statuses_ count], (NSUInteger)2, @""); + XCTAssertEqual([(NSNumber *)[statuses_ objectAtIndex:1] intValue], (int)kFIRReachabilityViaWifi, + @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityViaWifi, @""); + + FakeReachability.callback( + kFakeReachabilityObject, + kSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsConnectionRequired, + FakeReachability.callbackInfo); + + XCTAssertEqual([statuses_ count], (NSUInteger)3, @""); + XCTAssertEqual([(NSNumber *)[statuses_ objectAtIndex:2] intValue], + (int)kFIRReachabilityNotReachable, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityNotReachable, @""); + +#if TARGET_OS_IOS || TARGET_OS_TV + FakeReachability.callback( + kFakeReachabilityObject, + kSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsIsWWAN, + FakeReachability.callbackInfo); + + XCTAssertEqual([statuses_ count], (NSUInteger)4, @""); + XCTAssertEqual([(NSNumber *)[statuses_ objectAtIndex:3] intValue], + (int)kFIRReachabilityViaCellular, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityViaCellular, @""); + + FakeReachability.callback(kFakeReachabilityObject, kSCNetworkReachabilityFlagsIsWWAN, + FakeReachability.callbackInfo); + + XCTAssertEqual([statuses_ count], (NSUInteger)5, @""); + XCTAssertEqual([(NSNumber *)[statuses_ objectAtIndex:4] intValue], + (int)kFIRReachabilityNotReachable, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityNotReachable, @""); +#endif + + [checker_ stop]; + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + XCTAssertEqual(FakeReachability.callsMade, 5, @""); + + XCTAssertEqual(FakeReachability.createCall, 1, @""); + XCTAssertEqual(FakeReachability.setCallbackCall, 2, @""); + XCTAssertEqual(FakeReachability.scheduleCall, 3, @""); + XCTAssertEqual(FakeReachability.unscheduleCall, 4, @""); + XCTAssertEqual(FakeReachability.releaseCall, 5, @""); +} + +- (void)testApiCreateFail { + [checker_ setReachabilityApi:&kTestReachabilityApi]; + XCTAssertEqual([checker_ reachabilityApi], &kTestReachabilityApi, @""); + + createFail_ = YES; + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + XCTAssertFalse([checker_ start], @""); + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + [checker_ stop]; + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + XCTAssertEqual(FakeReachability.callsMade, 1, @""); + + XCTAssertEqual(FakeReachability.createCall, 1, @""); + XCTAssertEqual(FakeReachability.setCallbackCall, -1, @""); + XCTAssertEqual(FakeReachability.scheduleCall, -1, @""); + XCTAssertEqual(FakeReachability.unscheduleCall, -1, @""); + XCTAssertEqual(FakeReachability.releaseCall, -1, @""); + + XCTAssertEqual([statuses_ count], (NSUInteger)0, @""); +} + +- (void)testApiCallbackFail { + [checker_ setReachabilityApi:&kTestReachabilityApi]; + XCTAssertEqual([checker_ reachabilityApi], &kTestReachabilityApi, @""); + + setCallbackFail_ = YES; + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + XCTAssertFalse([checker_ start], @""); + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + [checker_ stop]; + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + XCTAssertEqual(FakeReachability.callsMade, 3, @""); + + XCTAssertEqual(FakeReachability.createCall, 1, @""); + XCTAssertEqual(FakeReachability.setCallbackCall, 2, @""); + XCTAssertEqual(FakeReachability.scheduleCall, -1, @""); + XCTAssertEqual(FakeReachability.unscheduleCall, -1, @""); + XCTAssertEqual(FakeReachability.releaseCall, 3, @""); + + XCTAssertEqual([statuses_ count], (NSUInteger)0, @""); +} + +- (void)testApiScheduleFail { + [checker_ setReachabilityApi:&kTestReachabilityApi]; + XCTAssertEqual([checker_ reachabilityApi], &kTestReachabilityApi, @""); + + scheduleUnscheduleFail_ = YES; + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + XCTAssertFalse([checker_ start], @""); + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + [checker_ stop]; + + XCTAssertFalse(checker_.isActive, @""); + XCTAssertEqual(checker_.reachabilityStatus, kFIRReachabilityUnknown, @""); + + XCTAssertEqual(FakeReachability.callsMade, 4, @""); + + XCTAssertEqual(FakeReachability.createCall, 1, @""); + XCTAssertEqual(FakeReachability.setCallbackCall, 2, @""); + XCTAssertEqual(FakeReachability.scheduleCall, 3, @""); + XCTAssertEqual(FakeReachability.unscheduleCall, -1, @""); + XCTAssertEqual(FakeReachability.releaseCall, 4, @""); + + XCTAssertEqual([statuses_ count], (NSUInteger)0, @""); +} + +- (void)testBadHost { + XCTAssertNil([[FIRReachabilityChecker alloc] + initWithReachabilityDelegate:self + loggerDelegate:(id<FIRNetworkLoggerDelegate>)self + withHost:nil], + @"Creating a checker with nil hostname must fail."); + XCTAssertNil([[FIRReachabilityChecker alloc] + initWithReachabilityDelegate:self + loggerDelegate:(id<FIRNetworkLoggerDelegate>)self + withHost:@""], + @"Creating a checker with empty hostname must fail."); +} + +@end |