Remove usage of unittest package from a number of tests.

Add simplified unittest replacement to package:expect.
(It is used in multi-tests, so it needs to be in an accessible place without using ".." in its path).

Change-Id: I60aa212ed67ffbdda17ca18fce1cdff16237f4fe
Reviewed-on: https://dart-review.googlesource.com/65700
Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Jenny Messerly <jmesserly@google.com>
This commit is contained in:
Lasse R.H. Nielsen 2018-07-20 13:26:38 +00:00 committed by commit-bot@chromium.org
parent 555cca2b1a
commit b1eeacc30a
40 changed files with 408 additions and 66 deletions

View file

@ -0,0 +1,368 @@
// Copyright (c) 2018, 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.
/// A minimal, dependency-free emulation layer for a subset of the
/// unittest/test API used by the language and core library.
///
/// Compared with `minitest.dart`, this library supports and expects
/// asynchronous tests. It uses a `Zone` per test to collect errors in the
/// correct test.
/// It does not support `setUp` or `tearDown` methods,
/// and matchers are severely restricted.
///
/// A number of our language and core library tests were written against the
/// unittest package, which is now deprecated in favor of the new test package.
/// The latter is much better feature-wise, but is also quite complex and has
/// many dependencies. For low-level language and core library tests, we don't
/// want to have to pull in a large number of dependencies and be able to run
/// them correctly in order to run a test, so we want to test them against
/// something simpler.
///
/// When possible, we just use the tiny expect library. But to avoid rewriting
/// all of the existing tests that use unittest, they can instead use this,
/// which shims the unittest API with as little code as possible and calls into
/// expect.
///
/// Eventually, it would be good to refactor those tests to use the expect
/// package directly and remove this.
import 'dart:async';
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
void group(String name, body()) {
var oldName = _pushName(name);
try {
body();
} finally {
_popName(oldName);
}
}
void test(String name, body()) {
var oldName = _pushName(name);
var test = new _Test(_currentName)..asyncWait();
var result =
runZoned(body, zoneValues: {_testToken: test}, onError: test.fail);
if (result is Future) {
result.then((_) {
test.asyncDone();
}, onError: test.fail);
} else {
// Ensure all tests get to be set up first.
scheduleMicrotask(test.asyncDone);
}
_popName(oldName);
}
void expect(Object value, Object matcher) {
Matcher m;
if (matcher is _Matcher) {
m = matcher.call;
} else if (matcher is! Matcher) {
m = equals(matcher);
} else {
m = matcher;
}
m(value);
}
R Function() expectAsync0<R>(R Function() f, {int count = 1}) {
var test = _currentTest..asyncWait(count);
return () {
var result = f();
test.asyncDone();
return result;
};
}
R Function(A) expectAsync1<R, A>(R Function(A) f, {int count = 1}) {
var test = _currentTest..asyncWait(count);
return (A a) {
var result = f(a);
test.asyncDone();
return result;
};
}
R Function(A, B) expectAsync2<R, A, B>(R Function(A, B) f, {int count = 1}) {
var test = _currentTest..asyncWait(count);
return (A a, B b) {
var result = f(a, b);
test.asyncDone();
return result;
};
}
Function expectAsync(Function f, {int count = 1}) {
var f2 = f; // Avoid type-promoting f, we want dynamic invoations.
var test = _currentTest;
if (f2 is Function(Null, Null, Null, Null, Null)) {
test.asyncWait(count);
return ([a, b, c, d, e]) {
var result = f(a, b, c, d, e);
test.asyncDone();
return result;
};
}
if (f2 is Function(Null, Null, Null, Null)) {
test.asyncWait(count);
return ([a, b, c, d]) {
var result = f(a, b, c, d);
test.asyncDone();
return result;
};
}
if (f2 is Function(Null, Null, Null)) {
test.asyncWait(count);
return ([a, b, c]) {
var result = f(a, b, c);
test.asyncDone();
return result;
};
}
if (f2 is Function(Null, Null)) {
test.asyncWait(count);
return ([a, b]) {
var result = f(a, b);
test.asyncDone();
return result;
};
}
if (f2 is Function(Null)) {
test.asyncWait(count);
return ([a]) {
var result = f(a);
test.asyncDone();
return result;
};
}
if (f2 is Function()) {
test.asyncWait(count);
return () {
var result = f();
test.asyncDone();
return result;
};
}
throw new UnsupportedError(
"expectAsync only accepts up to five arguemnt functions");
}
// Matchers
typedef Matcher = void Function(Object);
Matcher same(Object o) => (v) {
Expect.identical(o, v);
};
Matcher equals(Object o) => (v) {
Expect.deepEquals(o, v);
};
Matcher greaterThan(num n) => (Object v) {
Expect.type<num>(v);
num value = v;
if (value > n) return;
Expect.fail("$v is not greater than $n");
};
Matcher greaterThanOrEqualTo(num n) => (Object v) {
Expect.type<num>(v);
num value = v;
if (value >= n) return;
Expect.fail("$v is not greater than $n");
};
Matcher lessThan(num n) => (Object v) {
Expect.type<num>(v);
num value = v;
if (value < n) return;
Expect.fail("$v is not less than $n");
};
Matcher lessThanOrEqualTo(num n) => (Object v) {
Expect.type<num>(v);
num value = v;
if (value <= n) return;
Expect.fail("$v is not less than $n");
};
void isTrue(Object v) {
Expect.isTrue(v);
}
void isFalse(Object v) {
Expect.isFalse(v);
}
void isNull(Object o) {
Expect.isNull(o);
}
bool isStateError(Object o) {
Expect.type<StateError>(o);
}
void _checkThrow<T>(Object v, void onError(error)) {
if (v is Future) {
var test = _currentTest..asyncWait();
v.then((_) {
Expect.fail("Did not throw");
}, onError: (e, s) {
if (e is! T) throw e;
if (onError != null) onError(e);
test.asyncDone();
});
return;
}
Expect.throws<T>(v, (e) {
onError(e);
return true;
});
}
void throws(Object v) {
_checkThrow<Object>(v, null);
}
Matcher throwsA(matcher) => (Object o) {
_checkThrow<Object>(o, (Object error) {
expect(error, matcher);
});
};
Matcher completion(matcher) => (Object o) {
Expect.type<Future>(o);
Future future = o;
_currentTest.asyncWait();
future.then((value) {
expect(value, matcher);
_currentTest.asyncDone();
});
};
void completes(Object o) {
Expect.type<Future>(o);
Future future = o;
_currentTest.asyncWait();
future.then((_) {
_currentTest.asyncDone();
});
}
void isMap(Object o) {
Expect.type<Map>(o);
}
void isList(Object o) {
Expect.type<List>(o);
}
abstract class _Matcher {
void call(Object o);
}
class isInstanceOf<T> implements _Matcher {
void call(Object o) {
Expect.type<T>(o);
}
}
void throwsArgumentError(Object v) {
_checkThrow<ArgumentError>(v, null);
}
String fail(String message) {
Expect.fail("$message");
}
// Internal helpers.
// The current combined name of the nesting [group] or [test].
String _currentName = null;
String _pushName(String newName) {
var oldName = _currentName;
if (oldName == null) {
_currentName = newName;
} else {
_currentName = "$oldName $newName";
}
return oldName;
}
void _popName(String oldName) {
_currentName = oldName;
}
// Key for zone value holding current test object.
final Object _testToken = new Object();
_Test get _currentTest =>
Zone.current[_testToken] ?? (throw new StateError("Not inside test!"));
class _Test {
static int activeTests = 0;
static int failedTests = 0;
final String name;
bool completed = false;
bool failed = false;
int asyncExpected = 0;
_Test(this.name) {
activeTests++;
}
void asyncWait([int n = 1]) {
if (completed) {
print("ERROR: $name: New operations started after completion."
"${StackTrace.current}");
} else if (asyncExpected == 0) {
asyncStart(); // Matched by asyncEnd in [_complete];
}
asyncExpected += n;
}
void asyncDone() {
if (asyncExpected == 0) {
print("ERROR: $name: More asyncEnds than asyncStarts.\n"
"${StackTrace.current}");
} else {
asyncExpected--;
if (asyncExpected == 0 && !completed) {
print("SUCCESS: $name");
_complete();
}
}
}
void fail(Object error, StackTrace stack) {
if (!completed) {
failed = true;
failedTests++;
print("FAILURE: $name: $error\n$stack");
_complete();
} else {
if (!failed) {
failed = true;
failedTests++;
}
print("FAILURE: $name: (after completion) $error\n$stack");
}
}
void _complete() {
assert(!completed);
completed = true;
activeTests--;
if (failedTests == 0) {
asyncEnd();
} else if (activeTests == 0) {
Zone.root.scheduleMicrotask(() {
Expect.fail("$failedTests tests failed");
});
}
}
}

View file

@ -4,9 +4,10 @@
library async_start_test;
import "package:unittest/unittest.dart";
import "dart:async";
import "package:expect/async_minitest.dart";
main() {
group("basic", () {
test("empty", () {
@ -105,7 +106,7 @@ main() {
});
test("Cannot yield* non-stream", () {
f(s) async* {
f(Object s) async* {
yield* s;
}
@ -115,8 +116,8 @@ main() {
});
});
test("Cannot yield* non-stream", () {
f(s) async* {
test("Cannot yield* non-stream 2", () {
f(Object s) async* {
yield* s;
}

View file

@ -53,12 +53,7 @@ async_call_test: RuntimeError # Timer interface not supported: Issue 7728.
async_star_await_pauses_test: RuntimeError # Need triage
async_star_no_cancel2_test: RuntimeError # Need triage
async_star_no_cancel_test: RuntimeError # Need triage
async_star_test/01: RuntimeError
async_star_test/02: RuntimeError
async_star_test/03: RuntimeError
async_star_test/04: RuntimeError
async_star_test/05: RuntimeError
async_star_test/none: RuntimeError
await_for_test: Skip # Jsshell does not provide periodic timers, Issue 7728
field_override_optimization_test: RuntimeError
field_type_check2_test/01: MissingRuntimeError

View file

@ -68,7 +68,6 @@ async_star_cancel_while_paused_test: RuntimeError
async_star_pause_test: Fail, OK
async_star_regression_2238_test: CompileTimeError, RuntimeError
async_star_test/01: CompileTimeError # Issue 2238.
async_star_test/02: RuntimeError
bad_named_parameters2_test/01: MissingCompileTimeError
bad_named_parameters_test/01: MissingCompileTimeError
bad_named_parameters_test/02: MissingCompileTimeError

View file

@ -2,7 +2,7 @@
// 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.
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'causal_async_exception_stack_helper.dart' as h;

View file

@ -2,7 +2,7 @@
// 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.
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'causal_async_exception_stack_helper.dart' as h;

View file

@ -8,7 +8,7 @@ library stream_controller_async_test;
import 'dart:async';
import 'package:expect/expect.dart';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'event_helper.dart';
import 'stream_state_helper.dart';
@ -670,7 +670,8 @@ void testAsBroadcast() {
}
void testSink({bool sync, bool broadcast, bool asBroadcast}) {
String type = "${sync?"S":"A"}${broadcast?"B":"S"}${asBroadcast?"aB":""}";
String type =
"${sync ? "S" : "A"}${broadcast ? "B" : "S"}${asBroadcast ? "aB" : ""}";
test("$type-controller-sink", () {
var done = expectAsync(() {});
var c = broadcast

View file

@ -8,7 +8,7 @@ library dart.test.stream_from_iterable;
import 'dart:async';
import 'package:expect/expect.dart';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'event_helper.dart';

View file

@ -4,7 +4,7 @@
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
main() {
test("stream iterator basic", () async {

View file

@ -8,7 +8,7 @@ library stream_join_test;
import 'dart:async';
import 'package:expect/expect.dart';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'event_helper.dart';

View file

@ -7,7 +7,7 @@ library dart.test.stream_from_iterable;
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
main() {
test("stream-periodic2", () {

View file

@ -7,7 +7,7 @@ library dart.test.stream_from_iterable;
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
// The stopwatch is more precise than the Timer.
// Some browsers (Firefox and IE so far) can trigger too early. So we add more

View file

@ -7,7 +7,7 @@ library dart.test.stream_from_iterable;
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
void runTest(period, maxElapsed, pauseDuration) {
Function done = expectAsync(() {});

View file

@ -7,7 +7,7 @@ library dart.test.stream_from_iterable;
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
watchMs(Stopwatch watch) {
int microsecs = watch.elapsedMicroseconds;

View file

@ -7,7 +7,7 @@ library dart.test.stream_from_iterable;
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
main() {
test("stream-periodic1", () {

View file

@ -7,7 +7,7 @@ library dart.test.stream_from_iterable;
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
main() {
test("stream-periodic1", () {

View file

@ -8,7 +8,7 @@ library stream_single_test;
import 'dart:async';
import 'package:expect/expect.dart';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'event_helper.dart';

View file

@ -8,7 +8,7 @@ library stream_single_test;
import 'dart:async';
import 'package:expect/expect.dart';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'event_helper.dart';

View file

@ -7,7 +7,7 @@ library stream_state_helper;
import 'dart:async';
import 'dart:collection';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
class SubscriptionProtocolTest {
final StreamProtocolTest _streamTest;

View file

@ -9,7 +9,7 @@ library stream_state_nonzero_timer_test;
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'stream_state_helper.dart';

View file

@ -5,7 +5,7 @@
// Test the event/callback protocol of the stream implementations.
library stream_state_test;
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'stream_state_helper.dart';

View file

@ -8,7 +8,7 @@ library stream_single_test;
import 'dart:async';
import 'package:expect/expect.dart';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
main() {
test("subscription.asFuture success", () {

View file

@ -7,7 +7,7 @@ library stream_subscription_cancel;
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
void main() {
test('subscription.cancel', () {

View file

@ -4,7 +4,7 @@
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
main() {
const ms5 = const Duration(milliseconds: 5);

View file

@ -7,7 +7,7 @@ library stream_transform_test;
import 'dart:async';
import 'package:expect/expect.dart';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'event_helper.dart';

View file

@ -8,7 +8,7 @@ library stream_join_test;
import 'dart:async';
import 'package:expect/expect.dart';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'event_helper.dart';

View file

@ -6,7 +6,7 @@ library timer_cancel1_test;
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
main() {
// Test that a timeout handler can cancel another.

View file

@ -4,16 +4,7 @@
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:unittest/src/expected_function.dart' show ExpectedFunction;
T Function() expectAsync0<T>(T Function() callback,
{int count: 1, int max: 0}) =>
new ExpectedFunction<T>(callback, count, max).max0;
T Function(A) expectAsync1<T, A>(T Function(A) callback,
{int count: 1, int max: 0}) =>
new ExpectedFunction<T>(callback, count, max).max1;
import 'package:expect/async_minitest.dart';
main() {
test("timer isActive test", () {

View file

@ -6,7 +6,7 @@ library timer_test;
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
const int STARTTIMEOUT = 1050;
const int DECREASE = 200;

View file

@ -6,7 +6,7 @@ library deferred_in_isolate2_test;
import 'dart:isolate';
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
import 'deferred_in_isolate2_lib.dart' deferred as lib;

View file

@ -9,7 +9,7 @@
library spawn_tests;
import 'dart:isolate';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
/* Dummy import so multi-test copies the file.
import 'spawn_uri_child_isolate.dart';

View file

@ -9,7 +9,7 @@
library NestedSpawnUriLibrary;
import 'dart:isolate';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
main() {
test('isolate fromUri - nested send and reply', () {

View file

@ -9,7 +9,7 @@
library spawn_tests;
import 'dart:isolate';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
main() {
test('isolate fromUri - send and reply', () {

View file

@ -9,7 +9,7 @@
library spawn_tests;
import 'dart:isolate';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
main() {
test('isolate fromUri - send and reply', () {

View file

@ -6,7 +6,7 @@ library multiple_timer_test;
import 'dart:isolate';
import 'dart:async';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
const Duration TIMEOUT = const Duration(milliseconds: 100);

View file

@ -822,9 +822,7 @@ html/canvas_pixel_array_type_alias_test/types2_runtimeTypeName: Fail, OK # Issue
[ $compiler == dart2js && $strong ]
async/future_or_type_test: RuntimeError
async/slow_consumer2_test: RuntimeError
async/stream_controller_async_test: RuntimeError
async/stream_distinct_test: RuntimeError
async/stream_join_test: RuntimeError
collection/list_test: RuntimeError
html/element_classes_test: RuntimeError

View file

@ -42,9 +42,7 @@ async/future_or_bad_type_test/implements: RuntimeError # Issue 29922
async/future_or_bad_type_test/none: RuntimeError # Issue 29922
async/future_test: RuntimeError # Issue 29922
async/slow_consumer_test: Pass, Timeout # Issue 29922
async/stream_controller_async_test: RuntimeError
async/stream_distinct_test: RuntimeError # Issue 29922
async/stream_join_test: RuntimeError
async/timer_not_available_test: RuntimeError
convert/base64_test/01: Fail, OK # Uses bit-wise operations to detect invalid values. Some large invalid values accepted by DDC/dart2js.
convert/chunked_conversion_utf88_test: Slow, Pass

View file

@ -12,9 +12,7 @@
[ $compiler == app_jitk ]
async/slow_consumer2_test: RuntimeError
async/stream_controller_async_test: RuntimeError
async/stream_distinct_test: RuntimeError
async/stream_join_test: RuntimeError
async/timer_not_available_test: RuntimeError
isolate/issue_21398_parent_isolate1_test: RuntimeError
isolate/issue_22778_test: Crash
@ -79,9 +77,7 @@ isolate/static_function_test: Skip # Flaky (https://github.com/dart-lang/sdk/iss
# ===== dartkp + dart_precompiled status lines =====
[ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
async/slow_consumer2_test: RuntimeError # Issue 31402 (Invocation arguments)
async/stream_controller_async_test: RuntimeError
async/stream_distinct_test: RuntimeError
async/stream_join_test: RuntimeError
async/timer_not_available_test: RuntimeError
html/*: SkipByDesign # dart:html not supported on VM.
isolate/compile_time_error_test/01: Crash
@ -129,8 +125,6 @@ mirrors/reflected_type_generics_test/02: Pass
# ===== dartk + vm status lines =====
[ $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
async/slow_consumer2_test: CompileTimeError # Issue 31402 (Invocation arguments)
async/stream_controller_async_test: CompileTimeError # Issue 31402 (Invocation arguments)
async/stream_join_test: CompileTimeError # Issue 31402 (Invocation arguments)
async/timer_not_available_test: RuntimeError
convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Infrequent timeouts.
html/*: SkipByDesign # dart:html not supported on VM.
@ -284,9 +278,7 @@ mirrors/library_uri_io_test: RuntimeError # Please triage.
[ $strong && ($compiler == dartk || $compiler == dartkb) ]
async/slow_consumer2_test: RuntimeError # Issue 31402 (Invocation arguments)
async/stream_controller_async_test: RuntimeError
async/stream_distinct_test: RuntimeError
async/stream_join_test: RuntimeError
isolate/issue_22778_test: Crash
isolate/kill_self_synchronously_test: RuntimeError
isolate/message_test: RuntimeError

View file

@ -9,7 +9,7 @@ library MirrorsTest;
import 'dart:io';
import 'dart:mirrors';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
class Class {}

View file

@ -7,9 +7,8 @@
library MirrorsTest;
import 'dart:mirrors';
import 'package:args/args.dart';
import 'package:unittest/unittest.dart';
import 'package:expect/async_minitest.dart';
testLibraryUri(var value, Uri expectedUri) {
var valueMirror = reflect(value);