Merge commit '0ea18ffb361300039787eebf76e89e181dca7c0a' into ci-test-data
diff --git a/tools/FAKE_COMMITS b/tools/FAKE_COMMITS
index 2a622d1..09d0af3 100644
--- a/tools/FAKE_COMMITS
+++ b/tools/FAKE_COMMITS
@@ -33,3 +33,16 @@
 Switch benchmark builders to Ubuntu 16.04
 Land a CL with no tryjobs, to validate a fix in copying approvals
 Confirm all approvals took effect
+
+ci-test-data branch:
+- commit with no test changes
+- no change, prepare for bisection test
+- another empty change
+- third empty change to prepare for bisection test
+- no changes to test results
+- no changes to test results
+- no changes to test results
+- no changes to test results
+- no changes to test results
+- no changes to test results
+- no changes to test results
diff --git a/tools/bots/ci_test_data_trigger b/tools/bots/ci_test_data_trigger
new file mode 100644
index 0000000..ed25505
--- /dev/null
+++ b/tools/bots/ci_test_data_trigger
@@ -0,0 +1,23 @@
+Modify this file to trigger a run of the builder the uses
+tools/bots/create_ci_test_data.dart to create synthetic
+test results.
+
+- Test new builder
+- Test after bug fix
+- Another bug fix
+- Also build dart
+- create new baseline build
+- trigger build with three commits
+- trigger build to test result database support
+- again
+- and again
+- and again
+- and again
+- let test fail
+- check that approvals are working
+- trigger bisection on test failure
+- trigger build after merge
+- create 'green' build
+- No changes to test results, trigger build
+- Make builder green
+- Trigger build
diff --git a/tools/bots/create_ci_test_data.dart b/tools/bots/create_ci_test_data.dart
new file mode 100644
index 0000000..a605f6d
--- /dev/null
+++ b/tools/bots/create_ci_test_data.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2020, 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.md file.
+
+/// This scripts is a very simple test runner that produces a results.json
+/// from a hard-coded list and can be used to create test data for the test
+/// result infrastructure on a builder.
+
+import 'dart:io';
+import 'dart:convert';
+
+import 'package:args/args.dart';
+
+const suite = "ci-test-data";
+
+const results = [
+  Result("test_a", "Pass"),
+  Result("test_b", "RuntimeError"),
+];
+
+class Result {
+  final String name;
+  final String result;
+
+  const Result(this.name, this.result);
+
+  Map<String, Object> toJson(String configuration) => {
+        "test_name": name,
+        "result": result,
+        "configuration": configuration,
+        "suite": suite,
+        "time_ms": 0,
+        "expected": "Pass",
+        "matches": result == "Pass",
+        "name": "$suite/$name",
+      };
+}
+
+main(args) {
+  var parser = new ArgParser()
+    ..addOption("named-configuration",
+        abbr: "n", help: "configuration name emitted json results")
+    ..addOption("output-directory",
+        help: "directory to which results.json is written");
+  var parsedArguments = parser.parse(args);
+  var configuration = parsedArguments["named-configuration"];
+  var outputDirectory = parsedArguments["output-directory"];
+  if (configuration == null || outputDirectory == null) {
+    print("usage: create_ci_test_data -n<CONFIGURATION> "
+        "--output-directory <PATH>");
+    exit(1);
+  }
+  var extendedResults =
+      results.map((result) => jsonEncode(result.toJson(configuration)));
+  StringBuffer sb = StringBuffer();
+  for (var result in extendedResults) {
+    sb.writeln(result);
+  }
+  var outputFile =
+      File.fromUri(Uri.directory(outputDirectory).resolve("results.json"));
+  outputFile.writeAsStringSync(sb.toString());
+}
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 5a01c59..e2dd3e1 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -373,6 +373,12 @@
     ]
   },
   "configurations": {
+    "ci-test-data": {
+      "options": {
+          "compiler": "none",
+          "builder-tag": "ci-test-data"
+      }
+    },
     "unittest-(linux|win|mac)": {
       "options": {
         "compiler": "dartk",
@@ -1027,6 +1033,30 @@
   },
   "builder_configurations": [
     {
+      "builders": ["ci-test-data"],
+      "meta": { "description": "creates synthetic results for testing" },
+      "steps": [
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=release",
+            "--arch=x64",
+            "runtime"
+          ]
+        },
+        {
+          "name": "create results",
+          "script": "out/ReleaseX64/dart",
+          "arguments": [
+            "tools/bots/create_ci_test_data.dart",
+            "-nci-test-data"
+          ],
+          "testRunner": true
+        }
+      ]
+    },
+    {
       "builders": [
         "front-end-linux-release-x64",
         "front-end-mac-release-x64",
diff --git a/tools/bots/update_blamelists.dart b/tools/bots/update_blamelists.dart
index ff795ff..1d40da1 100644
--- a/tools/bots/update_blamelists.dart
+++ b/tools/bots/update_blamelists.dart
@@ -167,7 +167,8 @@
     print(parser.usage);
     exit(1);
   }
-  var results = await loadResultsMap(options['results']);
+  var content = (await File(options['results']).readAsString()).trim();
+  var results = await parseResultsMap(content);
   if (results.isEmpty) {
     print("No test results provided, nothing to update.");
     return;