]> git.saurik.com Git - apple/configd.git/blob - sctest/SCTestPreferences.m
configd-1061.40.2.tar.gz
[apple/configd.git] / sctest / SCTestPreferences.m
1 /*
2 * Copyright (c) 2016, 2017 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #import "SCTest.h"
25 #import "SCTestUtils.h"
26
27 @interface SCTestPreferences : SCTest
28 @property SCPreferencesRef prefs;
29 @end
30
31 @implementation SCTestPreferences
32
33 + (NSString *)command
34 {
35 return @"preferences";
36 }
37
38 + (NSString *)commandDescription
39 {
40 return @"Tests the SCPreferences code path";
41 }
42
43 - (instancetype)initWithOptions:(NSDictionary *)options
44 {
45 self = [super initWithOptions:options];
46 if (self) {
47 _prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
48 }
49 return self;
50 }
51
52 - (void)dealloc
53 {
54 if (self.prefs != NULL) {
55 CFRelease(self.prefs);
56 self.prefs = NULL;
57 }
58 }
59
60 - (void)start
61 {
62 if (self.options[kSCTestPreferencesServiceList]) {
63 NSDictionary *services = (__bridge NSDictionary *)SCPreferencesGetValue(self.prefs, kSCPrefNetworkServices);
64 if (services != nil) {
65 [self printNetworkServicesFromDict:services];
66 } else {
67 SCTestLog("No services present!");
68 }
69 }
70
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);
75 int counter = 1;
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]);
80 }
81 CFRelease(set);
82 }
83
84 [self cleanupAndExitWithErrorCode:0];
85 }
86
87 - (void)printNetworkServicesFromDict:(NSDictionary *)serviceDict
88 {
89 int counter = 1;
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]);
94 }
95 }
96
97 - (BOOL)unitTest
98 {
99 BOOL allUnitTestsPassed = YES;
100 allUnitTestsPassed &= [self unitTestNetworkServicesSanity];
101 allUnitTestsPassed &= [self unitTestPreferencesAPI];
102 allUnitTestsPassed &= [self unitTestPreferencesSession];
103 return allUnitTestsPassed;
104
105 }
106
107 - (BOOL)unitTestNetworkServicesSanity
108 {
109 // We verify that every service has a unique name, an interface, an IPv4 config method and and IPv6 config method.
110 NSArray *sets;
111 NSDictionary *services;
112 SCTestPreferences *test;
113
114 test = [[SCTestPreferences alloc] initWithOptions:self.options];
115
116 sets = (__bridge_transfer NSArray *)SCNetworkSetCopyAll(test.prefs);
117 if (sets == nil || [sets count] == 0) {
118 SCTestLog("No sets present!");
119 return NO;
120 }
121
122 services = (__bridge NSDictionary *)SCPreferencesGetValue(test.prefs, kSCPrefNetworkServices);
123 if (services == nil || [services count] == 0) {
124 SCTestLog("No services present!");
125 return NO;
126 }
127
128 for (id setPtr in sets) {
129 SCNetworkSetRef set = (__bridge SCNetworkSetRef)setPtr;
130 NSArray *serviceArray = nil;
131 NSMutableArray *serviceNameArray = nil;
132 NSString *setID;
133
134 setID = (__bridge NSString *)SCNetworkSetGetSetID(set);
135
136 serviceArray = (__bridge_transfer NSArray *)SCNetworkSetCopyServices(set);
137 if (serviceArray == nil) {
138 SCTestLog("No services in set %@!", setID);
139 continue;
140 }
141
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;
150 NSString *serviceID;
151 NSString *interfaceType;
152 SCNetworkServiceRef service;
153 SCNetworkInterfaceRef interface;
154 SCNetworkProtocolRef ipv4Protocol;
155 SCNetworkProtocolRef ipv6Protocol;
156
157
158 service = (__bridge SCNetworkServiceRef)servicePTR;
159 serviceID = (__bridge NSString *)SCNetworkServiceGetServiceID(service);
160
161 serviceDict = [services objectForKey:serviceID];
162 if (![serviceDict isKindOfClass:[NSDictionary class]]) {
163 SCTestLog("Service is not a dictionary");
164 return NO;
165 }
166
167 serviceName = (__bridge NSString *)SCNetworkServiceGetName(service);
168 if (serviceName != nil) {
169 // Check if the name is unique
170 BOOL namePresent = [serviceNameArray containsObject:serviceName];
171 if (!namePresent) {
172 [serviceNameArray addObject:serviceName];
173 } else {
174 SCTestLog("Duplicate services with name %@ exist", serviceName);
175 return NO;
176 }
177 } else {
178 SCTestLog("Service ID %@ does not have a name", serviceID);
179 return NO;
180 }
181
182 interface = SCNetworkServiceGetInterface(service);
183 if (interface == nil) {
184 SCTestLog("Service %@ does not have an interface", serviceName);
185 return NO;
186 }
187
188 interfaceType = (__bridge NSString *)SCNetworkInterfaceGetInterfaceType(interface);
189 if (interfaceType == nil || [interfaceType length] == 0) {
190 SCTestLog("Service %@ does not have an interface type", serviceName);
191 return NO;
192 }
193 #if TARGET_OS_IPHONE
194 if ([interfaceType containsString:@"CommCenter"]) {
195 // CommCenter services typically do not have an ipv4/v6 data OR config method. Skip such services.
196 continue;
197 }
198 #endif // TARGET_OS_IPHONE
199 ipv4Protocol = SCNetworkServiceCopyProtocol(service, kSCNetworkProtocolTypeIPv4);
200 ipv6Protocol = SCNetworkServiceCopyProtocol(service, kSCNetworkProtocolTypeIPv6);
201
202 if (ipv4Protocol != NULL) {
203 ipv4ProtocolConfig = (__bridge NSDictionary *)SCNetworkProtocolGetConfiguration(ipv4Protocol);
204 if (ipv4ProtocolConfig != nil) {
205 ipv4Dict = [ipv4ProtocolConfig copy];
206 }
207 CFRelease(ipv4Protocol);
208 }
209
210 if (ipv6Protocol != NULL) {
211 ipv6ProtocolConfig = (__bridge NSDictionary *)SCNetworkProtocolGetConfiguration(ipv6Protocol);
212 if (ipv6ProtocolConfig != nil) {
213 ipv6Dict = [ipv6ProtocolConfig copy];
214 }
215 CFRelease(ipv6Protocol);
216 }
217
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);
221 return NO;
222 }
223
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);
227 return NO;
228 }
229 }
230 }
231
232 SCTestLog("Verified that the Network Services have valid configurations");
233
234 return YES;
235 }
236
237 - (BOOL)unitTestPreferencesSession
238 {
239 SCPreferencesRef prefs;
240 prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
241 if (prefs == NULL) {
242 SCTestLog("Failed to create SCPreferences. Error: %s", SCErrorString(SCError()));
243 return NO;
244 } else {
245 CFRelease(prefs);
246 }
247
248 prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization, NULL);
249 if (prefs == NULL) {
250 SCTestLog("Failed to create SCPreferences w/options. Error: %s", SCErrorString(SCError()));
251 return NO;
252 } else {
253 CFRelease(prefs);
254 }
255
256 prefs = SCPreferencesCreateWithAuthorization(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization);
257 if (prefs == NULL) {
258 SCTestLog("Failed to create SCPreferences w/options. Error: %s", SCErrorString(SCError()));
259 return NO;
260 } else {
261 CFRelease(prefs);
262 }
263
264 SCTestLog("Verified that the preferences session can be created");
265 return YES;
266 }
267
268 - (BOOL)unitTestPreferencesAPI
269 {
270 BOOL ok = NO;
271 int iterations = 100;
272 NSDictionary *prefsOptions;
273 NSMutableArray *keys;
274 NSMutableArray *values;
275 SCTestPreferences *test;
276 NSArray *keyList;
277
278 test = [[SCTestPreferences alloc] initWithOptions:self.options];
279 if (test.prefs != NULL) {
280 CFRelease(test.prefs);
281 test.prefs = NULL;
282 }
283
284 prefsOptions = @{(__bridge NSString *)kSCPreferencesOptionRemoveWhenEmpty:(__bridge NSNumber *)kCFBooleanTrue};
285 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
286 CFSTR("SCTest"),
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()));
292 return NO;
293 }
294
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];
300
301 ok = SCPreferencesLock(test.prefs, true);
302 if (!ok) {
303 SCTestLog("Failed to get preferences lock. Error: %s", SCErrorString(SCError()));
304 return NO;
305 }
306
307 ok = SCPreferencesSetValue(test.prefs, (__bridge CFStringRef)uuidKey.UUIDString, (__bridge CFStringRef)uuidValue.UUIDString);
308 if (!ok) {
309 SCTestLog("Failed to set preferences value. Error: %s", SCErrorString(SCError()));
310 return NO;
311 }
312
313 ok = SCPreferencesUnlock(test.prefs);
314 if (!ok) {
315 SCTestLog("Failed to release preferences lock. Error: %s", SCErrorString(SCError()));
316 return NO;
317 }
318
319 [keys addObject:uuidKey.UUIDString];
320 [values addObject:uuidValue.UUIDString];
321 }
322
323 ok = SCPreferencesCommitChanges(test.prefs);
324 if (!ok) {
325 SCTestLog("Failed to commit preferences. Error: %s", SCErrorString(SCError()));
326 return NO;
327 }
328
329 CFRelease(test.prefs);
330 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
331 CFSTR("SCTest"),
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()));
337 return NO;
338 }
339
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()));
343 return NO;
344 }
345
346 for (NSString *key in keys) {
347 NSString *valueString = (__bridge NSString *)SCPreferencesGetValue(test.prefs, (__bridge CFStringRef)key);
348 if (!valueString) {
349 SCTestLog("Failed to get value from preferences. Error: %s", SCErrorString(SCError()));
350 return NO;
351 }
352
353 BOOL ok = [values containsObject:valueString];
354 if (!ok) {
355 SCTestLog("Incorrect value fetched from preferences");
356 return NO;
357 }
358 }
359
360 ok = SCPreferencesRemoveAllValues(test.prefs);
361 if (!ok) {
362 SCTestLog("Failed to remove values preferences. Error: %s", SCErrorString(SCError()));
363 return NO;
364 }
365
366 ok = SCPreferencesCommitChanges(test.prefs);
367 if (!ok) {
368 SCTestLog("Failed to commit preferences. Error: %s", SCErrorString(SCError()));
369 return NO;
370 }
371
372 CFRelease(test.prefs);
373 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
374 CFSTR("SCTest"),
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()));
380 return NO;
381 }
382
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()));
386 return NO;
387 }
388
389 SCTestLog("Verified that SCPreferences APIs behave as expected");
390 return ok;
391 }
392
393 - (void)cleanupAndExitWithErrorCode:(int)error
394 {
395 [super cleanupAndExitWithErrorCode:error];
396 }
397
398 @end