16
16
#import " bp/src/SimulatorHelper.h"
17
17
#import " BPPacker.h"
18
18
#import " BPRunner.h"
19
+ #import " BPSwimlane.h"
19
20
20
21
#include < mach/mach.h>
21
22
#include < mach/mach_host.h>
@@ -69,66 +70,6 @@ + (instancetype)BPRunnerWithConfig:(BPConfiguration *)config
69
70
return runner;
70
71
}
71
72
72
- - (NSTask *)newTaskWithBundle : (BPXCTestFile *)bundle
73
- andNumber : (NSUInteger )number
74
- andDevice : (NSString *)deviceID
75
- andCompletionBlock : (void (^)(NSTask *))block {
76
- BPConfiguration *cfg = [self .config mutableCopy ];
77
- assert (cfg);
78
- cfg.appBundlePath = bundle.UITargetAppPath ?: bundle.testHostPath ;
79
- cfg.testBundlePath = bundle.testBundlePath ;
80
- cfg.testRunnerAppPath = bundle.UITargetAppPath ? bundle.testHostPath : nil ;
81
- cfg.testCasesToSkip = bundle.skipTestIdentifiers ;
82
- if (cfg.commandLineArguments ) {
83
- [cfg.commandLineArguments arrayByAddingObjectsFromArray: bundle.commandLineArguments];
84
- } else {
85
- cfg.commandLineArguments = bundle.commandLineArguments ;
86
- }
87
- if (cfg.environmentVariables ) {
88
- NSMutableDictionary *newEnv = [[NSMutableDictionary alloc ] initWithDictionary: cfg.environmentVariables];
89
- for (NSString *key in bundle.environmentVariables ) {
90
- newEnv[key] = bundle.environmentVariables [key];
91
- }
92
- cfg.environmentVariables = (NSDictionary <NSString *, NSString *>*) newEnv;
93
- } else {
94
- cfg.environmentVariables = bundle.environmentVariables ;
95
- }
96
- cfg.dependencies = bundle.dependencies ;
97
- if (self.config .cloneSimulator ) {
98
- cfg.templateSimUDID = self.testHostSimTemplates [bundle.testHostPath];
99
- }
100
- NSError *err;
101
- NSString *tmpFileName = [NSString stringWithFormat: @" %@ /bluepill-%u -config" ,
102
- NSTemporaryDirectory (),
103
- getpid ()];
104
-
105
- cfg.configOutputFile = [BPUtils mkstemp: tmpFileName withError: &err];
106
- if (!cfg.configOutputFile ) {
107
- fprintf (stderr, " ERROR: %s \n " , [[err localizedDescription ] UTF8String ]);
108
- return nil ;
109
- }
110
- cfg.outputDirectory = [self .config.outputDirectory
111
- stringByAppendingPathComponent:
112
- [NSString stringWithFormat: @" BP-%lu " , (unsigned long )number]];
113
- cfg.testTimeEstimatesJsonFile = self.config .testTimeEstimatesJsonFile ;
114
- [cfg printConfig ];
115
- NSTask *task = [[NSTask alloc ] init ];
116
- [task setLaunchPath: self .bpExecutable];
117
- [task setArguments: @[@" -c" , cfg.configOutputFile]];
118
- NSMutableDictionary *env = [[NSMutableDictionary alloc ] init ];
119
- [env addEntriesFromDictionary: [[NSProcessInfo processInfo ] environment ]];
120
- [env setObject: [NSString stringWithFormat: @" %lu " , number] forKey: @" _BP_NUM" ];
121
- [task setEnvironment: env];
122
- [task setTerminationHandler: ^(NSTask *task) {
123
- [[NSFileManager defaultManager ] removeItemAtPath: cfg.configOutputFile
124
- error: nil ];
125
- [BPUtils printInfo: INFO withString: @" BP-%lu (PID %u ) has finished with exit code %d ." ,
126
- number, [task processIdentifier ], [task terminationStatus ]];
127
- block (task);
128
- }];
129
- return task;
130
- }
131
-
132
73
- (NSTask *)newTaskToDeleteDevice : (NSString *)deviceID andNumber : (NSUInteger )number {
133
74
NSTask *task = [[NSTask alloc ] init ];
134
75
[task setLaunchPath: self .bpExecutable];
@@ -210,15 +151,18 @@ - (int)runWithBPXCTestFiles:(NSArray<BPXCTestFile *> *)xcTestFiles {
210
151
[bundles addObjectsFromArray: copyBundles];
211
152
}
212
153
[BPUtils printInfo: INFO withString: @" Packed tests into %lu bundles" , (unsigned long )[bundles count ]];
213
- __block NSUInteger launchedTasks = 0 ;
214
154
NSUInteger taskNumber = 0 ;
215
155
__block int rc = 0 ;
216
156
157
+ self.swimlaneList = [[NSMutableArray alloc ] initWithCapacity: numSims];
158
+ for (NSUInteger i = 1 ; i <= numSims; i++) {
159
+ BPSwimlane *swimlane = [BPSwimlane BPSwimlaneWithLaneID: i];
160
+ [self .swimlaneList addObject: swimlane];
161
+ }
162
+
217
163
int maxProcs = maxprocs ();
218
164
int seconds = 0 ;
219
- __block NSMutableArray *taskList = [[NSMutableArray alloc ] init ];
220
165
__block NSMutableArray *deviceList = [[NSMutableArray alloc ] init ];
221
- self.nsTaskList = [[NSMutableArray alloc ] init ];
222
166
int old_interrupted = interrupted;
223
167
NSRunningApplication *app;
224
168
if (_config.headlessMode == NO ) {
@@ -244,46 +188,53 @@ - (int)runWithBPXCTestFiles:(NSArray<BPXCTestFile *> *)xcTestFiles {
244
188
int noLaunchedTasks;
245
189
int canLaunchTask;
246
190
@synchronized (self) {
247
- noLaunchedTasks = (launchedTasks == 0 );
248
- canLaunchTask = (launchedTasks < numSims);
191
+ NSUInteger busySwimlaneCount = [self busySwimlaneCount ];
192
+ noLaunchedTasks = (busySwimlaneCount == 0 );
193
+ canLaunchTask = (busySwimlaneCount < numSims);
249
194
}
250
195
if (noLaunchedTasks && (bundles.count == 0 || interrupted)) break ;
251
196
if (bundles.count > 0 && canLaunchTask && !interrupted) {
252
197
NSString *deviceID = nil ;
198
+ BPSwimlane *swimlane = nil ;
253
199
@synchronized (self) {
254
200
if ([deviceList count ] > 0 ) {
255
201
deviceID = [deviceList objectAtIndex: 0 ];
256
202
[deviceList removeObjectAtIndex: 0 ];
257
203
}
204
+ swimlane = [self firstIdleSwimlane ];
205
+ swimlane.isBusy = YES ;
258
206
}
259
- NSTask *task = [self newTaskWithBundle: [bundles objectAtIndex: 0 ] andNumber: ++taskNumber andDevice: deviceID andCompletionBlock: ^(NSTask * _Nonnull task) {
207
+ BPXCTestFile *bundle = [bundles objectAtIndex: 0 ];
208
+ [swimlane launchTaskWithBundle: bundle
209
+ andConfig: self .config
210
+ andLaunchPath: self .bpExecutable
211
+ andNumber: ++taskNumber
212
+ andDevice: deviceID
213
+ andTemplateSimUDID: self .testHostSimTemplates[bundle.testHostPath]
214
+ andCompletionBlock: ^(NSTask * _Nonnull task) {
260
215
@synchronized (self) {
261
- launchedTasks--;
262
- [taskList removeObject: [NSString stringWithFormat: @" %lu " , taskNumber]];
263
- [self .nsTaskList removeObject: task];
264
216
rc = (rc || [task terminationStatus ]);
265
217
};
266
218
[BPUtils printInfo: INFO withString: @" PID %d exited %d ." , [task processIdentifier ], [task terminationStatus ]];
267
219
rc = (rc || [task terminationStatus ]);
268
220
}];
269
- if (!task) {
270
- [BPUtils printInfo: ERROR withString: @" task is nil!" ];
271
- exit (1 );
272
- }
273
- [task launch ];
274
221
@synchronized (self) {
275
- [taskList addObject: [NSString stringWithFormat: @" %lu " , taskNumber]];
276
- [self .nsTaskList addObject: task];
277
222
[bundles removeObjectAtIndex: 0 ];
278
- [BPUtils printInfo: INFO withString: @" Started BP-%lu (PID %d )." , taskNumber, [task processIdentifier ]];
279
- launchedTasks++;
280
223
}
281
224
}
282
225
sleep (1 );
283
226
if (seconds % 30 == 0 ) {
284
227
NSString *listString;
228
+ NSUInteger launchedTasks = 0 ;
285
229
@synchronized (self) {
286
- listString = [taskList componentsJoinedByString: @" , " ];
230
+ NSMutableArray *taskNumberList = [[NSMutableArray alloc ] init ];
231
+ for (BPSwimlane *swimlane in self.swimlaneList ) {
232
+ if (swimlane.isBusy ) {
233
+ launchedTasks++;
234
+ [taskNumberList addObject: [NSString stringWithFormat: @" %lu " , swimlane.taskNumber]];
235
+ }
236
+ }
237
+ listString = [taskNumberList componentsJoinedByString: @" , " ];
287
238
}
288
239
[BPUtils printInfo: INFO withString: @" %lu BP(s) still running. [%@ ]" , launchedTasks, listString];
289
240
[BPUtils printInfo: INFO withString: @" Using %d of %d processes." , numprocs (), maxProcs];
@@ -319,13 +270,11 @@ - (int)runWithBPXCTestFiles:(NSArray<BPXCTestFile *> *)xcTestFiles {
319
270
}
320
271
321
272
- (void )interrupt {
322
- if (self.nsTaskList == nil ) return ;
273
+ if (self.swimlaneList == nil ) return ;
323
274
324
- for (int i = 0 ; i < [ self .nsTaskList count ]; i++ ) {
325
- [(( NSTask *)[ self .nsTaskList objectAtIndex: i]) interrupt ];
275
+ for (BPSwimlane *swimlane in self.swimlaneList ) {
276
+ [swimlane interrupt ];
326
277
}
327
-
328
- [self .nsTaskList removeAllObjects ];
329
278
}
330
279
331
280
- (void )addCounters {
@@ -390,4 +339,23 @@ - (void)addCounters {
390
339
}
391
340
}
392
341
342
+ - (NSUInteger )busySwimlaneCount {
343
+ NSUInteger count = 0 ;
344
+ for (BPSwimlane *swimlane in self.swimlaneList ) {
345
+ if (swimlane.isBusy ) {
346
+ count++;
347
+ }
348
+ }
349
+ return count;
350
+ }
351
+
352
+ - (BPSwimlane *)firstIdleSwimlane {
353
+ for (BPSwimlane *swimlane in self.swimlaneList ) {
354
+ if (!swimlane.isBusy ) {
355
+ return swimlane;
356
+ }
357
+ }
358
+ return nil ;
359
+ }
360
+
393
361
@end
0 commit comments