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

Unified Diff: mojo/public/dart/third_party/unittest/lib/unittest.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/unittest/lib/unittest.dart
diff --git a/mojo/public/dart/third_party/unittest/lib/unittest.dart b/mojo/public/dart/third_party/unittest/lib/unittest.dart
new file mode 100644
index 0000000000000000000000000000000000000000..51ccff432e8491623e54374163ea450e199fa7dc
--- /dev/null
+++ b/mojo/public/dart/third_party/unittest/lib/unittest.dart
@@ -0,0 +1,440 @@
+// 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 unittest;
+
+import 'dart:async';
+import 'dart:collection';
+
+import 'src/configuration.dart';
+import 'src/expected_function.dart';
+import 'src/group_context.dart';
+import 'src/internal_test_case.dart';
+import 'src/matcher.dart' show TestFailure, wrapAsync;
+import 'src/test_case.dart';
+import 'src/test_environment.dart';
+
+export 'src/configuration.dart';
+export 'src/matcher.dart';
+export 'src/simple_configuration.dart';
+export 'src/test_case.dart';
+
+/// The signature for a function passed to [test].
+typedef dynamic TestFunction();
+
+/// [Configuration] used by the unittest library.
+///
+/// Note that if a configuration has not been set, calling this getter will
+/// create a default configuration.
+Configuration get unittestConfiguration {
+ if (config == null) environment.config = new Configuration();
+ return config;
+}
+
+/// If `true`, stack traces are reformatted to be more readable.
+bool formatStacks = true;
+
+/// If `true`, irrelevant frames are filtered from the stack trace.
+///
+/// This does nothing if [formatStacks] is false.
+bool filterStacks = true;
+
+/// Separator used between group names and test names.
+String groupSep = ' ';
+
+/// Sets the [Configuration] used by the unittest library.
+///
+/// Throws a [StateError] if there is an existing, incompatible value.
+void set unittestConfiguration(Configuration value) {
+ if (identical(config, value)) return;
+ if (config != null) {
+ logMessage('Warning: The unittestConfiguration has already been set. New '
+ 'unittestConfiguration ignored.');
+ } else {
+ environment.config = value;
+ }
+}
+
+/// Logs [message] associated with the current test case.
+///
+/// Tests should use this instead of [print].
+void logMessage(String message) =>
+ config.onLogMessage(currentTestCase, message);
+
+/// The test cases that have been defined so far.
+List<TestCase> get testCases =>
+ new UnmodifiableListView<TestCase>(environment.testCases);
+
+/// The interval (in milliseconds) after which a non-microtask asynchronous
+/// delay will be scheduled between tests.
+///
+/// This is used to avoid starving the DOM or other non-microtask events.
+const int BREATH_INTERVAL = 200;
+
+/// The [TestCase] currently being executed.
+TestCase get currentTestCase => (environment.currentTestCaseIndex >= 0 &&
+ environment.currentTestCaseIndex < testCases.length)
+ ? testCases[environment.currentTestCaseIndex]
+ : null;
+
+/// The same as [currentTestCase], but typed as an [InternalTestCase].
+InternalTestCase get _currentTestCase => currentTestCase as InternalTestCase;
+
+/// The result string for a passing test case.
+const PASS = 'pass';
+
+/// The result string for a failing test case.
+const FAIL = 'fail';
+
+/// The result string for an test case with an error.
+const ERROR = 'error';
+
+/// Creates a new test case with the given description and body.
+///
+/// The description will be added to the descriptions of any surrounding
+/// [group]s.
+void test(String description, TestFunction body) {
+ _requireNotRunning();
+ ensureInitialized();
+
+ if (environment.soloTestSeen && environment.soloNestingLevel == 0) return;
+ var testCase = new InternalTestCase(
+ testCases.length + 1, _fullDescription(description), body);
+ environment.testCases.add(testCase);
+}
+
+/// Returns [description] with all of its group prefixes prepended.
+String _fullDescription(String description) {
+ var group = environment.currentContext.fullName;
+ if (description == null) return group;
+ return group != '' ? '$group$groupSep$description' : description;
+}
+
+/// A convenience function for skipping a test.
+void skip_test(String spec, TestFunction body) {}
+
+/// Creates a new test case with the given description and body.
+///
+/// If [solo_test] is used instead of [test], then all non-solo tests will be
+/// disabled. Note that if [solo_group] is used as well, all tests in the group
+/// will be enabled, regardless of whether they use [test] or [solo_test], or
+/// whether they are in a nested [group] versus [solo_group]. Put another way,
+/// if there are any calls to [solo_test] or [solo_group] in a test file, all
+/// tests that are not inside a [solo_group] will be disabled unless they are
+/// [solo_test]s.
+void solo_test(String spec, TestFunction body) {
+ _requireNotRunning();
+ ensureInitialized();
+ if (!environment.soloTestSeen) {
+ environment.soloTestSeen = true;
+ // This is the first solo-ed test. Discard all tests up to now.
+ environment.testCases.clear();
+ }
+ environment.soloNestingLevel++;
+ try {
+ test(spec, body);
+ } finally {
+ environment.soloNestingLevel--;
+ }
+}
+
+/// Indicate that [callback] is expected to be called [count] number of times
+/// (by default 1).
+///
+/// The unittest framework will wait for the callback to run the [count] times
+/// before it considers the current test to be complete. Using [expectAsync]
+/// will also ensure that errors that occur within [callback] are tracked and
+/// reported. [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}) =>
+ 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. Using [expectAsyncUntil] will
+/// also ensure that errors that occur within [callback] are tracked and
+/// reported. [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}) => new ExpectedFunction(callback, 0, -1,
+ id: id, reason: reason, isDone: isDone).func;
+
+/// Creates a group of tests.
+///
+/// A group's description is included in the descriptions of any tests or
+/// sub-groups it contains. [setUp] and [tearDown] are also scoped to the
+/// containing group.
+void group(String description, void body()) {
+ ensureInitialized();
+ _requireNotRunning();
+ environment.currentContext =
+ new GroupContext(environment.currentContext, description);
+ try {
+ body();
+ } catch (e, trace) {
+ var stack = (trace == null) ? '' : ': ${trace.toString()}';
+ environment.uncaughtErrorMessage = "${e.toString()}$stack";
+ } finally {
+ // Now that the group is over, restore the previous one.
+ environment.currentContext = environment.currentContext.parent;
+ }
+}
+
+/// A convenience function for skipping a group of tests.
+void skip_group(String description, void body()) {}
+
+/// Creates a group of tests.
+///
+/// If [solo_group] is used instead of [group], then all tests not declared with
+/// [solo_test] or in a [solo_group] will be disabled. Note that all tests in a
+/// [solo_group] will be run, regardless of whether they're declared with [test]
+/// or [solo_test].
+///
+/// [skip_test] and [skip_group] take precedence over [solo_group].
+void solo_group(String description, void body()) {
+ _requireNotRunning();
+ ensureInitialized();
+ if (!environment.soloTestSeen) {
+ environment.soloTestSeen = true;
+ // This is the first solo-ed group. Discard all tests up to now.
+ environment.testCases.clear();
+ }
+ ++environment.soloNestingLevel;
+ try {
+ group(description, body);
+ } finally {
+ --environment.soloNestingLevel;
+ }
+}
+
+/// Registers a function to be run before tests.
+///
+/// This function will be called before each test is run. [callback] may be
+/// asynchronous; if so, it must return a [Future].
+///
+/// If this is called within a test group, it applies only to tests in that
+/// group. [callback] will be run after any set-up callbacks in parent groups or
+/// at the top level.
+void setUp(Function callback) {
+ _requireNotRunning();
+ environment.currentContext.testSetUp = callback;
+}
+
+/// Registers a function to be run after tests.
+///
+/// This function will be called after each test is run. [callback] may be
+/// asynchronous; if so, it must return a [Future].
+///
+/// If this is called within a test group, it applies only to tests in that
+/// group. [callback] will be run before any tear-down callbacks in parent groups or
+/// at the top level.
+void tearDown(Function callback) {
+ _requireNotRunning();
+ environment.currentContext.testTearDown = callback;
+}
+
+/// Advance to the next test case.
+void _nextTestCase() {
+ environment.currentTestCaseIndex++;
+ _runTest();
+}
+
+/// Handle an error that occurs outside of any test.
+void handleExternalError(e, String message, [stackTrace]) {
+ var msg = '$message\nCaught $e';
+
+ if (currentTestCase != null) {
+ _currentTestCase.error(msg, stackTrace);
+ } else {
+ environment.uncaughtErrorMessage = "$msg: $stackTrace";
+ }
+}
+
+/// Remove any tests that match [testFilter].
+///
+/// [testFilter] can be a predicate function, a [RegExp], or a [String]. If it's
+/// a function, it's called with each [TestCase]. If it's a [String], it's
+/// parsed as a [RegExp] and matched against each [TestCase.description].
+///
+/// This is different from enabling or disabling tests in that it removes the
+/// tests completely.
+void filterTests(testFilter) {
+ var filterFunction;
+ if (testFilter is String) {
+ var re = new RegExp(testFilter);
+ filterFunction = (t) => re.hasMatch(t.description);
+ } else if (testFilter is RegExp) {
+ filterFunction = (t) => testFilter.hasMatch(t.description);
+ } else if (testFilter is Function) {
+ filterFunction = testFilter;
+ }
+ environment.testCases.retainWhere(filterFunction);
+}
+
+/// Runs all queued tests, one at a time.
+void runTests() {
+ _requireNotRunning();
+ _ensureInitialized(false);
+ environment.currentTestCaseIndex = 0;
+ config.onStart();
+ _runTest();
+}
+
+/// Registers an exception that was caught for the current test.
+void registerException(error, [StackTrace stackTrace]) =>
+ _currentTestCase.registerException(error, stackTrace);
+
+/// Runs the next test.
+void _runTest() {
+ if (environment.currentTestCaseIndex >= testCases.length) {
+ assert(environment.currentTestCaseIndex == testCases.length);
+ _completeTests();
+ return;
+ }
+
+ var testCase = _currentTestCase;
+ var f = runZoned(testCase.run, onError: (error, stack) {
+ // TODO(kevmoo) Do a better job of flagging these are async errors.
+ // https://code.google.com/p/dart/issues/detail?id=16530
+ testCase.registerException(error, stack);
+ });
+
+ var timer;
+ var timeout = unittestConfiguration.timeout;
+ if (timeout != null) {
+ try {
+ timer = new Timer(timeout, () {
+ testCase.error("Test timed out after ${timeout.inSeconds} seconds.");
+ _nextTestCase();
+ });
+ } on UnsupportedError catch (e) {
+ if (e.message != "Timer greater than 0.") rethrow;
+ // Support running on d8 and jsshell which don't support timers.
+ }
+ }
+
+ f.whenComplete(() {
+ if (timer != null) timer.cancel();
+ var now = new DateTime.now().millisecondsSinceEpoch;
+ if (now - environment.lastBreath >= BREATH_INTERVAL) {
+ environment.lastBreath = now;
+ Timer.run(_nextTestCase);
+ } else {
+ scheduleMicrotask(_nextTestCase); // Schedule the next test.
+ }
+ });
+}
+
+/// Notify the configuration that the testing has finished.
+void _completeTests() {
+ if (!environment.initialized) return;
+
+ var passed = 0;
+ var failed = 0;
+ var errors = 0;
+ for (var testCase in testCases) {
+ switch (testCase.result) {
+ case PASS:
+ passed++;
+ break;
+ case FAIL:
+ failed++;
+ break;
+ case ERROR:
+ errors++;
+ break;
+ }
+ }
+
+ config.onSummary(
+ passed, failed, errors, testCases, environment.uncaughtErrorMessage);
+ config.onDone(passed > 0 &&
+ failed == 0 &&
+ errors == 0 &&
+ environment.uncaughtErrorMessage == null);
+ environment.initialized = false;
+ environment.currentTestCaseIndex = -1;
+}
+
+/// Initializes the test environment if it hasn't already been initialized.
+void ensureInitialized() {
+ _ensureInitialized(true);
+}
+
+/// Initializes the test environment.
+///
+/// If [configAutoStart] is `true`, schedule a microtask to run the tests. This
+/// microtask is expected to run after all the tests are defined.
+void _ensureInitialized(bool configAutoStart) {
+ if (environment.initialized) return;
+
+ environment.initialized = true;
+ // Hook our async guard into the matcher library.
+ wrapAsync = (f, [id]) => expectAsync(f, id: id);
+
+ environment.uncaughtErrorMessage = null;
+
+ unittestConfiguration.onInit();
+
+ // Immediately queue the suite up. It will run after a timeout (i.e. after
+ // main() has returned).
+ if (configAutoStart && config.autoStart) scheduleMicrotask(runTests);
+}
+
+/// Remove all tests other than the one identified by [id].
+void setSoloTest(int id) =>
+ environment.testCases.retainWhere((t) => t.id == id);
+
+/// Enable the test identified by [id].
+void enableTest(int id) => _setTestEnabledState(id, enable: true);
+
+/// Disable the test by [id].
+void disableTest(int id) => _setTestEnabledState(id, enable: false);
+
+/// Enable or disable the test identified by [id].
+void _setTestEnabledState(int id, {bool enable: true}) {
+ // Try fast path first.
+ if (testCases.length > id && testCases[id].id == id) {
+ environment.testCases[id].enabled = enable;
+ } else {
+ for (var i = 0; i < testCases.length; i++) {
+ if (testCases[i].id != id) continue;
+ environment.testCases[i].enabled = enable;
+ break;
+ }
+ }
+}
+
+/// Throws a [StateError] if tests are running.
+void _requireNotRunning() {
+ if (environment.currentTestCaseIndex == -1) return;
+ throw new StateError('Not allowed when tests are running.');
+}
+
+/// Creates a test environment running in its own zone scope.
+///
+/// This allows for multiple invocations of the unittest library in the same
+/// application instance. This is useful when, for example, creating a test
+/// runner application which needs to create a new pristine test environment on
+/// each invocation to run a given set of tests.
+withTestEnvironment(callback()) {
+ return runZoned(callback,
+ zoneValues: {#unittest.environment: new TestEnvironment()});
+}
« no previous file with comments | « mojo/public/dart/third_party/unittest/lib/test_controller.js ('k') | mojo/public/dart/third_party/unittest/lib/vm_config.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698