Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 schedule; | 5 library schedule; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import '../../../../pkg/unittest/lib/unittest.dart' as unittest; | 10 import '../../../../pkg/unittest/lib/unittest.dart' as unittest; |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 // registered in the error list and re-throw it. | 150 // registered in the error list and re-throw it. |
| 151 _addError(e); | 151 _addError(e); |
| 152 throw e; | 152 throw e; |
| 153 }); | 153 }); |
| 154 }).whenComplete(() { | 154 }).whenComplete(() { |
| 155 if (_timeoutTimer != null) _timeoutTimer.cancel(); | 155 if (_timeoutTimer != null) _timeoutTimer.cancel(); |
| 156 _state = ScheduleState.DONE; | 156 _state = ScheduleState.DONE; |
| 157 }); | 157 }); |
| 158 } | 158 } |
| 159 | 159 |
| 160 /// Stop the current [TaskQueue] after the current task and any out-of-band | |
| 161 /// tasks stop executing. If this is called before [this] has started running, | |
| 162 /// no tasks in the [tasks] queue will be run. | |
| 163 /// | |
| 164 /// This won't cause an error, but any errors that are otherwise signaled will | |
| 165 /// still cause the test to fail. | |
| 166 void abort() { | |
| 167 if (_state == ScheduleState.DONE) { | |
| 168 throw new StateError("abort called after the schedule has finished " | |
|
Bob Nystrom
2013/03/14 22:29:18
"abort called" -> "Aborted" or "Called abort()"
nweiz
2013/03/14 22:37:23
Done.
| |
| 169 "running."); | |
| 170 } | |
| 171 | |
| 172 currentQueue._abort(); | |
| 173 } | |
| 174 | |
| 160 /// Signals that an out-of-band error has occurred. Using [wrapAsync] along | 175 /// Signals that an out-of-band error has occurred. Using [wrapAsync] along |
| 161 /// with `throw` is usually preferable to calling this directly. | 176 /// with `throw` is usually preferable to calling this directly. |
| 162 /// | 177 /// |
| 163 /// The metadata in [AsyncError]s and [ScheduleError]s will be preserved. | 178 /// The metadata in [AsyncError]s and [ScheduleError]s will be preserved. |
| 164 void signalError(error, [stackTrace]) { | 179 void signalError(error, [stackTrace]) { |
| 165 heartbeat(); | 180 heartbeat(); |
| 166 | 181 |
| 167 var scheduleError = new ScheduleError.from(this, error, | 182 var scheduleError = new ScheduleError.from(this, error, |
| 168 stackTrace: stackTrace); | 183 stackTrace: stackTrace); |
| 169 if (_state == ScheduleState.DONE) { | 184 if (_state == ScheduleState.DONE) { |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 335 ScheduleError _error; | 350 ScheduleError _error; |
| 336 | 351 |
| 337 /// The [SubstituteFuture] for the currently-running task in the queue, or | 352 /// The [SubstituteFuture] for the currently-running task in the queue, or |
| 338 /// null if no task is currently running. | 353 /// null if no task is currently running. |
| 339 SubstituteFuture _taskFuture; | 354 SubstituteFuture _taskFuture; |
| 340 | 355 |
| 341 /// The toal number of out-of-band callbacks that have been registered on | 356 /// The toal number of out-of-band callbacks that have been registered on |
| 342 /// [this]. | 357 /// [this]. |
| 343 int _totalCallbacks = 0; | 358 int _totalCallbacks = 0; |
| 344 | 359 |
| 360 /// Whether to stop running after the current task. | |
| 361 bool _aborted = false; | |
| 362 | |
| 345 // TODO(nweiz): make this a read-only view when issue 8321 is fixed. | 363 // TODO(nweiz): make this a read-only view when issue 8321 is fixed. |
| 346 /// The descriptions of all callbacks that are blocking the completion of | 364 /// The descriptions of all callbacks that are blocking the completion of |
| 347 /// [this]. | 365 /// [this]. |
| 348 Collection<String> get pendingCallbacks => _pendingCallbacks; | 366 Collection<String> get pendingCallbacks => _pendingCallbacks; |
| 349 final _pendingCallbacks = new Queue<String>(); | 367 final _pendingCallbacks = new Queue<String>(); |
| 350 | 368 |
| 351 /// A completer that will be completed once [_pendingCallbacks] becomes empty | 369 /// A completer that will be completed once [_pendingCallbacks] becomes empty |
| 352 /// after the queue finishes running its tasks. | 370 /// after the queue finishes running its tasks. |
| 353 Future get _noPendingCallbacks => _noPendingCallbacksCompleter.future; | 371 Future get _noPendingCallbacks => _noPendingCallbacksCompleter.future; |
| 354 final Completer _noPendingCallbacksCompleter = new Completer(); | 372 final Completer _noPendingCallbacksCompleter = new Completer(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 411 return task.result; | 429 return task.result; |
| 412 } | 430 } |
| 413 | 431 |
| 414 /// Runs all the tasks in this queue in order. | 432 /// Runs all the tasks in this queue in order. |
| 415 Future _run() { | 433 Future _run() { |
| 416 _schedule._currentQueue = this; | 434 _schedule._currentQueue = this; |
| 417 _schedule.heartbeat(); | 435 _schedule.heartbeat(); |
| 418 return Future.forEach(_contents, (task) { | 436 return Future.forEach(_contents, (task) { |
| 419 _schedule._currentTask = task; | 437 _schedule._currentTask = task; |
| 420 if (_error != null) throw _error; | 438 if (_error != null) throw _error; |
| 439 if (_aborted) return; | |
| 421 | 440 |
| 422 _taskFuture = new SubstituteFuture(task.fn()); | 441 _taskFuture = new SubstituteFuture(task.fn()); |
| 423 return _taskFuture.whenComplete(() { | 442 return _taskFuture.whenComplete(() { |
| 424 _taskFuture = null; | 443 _taskFuture = null; |
| 425 _schedule.heartbeat(); | 444 _schedule.heartbeat(); |
| 426 }).catchError((e) { | 445 }).catchError((e) { |
| 427 var error = new ScheduleError.from(_schedule, e); | 446 var error = new ScheduleError.from(_schedule, e); |
| 428 _signalError(error); | 447 _signalError(error); |
| 429 throw _error; | 448 throw _error; |
| 430 }); | 449 }); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 444 }); | 463 }); |
| 445 }).whenComplete(() { | 464 }).whenComplete(() { |
| 446 _schedule.heartbeat(); | 465 _schedule.heartbeat(); |
| 447 // If the tasks were otherwise successful, make sure we throw any | 466 // If the tasks were otherwise successful, make sure we throw any |
| 448 // out-of-band errors. If a task failed, make sure we throw the most | 467 // out-of-band errors. If a task failed, make sure we throw the most |
| 449 // recent error. | 468 // recent error. |
| 450 if (_error != null) throw _error; | 469 if (_error != null) throw _error; |
| 451 }); | 470 }); |
| 452 } | 471 } |
| 453 | 472 |
| 473 /// Stops this queue after the current task and any out-of-band callbacks | |
| 474 /// finish running. | |
| 475 void _abort() { | |
| 476 assert(_schedule.state == ScheduleState.SET_UP || isRunning); | |
| 477 _aborted = true; | |
| 478 } | |
| 479 | |
| 454 /// Returns a function wrapping [fn] that pipes any errors into the schedule | 480 /// Returns a function wrapping [fn] that pipes any errors into the schedule |
| 455 /// chain. This will also block [this] from completing until the returned | 481 /// chain. This will also block [this] from completing until the returned |
| 456 /// function has been called. It's used to ensure that out-of-band callbacks | 482 /// function has been called. It's used to ensure that out-of-band callbacks |
| 457 /// are properly handled by the scheduled test. | 483 /// are properly handled by the scheduled test. |
| 458 Function _wrapAsync(fn(arg), String description) { | 484 Function _wrapAsync(fn(arg), String description) { |
| 459 assert(_schedule.state == ScheduleState.SET_UP || isRunning); | 485 assert(_schedule.state == ScheduleState.SET_UP || isRunning); |
| 460 | 486 |
| 461 // It's possible that the queue timed out before [fn] finished. | 487 // It's possible that the queue timed out before [fn] finished. |
| 462 bool _timedOut() => | 488 bool _timedOut() => |
| 463 _schedule.currentQueue != this || pendingCallbacks.isEmpty; | 489 _schedule.currentQueue != this || pendingCallbacks.isEmpty; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 546 var childLines = child.toString().split("\n"); | 572 var childLines = child.toString().split("\n"); |
| 547 lines.add(" $prefix ${childLines.first}"); | 573 lines.add(" $prefix ${childLines.first}"); |
| 548 lines.addAll(childLines.skip(1).map((line) => " | $line")); | 574 lines.addAll(childLines.skip(1).map((line) => " | $line")); |
| 549 } | 575 } |
| 550 } | 576 } |
| 551 | 577 |
| 552 return lines.join("\n"); | 578 return lines.join("\n"); |
| 553 }).join("\n"); | 579 }).join("\n"); |
| 554 } | 580 } |
| 555 } | 581 } |
| OLD | NEW |