SCTestPreferences.m [plain text]
/*
* Copyright (c) 2016 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#import "SCTest.h"
#import "SCTestUtils.h"
@interface SCTestPreferences : SCTest
@property SCPreferencesRef prefs;
@end
@implementation SCTestPreferences
+ (NSString *)command
{
return @"preferences";
}
+ (NSString *)commandDescription
{
return @"Tests the SCPreferences code path";
}
- (instancetype)initWithOptions:(NSDictionary *)options
{
self = [super initWithOptions:options];
if (self) {
_prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
}
return self;
}
- (void)dealloc
{
if (self.prefs != NULL) {
CFRelease(self.prefs);
self.prefs = NULL;
}
}
- (void)start
{
if (self.options[kSCTestPreferencesServiceList]) {
NSDictionary *services = (__bridge NSDictionary *)SCPreferencesGetValue(self.prefs, kSCPrefNetworkServices);
if (services != nil) {
[self printNetworkServicesFromDict:services];
} else {
SCTestLog("No services present!");
}
}
if (self.options[kSCTestPreferencesServiceOrder]) {
SCNetworkSetRef set = SCNetworkSetCopyCurrent(self.prefs);
NSArray *serviceID = (__bridge NSArray *)SCNetworkSetGetServiceOrder(set);
NSDictionary *services = (__bridge NSDictionary *)SCPreferencesGetValue(self.prefs, kSCPrefNetworkServices);
int counter = 1;
SCTestLog("Network service order");
for (NSString *key in serviceID) {
NSDictionary *dict = [services objectForKey:key];
SCTestLog("\n }
CFRelease(set);
}
[self cleanupAndExitWithErrorCode:0];
}
- (void)printNetworkServicesFromDict:(NSDictionary *)serviceDict
{
int counter = 1;
SCTestLog("Network Services");
for (NSString *key in serviceDict) {
NSDictionary *dict = [serviceDict objectForKey:key];
SCTestLog("\n }
}
- (BOOL)unitTest
{
BOOL allUnitTestsPassed = YES;
allUnitTestsPassed &= [self unitTestNetworkServicesSanity];
allUnitTestsPassed &= [self unitTestPreferencesAPI];
allUnitTestsPassed &= [self unitTestPreferencesSession];
return allUnitTestsPassed;
}
- (BOOL)unitTestNetworkServicesSanity
{
// We verify that every service has a unique name, an interface, an IPv4 config method and and IPv6 config method.
NSDictionary *services;
NSMutableArray *serviceNameArray;
SCTestPreferences *test;
test = [[SCTestPreferences alloc] initWithOptions:self.options];
services = (__bridge NSDictionary *)SCPreferencesGetValue(test.prefs, kSCPrefNetworkServices);
if (services == NULL) {
SCTestLog("No services present!");
return NO;
}
serviceNameArray = [[NSMutableArray alloc] init];
for (NSString *serviceID in services) {
NSDictionary *serviceDict;
NSString *serviceName;
NSDictionary *interfaceDict;
NSString *interfaceType;
NSDictionary *ipv4Dict;
NSDictionary *ipv6Dict;
serviceDict = [services objectForKey:serviceID];
if (![serviceDict isKindOfClass:[NSDictionary class]]) {
SCTestLog("Service is not a dictionary");
return NO;
}
serviceName = [serviceDict objectForKey:(__bridge NSString *)kSCPropNetServiceUserDefinedName];
if (serviceName != nil) {
// Check if the name is unique
BOOL namePresent = [serviceNameArray containsObject:serviceName];
if (!namePresent) {
[serviceNameArray addObject:serviceName];
} else {
SCTestLog("Duplicate services with name return NO;
}
} else {
SCTestLog("Service ID return NO;
}
interfaceDict = [serviceDict objectForKey:(__bridge NSString *)kSCCompInterface];
if (interfaceDict == nil) {
SCTestLog("Service return NO;
}
interfaceType = [interfaceDict objectForKey:(__bridge NSString *)kSCPropNetInterfaceType];
if (interfaceType != nil && [interfaceType containsString:@"CommCenter"]) {
// CommCenter services typically do not have an ipv4/v6 data OR config method. Skip such services.
continue;
}
ipv4Dict = [serviceDict objectForKey:(__bridge NSString *)kSCEntNetIPv4];
ipv6Dict = [serviceDict objectForKey:(__bridge NSString *)kSCEntNetIPv6];
// Check that we have at least one IP config method
if (ipv4Dict == nil && ipv6Dict == nil) {
SCTestLog("Service return NO;
}
if ([ipv4Dict objectForKey:(__bridge NSString *)kSCPropNetIPv4ConfigMethod] == nil &&
[ipv6Dict objectForKey:(__bridge NSString *)kSCPropNetIPv6ConfigMethod] == nil) {
SCTestLog("Service return NO;
}
}
SCTestLog("Verified that the Network Services have valid configurations");
return YES;
}
- (BOOL)unitTestPreferencesSession
{
SCPreferencesRef prefs;
prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
if (prefs == NULL) {
SCTestLog("Failed to create SCPreferences. Error: return NO;
} else {
CFRelease(prefs);
}
prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization, NULL);
if (prefs == NULL) {
SCTestLog("Failed to create SCPreferences w/options. Error: return NO;
} else {
CFRelease(prefs);
}
prefs = SCPreferencesCreateWithAuthorization(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization);
if (prefs == NULL) {
SCTestLog("Failed to create SCPreferences w/options. Error: return NO;
} else {
CFRelease(prefs);
}
SCTestLog("Verified that the preferences session can be created");
return YES;
}
- (BOOL)unitTestPreferencesAPI
{
BOOL ok = NO;
int iterations = 1000;
NSDictionary *prefsOptions;
NSMutableArray *keys;
NSMutableArray *values;
SCTestPreferences *test;
NSArray *keyList;
test = [[SCTestPreferences alloc] initWithOptions:self.options];
if (test.prefs != NULL) {
CFRelease(test.prefs);
test.prefs = NULL;
}
prefsOptions = @{(__bridge NSString *)kSCPreferencesOptionRemoveWhenEmpty:(__bridge NSNumber *)kCFBooleanTrue};
test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
CFSTR("SCTest"),
CFSTR("SCTestPreferences.plist"),
kSCPreferencesUseEntitlementAuthorization,
(__bridge CFDictionaryRef)prefsOptions);
if (test.prefs == NULL) {
SCTestLog("Failed to create a preferences session. Error: return NO;
}
keys = [[NSMutableArray alloc] init];
values = [[NSMutableArray alloc] init];
for (int i = 0; i < iterations; i++) {
NSUUID *uuidKey = [NSUUID UUID];
NSUUID *uuidValue = [NSUUID UUID];
ok = SCPreferencesLock(test.prefs, true);
if (!ok) {
SCTestLog("Failed to get preferences lock. Error: return NO;
}
ok = SCPreferencesSetValue(test.prefs, (__bridge CFStringRef)uuidKey.UUIDString, (__bridge CFStringRef)uuidValue.UUIDString);
if (!ok) {
SCTestLog("Failed to set preferences value. Error: return NO;
}
ok = SCPreferencesUnlock(test.prefs);
if (!ok) {
SCTestLog("Failed to release preferences lock. Error: return NO;
}
[keys addObject:uuidKey.UUIDString];
[values addObject:uuidValue.UUIDString];
}
ok = SCPreferencesCommitChanges(test.prefs);
if (!ok) {
SCTestLog("Failed to commit preferences. Error: return NO;
}
CFRelease(test.prefs);
test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
CFSTR("SCTest"),
CFSTR("SCTestPreferences.plist"),
kSCPreferencesUseEntitlementAuthorization,
(__bridge CFDictionaryRef)prefsOptions);
if (test.prefs == NULL) {
SCTestLog("Failed to create a preferences session. Error: return NO;
}
keyList = (__bridge_transfer NSArray *)SCPreferencesCopyKeyList(test.prefs);
if ([keyList count] < [keys count]) {
SCTestLog("Failed to copy all keys from preferences. Error: return NO;
}
for (NSString *key in keys) {
NSString *valueString = (__bridge NSString *)SCPreferencesGetValue(test.prefs, (__bridge CFStringRef)key);
if (!valueString) {
SCTestLog("Failed to get value from preferences. Error: return NO;
}
BOOL ok = [values containsObject:valueString];
if (!ok) {
SCTestLog("Incorrect value fetched from preferences");
return NO;
}
}
ok = SCPreferencesRemoveAllValues(test.prefs);
if (!ok) {
SCTestLog("Failed to remove values preferences. Error: return NO;
}
ok = SCPreferencesCommitChanges(test.prefs);
if (!ok) {
SCTestLog("Failed to commit preferences. Error: return NO;
}
CFRelease(test.prefs);
test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
CFSTR("SCTest"),
CFSTR("SCTestPreferences.plist"),
kSCPreferencesUseEntitlementAuthorization,
(__bridge CFDictionaryRef)prefsOptions);
if (test.prefs == NULL) {
SCTestLog("Failed to create a preferences session. Error: return NO;
}
keyList = (__bridge_transfer NSArray *)SCPreferencesCopyKeyList(test.prefs);
if ([keyList count] > 0) {
SCTestLog("Failed to remove all keys from preferences. Error: return NO;
}
SCTestLog("Verified that SCPreferences APIs behave as expected");
return ok;
}
- (void)cleanupAndExitWithErrorCode:(int)error
{
[super cleanupAndExitWithErrorCode:error];
}
@end