6 #import <Foundation/Foundation.h>
7 #import <Security/SecExperimentPriv.h>
8 #import <Security/SecTrustPriv.h>
9 #import <CoreFoundation/CFXPCBridge.h>
12 static NSString *kExperimentRunResultKeySkips = @"Skips";
13 static NSString *kExperimentRunResultKeyConfigurations = @"Configurations";
14 static NSString *kExperimentRunResultKeyRuns = @"Runs";
16 static NSDictionary<NSString *, NSObject *> *
17 run_experiment(const char *experiment_name, size_t num_runs, bool sampling_disabled)
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) {
25 CFDictionaryRef configuration = (CFDictionaryRef)_CFXPCCreateCFObjectFromXPCObject(experiment_config);
26 if (configuration != NULL) {
27 [configurations addObject:(__bridge NSDictionary *)configuration];
30 }, ^(const char * _Nonnull identifier) {
32 }, sampling_disabled);
35 return @{kExperimentRunResultKeyRuns: @(runs),
36 kExperimentRunResultKeySkips: @(skips),
37 kExperimentRunResultKeyConfigurations: configurations,
42 usage(const char *argv[])
44 fprintf(stderr, "Usage: %s [-h] [-s] [-e <experiment>] [-n <number of runs>]\n", argv[0]);
48 main(int argc, const char *argv[])
52 char * const *gargv = (char * const *)argv;
53 char *experiment_name = NULL;
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) {
61 experiment_name = strdup(optarg);
64 num_runs = (size_t)atoi(optarg);
67 sampling_disabled = false;
79 fprintf(stderr, "%s: FAILURE: unknown option \"%c\"\n", argv[0], arg);
85 fprintf(stderr, "%s: FAILURE: argument missing parameter \"%c\"\n", argv[0], arg);
86 free(experiment_name);
92 free(experiment_name);
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);
105 NSLog(@"Fetched asset version: %zu", (size_t)version);
110 CFErrorRef copy_error = NULL;
111 NSDictionary *asset = CFBridgingRelease(SecTrustOTASecExperimentCopyAsset(©_error));
112 if (copy_error != NULL) {
113 NSLog(@"Failed to copy asset: %@", copy_error);
114 free(experiment_name);
117 NSLog(@"Copied asset: %@", asset);
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);
128 NSLog(@"Not running experiment.");
131 free(experiment_name);