Add --logs parameter to compare_results.dart, and output logs
The logs of tests that start failing will be output at the end of stdout.
Change-Id: I93a85c983be278e93aaf7d7447438667c54b5185
Reviewed-on: https://dart-review.googlesource.com/c/85500
Reviewed-by: Jonas Termansen <sortie@google.com>
diff --git a/tools/bots/compare_results.dart b/tools/bots/compare_results.dart
index 6218338..62f06d9 100755
--- a/tools/bots/compare_results.dart
+++ b/tools/bots/compare_results.dart
@@ -34,7 +34,7 @@
flaked = flakinessData != null &&
flakinessData["outcomes"].contains(map["result"]);
- String get key => "$name:$configuration";
+ String get key => "$configuration:$name";
}
class Event {
@@ -78,8 +78,14 @@
bool firstSection = true;
-bool search(String description, String searchForStatus,
- String searchForApproval, List<Event> events, ArgResults options) {
+bool search(
+ String description,
+ String searchForStatus,
+ String searchForApproval,
+ List<Event> events,
+ ArgResults options,
+ Map<String, Map<String, dynamic>> logs,
+ List<String> logSection) {
bool judgement = false;
bool beganSection = false;
int count = options["count"] != null ? int.parse(options["count"]) : null;
@@ -106,7 +112,7 @@
if (options["unchanged"] && !event.unchanged) continue;
if (options["changed"] && !event.changed) continue;
if (!beganSection) {
- if (options["human"]) {
+ if (options["human"] && !options["logs-only"]) {
if (!firstSection) {
print("");
}
@@ -134,31 +140,31 @@
break;
}
}
- if (options["human"]) {
- if (options["verbose"]) {
- String expected =
- after.matches ? "" : ", expected ${after.expectation}";
+ String output;
+ if (options["verbose"]) {
+ if (options["human"]) {
+ String expect = after.matches ? "" : ", expected ${after.expectation}";
if (before == null || before.outcome == after.outcome) {
- print("${name} ${event.description} "
- "(${event.after.outcome}${expected})");
+ output = "$name ${event.description} "
+ "(${event.after.outcome}${expect})";
} else {
- print("${name} ${event.description} "
- "(${event.before?.outcome} -> ${event.after.outcome}${expected})");
+ output = "name ${event.description} "
+ "(${event.before?.outcome} -> ${event.after.outcome}${expect})";
}
} else {
- print(name);
- }
- } else {
- if (options["verbose"]) {
- print("$name "
- "${before?.outcome} ${after.outcome} "
+ output = "$name ${before?.outcome} ${after.outcome} "
"${before?.expectation} ${after.expectation} "
"${before?.matches} ${after.matches} "
- "${before?.flaked} ${after.flaked}");
- } else {
- print(name);
+ "${before?.flaked} ${after.flaked}";
}
}
+ if (logs != null) {
+ final log = logs[event.after.key];
+ if (log != null) logSection?.add("\n\nLog for $output\n${log["log"]}");
+ }
+ if (!options["logs-only"]) {
+ print(output);
+ }
}
return judgement;
@@ -202,6 +208,11 @@
abbr: "v",
help: "Show the old and new result for each test",
negatable: false);
+ parser.addOption("logs",
+ abbr: "l", help: "Path to file holding logs of failing tests.");
+ parser.addFlag("logs-only",
+ help: "Only print logs of failing tests, no other output",
+ negatable: false);
final options = parser.parse(args);
if (options["help"]) {
@@ -238,6 +249,9 @@
final approved = 3 <= parameters.length
? await loadResultsMap(parameters[2])
: <String, Map<String, dynamic>>{};
+ final logs = options['logs'] == null
+ ? <String, Map<String, dynamic>>{}
+ : await loadResultsMap(options['logs']);
final flakinessData = options["flakiness-data"] != null
? await loadResultsMap(options["flakiness-data"])
: <String, Map<String, dynamic>>{};
@@ -314,6 +328,7 @@
["approved", "unapproved"].where((option) => options[option]);
// Report tests matching the filters.
+ final logSection = <String>[];
bool judgement = false;
for (final searchForStatus
in searchForStatuses.isNotEmpty ? searchForStatuses : <String>[null]) {
@@ -327,8 +342,9 @@
final aboutApproval =
approvalDescriptions[searchForStatus][searchForApproval];
final sectionHeader = "The following tests $aboutStatus$aboutApproval:";
- bool possibleJudgement = search(
- sectionHeader, searchForStatus, searchForApproval, events, options);
+ final logSectionArg = searchForStatus == "failing" ? logSection : null;
+ bool possibleJudgement = search(sectionHeader, searchForStatus,
+ searchForApproval, events, options, logs, logSectionArg);
if ((searchForStatus == null || searchForStatus == "failing") &&
(searchForApproval == null || searchForApproval == "unapproved")) {
judgement = possibleJudgement;
@@ -336,20 +352,23 @@
}
}
+ if (logSection.isNotEmpty) {
+ print(logSection.join());
+ }
// Exit 1 only if --judgement and any test failed.
if (options["judgement"]) {
- if (options["human"] && !firstSection) {
+ if (options["human"] && !options["logs-only"] && !firstSection) {
print("");
}
String oldNew =
options["unchanged"] ? "old " : options["changed"] ? "new " : "";
if (judgement) {
- if (options["human"]) {
+ if (options["human"] && !options["logs-only"]) {
print("There were ${oldNew}test failures.");
}
exitCode = 1;
} else {
- if (options["human"]) {
+ if (options["human"] && !options["logs-only"]) {
print("No ${oldNew}test failures were found.");
}
}
diff --git a/tools/bots/results.dart b/tools/bots/results.dart
index 36b27f2..8405a6d 100644
--- a/tools/bots/results.dart
+++ b/tools/bots/results.dart
@@ -115,12 +115,7 @@
Map<String, Map<String, dynamic>> createResultsMap(
List<Map<String, dynamic>> results) =>
- new Map<String, Map<String, dynamic>>.fromIterable(
- results
- // TODO: Temporarily discard results in the old flaky.json format
- // This can be removed once every bot has run once after this commit
- // has landed, purging all old flakiness information.
- .where((result) => result["configuration"] != null),
+ new Map<String, Map<String, dynamic>>.fromIterable(results,
key: (dynamic result) =>
"${result["configuration"]}:${result["name"]}");