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

Unified Diff: mojo/public/dart/third_party/test/lib/src/frontend/expect_async.dart

Issue 1346773002: Stop running pub get at gclient sync time and fix build bugs (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 3 months 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
Index: mojo/public/dart/third_party/test/lib/src/frontend/expect_async.dart
diff --git a/mojo/public/dart/third_party/test/lib/src/frontend/expect_async.dart b/mojo/public/dart/third_party/test/lib/src/frontend/expect_async.dart
new file mode 100644
index 0000000000000000000000000000000000000000..696fae778cd6f2423649b207b345a5e52a646611
--- /dev/null
+++ b/mojo/public/dart/third_party/test/lib/src/frontend/expect_async.dart
@@ -0,0 +1,252 @@
+// Copyright (c) 2015, 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 test.frontend.expect_async;
+
+import 'dart:async';
+
+import '../backend/invoker.dart';
+import '../backend/state.dart';
+import 'expect.dart';
+
+/// An object used to detect unpassed arguments.
+const _PLACEHOLDER = const Object();
+
+// Functions used to check how many arguments a callback takes.
+typedef _Func0();
+typedef _Func1(a);
+typedef _Func2(a, b);
+typedef _Func3(a, b, c);
+typedef _Func4(a, b, c, d);
+typedef _Func5(a, b, c, d, e);
+typedef _Func6(a, b, c, d, e, f);
+
+typedef bool _IsDoneCallback();
+
+/// A wrapper for a function that ensures that it's called the appropriate
+/// number of times.
+///
+/// The containing test won't be considered to have completed successfully until
+/// this function has been called the appropriate number of times.
+///
+/// The wrapper function is accessible via [func]. It supports up to six
+/// optional and/or required positional arguments, but no named arguments.
+class _ExpectedFunction {
+ /// The wrapped callback.
+ final Function _callback;
+
+ /// The minimum number of calls that are expected to be made to the function.
+ ///
+ /// If fewer calls than this are made, the test will fail.
+ final int _minExpectedCalls;
+
+ /// The maximum number of calls that are expected to be made to the function.
+ ///
+ /// If more calls than this are made, the test will fail.
+ final int _maxExpectedCalls;
+
+ /// A callback that should return whether the function is not expected to have
+ /// any more calls.
+ ///
+ /// This will be called after every time the function is run. The test case
+ /// won't be allowed to terminate until it returns `true`.
+ ///
+ /// This may be `null`. If so, the function is considered to be done after
+ /// it's been run once.
+ final _IsDoneCallback _isDone;
+
+ /// A descriptive name for the function.
+ final String _id;
+
+ /// An optional description of why the function is expected to be called.
+ ///
+ /// If not passed, this will be an empty string.
+ final String _reason;
+
+ /// The number of times the function has been called.
+ int _actualCalls = 0;
+
+ /// The test invoker in which this function was wrapped.
+ Invoker get _invoker => _zone[#test.invoker];
+
+ /// The zone in which this function was wrapped.
+ final Zone _zone;
+
+ /// Whether this function has been called the requisite number of times.
+ bool _complete;
+
+ /// Wraps [callback] in a function that asserts that it's called at least
+ /// [minExpected] times and no more than [maxExpected] times.
+ ///
+ /// If passed, [id] is used as a descriptive name fo the function and [reason]
+ /// as a reason it's expected to be called. If [isDone] is passed, the test
+ /// won't be allowed to complete until it returns `true`.
+ _ExpectedFunction(Function callback, int minExpected, int maxExpected,
+ {String id, String reason, bool isDone()})
+ : this._callback = callback,
+ _minExpectedCalls = minExpected,
+ _maxExpectedCalls = (maxExpected == 0 && minExpected > 0)
+ ? minExpected
+ : maxExpected,
+ this._isDone = isDone,
+ this._reason = reason == null ? '' : '\n$reason',
+ this._zone = Zone.current,
+ this._id = _makeCallbackId(id, callback) {
+ if (_invoker == null) {
+ throw new StateError("[expectAsync] was called outside of a test.");
+ } else if (maxExpected > 0 && minExpected > maxExpected) {
+ throw new ArgumentError("max ($maxExpected) may not be less than count "
+ "($minExpected).");
+ }
+
+ if (isDone != null || minExpected > 0) {
+ _invoker.addOutstandingCallback();
+ _complete = false;
+ } else {
+ _complete = true;
+ }
+ }
+
+ /// Tries to find a reasonable name for [callback].
+ ///
+ /// If [id] is passed, uses that. Otherwise, tries to determine a name from
+ /// calling `toString`. If no name can be found, returns the empty string.
+ static String _makeCallbackId(String id, Function callback) {
+ if (id != null) return "$id ";
+
+ // If the callback is not an anonymous closure, try to get the
+ // name.
+ var toString = callback.toString();
+ var prefix = "Function '";
+ var start = toString.indexOf(prefix);
+ if (start == -1) return '';
+
+ start += prefix.length;
+ var end = toString.indexOf("'", start);
+ if (end == -1) return '';
+ return "${toString.substring(start, end)} ";
+ }
+
+ /// Returns a function that has the same number of positional arguments as the
+ /// wrapped function (up to a total of 6).
+ Function get func {
+ if (_callback is _Func6) return _max6;
+ if (_callback is _Func5) return _max5;
+ if (_callback is _Func4) return _max4;
+ if (_callback is _Func3) return _max3;
+ if (_callback is _Func2) return _max2;
+ if (_callback is _Func1) return _max1;
+ if (_callback is _Func0) return _max0;
+
+ _invoker.removeOutstandingCallback();
+ throw new ArgumentError(
+ 'The wrapped function has more than 6 required arguments');
+ }
+
+ // This indirection is critical. It ensures the returned function has an
+ // argument count of zero.
+ _max0() => _max6();
+
+ _max1([a0 = _PLACEHOLDER]) => _max6(a0);
+
+ _max2([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER]) => _max6(a0, a1);
+
+ _max3([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER]) =>
+ _max6(a0, a1, a2);
+
+ _max4([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER,
+ a3 = _PLACEHOLDER]) => _max6(a0, a1, a2, a3);
+
+ _max5([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER,
+ a3 = _PLACEHOLDER, a4 = _PLACEHOLDER]) => _max6(a0, a1, a2, a3, a4);
+
+ _max6([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER,
+ a3 = _PLACEHOLDER, a4 = _PLACEHOLDER, a5 = _PLACEHOLDER]) =>
+ _run([a0, a1, a2, a3, a4, a5].where((a) => a != _PLACEHOLDER));
+
+ /// Runs the wrapped function with [args] and returns its return value.
+ _run(Iterable args) {
+ // Note that in the old test, this returned `null` if it encountered an
+ // error, where now it just re-throws that error because Zone machinery will
+ // pass it to the invoker anyway.
+ try {
+ _actualCalls++;
+ if (_invoker.liveTest.isComplete &&
+ _invoker.liveTest.state.result == Result.success) {
+ throw 'Callback ${_id}called ($_actualCalls) after test case '
+ '${_invoker.liveTest.test.name} had already completed.$_reason';
+ } else if (_maxExpectedCalls >= 0 && _actualCalls > _maxExpectedCalls) {
+ throw new TestFailure('Callback ${_id}called more times than expected '
+ '($_maxExpectedCalls).$_reason');
+ }
+
+ return Function.apply(_callback, args.toList());
+ } catch (error, stackTrace) {
+ _zone.handleUncaughtError(error, stackTrace);
+ return null;
+ } finally {
+ _afterRun();
+ }
+ }
+
+ /// After each time the function is run, check to see if it's complete.
+ void _afterRun() {
+ if (_complete) return;
+ if (_minExpectedCalls > 0 && _actualCalls < _minExpectedCalls) return;
+ if (_isDone != null && !_isDone()) return;
+
+ // Mark this callback as complete and remove it from the test case's
+ // oustanding callback count; if that hits zero the test is done.
+ _complete = true;
+ _invoker.removeOutstandingCallback();
+ }
+}
+
+/// Indicate that [callback] is expected to be called [count] number of times
+/// (by default 1).
+///
+/// The test framework will wait for the callback to run the [count] times
+/// before it considers the current test to be complete. [callback] may take up
+/// to six optional or required positional arguments; named arguments are not
+/// supported.
+///
+/// [max] can be used to specify an upper bound on the number of calls; if this
+/// is exceeded the test will fail. If [max] is `0` (the default), the callback
+/// is expected to be called exactly [count] times. If [max] is `-1`, the
+/// callback is allowed to be called any number of times greater than [count].
+///
+/// Both [id] and [reason] are optional and provide extra information about the
+/// callback when debugging. [id] should be the name of the callback, while
+/// [reason] should be the reason the callback is expected to be called.
+Function expectAsync(Function callback,
+ {int count: 1, int max: 0, String id, String reason}) {
+ if (Invoker.current == null) {
+ throw new StateError("expectAsync() may only be called within a test.");
+ }
+
+ return new _ExpectedFunction(callback, count, max, id: id, reason: reason)
+ .func;
+}
+
+/// Indicate that [callback] is expected to be called until [isDone] returns
+/// true.
+///
+/// [isDone] is called after each time the function is run. Only when it returns
+/// true will the callback be considered complete. [callback] may take up to six
+/// optional or required positional arguments; named arguments are not
+/// supported.
+///
+/// Both [id] and [reason] are optional and provide extra information about the
+/// callback when debugging. [id] should be the name of the callback, while
+/// [reason] should be the reason the callback is expected to be called.
+Function expectAsyncUntil(Function callback, bool isDone(),
+ {String id, String reason}) {
+ if (Invoker.current == null) {
+ throw new StateError(
+ "expectAsyncUntil() may only be called within a test.");
+ }
+
+ return new _ExpectedFunction(callback, 0, -1,
+ id: id, reason: reason, isDone: isDone).func;
+}

Powered by Google App Engine
This is Rietveld 408576698