[CFE] DartDoc tests prints errors on crash better
Before:
```
Bang or other message!
Processed 4 test(s) in 205 ms.
3 OK; 0 bad; 1 crashed; 0 parse errors.
```
Now:
```
Failure:
Test from file://path/to/pkg/front_end/lib/src/kernel/body_builder.dart:10086:7 crashed with this message:
Bang or other message!
Stacktrace:
#0 debugName (package:front_end/src/kernel/body_builder.dart:10102:23)
Processed 4 test(s) in 90 ms.
3 OK; 0 bad; 1 crashed; 0 parse errors.
```
Change-Id: I49e8543dea5dc5285091fb57e8b92c45684fb5d8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/379060
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/test/dartdoc_test_test.dart b/pkg/front_end/test/dartdoc_test_test.dart
index 4588e5f..65e561d 100644
--- a/pkg/front_end/test/dartdoc_test_test.dart
+++ b/pkg/front_end/test/dartdoc_test_test.dart
@@ -150,7 +150,9 @@
expected = [
new impl.TestResult(tests[0], impl.TestOutcome.Crash)
// this weird message is from the VM!
- ..message = "type 'int' is not a subtype of type 'String' of 'other'",
+ ..message = "type 'int' is not a subtype of type 'String' of 'other'\n"
+ "\n"
+ "Stacktrace:",
new impl.TestResult(tests[1], impl.TestOutcome.Pass),
];
memoryFileSystem.entityForUri(test6).writeAsStringSync(test);
@@ -209,6 +211,32 @@
];
memoryFileSystem.entityForUri(test9).writeAsStringSync(test);
expect(await dartDocTest.process(test9), expected);
+
+ // Test crashes with stacktrace.
+ Uri test10 = new Uri(scheme: "darttest", path: "/test10.dart");
+ test = """
+// DartDocTest(await _internal(), 42)
+Future<int> _internal() async {
+ await Future.delayed(new Duration(milliseconds: 1));
+ if (1+1==2) throw "I threw!";
+ return 42;
+}
+""";
+ tests = extractTests(test, test10);
+ expect(tests.length, 1);
+ expected = [
+ new impl.TestResult(tests[0], impl.TestOutcome.Crash)
+ ..message = "I threw!"
+ "\n"
+ "\nStacktrace:"
+ "\n#0 _internal (darttest:/test10.dart:4:15)"
+ "\n<asynchronous suspension>",
+ ];
+ memoryFileSystem.entityForUri(test10).writeAsStringSync(test);
+ expect(await dartDocTest.process(test10), expected);
+
+ // TODO(jensj): Run in non-silent mode, but capturing the stdout, to verify
+ // the actually written text on stdout.
}
void testTestExtraction() {
diff --git a/pkg/front_end/tool/dart_doctest_impl.dart b/pkg/front_end/tool/dart_doctest_impl.dart
index cbccbda..10e22e8 100644
--- a/pkg/front_end/tool/dart_doctest_impl.dart
+++ b/pkg/front_end/tool/dart_doctest_impl.dart
@@ -122,15 +122,15 @@
case ExpectTest():
sb.writeln("try {");
sb.writeln(" dartDocTest.test(${test.call}, ${test.result});");
- sb.writeln("} catch (e) {");
- sb.writeln(" dartDocTest.crash(e);");
+ sb.writeln("} catch (e, st) {");
+ sb.writeln(" dartDocTest.crash(e, st);");
sb.writeln("}");
case ThrowsTest():
sb.writeln("try {");
sb.writeln(
" await dartDocTest.throws(() async { ${test.call}; });");
- sb.writeln("} catch (e) {");
- sb.writeln(" dartDocTest.crash(e);");
+ sb.writeln("} catch (e, st) {");
+ sb.writeln(" dartDocTest.crash(e, st);");
sb.writeln("}");
}
}
@@ -247,12 +247,26 @@
"Test from ${currentTest!.location} failed with this message:\n"
"$strippedMessage\n");
} else if (message.toString().startsWith("$_portMessageCrash: ")) {
+ List<String> strippedMessageLines = message
+ .toString()
+ .substring("$_portMessageCrash: ".length)
+ .split("\n");
+ int end = 1;
+ for (int i = 0; i < strippedMessageLines.length; i++) {
+ if (strippedMessageLines[i].contains(r"$dart$doc$test$tester ()")) {
+ end = i;
+ break;
+ }
+ }
String strippedMessage =
- message.toString().substring("$_portMessageCrash: ".length);
+ strippedMessageLines.sublist(0, end).join("\n");
+
result.add(new TestResult(currentTest!, TestOutcome.Crash)
..message = strippedMessage);
crashCount++;
- _print(strippedMessage);
+ _print("Failure:\n"
+ "Test from ${currentTest!.location} crashed with this message:\n"
+ "$strippedMessage\n");
} else if (message.toString().startsWith("$_portMessageParseError: ")) {
String strippedMessage =
message.toString().substring("$_portMessageParseError: ".length);
@@ -260,7 +274,9 @@
new TestResult(currentTest!, TestOutcome.TestCompilationError)
..message = strippedMessage);
parseErrorCount++;
- _print(strippedMessage);
+ _print("Failure:\n"
+ "Test from ${currentTest!.location} has a parse error:\n"
+ "$strippedMessage\n");
} else if (message == _portMessageDone) {
done = true;
// don't complete completer here. Expect the exit port to close.
@@ -373,9 +389,9 @@
}
}
- void crash(dynamic error) {
+ void crash(dynamic error, dynamic st) {
port.send("$_portMessageTest");
- port.send("$_portMessageCrash: \$error");
+ port.send("$_portMessageCrash: \$error\\n\\nStacktrace:\\n\$st");
}
void parseError(String message) {