2 * Copyright (c) 2016, 2017 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.
111 NSDictionary *services;
112 SCTestPreferences *test;
114 test = [[SCTestPreferences alloc] initWithOptions:self.options];
116 sets = (__bridge_transfer NSArray *)SCNetworkSetCopyAll(test.prefs);
117 if (sets == nil || [sets count] == 0) {
118 SCTestLog("No sets present!");
122 services = (__bridge NSDictionary *)SCPreferencesGetValue(test.prefs, kSCPrefNetworkServices);
123 if (services == nil || [services count] == 0) {
124 SCTestLog("No services present!");
128 for (id setPtr in sets) {
129 SCNetworkSetRef set = (__bridge SCNetworkSetRef)setPtr;
130 NSArray *serviceArray = nil;
131 NSMutableArray *serviceNameArray = nil;
134 setID = (__bridge NSString *)SCNetworkSetGetSetID(set);
136 serviceArray = (__bridge_transfer NSArray *)SCNetworkSetCopyServices(set);
137 if (serviceArray == nil) {
138 SCTestLog("No services in set %@!", setID);
142 serviceNameArray = [[NSMutableArray alloc] init];
143 for (id servicePTR in serviceArray) {
144 NSDictionary *serviceDict;
145 NSDictionary *ipv4Dict;
146 NSDictionary *ipv6Dict;
147 NSDictionary *ipv4ProtocolConfig;
148 NSDictionary *ipv6ProtocolConfig;
149 NSString *serviceName;
151 NSString *interfaceType;
152 SCNetworkServiceRef service;
153 SCNetworkInterfaceRef interface;
154 SCNetworkProtocolRef ipv4Protocol;
155 SCNetworkProtocolRef ipv6Protocol;
158 service = (__bridge SCNetworkServiceRef)servicePTR;
159 serviceID = (__bridge NSString *)SCNetworkServiceGetServiceID(service);
161 serviceDict = [services objectForKey:serviceID];
162 if (![serviceDict isKindOfClass:[NSDictionary class]]) {
163 SCTestLog("Service is not a dictionary");
167 serviceName = (__bridge NSString *)SCNetworkServiceGetName(service);
168 if (serviceName != nil) {
169 // Check if the name is unique
170 BOOL namePresent = [serviceNameArray containsObject:serviceName];
172 [serviceNameArray addObject:serviceName];
174 SCTestLog("Duplicate services with name %@ exist", serviceName);
178 SCTestLog("Service ID %@ does not have a name", serviceID);
182 interface = SCNetworkServiceGetInterface(service);
183 if (interface == nil) {
184 SCTestLog("Service %@ does not have an interface", serviceName);
188 interfaceType = (__bridge NSString *)SCNetworkInterfaceGetInterfaceType(interface);
189 if (interfaceType == nil || [interfaceType length] == 0) {
190 SCTestLog("Service %@ does not have an interface type", serviceName);
194 if ([interfaceType containsString:@"CommCenter"]) {
195 // CommCenter services typically do not have an ipv4/v6 data OR config method. Skip such services.
198 #endif // TARGET_OS_IPHONE
199 ipv4Protocol = SCNetworkServiceCopyProtocol(service, kSCNetworkProtocolTypeIPv4);
200 ipv6Protocol = SCNetworkServiceCopyProtocol(service, kSCNetworkProtocolTypeIPv6);
202 if (ipv4Protocol != NULL) {
203 ipv4ProtocolConfig = (__bridge NSDictionary *)SCNetworkProtocolGetConfiguration(ipv4Protocol);
204 if (ipv4ProtocolConfig != nil) {
205 ipv4Dict = [ipv4ProtocolConfig copy];
207 CFRelease(ipv4Protocol);
210 if (ipv6Protocol != NULL) {
211 ipv6ProtocolConfig = (__bridge NSDictionary *)SCNetworkProtocolGetConfiguration(ipv6Protocol);
212 if (ipv6ProtocolConfig != nil) {
213 ipv6Dict = [ipv6ProtocolConfig copy];
215 CFRelease(ipv6Protocol);
218 // Check that we have at least one IP config method
219 if (ipv4Dict == nil && ipv6Dict == nil) {
220 SCTestLog("Service %@ does not have an IP dictionary", serviceName);
224 if ([ipv4Dict objectForKey:(__bridge NSString *)kSCPropNetIPv4ConfigMethod] == nil &&
225 [ipv6Dict objectForKey:(__bridge NSString *)kSCPropNetIPv6ConfigMethod] == nil) {
226 SCTestLog("Service %@ does not have an IP Config Method", serviceName);
232 SCTestLog("Verified that the Network Services have valid configurations");
237 - (BOOL)unitTestPreferencesSession
239 SCPreferencesRef prefs;
240 prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
242 SCTestLog("Failed to create SCPreferences. Error: %s", SCErrorString(SCError()));
248 prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization, NULL);
250 SCTestLog("Failed to create SCPreferences w/options. Error: %s", SCErrorString(SCError()));
256 prefs = SCPreferencesCreateWithAuthorization(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization);
258 SCTestLog("Failed to create SCPreferences w/options. Error: %s", SCErrorString(SCError()));
264 SCTestLog("Verified that the preferences session can be created");
268 - (BOOL)unitTestPreferencesAPI
271 int iterations = 100;
272 NSDictionary *prefsOptions;
273 NSMutableArray *keys;
274 NSMutableArray *values;
275 SCTestPreferences *test;
278 test = [[SCTestPreferences alloc] initWithOptions:self.options];
279 if (test.prefs != NULL) {
280 CFRelease(test.prefs);
284 prefsOptions = @{(__bridge NSString *)kSCPreferencesOptionRemoveWhenEmpty:(__bridge NSNumber *)kCFBooleanTrue};
285 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
287 CFSTR("SCTestPreferences.plist"),
288 kSCPreferencesUseEntitlementAuthorization,
289 (__bridge CFDictionaryRef)prefsOptions);
290 if (test.prefs == NULL) {
291 SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
295 keys = [[NSMutableArray alloc] init];
296 values = [[NSMutableArray alloc] init];
297 for (int i = 0; i < iterations; i++) {
298 NSUUID *uuidKey = [NSUUID UUID];
299 NSUUID *uuidValue = [NSUUID UUID];
301 ok = SCPreferencesLock(test.prefs, true);
303 SCTestLog("Failed to get preferences lock. Error: %s", SCErrorString(SCError()));
307 ok = SCPreferencesSetValue(test.prefs, (__bridge CFStringRef)uuidKey.UUIDString, (__bridge CFStringRef)uuidValue.UUIDString);
309 SCTestLog("Failed to set preferences value. Error: %s", SCErrorString(SCError()));
313 ok = SCPreferencesUnlock(test.prefs);
315 SCTestLog("Failed to release preferences lock. Error: %s", SCErrorString(SCError()));
319 [keys addObject:uuidKey.UUIDString];
320 [values addObject:uuidValue.UUIDString];
323 ok = SCPreferencesCommitChanges(test.prefs);
325 SCTestLog("Failed to commit preferences. Error: %s", SCErrorString(SCError()));
329 CFRelease(test.prefs);
330 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
332 CFSTR("SCTestPreferences.plist"),
333 kSCPreferencesUseEntitlementAuthorization,
334 (__bridge CFDictionaryRef)prefsOptions);
335 if (test.prefs == NULL) {
336 SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
340 keyList = (__bridge_transfer NSArray *)SCPreferencesCopyKeyList(test.prefs);
341 if ([keyList count] < [keys count]) {
342 SCTestLog("Failed to copy all keys from preferences. Error: %s", SCErrorString(SCError()));
346 for (NSString *key in keys) {
347 NSString *valueString = (__bridge NSString *)SCPreferencesGetValue(test.prefs, (__bridge CFStringRef)key);
349 SCTestLog("Failed to get value from preferences. Error: %s", SCErrorString(SCError()));
353 BOOL ok = [values containsObject:valueString];
355 SCTestLog("Incorrect value fetched from preferences");
360 ok = SCPreferencesRemoveAllValues(test.prefs);
362 SCTestLog("Failed to remove values preferences. Error: %s", SCErrorString(SCError()));
366 ok = SCPreferencesCommitChanges(test.prefs);
368 SCTestLog("Failed to commit preferences. Error: %s", SCErrorString(SCError()));
372 CFRelease(test.prefs);
373 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
375 CFSTR("SCTestPreferences.plist"),
376 kSCPreferencesUseEntitlementAuthorization,
377 (__bridge CFDictionaryRef)prefsOptions);
378 if (test.prefs == NULL) {
379 SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
383 keyList = (__bridge_transfer NSArray *)SCPreferencesCopyKeyList(test.prefs);
384 if ([keyList count] > 0) {
385 SCTestLog("Failed to remove all keys from preferences. Error: %s", SCErrorString(SCError()));
389 SCTestLog("Verified that SCPreferences APIs behave as expected");
393 - (void)cleanupAndExitWithErrorCode:(int)error
395 [super cleanupAndExitWithErrorCode:error];