]> git.saurik.com Git - apple/security.git/blob - experiment/tool/experimentTool.m
Security-59306.61.1.tar.gz
[apple/security.git] / experiment / tool / experimentTool.m
1 //
2 // experimentTool.m
3 // experimentTool
4 //
5
6 #import <Foundation/Foundation.h>
7 #import <Security/SecExperimentPriv.h>
8 #import <Security/SecTrustPriv.h>
9 #import <CoreFoundation/CFXPCBridge.h>
10 #import <xpc/xpc.h>
11
12 static NSString *kExperimentRunResultKeySkips = @"Skips";
13 static NSString *kExperimentRunResultKeyConfigurations = @"Configurations";
14 static NSString *kExperimentRunResultKeyRuns = @"Runs";
15
16 static NSDictionary<NSString *, NSObject *> *
17 run_experiment(const char *experiment_name, size_t num_runs, bool sampling_disabled)
18 {
19 __block size_t runs = 0;
20 __block size_t skips = 0;
21 __block NSMutableArray<NSDictionary *> *configurations = [[NSMutableArray<NSDictionary *> alloc] init];
22 for (size_t i = 0; i < num_runs; i++) {
23 (void)sec_experiment_run_with_sampling_disabled(experiment_name, ^bool(const char *identifier, xpc_object_t experiment_config) {
24 runs++;
25 CFDictionaryRef configuration = (CFDictionaryRef)_CFXPCCreateCFObjectFromXPCObject(experiment_config);
26 if (configuration != NULL) {
27 [configurations addObject:(__bridge NSDictionary *)configuration];
28 }
29 return true;
30 }, ^(const char * _Nonnull identifier) {
31 skips++;
32 }, sampling_disabled);
33 }
34
35 return @{kExperimentRunResultKeyRuns: @(runs),
36 kExperimentRunResultKeySkips: @(skips),
37 kExperimentRunResultKeyConfigurations: configurations,
38 };
39 }
40
41 static void
42 usage(const char *argv[])
43 {
44 fprintf(stderr, "Usage: %s [-h] [-s] [-e <experiment>] [-n <number of runs>]\n", argv[0]);
45 }
46
47 int
48 main(int argc, const char *argv[])
49 {
50 BOOL showUsage = NO;
51 int arg = 0;
52 char * const *gargv = (char * const *)argv;
53 char *experiment_name = NULL;
54 size_t num_runs = 0;
55 bool sampling_disabled = true;
56 bool update_asset = false;
57 bool read_asset = false;
58 while ((arg = getopt(argc, gargv, "e:n:sruh")) != -1) {
59 switch (arg) {
60 case 'e':
61 experiment_name = strdup(optarg);
62 break;
63 case 'n':
64 num_runs = (size_t)atoi(optarg);
65 break;
66 case 's':
67 sampling_disabled = false;
68 break;
69 case 'r':
70 read_asset = true;
71 break;
72 case 'u':
73 update_asset = true;
74 break;
75 case 'h':
76 showUsage = YES;
77 break;
78 default:
79 fprintf(stderr, "%s: FAILURE: unknown option \"%c\"\n", argv[0], arg);
80 return -1;
81 }
82 }
83
84 if (optind != argc) {
85 fprintf(stderr, "%s: FAILURE: argument missing parameter \"%c\"\n", argv[0], arg);
86 free(experiment_name);
87 return -2;
88 }
89
90 if (showUsage) {
91 usage(argv);
92 free(experiment_name);
93 return EXIT_SUCCESS;
94 }
95
96 uint64_t version = 0;
97 if (update_asset) {
98 CFErrorRef update_error = NULL;
99 version = SecTrustOTASecExperimentGetUpdatedAsset(&update_error);
100 if (update_error != NULL) {
101 NSLog(@"Failed to fetch latest asset: %@", (__bridge NSError *)update_error);
102 free(experiment_name);
103 return -3;
104 } else {
105 NSLog(@"Fetched asset version: %zu", (size_t)version);
106 }
107 }
108
109 if (read_asset) {
110 CFErrorRef copy_error = NULL;
111 NSDictionary *asset = CFBridgingRelease(SecTrustOTASecExperimentCopyAsset(&copy_error));
112 if (copy_error != NULL) {
113 NSLog(@"Failed to copy asset: %@", copy_error);
114 free(experiment_name);
115 return -4;
116 } else {
117 NSLog(@"Copied asset: %@", asset);
118 }
119 }
120
121 if (num_runs > 0) {
122 NSLog(@"Running %zu experiments with asset verison %llu", num_runs, version);
123 NSDictionary<NSString *, NSObject *> *results = run_experiment(experiment_name, num_runs, sampling_disabled);
124 [results enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSObject * _Nonnull obj, BOOL * _Nonnull stop) {
125 NSLog(@"Experiment %@: %@", key, obj);
126 }];
127 } else {
128 NSLog(@"Not running experiment.");
129 }
130
131 free(experiment_name);
132 return EXIT_SUCCESS;
133 }