2 * Copyright (c) 2016 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 #import "SCTestUtils.h"
27 @interface SCTestPreferences : SCTest
28 @property SCPreferencesRef prefs;
31 @implementation SCTestPreferences
35 return @"preferences";
38 + (NSString *)commandDescription
40 return @"Tests the SCPreferences code path";
43 - (instancetype)initWithOptions:(NSDictionary *)options
45 self = [super initWithOptions:options];
47 _prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
54 if (self.prefs != NULL) {
55 CFRelease(self.prefs);
62 if (self.options[kSCTestPreferencesServiceList]) {
63 NSDictionary *services = (__bridge NSDictionary *)SCPreferencesGetValue(self.prefs, kSCPrefNetworkServices);
64 if (services != nil) {
65 [self printNetworkServicesFromDict:services];
67 SCTestLog("No services present!");
71 if (self.options[kSCTestPreferencesServiceOrder]) {
72 SCNetworkSetRef set = SCNetworkSetCopyCurrent(self.prefs);
73 NSArray *serviceID = (__bridge NSArray *)SCNetworkSetGetServiceOrder(set);
74 NSDictionary *services = (__bridge NSDictionary *)SCPreferencesGetValue(self.prefs, kSCPrefNetworkServices);
76 SCTestLog("Network service order");
77 for (NSString *key in serviceID) {
78 NSDictionary *dict = [services objectForKey:key];
79 SCTestLog("\n%d: %@\n\tUserDefinedName: %@", counter++, key, [dict objectForKey:(__bridge NSString *)kSCPropNetServiceUserDefinedName]);
84 [self cleanupAndExitWithErrorCode:0];
87 - (void)printNetworkServicesFromDict:(NSDictionary *)serviceDict
90 SCTestLog("Network Services");
91 for (NSString *key in serviceDict) {
92 NSDictionary *dict = [serviceDict objectForKey:key];
93 SCTestLog("\n%d: %@\n\tUserDefinedName: %@", counter++, key, [dict objectForKey:(__bridge NSString *)kSCPropNetServiceUserDefinedName]);
99 BOOL allUnitTestsPassed = YES;
100 allUnitTestsPassed &= [self unitTestNetworkServicesSanity];
101 allUnitTestsPassed &= [self unitTestPreferencesAPI];
102 allUnitTestsPassed &= [self unitTestPreferencesSession];
103 return allUnitTestsPassed;
107 - (BOOL)unitTestNetworkServicesSanity
109 // We verify that every service has a unique name, an interface, an IPv4 config method and and IPv6 config method.
110 NSDictionary *services;
111 NSMutableArray *serviceNameArray;
112 SCTestPreferences *test;
114 test = [[SCTestPreferences alloc] initWithOptions:self.options];
115 services = (__bridge NSDictionary *)SCPreferencesGetValue(test.prefs, kSCPrefNetworkServices);
116 if (services == NULL) {
117 SCTestLog("No services present!");
121 serviceNameArray = [[NSMutableArray alloc] init];
122 for (NSString *serviceID in services) {
123 NSDictionary *serviceDict;
124 NSString *serviceName;
125 NSDictionary *interfaceDict;
126 NSString *interfaceType;
127 NSDictionary *ipv4Dict;
128 NSDictionary *ipv6Dict;
130 serviceDict = [services objectForKey:serviceID];
131 if (![serviceDict isKindOfClass:[NSDictionary class]]) {
132 SCTestLog("Service is not a dictionary");
136 serviceName = [serviceDict objectForKey:(__bridge NSString *)kSCPropNetServiceUserDefinedName];
137 if (serviceName != nil) {
138 // Check if the name is unique
139 BOOL namePresent = [serviceNameArray containsObject:serviceName];
141 [serviceNameArray addObject:serviceName];
143 SCTestLog("Duplicate services with name %@ exist", serviceName);
147 SCTestLog("Service ID %@ does not have a name", serviceID);
151 interfaceDict = [serviceDict objectForKey:(__bridge NSString *)kSCCompInterface];
152 if (interfaceDict == nil) {
153 SCTestLog("Service %@ does not have an interface", serviceName);
157 interfaceType = [interfaceDict objectForKey:(__bridge NSString *)kSCPropNetInterfaceType];
158 if (interfaceType != nil && [interfaceType containsString:@"CommCenter"]) {
159 // CommCenter services typically do not have an ipv4/v6 data OR config method. Skip such services.
163 ipv4Dict = [serviceDict objectForKey:(__bridge NSString *)kSCEntNetIPv4];
164 ipv6Dict = [serviceDict objectForKey:(__bridge NSString *)kSCEntNetIPv6];
166 // Check that we have at least one IP config method
167 if (ipv4Dict == nil && ipv6Dict == nil) {
168 SCTestLog("Service %@ does not have an IP dictionary", serviceName);
172 if ([ipv4Dict objectForKey:(__bridge NSString *)kSCPropNetIPv4ConfigMethod] == nil &&
173 [ipv6Dict objectForKey:(__bridge NSString *)kSCPropNetIPv6ConfigMethod] == nil) {
174 SCTestLog("Service %@ does not have an IP Config Method", serviceName);
179 SCTestLog("Verified that the Network Services have valid configurations");
184 - (BOOL)unitTestPreferencesSession
186 SCPreferencesRef prefs;
187 prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
189 SCTestLog("Failed to create SCPreferences. Error: %s", SCErrorString(SCError()));
195 prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization, NULL);
197 SCTestLog("Failed to create SCPreferences w/options. Error: %s", SCErrorString(SCError()));
203 prefs = SCPreferencesCreateWithAuthorization(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization);
205 SCTestLog("Failed to create SCPreferences w/options. Error: %s", SCErrorString(SCError()));
211 SCTestLog("Verified that the preferences session can be created");
215 - (BOOL)unitTestPreferencesAPI
218 int iterations = 1000;
219 NSDictionary *prefsOptions;
220 NSMutableArray *keys;
221 NSMutableArray *values;
222 SCTestPreferences *test;
225 test = [[SCTestPreferences alloc] initWithOptions:self.options];
226 if (test.prefs != NULL) {
227 CFRelease(test.prefs);
231 prefsOptions = @{(__bridge NSString *)kSCPreferencesOptionRemoveWhenEmpty:(__bridge NSNumber *)kCFBooleanTrue};
232 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
234 CFSTR("SCTestPreferences.plist"),
235 kSCPreferencesUseEntitlementAuthorization,
236 (__bridge CFDictionaryRef)prefsOptions);
237 if (test.prefs == NULL) {
238 SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
242 keys = [[NSMutableArray alloc] init];
243 values = [[NSMutableArray alloc] init];
244 for (int i = 0; i < iterations; i++) {
245 NSUUID *uuidKey = [NSUUID UUID];
246 NSUUID *uuidValue = [NSUUID UUID];
248 ok = SCPreferencesLock(test.prefs, true);
250 SCTestLog("Failed to get preferences lock. Error: %s", SCErrorString(SCError()));
254 ok = SCPreferencesSetValue(test.prefs, (__bridge CFStringRef)uuidKey.UUIDString, (__bridge CFStringRef)uuidValue.UUIDString);
256 SCTestLog("Failed to set preferences value. Error: %s", SCErrorString(SCError()));
260 ok = SCPreferencesUnlock(test.prefs);
262 SCTestLog("Failed to release preferences lock. Error: %s", SCErrorString(SCError()));
266 [keys addObject:uuidKey.UUIDString];
267 [values addObject:uuidValue.UUIDString];
270 ok = SCPreferencesCommitChanges(test.prefs);
272 SCTestLog("Failed to commit preferences. Error: %s", SCErrorString(SCError()));
276 CFRelease(test.prefs);
277 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
279 CFSTR("SCTestPreferences.plist"),
280 kSCPreferencesUseEntitlementAuthorization,
281 (__bridge CFDictionaryRef)prefsOptions);
282 if (test.prefs == NULL) {
283 SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
287 keyList = (__bridge_transfer NSArray *)SCPreferencesCopyKeyList(test.prefs);
288 if ([keyList count] < [keys count]) {
289 SCTestLog("Failed to copy all keys from preferences. Error: %s", SCErrorString(SCError()));
293 for (NSString *key in keys) {
294 NSString *valueString = (__bridge NSString *)SCPreferencesGetValue(test.prefs, (__bridge CFStringRef)key);
296 SCTestLog("Failed to get value from preferences. Error: %s", SCErrorString(SCError()));
300 BOOL ok = [values containsObject:valueString];
302 SCTestLog("Incorrect value fetched from preferences");
307 ok = SCPreferencesRemoveAllValues(test.prefs);
309 SCTestLog("Failed to remove values preferences. Error: %s", SCErrorString(SCError()));
313 ok = SCPreferencesCommitChanges(test.prefs);
315 SCTestLog("Failed to commit preferences. Error: %s", SCErrorString(SCError()));
319 CFRelease(test.prefs);
320 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
322 CFSTR("SCTestPreferences.plist"),
323 kSCPreferencesUseEntitlementAuthorization,
324 (__bridge CFDictionaryRef)prefsOptions);
325 if (test.prefs == NULL) {
326 SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
330 keyList = (__bridge_transfer NSArray *)SCPreferencesCopyKeyList(test.prefs);
331 if ([keyList count] > 0) {
332 SCTestLog("Failed to remove all keys from preferences. Error: %s", SCErrorString(SCError()));
336 SCTestLog("Verified that SCPreferences APIs behave as expected");
340 - (void)cleanupAndExitWithErrorCode:(int)error
342 [super cleanupAndExitWithErrorCode:error];