]> git.saurik.com Git - apple/configd.git/blob - sctest/SCTestUtils.m
configd-1109.60.2.tar.gz
[apple/configd.git] / sctest / SCTestUtils.m
1 /*
2 * Copyright (c) 2016 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 <Foundation/Foundation.h>
25 #import "SCTest.h"
26 #import "SCTestUtils.h"
27 #import <mach/mach_time.h>
28
29 NSArray<NSString *> *
30 getTestClasses()
31 {
32 static NSMutableArray *subclassNames = nil;
33 Class base;
34 unsigned int classListCount;
35 Class *classList;
36
37 if (subclassNames != nil) {
38 return subclassNames;
39 }
40
41 base = [SCTest class];
42 classListCount = 0;
43 classList = objc_copyClassList(&classListCount);
44 subclassNames = [[NSMutableArray alloc] init];
45
46 if (classList) {
47 for (unsigned int i = 0; i < classListCount; i++) {
48 Class superClass = class_getSuperclass(classList[i]);
49 while (superClass && superClass != base) {
50 superClass = class_getSuperclass(superClass);
51 }
52
53 if (superClass == base) {
54 [subclassNames addObject:@(class_getName(classList[i]))];
55 }
56 }
57 free(classList);
58 }
59
60 [subclassNames sortUsingComparator: ^(id obj1, id obj2) {
61 NSString *className1 = obj1;
62 NSString *className2 = obj2;
63 return [className1 compare:className2 options:NSCaseInsensitiveSearch];
64 }];
65
66 return subclassNames;
67 }
68
69 NSArray<NSString *> *
70 getUnitTestListForClass(Class base)
71 {
72 NSMutableArray<NSString *> *unitTestNames = nil;
73 unsigned int methodListCount = 0;
74 Method *methodList = NULL;
75
76 methodList = class_copyMethodList(base, &methodListCount);
77 if (methodList) {
78 unitTestNames = [[NSMutableArray alloc] initWithCapacity:methodListCount];
79 for (unsigned int i = 0; i < methodListCount; i++) {
80 NSString *name = @(sel_getName(method_getName(methodList[i])));
81 if ([name isEqualToString:@"unitTest"]) {
82 continue;
83 } else if (![name hasPrefix:@"unitTest"]) {
84 continue;
85 }
86
87 [unitTestNames addObject:name];
88 }
89 free(methodList);
90 }
91
92 return unitTestNames;
93 }
94
95 NSDictionary *
96 getOptionsDictionary(int argc, const char **argv)
97 {
98 NSMutableDictionary *options;
99 NSNumberFormatter *numberFormatter;
100 int ch;
101 int i;
102 struct option entries[] = {
103 kSCTestOptionEntries
104 };
105
106 options = [NSMutableDictionary dictionary];
107 optind = 0;
108 optreset = 1;
109 numberFormatter = [[NSNumberFormatter alloc] init];
110
111 while ((ch = getopt_long_only(argc, (char * const *)argv, "", entries, &i)) == 0) {
112 struct option opt = entries[i];
113 NSString *optKey = [NSString stringWithFormat:@"%s_Str", opt.name]; // ... "_Str" suffix is standardized across all keys.
114 id optVal = nil;
115
116 if (opt.has_arg) {
117 // Parse the optarg
118
119 // Attempt string
120 optVal = @(optarg);
121
122 if (optVal == nil) {
123 // Fall back to NSData
124 // WARNING: Doesn't work if it contains '\0'
125 optVal = [NSData dataWithBytes:optarg length:strlen(optarg)];
126 } else {
127 // Use NSNumber if the argument is a number
128 NSNumber *number = [numberFormatter numberFromString:optVal];
129 if (number) {
130 optVal = number;
131 }
132 }
133 } else {
134 optVal = @YES;
135 }
136
137 // Handle multiple option instances
138 id existingValue = options[optKey];
139 if (existingValue) {
140 if ([existingValue isKindOfClass:[NSMutableArray class]]) {
141 [(NSMutableArray *)existingValue addObject:optVal];
142 optVal = existingValue;
143 } else if ([existingValue isKindOfClass:[NSArray class]]) {
144 NSMutableArray *tempArray = [NSMutableArray arrayWithArray:existingValue];
145 [tempArray addObject:optVal];
146 optVal = tempArray;
147 } else {
148 optVal = @[existingValue, optVal];
149 }
150 }
151
152 options[optKey] = optVal;
153 }
154
155 if (ch > 0) {
156 return nil;
157 }
158
159 return options;
160 }
161
162 static void
163 cpu_routine(CPUUsageInfoInner *usage)
164 {
165 host_name_port_t host;
166 host_cpu_load_info_data_t host_load;
167 mach_msg_type_number_t count;
168 kern_return_t kret;
169
170 if (usage == NULL) {
171 return;
172 }
173
174 host = mach_host_self();
175 count = HOST_CPU_LOAD_INFO_COUNT;
176 kret = host_statistics(host, HOST_CPU_LOAD_INFO, (host_info_t)&host_load, &count);
177 if (kret) {
178 return;
179 }
180
181 // ms per tick. 1 tick is 10 ms.
182 usage->user = ((uint64_t)host_load.cpu_ticks[CPU_STATE_USER]) * 10;
183 usage->sys = ((uint64_t)host_load.cpu_ticks[CPU_STATE_SYSTEM]) * 10;
184 usage->idle = ((uint64_t)host_load.cpu_ticks[CPU_STATE_IDLE]) * 10;
185 }
186
187 void
188 cpuStart(CPUUsageInfo *cpu)
189 {
190 cpu_routine(&cpu->startCPU);
191 }
192
193 void
194 cpuEnd(CPUUsageInfo *cpu)
195 {
196 cpu_routine(&cpu->endCPU);
197 }
198
199 NSString *
200 createUsageStringForCPU(CPUUsageInfo *cpu)
201 {
202 uint64_t userelapsed = cpu->endCPU.user - cpu->startCPU.user;
203 uint64_t systemelapsed = cpu->endCPU.sys - cpu->startCPU.sys;
204 uint64_t idleelapsed = cpu->endCPU.idle - cpu->startCPU.idle;
205 uint64_t totalelapsed = userelapsed + systemelapsed + idleelapsed;
206 double u = ((double)userelapsed * 100)/totalelapsed;
207 double s = ((double)systemelapsed * 100)/totalelapsed;
208 double i = ((double)idleelapsed * 100)/totalelapsed;
209
210 return [NSString stringWithFormat:@"%1.02f%% user %1.02f%% sys %1.02f%% idle", u, s, i];
211 }
212
213 static void
214 timer_routine(struct timespec *ts)
215 {
216 uint64_t diff;
217 static uint32_t orwl_timebase_numer = 0;
218 static uint32_t orwl_timebase_denom = 0;
219 static uint64_t orwl_timestart = 0;
220 if (orwl_timestart == 0) {
221 mach_timebase_info_data_t tb = { 0, 0 };
222 mach_timebase_info(&tb);
223 orwl_timebase_numer = tb.numer;
224 orwl_timebase_denom = tb.denom;
225 orwl_timestart = mach_absolute_time();
226 }
227 if (0 == orwl_timebase_denom) {
228 orwl_timebase_denom = 1;
229 }
230 diff = ((mach_absolute_time() - orwl_timestart) * orwl_timebase_numer) / orwl_timebase_denom;
231 ts->tv_sec = (size_t)(diff / NSEC_PER_SEC);
232 ts->tv_nsec = (size_t)(diff - (ts->tv_sec * NSEC_PER_SEC));
233 }
234
235 void
236 timerStart(timerInfo *timer)
237 {
238 timer_routine(&timer->startTime);
239 }
240
241 void
242 timerEnd(timerInfo *timer)
243 {
244 timer_routine(&timer->endTime);
245 }
246
247 NSString *
248 createUsageStringForTimer(timerInfo *timer)
249 {
250 double elapsed;
251 int64_t nsecs = timer->endTime.tv_nsec - timer->startTime.tv_nsec;
252 uint64_t secs = timer->endTime.tv_sec - timer->startTime.tv_sec;
253 if (nsecs < 0) {
254 nsecs += NSEC_PER_SEC;
255 secs -= 1;
256 }
257
258 elapsed = (double)secs + (double)nsecs / NSEC_PER_SEC;
259 return [NSString stringWithFormat:@"%f", elapsed];
260 }