Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #library("test_runner"); | 5 #library("test_runner"); |
| 6 | 6 |
| 7 #import("status_file_parser.dart"); | 7 #import("status_file_parser.dart"); |
| 8 #import("test_progress.dart"); | 8 #import("test_progress.dart"); |
| 9 #import("test_suite.dart"); | 9 #import("test_suite.dart"); |
| 10 | 10 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 Date _startTime; | 169 Date _startTime; |
| 170 Timer _timer; | 170 Timer _timer; |
| 171 | 171 |
| 172 DartcBatchRunnerProcess(String this._executable) { | 172 DartcBatchRunnerProcess(String this._executable) { |
| 173 _startProcess(); | 173 _startProcess(); |
| 174 } | 174 } |
| 175 | 175 |
| 176 bool get active() => _currentTest != null; | 176 bool get active() => _currentTest != null; |
| 177 | 177 |
| 178 void startTest(TestCase testCase) { | 178 void startTest(TestCase testCase) { |
| 179 _currentTest = testCase; | |
| 180 if (testCase.executablePath != _executable) { | |
| 181 // Restart this runner with the right executable for this test. | |
| 182 _executable = testCase.executablePath; | |
| 183 _process.exitHandler = (exitCode) { | |
| 184 _process.close(); | |
| 185 _startProcess(); | |
| 186 doStartTest(testCase); | |
| 187 }; | |
| 188 _process.kill(); | |
| 189 } else { | |
| 190 doStartTest(testCase); | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 void terminate() { | |
| 195 _process.exitHandler = (exitCode) { | |
| 196 _process.close(); | |
| 197 }; | |
| 198 _process.kill(); | |
| 199 } | |
| 200 | |
| 201 void doStartTest(TestCase testCase) { | |
| 179 _startTime = new Date.now(); | 202 _startTime = new Date.now(); |
| 180 _currentTest = testCase; | |
| 181 _testStdout = new List<String>(); | 203 _testStdout = new List<String>(); |
| 182 _testStderr = new List<String>(); | 204 _testStderr = new List<String>(); |
| 183 _stdoutStream.dataHandler = _readOutput(_stdoutStream, _testStdout); | 205 _stdoutStream.dataHandler = _readOutput(_stdoutStream, _testStdout); |
| 184 _stderrStream.dataHandler = _readOutput(_stderrStream, _testStderr); | 206 _stderrStream.dataHandler = _readOutput(_stderrStream, _testStderr); |
| 185 _timer = new Timer(_timeoutHandler(testCase), | 207 _timer = new Timer(_timeoutHandler(testCase), |
| 186 testCase.timeout * 1000, | 208 testCase.timeout * 1000, |
| 187 false); | 209 false); |
| 188 _process.stdin.write(_createArgumentsLine(testCase.arguments).charCodes()); | 210 _process.stdin.write(_createArgumentsLine(testCase.arguments).charCodes()); |
| 189 } | 211 } |
| 190 | 212 |
| 191 void terminate() { | |
| 192 _process.exitHandler = (exitCode) { | |
| 193 _process.close(); | |
| 194 }; | |
| 195 _process.kill(); | |
| 196 } | |
| 197 | |
| 198 String _createArgumentsLine(List<String> arguments) { | 213 String _createArgumentsLine(List<String> arguments) { |
| 199 var buffer = new StringBuffer(); | 214 var buffer = new StringBuffer(); |
| 200 for (var i = 0; i < arguments.length; i++) { | 215 for (var i = 0; i < arguments.length; i++) { |
| 201 buffer.add("${arguments[i]} "); | 216 buffer.add("${arguments[i]} "); |
| 202 } | 217 } |
| 203 buffer.add("\n"); | 218 buffer.add("\n"); |
| 204 return buffer.toString(); | 219 return buffer.toString(); |
| 205 } | 220 } |
| 206 | 221 |
| 207 int _reportResult(String output) { | 222 int _reportResult(String output) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 _process.exitHandler = _exitHandler; | 289 _process.exitHandler = _exitHandler; |
| 275 _process.start(); | 290 _process.start(); |
| 276 } | 291 } |
| 277 } | 292 } |
| 278 | 293 |
| 279 | 294 |
| 280 class ProcessQueue { | 295 class ProcessQueue { |
| 281 int _numProcesses = 0; | 296 int _numProcesses = 0; |
| 282 int _activeTestListers = 0; | 297 int _activeTestListers = 0; |
| 283 int _maxProcesses; | 298 int _maxProcesses; |
| 299 Function _enqueueMoreWork; | |
| 284 Queue<TestCase> _tests; | 300 Queue<TestCase> _tests; |
| 285 ProgressIndicator _progress; | 301 ProgressIndicator _progress; |
| 286 | 302 // For dartc batch processing we keep a list of batch processes. |
| 287 // For dartc batch processing we keep a list of batch processes for | 303 List<DartcBatchRunnerProcess> _batchProcesses; |
| 288 // each of debug and release mode. If dartc tests are run in both | |
| 289 // release and debug mode this will spawn many processes but only | |
| 290 // half of them will be active at a time. | |
| 291 Map<String, List<DartcBatchRunnerProcess>> _batchProcessesMap; | |
| 292 | 304 |
| 293 ProcessQueue(int this._maxProcesses, | 305 ProcessQueue(int this._maxProcesses, |
| 294 String progress, | 306 String progress, |
| 295 Date start_time) | 307 Date start_time, |
| 308 Function this._enqueueMoreWork) | |
| 296 : _tests = new Queue<TestCase>(), | 309 : _tests = new Queue<TestCase>(), |
| 297 _progress = new ProgressIndicator.fromName(progress, start_time), | 310 _progress = new ProgressIndicator.fromName(progress, start_time), |
| 298 _batchProcessesMap = new Map<String, List<DartcBatchRunnerProcess>>() { | 311 _batchProcesses = new List<DartcBatchRunnerProcess>() { |
| 299 _maxProcesses = _maxProcesses; | 312 _maxProcesses = _maxProcesses; |
| 313 if (!_enqueueMoreWork(this)) _progress.allDone(); | |
| 300 } | 314 } |
| 301 | 315 |
| 302 void addTestSuite(TestSuite testSuite) { | 316 void addTestSuite(TestSuite testSuite) { |
| 303 _activeTestListers++; | 317 _activeTestListers++; |
| 304 testSuite.forEachTest(_runTest, _testListerDone); | 318 testSuite.forEachTest(_runTest, _testListerDone); |
| 305 } | 319 } |
| 306 | 320 |
| 307 void _testListerDone() { | 321 void _testListerDone() { |
| 308 _activeTestListers--; | 322 _activeTestListers--; |
| 309 _checkDone(); | 323 _checkDone(); |
| 310 } | 324 } |
| 311 | 325 |
| 312 void _checkDone() { | 326 void _checkDone() { |
| 313 if (_activeTestListers == 0 && _tests.isEmpty() && _numProcesses == 0) { | 327 if (_activeTestListers == 0 && |
| 328 !_enqueueMoreWork(this) && | |
|
Bill Hesse
2011/12/02 13:10:06
Should you comment here that enqueueMoreWork is an
Mads Ager (google)
2011/12/02 13:32:49
Yes, I should. Thanks.
| |
| 329 _tests.isEmpty() && | |
| 330 _numProcesses == 0) { | |
| 314 _terminateDartcBatchRunners(); | 331 _terminateDartcBatchRunners(); |
| 315 _progress.allDone(); | 332 _progress.allDone(); |
| 316 } | 333 } |
| 317 } | 334 } |
| 318 | 335 |
| 319 void _runTest(TestCase test) { | 336 void _runTest(TestCase test) { |
| 320 _progress.testAdded(); | 337 _progress.testAdded(); |
| 321 _tests.add(test); | 338 _tests.add(test); |
| 322 _tryRunTest(); | 339 _tryRunTest(); |
| 323 } | 340 } |
| 324 | 341 |
| 325 void _terminateDartcBatchRunners() { | 342 void _terminateDartcBatchRunners() { |
| 326 _batchProcessesMap.forEach((key, value) { | 343 _batchProcesses.forEach((runner) => runner.terminate()); |
| 327 for (int i = 0; i < value.length; i++) { | |
| 328 value[i].terminate(); | |
| 329 } | |
| 330 }); | |
| 331 } | 344 } |
| 332 | 345 |
| 333 DartcBatchRunnerProcess _getDartcBatchRunnerProcess(TestCase test) { | 346 void _ensureDartcBatchRunnersStarted(String executable) { |
| 334 var batchProcesses = _batchProcessesMap[test.executablePath]; | 347 if (_batchProcesses.length == 0) { |
| 335 if (batchProcesses == null) { | |
| 336 // Dartc batch processing is heavy. Scale down the number of | |
| 337 // concurrent tasks to be no more than the actual number of | |
| 338 // processors even when running dartc benchmarks in both debug | |
| 339 // and release mode. | |
| 340 var processors = new Platform().numberOfProcessors(); | |
| 341 if (_maxProcesses >= (processors / 2)) { | |
| 342 _maxProcesses = (processors / 2).toInt(); | |
| 343 } | |
| 344 batchProcesses = new List<DartcBatchRunnerProcess>(_maxProcesses); | |
| 345 _batchProcessesMap[test.executablePath] = batchProcesses; | |
| 346 for (int i = 0; i < _maxProcesses; i++) { | 348 for (int i = 0; i < _maxProcesses; i++) { |
| 347 batchProcesses[i] = new DartcBatchRunnerProcess(test.executablePath); | 349 _batchProcesses.add(new DartcBatchRunnerProcess(executable)); |
| 348 } | 350 } |
| 349 } | 351 } |
| 350 for (int i = 0; i < batchProcesses.length; i++) { | 352 } |
| 351 var runner = batchProcesses[i]; | 353 |
| 354 DartcBatchRunnerProcess _getDartcBatchRunnerProcess() { | |
| 355 for (int i = 0; i < _batchProcesses.length; i++) { | |
| 356 var runner = _batchProcesses[i]; | |
| 352 if (!runner.active) return runner; | 357 if (!runner.active) return runner; |
| 353 } | 358 } |
| 354 throw new Exception('Unable to find inactive batch runner.'); | 359 throw new Exception('Unable to find inactive batch runner.'); |
| 355 } | 360 } |
| 356 | 361 |
| 357 void _tryRunTest() { | 362 void _tryRunTest() { |
| 358 _checkDone(); | 363 _checkDone(); |
| 359 if (_numProcesses < _maxProcesses && !_tests.isEmpty()) { | 364 if (_numProcesses < _maxProcesses && !_tests.isEmpty()) { |
| 360 TestCase test = _tests.removeFirst(); | 365 TestCase test = _tests.removeFirst(); |
| 361 _progress.start(test); | 366 _progress.start(test); |
| 362 Function oldCallback = test.completedHandler; | 367 Function oldCallback = test.completedHandler; |
| 363 Function wrapper = (TestCase test_arg) { | 368 Function wrapper = (TestCase test_arg) { |
| 364 _numProcesses--; | 369 _numProcesses--; |
| 365 _progress.done(test_arg); | 370 _progress.done(test_arg); |
| 366 _tryRunTest(); | 371 _tryRunTest(); |
| 367 oldCallback(test_arg); | 372 oldCallback(test_arg); |
| 368 }; | 373 }; |
| 369 test.completedHandler = wrapper; | 374 test.completedHandler = wrapper; |
| 370 if (test.executablePath.contains('dartc_test')) { | 375 if (test.executablePath.contains('compiler')) { |
| 371 _getDartcBatchRunnerProcess(test).startTest(test); | 376 _ensureDartcBatchRunnersStarted(test.executablePath); |
| 377 _getDartcBatchRunnerProcess().startTest(test); | |
| 372 } else { | 378 } else { |
| 373 new RunningProcess(test).start(); | 379 new RunningProcess(test).start(); |
| 374 } | 380 } |
| 375 _numProcesses++; | 381 _numProcesses++; |
| 376 } | 382 } |
| 377 } | 383 } |
| 378 } | 384 } |
| OLD | NEW |