blob: 6872f18563ca3ae7c447cfaa03014378a56575e0 [file] [log] [blame]
// Copyright (c) 2023, 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.
//
// Note: we pass --save-debugging-info=* without --dwarf-stack-traces to
// make this test pass on vm-aot-dwarf-* builders.
//
// VMOptions=--save-debugging-info=$TEST_COMPILATION_DIR/debug.so
// VMOptions=--dwarf-stack-traces --save-debugging-info=$TEST_COMPILATION_DIR/debug.so
// @dart=2.9
import 'dart:async';
import 'package:expect/expect.dart';
import 'harness.dart' as harness;
// Test functions:
Future<void> throwSync() {
throw 'throw from throwSync';
}
Future<void> throwAsync() async {
await 0;
throw 'throw from throwAsync';
}
// ----
// Scenario: All async functions yielded at least once before throw:
// ----
Future<void> allYield() async {
await 0;
await allYield2();
}
Future<void> allYield2() async {
await 0;
await allYield3();
}
Future<void> allYield3() async {
await 0;
throwSync();
}
// ----
// Scenario: None of the async functions yielded before the throw:
// ----
Future<void> noYields() async {
await noYields2();
}
Future<void> noYields2() async {
await noYields3();
}
Future<void> noYields3() async {
throwSync();
}
// ----
// Scenario: Mixed yielding and non-yielding frames:
// ----
Future<void> mixedYields() async {
await mixedYields2();
}
Future<void> mixedYields2() async {
await 0;
await mixedYields3();
}
Future<void> mixedYields3() async {
return throwAsync();
}
// ----
// Scenario: Non-async frame:
// ----
Future<void> syncSuffix() async {
await syncSuffix2();
}
Future<void> syncSuffix2() async {
await 0;
await syncSuffix3();
}
Future<void> syncSuffix3() {
return throwAsync();
}
// ----
// Scenario: Caller is non-async, has no upwards stack:
// ----
Future nonAsyncNoStack() async => await nonAsyncNoStack1();
Future nonAsyncNoStack1() async => await nonAsyncNoStack2();
Future nonAsyncNoStack2() async => Future.value(0).then((_) => throwAsync());
// ----
// Scenario: async*:
// ----
Future awaitEveryAsyncStarThrowSync() async {
await for (Future v in asyncStarThrowSync()) {
await v;
}
}
Stream<Future> asyncStarThrowSync() async* {
for (int i = 0; i < 2; i++) {
await i;
yield throwSync();
}
}
Future awaitEveryAsyncStarThrowAsync() async {
await for (Future v in asyncStarThrowAsync()) {
await v;
}
}
Stream<Future> asyncStarThrowAsync() async* {
for (int i = 0; i < 2; i++) {
await i;
yield Future.value(i);
await throwAsync();
}
}
Future listenAsyncStarThrowAsync() async {
final _output = [];
// Listening to an async* doesn't create the usual await-for StreamIterator.
StreamSubscription ss = asyncStarThrowAsync().listen((Future f) {
_output.add('unique value');
});
await ss.asFuture();
if (_output.length == 44) {
print(_output);
}
}
// ----
// Scenario: All async functions yielded and we run in a custom zone with a
// custom error handler.
// ----
Future<void> customErrorZone() async {
final completer = Completer<void>();
runZonedGuarded(() async {
await allYield();
completer.complete(null);
}, (e, s) {
completer.completeError(e, s);
});
return completer.future;
}
// ----
// Scenario: Future.timeout:
// ----
Future awaitTimeout() async {
await (throwAsync().timeout(Duration(seconds: 1)));
}
// ----
// Scenario: Future.wait:
// ----
Future awaitWait() async {
await Future.wait([
throwAsync(),
() async {
await Future.value();
}()
]);
}
// ----
// Scenario: Future.whenComplete:
// ----
Future futureSyncWhenComplete() {
return Future.sync(throwAsync).whenComplete(() => 'nop');
}
// ----
// Scenario: Future.then:
// ----
Future futureThen() {
return Future.value(0).then((value) {
throwSync();
}).then(_doSomething);
}
void _doSomething(_) {
Expect.fail('Should not reach doSomething');
}
Future<void> doTestAwait(Future f()) async {
await f();
Expect.fail('No exception thrown!');
}
Future<void> doTestAwaitThen(Future f()) async {
// Passing (e) {} to then() can cause the closure instructions to be
// deduped, changing the stack trace to the deduped owner, so we
// duplicate the Expect.fail() call in the closure.
await f().then((e) => Expect.fail('No exception thrown!'));
}
Future<void> doTestAwaitCatchError(Future f()) async {
Object error;
StackTrace stackTrace;
await f().catchError((e, s) {
error = e;
stackTrace = s;
});
return Future.error(error, stackTrace);
}
Future<void> main(List<String> args) async {
if (harness.shouldSkip()) {
return;
}
harness.configure(currentExpectations);
final tests = [
allYield,
noYields,
mixedYields,
syncSuffix,
nonAsyncNoStack,
awaitEveryAsyncStarThrowSync,
awaitEveryAsyncStarThrowAsync,
listenAsyncStarThrowAsync,
customErrorZone,
awaitTimeout,
awaitWait,
futureSyncWhenComplete,
futureThen,
];
for (var test in tests) {
await harness.runTest(() => doTestAwait(test));
await harness.runTest(() => doTestAwaitThen(test));
await harness.runTest(() => doTestAwaitCatchError(test));
}
harness.updateExpectations();
}
// CURRENT EXPECTATIONS BEGIN
final currentExpectations = [
"""
#0 throwSync (%test%)
#1 allYield3 (%test%)
<asynchronous suspension>
#2 allYield2 (%test%)
<asynchronous suspension>
#3 allYield (%test%)
<asynchronous suspension>
#4 doTestAwait (%test%)
<asynchronous suspension>
#5 runTest (harness.dart)
<asynchronous suspension>
#6 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 allYield3 (%test%)
<asynchronous suspension>
#2 allYield2 (%test%)
<asynchronous suspension>
#3 allYield (%test%)
<asynchronous suspension>
#4 doTestAwaitThen.<anonymous closure> (%test%)
<asynchronous suspension>
#5 doTestAwaitThen (%test%)
<asynchronous suspension>
#6 runTest (harness.dart)
<asynchronous suspension>
#7 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 allYield3 (%test%)
<asynchronous suspension>
#2 allYield2 (%test%)
<asynchronous suspension>
#3 allYield (%test%)
<asynchronous suspension>
#4 doTestAwaitCatchError (%test%)
<asynchronous suspension>
#5 runTest (harness.dart)
<asynchronous suspension>
#6 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 noYields3 (%test%)
#2 noYields2 (%test%)
#3 noYields (%test%)
#4 doTestAwait (%test%)
#5 main.<anonymous closure> (%test%)
#6 runTest (harness.dart)
#7 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 noYields3 (%test%)
#2 noYields2 (%test%)
#3 noYields (%test%)
#4 doTestAwaitThen (%test%)
#5 main.<anonymous closure> (%test%)
#6 runTest (harness.dart)
#7 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 noYields3 (%test%)
#2 noYields2 (%test%)
#3 noYields (%test%)
#4 doTestAwaitCatchError (%test%)
#5 main.<anonymous closure> (%test%)
#6 runTest (harness.dart)
#7 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 mixedYields2 (%test%)
<asynchronous suspension>
#2 mixedYields (%test%)
<asynchronous suspension>
#3 doTestAwait (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 mixedYields2 (%test%)
<asynchronous suspension>
#2 mixedYields (%test%)
<asynchronous suspension>
#3 doTestAwaitThen.<anonymous closure> (%test%)
<asynchronous suspension>
#4 doTestAwaitThen (%test%)
<asynchronous suspension>
#5 runTest (harness.dart)
<asynchronous suspension>
#6 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 mixedYields2 (%test%)
<asynchronous suspension>
#2 mixedYields (%test%)
<asynchronous suspension>
#3 doTestAwaitCatchError (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 syncSuffix2 (%test%)
<asynchronous suspension>
#2 syncSuffix (%test%)
<asynchronous suspension>
#3 doTestAwait (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 syncSuffix2 (%test%)
<asynchronous suspension>
#2 syncSuffix (%test%)
<asynchronous suspension>
#3 doTestAwaitThen.<anonymous closure> (%test%)
<asynchronous suspension>
#4 doTestAwaitThen (%test%)
<asynchronous suspension>
#5 runTest (harness.dart)
<asynchronous suspension>
#6 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 syncSuffix2 (%test%)
<asynchronous suspension>
#2 syncSuffix (%test%)
<asynchronous suspension>
#3 doTestAwaitCatchError (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 nonAsyncNoStack1 (%test%)
<asynchronous suspension>
#2 nonAsyncNoStack (%test%)
<asynchronous suspension>
#3 doTestAwait (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 nonAsyncNoStack1 (%test%)
<asynchronous suspension>
#2 nonAsyncNoStack (%test%)
<asynchronous suspension>
#3 doTestAwaitThen.<anonymous closure> (%test%)
<asynchronous suspension>
#4 doTestAwaitThen (%test%)
<asynchronous suspension>
#5 runTest (harness.dart)
<asynchronous suspension>
#6 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 nonAsyncNoStack1 (%test%)
<asynchronous suspension>
#2 nonAsyncNoStack (%test%)
<asynchronous suspension>
#3 doTestAwaitCatchError (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 asyncStarThrowSync (%test%)
<asynchronous suspension>
#2 awaitEveryAsyncStarThrowSync (%test%)
<asynchronous suspension>
#3 doTestAwait (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 asyncStarThrowSync (%test%)
<asynchronous suspension>
#2 awaitEveryAsyncStarThrowSync (%test%)
<asynchronous suspension>
#3 doTestAwaitThen.<anonymous closure> (%test%)
<asynchronous suspension>
#4 doTestAwaitThen (%test%)
<asynchronous suspension>
#5 runTest (harness.dart)
<asynchronous suspension>
#6 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 asyncStarThrowSync (%test%)
<asynchronous suspension>
#2 awaitEveryAsyncStarThrowSync (%test%)
<asynchronous suspension>
#3 doTestAwaitCatchError (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 asyncStarThrowAsync (%test%)
<asynchronous suspension>
#2 awaitEveryAsyncStarThrowAsync (%test%)
<asynchronous suspension>
#3 doTestAwait (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 asyncStarThrowAsync (%test%)
<asynchronous suspension>
#2 awaitEveryAsyncStarThrowAsync (%test%)
<asynchronous suspension>
#3 doTestAwaitThen.<anonymous closure> (%test%)
<asynchronous suspension>
#4 doTestAwaitThen (%test%)
<asynchronous suspension>
#5 runTest (harness.dart)
<asynchronous suspension>
#6 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 asyncStarThrowAsync (%test%)
<asynchronous suspension>
#2 awaitEveryAsyncStarThrowAsync (%test%)
<asynchronous suspension>
#3 doTestAwaitCatchError (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 asyncStarThrowAsync (%test%)
<asynchronous suspension>
#2 listenAsyncStarThrowAsync.<anonymous closure> (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 asyncStarThrowAsync (%test%)
<asynchronous suspension>
#2 listenAsyncStarThrowAsync.<anonymous closure> (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 asyncStarThrowAsync (%test%)
<asynchronous suspension>
#2 listenAsyncStarThrowAsync.<anonymous closure> (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 allYield3 (%test%)
<asynchronous suspension>
#2 allYield2 (%test%)
<asynchronous suspension>
#3 allYield (%test%)
<asynchronous suspension>
#4 customErrorZone.<anonymous closure> (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 allYield3 (%test%)
<asynchronous suspension>
#2 allYield2 (%test%)
<asynchronous suspension>
#3 allYield (%test%)
<asynchronous suspension>
#4 customErrorZone.<anonymous closure> (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 allYield3 (%test%)
<asynchronous suspension>
#2 allYield2 (%test%)
<asynchronous suspension>
#3 allYield (%test%)
<asynchronous suspension>
#4 customErrorZone.<anonymous closure> (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 Future.timeout.<anonymous closure> (future_impl.dart)
<asynchronous suspension>
#2 awaitTimeout (%test%)
<asynchronous suspension>
#3 doTestAwait (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 Future.timeout.<anonymous closure> (future_impl.dart)
<asynchronous suspension>
#2 awaitTimeout (%test%)
<asynchronous suspension>
#3 doTestAwaitThen.<anonymous closure> (%test%)
<asynchronous suspension>
#4 doTestAwaitThen (%test%)
<asynchronous suspension>
#5 runTest (harness.dart)
<asynchronous suspension>
#6 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 Future.timeout.<anonymous closure> (future_impl.dart)
<asynchronous suspension>
#2 awaitTimeout (%test%)
<asynchronous suspension>
#3 doTestAwaitCatchError (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 Future.wait.<anonymous closure> (future.dart)
<asynchronous suspension>
#2 awaitWait (%test%)
<asynchronous suspension>
#3 doTestAwait (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 Future.wait.<anonymous closure> (future.dart)
<asynchronous suspension>
#2 awaitWait (%test%)
<asynchronous suspension>
#3 doTestAwaitThen.<anonymous closure> (%test%)
<asynchronous suspension>
#4 doTestAwaitThen (%test%)
<asynchronous suspension>
#5 runTest (harness.dart)
<asynchronous suspension>
#6 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 Future.wait.<anonymous closure> (future.dart)
<asynchronous suspension>
#2 awaitWait (%test%)
<asynchronous suspension>
#3 doTestAwaitCatchError (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 futureSyncWhenComplete.<anonymous closure> (%test%)
<asynchronous suspension>
#2 doTestAwait (%test%)
<asynchronous suspension>
#3 runTest (harness.dart)
<asynchronous suspension>
#4 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 futureSyncWhenComplete.<anonymous closure> (%test%)
<asynchronous suspension>
#2 doTestAwaitThen.<anonymous closure> (%test%)
<asynchronous suspension>
#3 doTestAwaitThen (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwAsync (%test%)
<asynchronous suspension>
#1 futureSyncWhenComplete.<anonymous closure> (%test%)
<asynchronous suspension>
#2 doTestAwaitCatchError (%test%)
<asynchronous suspension>
#3 runTest (harness.dart)
<asynchronous suspension>
#4 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 futureThen.<anonymous closure> (%test%)
<asynchronous suspension>
#2 _doSomething (%test%)
<asynchronous suspension>
#3 doTestAwait (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 futureThen.<anonymous closure> (%test%)
<asynchronous suspension>
#2 _doSomething (%test%)
<asynchronous suspension>
#3 doTestAwaitThen.<anonymous closure> (%test%)
<asynchronous suspension>
#4 doTestAwaitThen (%test%)
<asynchronous suspension>
#5 runTest (harness.dart)
<asynchronous suspension>
#6 main (%test%)
<asynchronous suspension>""",
"""
#0 throwSync (%test%)
#1 futureThen.<anonymous closure> (%test%)
<asynchronous suspension>
#2 _doSomething (%test%)
<asynchronous suspension>
#3 doTestAwaitCatchError (%test%)
<asynchronous suspension>
#4 runTest (harness.dart)
<asynchronous suspension>
#5 main (%test%)
<asynchronous suspension>"""
];
// CURRENT EXPECTATIONS END