Reland "[pkg/test_runner] Write experiments to results.json"

This is a reland of 4e34ea06a9ed5de40b0ea37b538389dd7a1bf6e7

TBR=athom@google.com

Original change's description:
> [pkg/test_runner] Write experiments to results.json
>
> Change-Id: I32423ddf665a24443de1ad60ca8f323f5c6d3aca
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196489
> Reviewed-by: Alexander Thomas <athom@google.com>
> Commit-Queue: Karl Klose <karlklose@google.com>

Change-Id: I894616f77cb47df25c8da46d2bf6ddb87734db41
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/198404
Reviewed-by: Karl Klose <karlklose@google.com>
Commit-Queue: Karl Klose <karlklose@google.com>
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index 55bf077..95c7dcb 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -9,6 +9,7 @@
 import 'path.dart';
 import 'repository.dart';
 import 'runtime_configuration.dart';
+import 'test_case.dart' show TestCase;
 import 'test_file.dart';
 import 'utils.dart';
 
@@ -25,10 +26,7 @@
 /// list allows the result of calling this to be spread into another list.
 List<String> _experimentsArgument(
     TestConfiguration configuration, TestFile testFile) {
-  var experiments = {
-    ...configuration.experiments,
-    ...testFile.experiments,
-  };
+  var experiments = TestCase.getExperiments(testFile, configuration);
   if (experiments.isEmpty) {
     return const [];
   }
diff --git a/pkg/test_runner/lib/src/test_case.dart b/pkg/test_runner/lib/src/test_case.dart
index 9316d76..995bf0a 100644
--- a/pkg/test_runner/lib/src/test_case.dart
+++ b/pkg/test_runner/lib/src/test_case.dart
@@ -66,6 +66,16 @@
     assert(commands.isNotEmpty);
   }
 
+  List<String> get experiments => getExperiments(testFile, configuration);
+
+  static List<String> getExperiments(
+      TestFile testFile, TestConfiguration configuration) {
+    return [
+      ...testFile.experiments,
+      ...configuration.experiments,
+    ];
+  }
+
   TestCase indexedCopy(int index) {
     var newCommands = commands.map((c) => c.indexedCopy(index)).toList();
     return TestCase(displayName, newCommands, configuration, expectedOutcomes,
diff --git a/pkg/test_runner/lib/src/test_progress.dart b/pkg/test_runner/lib/src/test_progress.dart
index a089688..8d01e3d 100644
--- a/pkg/test_runner/lib/src/test_progress.dart
+++ b/pkg/test_runner/lib/src/test_progress.dart
@@ -656,7 +656,7 @@
     var testName = name.substring(index + 1);
     var time =
         test.commandOutputs.values.fold(Duration.zero, (d, o) => d + o.time);
-
+    var experiments = test.experiments;
     var record = {
       "name": name,
       "configuration": test.configuration.configuration.name,
@@ -665,7 +665,8 @@
       "time_ms": time.inMilliseconds,
       "result": test.realResult.toString(),
       "expected": test.realExpected.toString(),
-      "matches": test.realResult.canBeOutcomeOf(test.realExpected)
+      "matches": test.realResult.canBeOutcomeOf(test.realExpected),
+      if (experiments.isNotEmpty) "experiments": experiments,
     };
     _results.add(record);
     if (test.configuration.writeLogs && record['matches'] != true) {