Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: pkg/scheduled_test/lib/src/schedule.dart

Issue 812253002: Delete a bunch of packages that are now on GitHub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Un-delete http Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/scheduled_test/lib/src/mock_clock.dart ('k') | pkg/scheduled_test/lib/src/schedule_error.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/scheduled_test/lib/src/schedule.dart
diff --git a/pkg/scheduled_test/lib/src/schedule.dart b/pkg/scheduled_test/lib/src/schedule.dart
deleted file mode 100644
index 5bf59478c4e373f31ac34fd0cc11ff667263371f..0000000000000000000000000000000000000000
--- a/pkg/scheduled_test/lib/src/schedule.dart
+++ /dev/null
@@ -1,618 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library schedule;
-
-import 'dart:async';
-import 'dart:collection';
-
-import 'package:stack_trace/stack_trace.dart';
-
-import 'mock_clock.dart' as mock_clock;
-import 'schedule_error.dart';
-import 'substitute_future.dart';
-import 'task.dart';
-import 'utils.dart';
-
-/// The schedule of tasks to run for a single test. This has three separate task
-/// queues: [tasks], [onComplete], and [onException]. It also provides
-/// visibility into the current state of the schedule.
-class Schedule {
- /// The main task queue for the schedule. These tasks are run before the other
- /// queues and generally constitute the main test body.
- TaskQueue get tasks => _tasks;
- TaskQueue _tasks;
-
- /// The queue of tasks to run if an error is caught while running [tasks]. The
- /// error will be available in [errors]. These tasks won't be run if no error
- /// occurs. Note that expectation failures count as errors.
- ///
- /// This queue runs before [onComplete], and errors in [onComplete] will not
- /// cause this queue to be run.
- ///
- /// If an error occurs in a task in this queue, all further tasks will be
- /// skipped.
- TaskQueue get onException => _onException;
- TaskQueue _onException;
-
- /// The queue of tasks to run after [tasks] and possibly [onException] have
- /// run. This queue will run whether or not an error occurred. If one did, it
- /// will be available in [errors]. Note that expectation failures count as
- /// errors.
- ///
- /// This queue runs after [onException]. If an error occurs while running
- /// [onException], that error will be available in [errors] after the original
- /// error.
- ///
- /// If an error occurs in a task in this queue, all further tasks will be
- /// skipped.
- TaskQueue get onComplete => _onComplete;
- TaskQueue _onComplete;
-
- /// Returns the [Task] that's currently executing, or `null` if there is no
- /// such task. This will be `null` both before the schedule starts running and
- /// after it's finished.
- Task get currentTask => _currentTask;
- Task _currentTask;
-
- /// The current state of the schedule.
- ScheduleState get state => _state;
- ScheduleState _state = ScheduleState.SET_UP;
-
- /// Errors thrown by the task queues.
- ///
- /// When running tasks in [tasks], this will always be empty. If an error
- /// occurs in [tasks], it will be added to this list and then [onException]
- /// will be run. If an error occurs there as well, it will be added to this
- /// list and [onComplete] will be run. Errors thrown during [onComplete] will
- /// also be added to this list, although no scheduled tasks will be run
- /// afterwards.
- ///
- /// Any out-of-band callbacks that throw errors will also have those errors
- /// added to this list.
- List<ScheduleError> get errors =>
- new UnmodifiableListView<ScheduleError>(_errors);
- final _errors = <ScheduleError>[];
-
- /// Additional debugging info registered via [addDebugInfo].
- List<String> get debugInfo => new UnmodifiableListView<String>(_debugInfo);
- final _debugInfo = <String>[];
-
- /// The task queue that's currently being run. One of [tasks], [onException],
- /// or [onComplete]. This starts as [tasks], and can only be `null` after the
- /// schedule is done.
- TaskQueue get currentQueue =>
- _state == ScheduleState.DONE ? null : _currentQueue;
- TaskQueue _currentQueue;
-
- /// The time to wait before terminating a task queue for inactivity. Defaults
- /// to 5 seconds. This can be set to `null` to disable timeouts entirely. Note
- /// that the timeout is the maximum time a task is allowed between
- /// interactions with the schedule, *not* the maximum time an entire test is
- /// allowed. See also [heartbeat].
- ///
- /// If a task queue times out, an error will be raised that can be handled as
- /// usual in the [onException] and [onComplete] queues. If [onException] times
- /// out, that can only be handled in [onComplete]; if [onComplete] times out,
- /// that cannot be handled.
- ///
- /// If a task times out and then later completes with an error, that error
- /// cannot be handled. The user will still be notified of it.
- Duration get timeout => _timeout;
- Duration _timeout = new Duration(seconds: 5);
- set timeout(Duration duration) {
- _timeout = duration;
- heartbeat();
- }
-
- /// The timer for keeping track of task timeouts. This may be null.
- Timer _timeoutTimer;
-
- /// Creates a new schedule with empty task queues.
- Schedule() {
- _tasks = new TaskQueue._("tasks", this);
- _onComplete = new TaskQueue._("onComplete", this);
- _onException = new TaskQueue._("onException", this);
- _currentQueue = _tasks;
-
- heartbeat();
- }
-
- /// Sets up this schedule by running [setUp], then runs all the task queues in
- /// order. Any errors in [setUp] will cause [onException] to run.
- Future run(void setUp()) {
- return new Future.value().then((_) {
- try {
- setUp();
- } catch (e, stackTrace) {
- // Even though the scheduling failed, we need to run the onException and
- // onComplete queues, so we set the schedule state to RUNNING.
- _state = ScheduleState.RUNNING;
- throw new ScheduleError.from(this, e, stackTrace: stackTrace);
- }
-
- _state = ScheduleState.RUNNING;
- return tasks._run();
- }).catchError((error, stackTrace) {
- _addError(error, stackTrace);
- return onException._run().catchError((innerError, innerTrace) {
- // If an error occurs in a task in the onException queue, make sure it's
- // registered in the error list and re-throw it. We could also re-throw
- // `error`; ultimately, all the errors will be shown to the user if any
- // ScheduleError is thrown.
- _addError(innerError, innerTrace);
- throw innerError;
- }).then((_) {
- // If there are no errors in the onException queue, re-throw the
- // original error that caused it to run.
- throw error;
- });
- }).whenComplete(() {
- return onComplete._run().catchError((error, stackTrace) {
- // If an error occurs in a task in the onComplete queue, make sure it's
- // registered in the error list and re-throw it.
- _addError(error, stackTrace);
- throw error;
- });
- }).whenComplete(() {
- if (_timeoutTimer != null) _timeoutTimer.cancel();
- _state = ScheduleState.DONE;
- });
- }
-
- /// Stop the current [TaskQueue] after the current task and any out-of-band
- /// tasks stop executing. If this is called before [this] has started running,
- /// no tasks in the [tasks] queue will be run.
- ///
- /// This won't cause an error, but any errors that are otherwise signaled will
- /// still cause the test to fail.
- void abort() {
- if (_state == ScheduleState.DONE) {
- throw new StateError("Called abort() after the schedule has finished "
- "running.");
- }
-
- currentQueue._abort();
- }
-
- /// Signals that an out-of-band error has occurred. Using [wrapAsync] along
- /// with `throw` is usually preferable to calling this directly.
- ///
- /// The metadata in [ScheduleError]s will be preserved.
- void signalError(error, [stackTrace]) {
- heartbeat();
-
- var scheduleError = new ScheduleError.from(this, error,
- stackTrace: stackTrace);
- if (_state == ScheduleState.DONE) {
- throw new StateError(
- "An out-of-band error was signaled outside of wrapAsync after the "
- "schedule finished running.\n"
- "${errorString()}");
- } else if (state == ScheduleState.SET_UP) {
- // If we're setting up, throwing the error will pipe it into the main
- // error-handling code.
- throw scheduleError;
- } else {
- _currentQueue._signalError(scheduleError);
- }
- }
-
- /// Adds [info] to the debugging output that will be printed if the test
- /// fails. Unlike [signalError], this won't cause the test to fail, nor will
- /// it short-circuit the current [TaskQueue]; it's just useful for providing
- /// additional information that may not fit cleanly into an existing error.
- void addDebugInfo(String info) => _debugInfo.add(info);
-
- /// Notifies the schedule of an error that occurred in a task or out-of-band
- /// callback after the appropriate queue has timed out. If this schedule is
- /// still running, the error will be added to the errors list to be shown
- /// along with the timeout error; otherwise, a top-level error will be thrown.
- void _signalPostTimeoutError(error, [stackTrace]) {
- var scheduleError = new ScheduleError.from(this, error,
- stackTrace: stackTrace);
- _addError(scheduleError);
- if (_state == ScheduleState.DONE) {
- throw new StateError(
- "An out-of-band error was caught after the test timed out.\n"
- "${errorString()}");
- }
- }
-
- /// Returns a function wrapping [fn] that pipes any errors into the schedule
- /// chain. This will also block the current task queue from completing until
- /// the returned function has been called. It's used to ensure that
- /// out-of-band callbacks are properly handled by the scheduled test.
- ///
- /// [description] provides an optional description of the callback, which is
- /// used when generating error messages.
- ///
- /// The top-level `wrapAsync` function should usually be used in preference to
- /// this in test code.
- Function wrapAsync(fn(arg), [String description]) {
- if (_state == ScheduleState.DONE) {
- throw new StateError("wrapAsync called after the schedule has finished "
- "running.");
- }
- heartbeat();
-
- return currentQueue._wrapAsync(fn, description);
- }
-
- /// Like [wrapAsync], this ensures that the current task queue waits for
- /// out-of-band asynchronous code, and that errors raised in that code are
- /// handled correctly. However, [wrapFuture] wraps a [Future] chain rather
- /// than a single callback.
- ///
- /// The returned [Future] completes to the same value or error as [future].
- ///
- /// [description] provides an optional description of the future, which is
- /// used when generating error messages.
- ///
- /// The top-level `wrapFuture` function should usually be used in preference
- /// to this in test code.
- Future wrapFuture(Future future, [String description]) {
- var done = wrapAsync((fn) => fn(), description);
-
- future = future.then((result) => done(() => result))
- .catchError((error, stackTrace) {
- done(() {
- throw new ScheduleError.from(this, error, stackTrace: stackTrace);
- });
- // wrapAsync will catch the first throw, so we throw [e] again so it
- // propagates through the Future chain.
- throw error;
- });
-
- // Don't top-level the error, since it's already been signaled to the
- // schedule.
- future.catchError((_) => null);
-
- return future;
- }
-
- /// Returns a string representation of all errors registered on this schedule.
- String errorString() {
- if (errors.isEmpty) return "The schedule had no errors.";
- if (errors.length == 1 && debugInfo.isEmpty) return errors.first.toString();
-
- var border = "\n==========================================================="
- "=====================\n";
- var errorStrings = errors.map((e) => e.toString()).join(border);
- var message = "The schedule had ${errors.length} errors:\n$errorStrings";
-
- if (!debugInfo.isEmpty) {
- message = "$message$border\nDebug info:\n${debugInfo.join(border)}";
- }
-
- return message;
- }
-
- /// Notifies the schedule that progress is being made on an asynchronous task.
- /// This resets the timeout timer, and can be used in long-running tasks to
- /// keep them from timing out.
- void heartbeat() {
- if (_timeoutTimer != null) _timeoutTimer.cancel();
- if (_timeout == null) {
- _timeoutTimer = null;
- } else {
- _timeoutTimer = mock_clock.newTimer(_timeout, () {
- _timeoutTimer = null;
- currentQueue._signalTimeout(new ScheduleError.from(this, "The schedule "
- "timed out after $_timeout of inactivity."));
- });
- }
- }
-
- /// Register an error in the schedule's error list. This ensures that there
- /// are no duplicate errors, and that all errors are wrapped in
- /// [ScheduleError].
- void _addError(error, [StackTrace stackTrace]) {
- error = new ScheduleError.from(this, error, stackTrace: stackTrace);
- if (errors.contains(error)) return;
- _errors.add(error);
- }
-}
-
-/// An enum of states for a [Schedule].
-class ScheduleState {
- /// The schedule can have tasks added to its queue, but is not yet running
- /// them.
- static const SET_UP = const ScheduleState._("SET_UP");
-
- /// The schedule is actively running tasks. This includes running tasks in
- /// [Schedule.onException] and [Schedule.onComplete].
- static const RUNNING = const ScheduleState._("RUNNING");
-
- /// The schedule has finished running all its tasks, either successfully or
- /// with an error.
- static const DONE = const ScheduleState._("DONE");
-
- /// The name of the state.
- final String name;
-
- const ScheduleState._(this.name);
-
- String toString() => name;
-}
-
-/// A queue of asynchronous tasks to execute in order.
-class TaskQueue {
- /// The tasks in the queue.
- List<Task> get contents => new UnmodifiableListView<Task>(_contents);
- final _contents = new Queue<Task>();
-
- /// The name of the queue, for debugging purposes.
- final String name;
-
- /// The [Schedule] that created this queue.
- final Schedule _schedule;
-
- /// An out-of-band error signaled by [_schedule]. If this is non-null, it
- /// indicates that the queue should stop as soon as possible and re-throw this
- /// error.
- ScheduleError _error;
-
- /// The [SubstituteFuture] for the currently-running task in the queue, or
- /// null if no task is currently running.
- SubstituteFuture _taskFuture;
-
- /// The toal number of out-of-band callbacks that have been registered on
- /// [this].
- int _totalCallbacks = 0;
-
- /// Whether to stop running after the current task.
- bool _aborted = false;
-
- /// The descriptions of all callbacks that are blocking the completion of
- /// [this].
- List<PendingCallback> get pendingCallbacks =>
- new UnmodifiableListView<PendingCallback>(_pendingCallbacks);
- final _pendingCallbacks = new Queue<PendingCallback>();
-
- /// A completer that will be completed once [_pendingCallbacks] becomes empty
- /// after the queue finishes running its tasks.
- Future get _noPendingCallbacks => _noPendingCallbacksCompleter.future;
- final Completer _noPendingCallbacksCompleter = new Completer();
-
- /// A [Future] that completes when the tasks in [this] are all complete. If an
- /// error occurs while running this queue, the returned [Future] will complete
- /// with that error.
- ///
- /// The returned [Future] can complete before outstanding out-of-band
- /// callbacks have finished running.
- Future get onTasksComplete => _onTasksCompleteCompleter.future;
- final _onTasksCompleteCompleter = new Completer();
-
- TaskQueue._(this.name, this._schedule) {
- // Avoid top-leveling errors that are passed to onTasksComplete if there are
- // no listeners.
- onTasksComplete.catchError((_) {});
- }
-
- /// Whether this queue is currently running.
- bool get isRunning => _schedule.state == ScheduleState.RUNNING &&
- _schedule.currentQueue == this;
-
- /// Whether this queue is running its tasks (as opposed to waiting for
- /// out-of-band callbacks or not running at all).
- bool get isRunningTasks => isRunning && _schedule.currentTask != null;
-
- /// Schedules a task, [fn], to run asynchronously as part of this queue. Tasks
- /// will be run in the order they're scheduled. In [fn] returns a [Future],
- /// tasks after it won't be run until that [Future] completes.
- ///
- /// The return value will be completed once the scheduled task has finished
- /// running. Its return value is the same as the return value of [fn], or the
- /// value it completes to if it's a [Future].
- ///
- /// If [description] is passed, it's used to describe the task for debugging
- /// purposes when an error occurs.
- ///
- /// If this is called when this queue is currently running, it will run [fn]
- /// on the next event loop iteration rather than adding it to a queue--this is
- /// known as a "nested task". The current task will not complete until [fn]
- /// (and any [Future] it returns) has finished running. Any errors in [fn]
- /// will automatically be handled. Nested tasks run in parallel, unlike
- /// top-level tasks which run in sequence.
- Future schedule(fn(), [String description]) {
- if (isRunning) {
- var task = _schedule.currentTask;
- var wrappedFn = () => _schedule.wrapFuture(
- new Future.value().then((_) => fn()));
- if (task == null) return wrappedFn();
- return task.runChild(wrappedFn, description);
- }
-
- var task = new Task(() {
- return syncFuture(fn).catchError((e, stackTrace) {
- throw new ScheduleError.from(_schedule, e, stackTrace: stackTrace);
- });
- }, description, this);
- _contents.add(task);
- return task.result;
- }
-
- /// Runs all the tasks in this queue in order.
- Future _run() {
- _schedule._currentQueue = this;
- _schedule.heartbeat();
- return Future.forEach(_contents, (task) {
- _schedule._currentTask = task;
- if (_error != null) throw _error;
- if (_aborted) return null;
-
- _taskFuture = new SubstituteFuture(task.fn());
- return _taskFuture.whenComplete(() {
- _taskFuture = null;
- _schedule.heartbeat();
- }).catchError((e, trace) {
- var error = new ScheduleError.from(_schedule, e, stackTrace: trace);
- _signalError(error);
- throw _error;
- });
- }).whenComplete(() {
- _schedule._currentTask = null;
- }).then((_) {
- _onTasksCompleteCompleter.complete();
- }).catchError((e, stackTrace) {
- _onTasksCompleteCompleter.completeError(e, stackTrace);
- throw e;
- }).whenComplete(() {
- if (pendingCallbacks.isEmpty) return null;
- return _noPendingCallbacks.catchError((e, stackTrace) {
- // Signal the error rather than passing it through directly so that if a
- // timeout happens after an in-task error, both are reported.
- _signalError(new ScheduleError.from(_schedule, e,
- stackTrace: stackTrace));
- });
- }).whenComplete(() {
- _schedule.heartbeat();
- // If the tasks were otherwise successful, make sure we throw any
- // out-of-band errors. If a task failed, make sure we throw the most
- // recent error.
- if (_error != null) throw _error;
- });
- }
-
- /// Stops this queue after the current task and any out-of-band callbacks
- /// finish running.
- void _abort() {
- assert(_schedule.state == ScheduleState.SET_UP || isRunning);
- _aborted = true;
- }
-
- /// Returns a function wrapping [fn] that pipes any errors into the schedule
- /// chain. This will also block [this] from completing until the returned
- /// function has been called. It's used to ensure that out-of-band callbacks
- /// are properly handled by the scheduled test.
- Function _wrapAsync(fn(arg), String description) {
- assert(_schedule.state == ScheduleState.SET_UP || isRunning);
-
- // It's possible that the queue timed out before [fn] finished.
- bool _timedOut() =>
- _schedule.currentQueue != this || pendingCallbacks.isEmpty;
-
- _totalCallbacks++;
- var chain = new Chain.current();
- var pendingCallback = new PendingCallback._(() {
- var fullDescription = description;
- if (fullDescription == null) {
- fullDescription = "Out-of-band operation #${_totalCallbacks}";
- }
-
- var stackString = prefixLines(terseTraceString(chain));
- fullDescription += "\n\nStack chain:\n$stackString";
- return fullDescription;
- });
- _pendingCallbacks.add(pendingCallback);
-
- return (arg) {
- try {
- return fn(arg);
- } catch (e, stackTrace) {
- var error = new ScheduleError.from(
- _schedule, e, stackTrace: stackTrace);
- if (_timedOut()) {
- _schedule._signalPostTimeoutError(error);
- } else {
- _schedule.signalError(error);
- }
- } finally {
- if (_timedOut()) return null;
-
- _pendingCallbacks.remove(pendingCallback);
- if (_pendingCallbacks.isEmpty && !isRunningTasks) {
- _noPendingCallbacksCompleter.complete();
- }
- }
- };
- }
-
- /// Signals that an out-of-band error has been detected and the queue should
- /// stop running as soon as possible.
- void _signalError(ScheduleError error) {
- // If multiple errors are detected while a task is running, make sure the
- // earlier ones are recorded in the schedule.
- if (_error != null) _schedule._addError(_error);
- _error = error;
- }
-
- /// Notifies the queue that it has timed out and it needs to terminate
- /// immediately with a timeout error.
- void _signalTimeout(ScheduleError error) {
- _pendingCallbacks.clear();
- if (!isRunningTasks) {
- _noPendingCallbacksCompleter.completeError(error);
- } else if (_taskFuture != null) {
- // Catch errors coming off the old task future, in case it completes after
- // timing out.
- _taskFuture.substitute(new Future.error(error))
- .catchError((e, stackTrace) {
- _schedule._signalPostTimeoutError(e, stackTrace);
- });
- } else {
- // This branch probably won't be reached, but it's conceivable that the
- // event loop might get pumped when _taskFuture is null but we haven't yet
- // finished running all the tasks.
- _signalError(error);
- }
- }
-
- String toString() => name;
-
- /// Returns a detailed representation of the queue as a tree of tasks. If
- /// [highlight] is passed, that task is specially highlighted.
- ///
- /// [highlight] must be a task in this queue.
- String generateTree([Task highlight]) {
- assert(highlight == null || highlight.queue == this);
- return _contents.map((task) {
- var taskString = task == highlight
- ? task.toStringWithStackTrace()
- : task.toString();
- taskString = prefixLines(taskString,
- firstPrefix: task == highlight ? "> " : "* ");
-
- if (task == highlight && !task.children.isEmpty) {
- var childrenString = task.children.map((child) {
- var prefix = ">";
- if (child.state == TaskState.ERROR) {
- prefix = "X";
- } else if (child.state == TaskState.SUCCESS) {
- prefix = "*";
- }
-
- var childString = prefix == "*"
- ? child.toString()
- : child.toStringWithStackTrace();
- return prefixLines(childString,
- firstPrefix: " $prefix ", prefix: " | ");
- }).join('\n');
- taskString = '$taskString\n$childrenString';
- }
-
- return taskString;
- }).join("\n");
- }
-}
-
-/// A thunk for lazily resolving the description of a [PendingCallback].
-typedef String _DescriptionThunk();
-
-/// An identifier for an out-of-band callback running during a schedule.
-class PendingCallback {
- final _DescriptionThunk _thunk;
- String _description;
-
- /// The string description of the callback.
- String get description {
- if (_description == null) _description = _thunk();
- return _description;
- }
-
- String toString() => description;
-
- PendingCallback._(this._thunk);
-}
« no previous file with comments | « pkg/scheduled_test/lib/src/mock_clock.dart ('k') | pkg/scheduled_test/lib/src/schedule_error.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698