]> git.saurik.com Git - apple/configd.git/blob - sctest/SCTestPreferences.m
configd-1109.101.1.tar.gz
[apple/configd.git] / sctest / SCTestPreferences.m
1 /*
2 * Copyright (c) 2016, 2017, 2019 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 #import <notify.h>
27 #import <SystemConfiguration/scprefs_observer.h>
28
29 @interface SCTestPreferences : SCTest
30 @property SCPreferencesRef prefs;
31 @property dispatch_semaphore_t sem;
32 @property int counter;
33 @end
34
35 @implementation SCTestPreferences
36
37 + (NSString *)command
38 {
39 return @"preferences";
40 }
41
42 + (NSString *)commandDescription
43 {
44 return @"Tests the SCPreferences code path";
45 }
46
47 - (instancetype)initWithOptions:(NSDictionary *)options
48 {
49 self = [super initWithOptions:options];
50 if (self) {
51 _prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
52 }
53 return self;
54 }
55
56 - (void)dealloc
57 {
58 if (self.prefs != NULL) {
59 CFRelease(self.prefs);
60 self.prefs = NULL;
61 }
62 }
63
64 - (void)start
65 {
66 if (self.options[kSCTestPreferencesServiceList]) {
67 NSDictionary *services = (__bridge NSDictionary *)SCPreferencesGetValue(self.prefs, kSCPrefNetworkServices);
68 if (services != nil) {
69 [self printNetworkServicesFromDict:services];
70 } else {
71 SCTestLog("No services present!");
72 }
73 }
74
75 if (self.options[kSCTestPreferencesServiceOrder]) {
76 SCNetworkSetRef set = SCNetworkSetCopyCurrent(self.prefs);
77 NSArray *serviceID = (__bridge NSArray *)SCNetworkSetGetServiceOrder(set);
78 NSDictionary *services = (__bridge NSDictionary *)SCPreferencesGetValue(self.prefs, kSCPrefNetworkServices);
79 int counter = 1;
80 SCTestLog("Network service order");
81 for (NSString *key in serviceID) {
82 NSDictionary *dict = [services objectForKey:key];
83 SCTestLog("\n%d: %@\n\tUserDefinedName: %@", counter++, key, [dict objectForKey:(__bridge NSString *)kSCPropNetServiceUserDefinedName]);
84 }
85 CFRelease(set);
86 }
87
88 [self cleanupAndExitWithErrorCode:0];
89 }
90
91 - (void)printNetworkServicesFromDict:(NSDictionary *)serviceDict
92 {
93 int counter = 1;
94 SCTestLog("Network Services");
95 for (NSString *key in serviceDict) {
96 NSDictionary *dict = [serviceDict objectForKey:key];
97 SCTestLog("\n%d: %@\n\tUserDefinedName: %@", counter++, key, [dict objectForKey:(__bridge NSString *)kSCPropNetServiceUserDefinedName]);
98 }
99 }
100
101 - (BOOL)unitTest
102 {
103 BOOL allUnitTestsPassed = YES;
104 allUnitTestsPassed &= [self unitTestNetworkServicesSanity];
105 allUnitTestsPassed &= [self unitTestPreferencesAPI];
106 allUnitTestsPassed &= [self unitTestPreferencesNotifications];
107 allUnitTestsPassed &= [self unitTestPreferencesObserver];
108 allUnitTestsPassed &= [self unitTestPreferencesSession];
109 return allUnitTestsPassed;
110
111 }
112
113 - (BOOL)unitTestNetworkServicesSanity
114 {
115 // We verify that every service has a unique name, an interface, an IPv4 config method and and IPv6 config method.
116 NSArray *sets;
117 NSDictionary *services;
118 SCTestPreferences *test;
119
120 test = [[SCTestPreferences alloc] initWithOptions:self.options];
121
122 sets = (__bridge_transfer NSArray *)SCNetworkSetCopyAll(test.prefs);
123 if (sets == nil || [sets count] == 0) {
124 SCTestLog("No sets present!");
125 return NO;
126 }
127
128 services = (__bridge NSDictionary *)SCPreferencesGetValue(test.prefs, kSCPrefNetworkServices);
129 if (services == nil || [services count] == 0) {
130 SCTestLog("No services present!");
131 return NO;
132 }
133
134 for (id setPtr in sets) {
135 SCNetworkSetRef set = (__bridge SCNetworkSetRef)setPtr;
136 NSArray *serviceArray = nil;
137 NSMutableArray *serviceNameArray = nil;
138 NSString *setID;
139
140 setID = (__bridge NSString *)SCNetworkSetGetSetID(set);
141
142 serviceArray = (__bridge_transfer NSArray *)SCNetworkSetCopyServices(set);
143 if (serviceArray == nil) {
144 SCTestLog("No services in set %@!", setID);
145 continue;
146 }
147
148 serviceNameArray = [[NSMutableArray alloc] init];
149 for (id servicePTR in serviceArray) {
150 NSDictionary *serviceDict;
151 NSDictionary *ipv4Dict;
152 NSDictionary *ipv6Dict;
153 NSDictionary *ipv4ProtocolConfig;
154 NSDictionary *ipv6ProtocolConfig;
155 NSString *serviceName;
156 NSString *serviceID;
157 NSString *interfaceType;
158 SCNetworkServiceRef service;
159 SCNetworkInterfaceRef interface;
160 SCNetworkProtocolRef ipv4Protocol;
161 SCNetworkProtocolRef ipv6Protocol;
162
163
164 service = (__bridge SCNetworkServiceRef)servicePTR;
165 serviceID = (__bridge NSString *)SCNetworkServiceGetServiceID(service);
166
167 serviceDict = [services objectForKey:serviceID];
168 if (![serviceDict isKindOfClass:[NSDictionary class]]) {
169 SCTestLog("Service is not a dictionary");
170 return NO;
171 }
172
173 serviceName = (__bridge NSString *)SCNetworkServiceGetName(service);
174 if (serviceName != nil) {
175 // Check if the name is unique
176 BOOL namePresent = [serviceNameArray containsObject:serviceName];
177 if (!namePresent) {
178 [serviceNameArray addObject:serviceName];
179 } else {
180 SCTestLog("Duplicate services with name %@ exist", serviceName);
181 return NO;
182 }
183 } else {
184 SCTestLog("Service ID %@ does not have a name", serviceID);
185 return NO;
186 }
187
188 interface = SCNetworkServiceGetInterface(service);
189 if (interface == nil) {
190 SCTestLog("Service %@ does not have an interface", serviceName);
191 return NO;
192 }
193
194 interfaceType = (__bridge NSString *)SCNetworkInterfaceGetInterfaceType(interface);
195 if (interfaceType == nil || [interfaceType length] == 0) {
196 SCTestLog("Service %@ does not have an interface type", serviceName);
197 return NO;
198 }
199 #if TARGET_OS_IPHONE
200 if ([interfaceType containsString:@"CommCenter"]) {
201 // CommCenter services typically do not have an ipv4/v6 data OR config method. Skip such services.
202 continue;
203 }
204 #endif // TARGET_OS_IPHONE
205 ipv4Protocol = SCNetworkServiceCopyProtocol(service, kSCNetworkProtocolTypeIPv4);
206 ipv6Protocol = SCNetworkServiceCopyProtocol(service, kSCNetworkProtocolTypeIPv6);
207
208 if (ipv4Protocol != NULL) {
209 ipv4ProtocolConfig = (__bridge NSDictionary *)SCNetworkProtocolGetConfiguration(ipv4Protocol);
210 if (ipv4ProtocolConfig != nil) {
211 ipv4Dict = [ipv4ProtocolConfig copy];
212 }
213 CFRelease(ipv4Protocol);
214 }
215
216 if (ipv6Protocol != NULL) {
217 ipv6ProtocolConfig = (__bridge NSDictionary *)SCNetworkProtocolGetConfiguration(ipv6Protocol);
218 if (ipv6ProtocolConfig != nil) {
219 ipv6Dict = [ipv6ProtocolConfig copy];
220 }
221 CFRelease(ipv6Protocol);
222 }
223
224 // Check that we have at least one IP config method
225 if (ipv4Dict == nil && ipv6Dict == nil) {
226 SCTestLog("Service %@ does not have an IP dictionary", serviceName);
227 return NO;
228 }
229
230 if ([ipv4Dict objectForKey:(__bridge NSString *)kSCPropNetIPv4ConfigMethod] == nil &&
231 [ipv6Dict objectForKey:(__bridge NSString *)kSCPropNetIPv6ConfigMethod] == nil) {
232 SCTestLog("Service %@ does not have an IP Config Method", serviceName);
233 return NO;
234 }
235 }
236 }
237
238 SCTestLog("Verified that the Network Services have valid configurations");
239
240 return YES;
241 }
242
243 static void
244 myNotificationsCallback(SCPreferencesRef prefs, SCPreferencesNotification notificationType, void *ctx)
245 {
246 #pragma unused(prefs)
247 #pragma unused(notificationType)
248 SCTestPreferences *test = (__bridge SCTestPreferences *)ctx;
249 test.counter++;
250 if (test.sem != NULL) {
251 dispatch_semaphore_signal(test.sem);
252 }
253 }
254
255 - (BOOL)unitTestPreferencesNotifications
256 {
257 dispatch_queue_t callbackQ;
258 const int iterations = 10;
259 BOOL ok = FALSE;
260 SCTestPreferences *test;
261 const int timeout = 1; // second
262
263 test = [[SCTestPreferences alloc] initWithOptions:self.options];
264 if (test.prefs != NULL) {
265 CFRelease(test.prefs);
266 test.prefs = NULL;
267 }
268
269 test.sem = dispatch_semaphore_create(0);
270
271 SCPreferencesContext ctx = {0, (__bridge void * _Nullable)(test), CFRetain, CFRelease, NULL};
272 NSDictionary *prefsOptions = @{(__bridge NSString *)kSCPreferencesOptionRemoveWhenEmpty:(__bridge NSNumber *)kCFBooleanTrue};
273 test.prefs = SCPreferencesCreateWithOptions(NULL,
274 CFSTR("SCTest"),
275 CFSTR("SCTestPreferences.plist"),
276 kSCPreferencesUseEntitlementAuthorization,
277 (__bridge CFDictionaryRef)prefsOptions);
278 if (test.prefs == NULL) {
279 SCTestLog("Failed to create SCPreferences. Error: %s", SCErrorString(SCError()));
280 ok = FALSE;
281 goto done;
282 }
283
284 ok = SCPreferencesSetCallback(test.prefs, myNotificationsCallback, &ctx);
285 if (!ok) {
286 SCTestLog("Failed to set callback. Error: %s", SCErrorString(SCError()));
287 goto done;
288 }
289
290 callbackQ = dispatch_queue_create("SCTestPreferences callback queue", NULL);
291 ok = SCPreferencesSetDispatchQueue(test.prefs, callbackQ);
292 if (!ok) {
293 SCTestLog("Failed to set dispatch queue. Error: %s", SCErrorString(SCError()));
294 goto done;
295 }
296
297 for (int i = 0; i < iterations; i++) {
298 NSUUID *uuid = [NSUUID UUID];
299 ok = SCPreferencesSetValue(test.prefs, CFSTR("test"), (__bridge CFStringRef)uuid.UUIDString);
300 if (!ok) {
301 SCTestLog("Failed to set value. Error: %s", SCErrorString(SCError()));
302 goto done;
303 }
304 ok = SCPreferencesCommitChanges(test.prefs);
305 if (!ok) {
306 SCTestLog("Failed to commit change. Error: %s", SCErrorString(SCError()));
307 goto done;
308 }
309 if (dispatch_semaphore_wait(test.sem, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC))) {
310 SCTestLog("Failed to get SCPreferences notification callback: #%d", i);
311 ok = FALSE;
312 goto done;
313 }
314 }
315
316 ok = SCPreferencesRemoveValue(test.prefs, CFSTR("test"));
317 if (!ok) {
318 SCTestLog("Failed to remove value. Error: %s", SCErrorString(SCError()));
319 goto done;
320 }
321 ok = SCPreferencesCommitChanges(test.prefs);
322 if (!ok) {
323 SCTestLog("Failed to commit change. Error: %s", SCErrorString(SCError()));
324 goto done;
325 }
326 if (dispatch_semaphore_wait(test.sem, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC))) {
327 SCTestLog("Failed to get SCPreferences notification callback: cleanup");
328 ok = FALSE;
329 goto done;
330 }
331
332 ok = SCPreferencesSetDispatchQueue(test.prefs, NULL);
333 if (!ok) {
334 SCTestLog("Failed to clear dispatch queue. Error: %s", SCErrorString(SCError()));
335 goto done;
336 }
337
338 SCTestLog("Verified that %d SCPreferences notification callbacks were delivered", iterations);
339
340 done :
341
342 CFRelease(test.prefs);
343 test.prefs = NULL;
344
345 return ok;
346 }
347
348 #define PREFS_OBSERVER_DOMAIN "com.apple.sctest"
349 #define PREFS_OBSERVER_PLIST PREFS_OBSERVER_DOMAIN ".plist"
350 #define MANAGED_PREFERENCES_PATH "/Library/Managed Preferences"
351 #if !TARGET_OS_IPHONE
352 #define PREFS_OBSERVER_KEY "com.apple.MCX._managementStatusChangedForDomains"
353 #define PREFS_OBSERVER_TYPE scprefs_observer_type_mcx
354 #define MANAGED_PREFERENCES_USER kCFPreferencesAnyUser
355 #else
356 #define PREFS_OBSERVER_KEY "com.apple.ManagedConfiguration.profileListChanged"
357 #define PREFS_OBSERVER_TYPE scprefs_observer_type_global
358 #define MANAGED_PREFERENCES_MOBILE_PATH MANAGED_PREFERENCES_PATH "/mobile"
359 #define MANAGED_PREFERENCES_USER CFSTR("mobile")
360 #endif
361
362 #import <CoreFoundation/CFPreferences_Private.h>
363
364 - (BOOL)unitTestPreferencesObserver
365 {
366 dispatch_queue_t callbackQ;
367 const int iterations = 10;
368 scprefs_observer_t observer;
369 Boolean ok = FALSE;
370 SCTestPreferences *test;
371 const int timeout = 1; // second
372
373 test = [[SCTestPreferences alloc] initWithOptions:self.options];
374 if (test.prefs != NULL) {
375 CFRelease(test.prefs);
376 test.prefs = NULL;
377 }
378
379 test.sem = dispatch_semaphore_create(0);
380
381 callbackQ = dispatch_queue_create("SCTestPreferences callback queue", NULL);
382 observer = _scprefs_observer_watch(PREFS_OBSERVER_TYPE, PREFS_OBSERVER_PLIST, callbackQ, ^{
383 test.counter++;
384 if (test.sem != NULL) {
385 dispatch_semaphore_signal(test.sem);
386 }
387 });
388
389 NSDictionary *prefsOptions = @{(__bridge NSString *)kSCPreferencesOptionRemoveWhenEmpty:(__bridge NSNumber *)kCFBooleanTrue};
390 test.prefs = SCPreferencesCreateWithOptions(NULL,
391 CFSTR("SCTest"),
392 CFSTR(MANAGED_PREFERENCES_PATH "/" PREFS_OBSERVER_PLIST),
393 NULL,
394 (__bridge CFDictionaryRef)prefsOptions);
395 if (test.prefs == NULL) {
396 SCTestLog("Failed to create SCPreferences. Error: %s", SCErrorString(SCError()));
397 goto done;
398 }
399
400 // let's make sure that the "/Library/Managed Configuration[/mobile]" directory exists
401 mkdir(MANAGED_PREFERENCES_PATH, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
402 #if TARGET_OS_IPHONE
403 mkdir(MANAGED_PREFERENCES_MOBILE_PATH, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
404 #endif // TARGET_OS_IPHONE
405
406 for (int i = 0; i < iterations; i++) {
407 // update prefs
408 NSUUID *uuid = [NSUUID UUID];
409 NSDictionary *keysAndValues = @{@"test" : uuid.UUIDString};
410 ok = _CFPreferencesWriteManagedDomain((__bridge CFDictionaryRef)keysAndValues,
411 MANAGED_PREFERENCES_USER,
412 FALSE,
413 CFSTR(PREFS_OBSERVER_DOMAIN));
414 if (!ok) {
415 SCTestLog("Failed to write (update) managed preferences");
416 goto done;
417 }
418 #if TARGET_OS_IPHONE
419 notify_post(PREFS_OBSERVER_KEY);
420 #endif // TARGET_OS_IPHONE
421 if (dispatch_semaphore_wait(test.sem, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC))) {
422 SCTestLog("Failed to get SCPreferences observer callback: #%d", i);
423 ok = FALSE;
424 goto done;
425 }
426 }
427
428 // post w/no changes
429 notify_post(PREFS_OBSERVER_KEY);
430 [test waitFor:0.01]; // delay after unrelated change
431
432 // zap prefs
433 ok = _CFPreferencesWriteManagedDomain((__bridge CFDictionaryRef)[NSDictionary dictionary],
434 MANAGED_PREFERENCES_USER,
435 FALSE,
436 CFSTR(PREFS_OBSERVER_DOMAIN));
437 if (!ok) {
438 SCTestLog("Failed to write (remove) managed preferences");
439 goto done;
440 }
441 #if TARGET_OS_IPHONE
442 notify_post(PREFS_OBSERVER_KEY);
443 #endif // TARGET_OS_IPHONE
444 if (dispatch_semaphore_wait(test.sem, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC))) {
445 SCTestLog("Failed to get SCPreferences observer callback: cleanup");
446 ok = FALSE;
447 goto done;
448 }
449
450 SCTestLog("Verified that %d CF/SCPreferences observer callbacks were delivered", iterations);
451
452 done :
453
454 _scprefs_observer_cancel(observer);
455
456 // cleanup the "/Library/Managed Configuration[/mobile]" directory
457 #if TARGET_OS_IPHONE
458 rmdir(MANAGED_PREFERENCES_MOBILE_PATH);
459 #endif // TARGET_OS_IPHONE
460 rmdir(MANAGED_PREFERENCES_PATH);
461
462 return ok;
463 }
464
465 - (BOOL)unitTestPreferencesSession
466 {
467 SCPreferencesRef prefs;
468
469 prefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("SCTest"), NULL);
470 if (prefs == NULL) {
471 SCTestLog("Failed to create SCPreferences. Error: %s", SCErrorString(SCError()));
472 return NO;
473 }
474 CFRelease(prefs);
475
476 prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization, NULL);
477 if (prefs == NULL) {
478 SCTestLog("Failed to create SCPreferences w/options. Error: %s", SCErrorString(SCError()));
479 return NO;
480 }
481 CFRelease(prefs);
482
483 prefs = SCPreferencesCreateWithAuthorization(kCFAllocatorDefault, CFSTR("SCTest"), NULL, kSCPreferencesUseEntitlementAuthorization);
484 if (prefs == NULL) {
485 SCTestLog("Failed to create SCPreferences w/options. Error: %s", SCErrorString(SCError()));
486 return NO;
487 }
488 CFRelease(prefs);
489
490 SCTestLog("Verified that the preferences session can be created");
491 return YES;
492 }
493
494 - (BOOL)unitTestPreferencesAPI
495 {
496 BOOL ok = NO;
497 int iterations = 100;
498 NSDictionary *prefsOptions;
499 NSMutableArray *keys;
500 NSMutableArray *values;
501 SCTestPreferences *test;
502 NSArray *keyList;
503
504 test = [[SCTestPreferences alloc] initWithOptions:self.options];
505 if (test.prefs != NULL) {
506 CFRelease(test.prefs);
507 test.prefs = NULL;
508 }
509
510 prefsOptions = @{(__bridge NSString *)kSCPreferencesOptionRemoveWhenEmpty:(__bridge NSNumber *)kCFBooleanTrue};
511 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
512 CFSTR("SCTest"),
513 CFSTR("SCTestPreferences.plist"),
514 kSCPreferencesUseEntitlementAuthorization,
515 (__bridge CFDictionaryRef)prefsOptions);
516 if (test.prefs == NULL) {
517 SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
518 return NO;
519 }
520
521 keys = [[NSMutableArray alloc] init];
522 values = [[NSMutableArray alloc] init];
523 for (int i = 0; i < iterations; i++) {
524 NSUUID *uuidKey = [NSUUID UUID];
525 NSUUID *uuidValue = [NSUUID UUID];
526
527 ok = SCPreferencesLock(test.prefs, true);
528 if (!ok) {
529 SCTestLog("Failed to get preferences lock. Error: %s", SCErrorString(SCError()));
530 return NO;
531 }
532
533 ok = SCPreferencesSetValue(test.prefs, (__bridge CFStringRef)uuidKey.UUIDString, (__bridge CFStringRef)uuidValue.UUIDString);
534 if (!ok) {
535 SCTestLog("Failed to set preferences value. Error: %s", SCErrorString(SCError()));
536 return NO;
537 }
538
539 ok = SCPreferencesUnlock(test.prefs);
540 if (!ok) {
541 SCTestLog("Failed to release preferences lock. Error: %s", SCErrorString(SCError()));
542 return NO;
543 }
544
545 [keys addObject:uuidKey.UUIDString];
546 [values addObject:uuidValue.UUIDString];
547 }
548
549 ok = SCPreferencesCommitChanges(test.prefs);
550 if (!ok) {
551 SCTestLog("Failed to commit preferences. Error: %s", SCErrorString(SCError()));
552 return NO;
553 }
554
555 CFRelease(test.prefs);
556 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
557 CFSTR("SCTest"),
558 CFSTR("SCTestPreferences.plist"),
559 kSCPreferencesUseEntitlementAuthorization,
560 (__bridge CFDictionaryRef)prefsOptions);
561 if (test.prefs == NULL) {
562 SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
563 return NO;
564 }
565
566 keyList = (__bridge_transfer NSArray *)SCPreferencesCopyKeyList(test.prefs);
567 if ([keyList count] < [keys count]) {
568 SCTestLog("Failed to copy all keys from preferences. Error: %s", SCErrorString(SCError()));
569 return NO;
570 }
571
572 for (NSString *key in keys) {
573 NSString *valueString = (__bridge NSString *)SCPreferencesGetValue(test.prefs, (__bridge CFStringRef)key);
574 if (!valueString) {
575 SCTestLog("Failed to get value from preferences. Error: %s", SCErrorString(SCError()));
576 return NO;
577 }
578
579 BOOL ok = [values containsObject:valueString];
580 if (!ok) {
581 SCTestLog("Incorrect value fetched from preferences");
582 return NO;
583 }
584 }
585
586 ok = SCPreferencesRemoveAllValues(test.prefs);
587 if (!ok) {
588 SCTestLog("Failed to remove values preferences. Error: %s", SCErrorString(SCError()));
589 return NO;
590 }
591
592 ok = SCPreferencesCommitChanges(test.prefs);
593 if (!ok) {
594 SCTestLog("Failed to commit preferences. Error: %s", SCErrorString(SCError()));
595 return NO;
596 }
597
598 CFRelease(test.prefs);
599 test.prefs = SCPreferencesCreateWithOptions(kCFAllocatorDefault,
600 CFSTR("SCTest"),
601 CFSTR("SCTestPreferences.plist"),
602 kSCPreferencesUseEntitlementAuthorization,
603 (__bridge CFDictionaryRef)prefsOptions);
604 if (test.prefs == NULL) {
605 SCTestLog("Failed to create a preferences session. Error: %s", SCErrorString(SCError()));
606 return NO;
607 }
608
609 keyList = (__bridge_transfer NSArray *)SCPreferencesCopyKeyList(test.prefs);
610 if ([keyList count] > 0) {
611 SCTestLog("Failed to remove all keys from preferences. Error: %s", SCErrorString(SCError()));
612 return NO;
613 }
614
615 SCTestLog("Verified that SCPreferences APIs behave as expected");
616 return ok;
617 }
618
619 - (void)cleanupAndExitWithErrorCode:(int)error
620 {
621 [super cleanupAndExitWithErrorCode:error];
622 }
623
624 @end