aboutsummaryrefslogtreecommitdiffhomepage
path: root/GoogleUtilities/Example/Tests/Reachability/GULReachabilityCheckerTest.m
diff options
context:
space:
mode:
Diffstat (limited to 'GoogleUtilities/Example/Tests/Reachability/GULReachabilityCheckerTest.m')
-rw-r--r--GoogleUtilities/Example/Tests/Reachability/GULReachabilityCheckerTest.m358
1 files changed, 358 insertions, 0 deletions
diff --git a/GoogleUtilities/Example/Tests/Reachability/GULReachabilityCheckerTest.m b/GoogleUtilities/Example/Tests/Reachability/GULReachabilityCheckerTest.m
new file mode 100644
index 0000000..da9fbf1
--- /dev/null
+++ b/GoogleUtilities/Example/Tests/Reachability/GULReachabilityCheckerTest.m
@@ -0,0 +1,358 @@
+// 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 <GoogleUtilities/GULReachabilityChecker.h>
+
+#import <XCTest/XCTest.h>
+
+#import "GULReachabilityChecker+Internal.h"
+
+@interface GULReachabilityCheckerTest : XCTestCase <GULReachabilityDelegate> {
+ @private
+ GULReachabilityChecker *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 GULReachabilityCheckerTest *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 GULReachabilityApi kTestReachabilityApi = {
+ ReachabilityCreateWithName, ReachabilitySetCallback, ReachabilityScheduleWithRunLoop,
+ ReachabilityUnscheduleFromRunLoop, ReachabilityRelease,
+};
+
+@implementation GULReachabilityCheckerTest
+
+- (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_ = [[GULReachabilityChecker alloc] initWithReachabilityDelegate:self 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:(GULReachabilityChecker *)reachability
+ statusChanged:(GULReachabilityStatus)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, kGULReachabilityUnknown, @"");
+
+ XCTAssertTrue([checker_ start], @"");
+
+ XCTAssertTrue(checker_.isActive, @"");
+ XCTAssertEqual([statuses_ count], (NSUInteger)0, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityUnknown, @"");
+
+ FakeReachability.callback(kFakeReachabilityObject, 0, FakeReachability.callbackInfo);
+
+ XCTAssertEqual([statuses_ count], (NSUInteger)1, @"");
+ XCTAssertEqual([(NSNumber *)[statuses_ objectAtIndex:0] intValue],
+ (int)kGULReachabilityNotReachable, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityNotReachable, @"");
+
+ FakeReachability.callback(kFakeReachabilityObject, kSCNetworkReachabilityFlagsReachable,
+ FakeReachability.callbackInfo);
+
+ XCTAssertEqual([statuses_ count], (NSUInteger)2, @"");
+ XCTAssertEqual([(NSNumber *)[statuses_ objectAtIndex:1] intValue], (int)kGULReachabilityViaWifi,
+ @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityViaWifi, @"");
+
+ FakeReachability.callback(
+ kFakeReachabilityObject,
+ kSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsConnectionRequired,
+ FakeReachability.callbackInfo);
+
+ XCTAssertEqual([statuses_ count], (NSUInteger)3, @"");
+ XCTAssertEqual([(NSNumber *)[statuses_ objectAtIndex:2] intValue],
+ (int)kGULReachabilityNotReachable, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityNotReachable, @"");
+
+#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)kGULReachabilityViaCellular, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityViaCellular, @"");
+
+ FakeReachability.callback(kFakeReachabilityObject, kSCNetworkReachabilityFlagsIsWWAN,
+ FakeReachability.callbackInfo);
+
+ XCTAssertEqual([statuses_ count], (NSUInteger)5, @"");
+ XCTAssertEqual([(NSNumber *)[statuses_ objectAtIndex:4] intValue],
+ (int)kGULReachabilityNotReachable, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityNotReachable, @"");
+#endif
+
+ [checker_ stop];
+
+ XCTAssertFalse(checker_.isActive, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityUnknown, @"");
+
+ 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, kGULReachabilityUnknown, @"");
+
+ XCTAssertFalse([checker_ start], @"");
+
+ XCTAssertFalse(checker_.isActive, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityUnknown, @"");
+
+ [checker_ stop];
+
+ XCTAssertFalse(checker_.isActive, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityUnknown, @"");
+
+ 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, kGULReachabilityUnknown, @"");
+
+ XCTAssertFalse([checker_ start], @"");
+
+ XCTAssertFalse(checker_.isActive, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityUnknown, @"");
+
+ [checker_ stop];
+
+ XCTAssertFalse(checker_.isActive, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityUnknown, @"");
+
+ 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, kGULReachabilityUnknown, @"");
+
+ XCTAssertFalse([checker_ start], @"");
+
+ XCTAssertFalse(checker_.isActive, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityUnknown, @"");
+
+ [checker_ stop];
+
+ XCTAssertFalse(checker_.isActive, @"");
+ XCTAssertEqual(checker_.reachabilityStatus, kGULReachabilityUnknown, @"");
+
+ 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([[GULReachabilityChecker alloc] initWithReachabilityDelegate:self withHost:nil],
+ @"Creating a checker with nil hostname must fail.");
+ XCTAssertNil([[GULReachabilityChecker alloc] initWithReachabilityDelegate:self withHost:@""],
+ @"Creating a checker with empty hostname must fail.");
+}
+
+@end