Add back Configuration.loadFromString constructor (#1534)

This API is not used within the test runner, but is used from
`build_test`.

Rename what was `loadFromString` to `parse` and move the file reading to
the `Configuration.load` constructor.
diff --git a/pkgs/test/CHANGELOG.md b/pkgs/test/CHANGELOG.md
index ac1bc19..5129b4c 100644
--- a/pkgs/test/CHANGELOG.md
+++ b/pkgs/test/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.17.7
+
+* Support the latest `test_core`.
+
 ## 1.17.6
 
 * Give a better error when `printOnFailure` is called from outside a test
diff --git a/pkgs/test/pubspec.yaml b/pkgs/test/pubspec.yaml
index 53a8e8d..d76fe06 100644
--- a/pkgs/test/pubspec.yaml
+++ b/pkgs/test/pubspec.yaml
@@ -1,5 +1,5 @@
 name: test
-version: 1.17.6
+version: 1.17.7
 description: >-
   A full featured library for writing and running Dart tests across platforms.
 repository: https://github.com/dart-lang/test/blob/master/pkgs/test
@@ -34,7 +34,7 @@
   yaml: ^3.0.0
   # Use an exact version until the test_api and test_core package are stable.
   test_api: 0.4.1
-  test_core: 0.3.26
+  test_core: 0.3.27
 
 dev_dependencies:
   fake_async: ^1.0.0
diff --git a/pkgs/test_core/CHANGELOG.md b/pkgs/test_core/CHANGELOG.md
index f9c0e05..d5da5c6 100644
--- a/pkgs/test_core/CHANGELOG.md
+++ b/pkgs/test_core/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.3.27
+
+* Restore the `Configuration.loadFromString` constructor.
+
 ## 0.3.26
 
 * Give a better error when `printOnFailure` is called from outside a test
diff --git a/pkgs/test_core/lib/src/runner/configuration.dart b/pkgs/test_core/lib/src/runner/configuration.dart
index 1873b7c..6bb3c35 100644
--- a/pkgs/test_core/lib/src/runner/configuration.dart
+++ b/pkgs/test_core/lib/src/runner/configuration.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:io';
 
 import 'package:boolean_selector/boolean_selector.dart';
 import 'package:collection/collection.dart';
@@ -202,15 +203,31 @@
   /// Throws a [FormatException] if [args] are invalid.
   factory Configuration.parse(List<String> arguments) => args.parse(arguments);
 
-  /// Loads the configuration from [path].
+  /// Loads configuration from [path].
   ///
-  /// If [global] is `true`, this restricts the configuration file to only rules
-  /// that are supported globally.
+  /// If [global] is `true`, this restricts the configuration to rules that are
+  /// supported globally.
   ///
   /// Throws an [IOException] if [path] does not exist or cannot be read. Throws
-  /// a [FormatException] if its contents are invalid.
-  factory Configuration.load(String path, {bool global = false}) =>
-      load(path, global: global);
+  /// a [FormatException] if the file contents are invalid.
+  factory Configuration.load(String path, {bool global = false}) {
+    final content = File(path).readAsStringSync();
+    final sourceUrl = p.toUri(path);
+    return parse(content, global: global, sourceUrl: sourceUrl);
+  }
+
+  /// Parses configuration from YAML formatted [content].
+  ///
+  /// If [global] is `true`, this restricts the configuration to rules that are
+  /// supported globally.
+  ///
+  /// If [sourceUrl] is provided it will be set as the source url for the yaml
+  /// document.
+  ///
+  /// Throws a [FormatException] if the content is invalid.
+  factory Configuration.loadFromString(String content,
+          {bool global = false, Uri? sourceUrl}) =>
+      parse(content, global: global, sourceUrl: sourceUrl);
 
   factory Configuration(
       {bool? help,
diff --git a/pkgs/test_core/lib/src/runner/configuration/load.dart b/pkgs/test_core/lib/src/runner/configuration/load.dart
index 8ac202a..57084e1 100644
--- a/pkgs/test_core/lib/src/runner/configuration/load.dart
+++ b/pkgs/test_core/lib/src/runner/configuration/load.dart
@@ -24,7 +24,6 @@
 import '../runtime_selection.dart';
 import '../suite.dart';
 import 'custom_runtime.dart';
-import 'load.dart' as self;
 import 'reporters.dart';
 import 'runtime_settings.dart';
 
@@ -41,7 +40,7 @@
 final _packageName =
     RegExp('^${_identifierRegExp.pattern}(\\.${_identifierRegExp.pattern})*\$');
 
-/// Loads configuration information from a YAML file at [path].
+/// Parses configuration from YAML formatted [content].
 ///
 /// If [global] is `true`, this restricts the configuration file to only rules
 /// that are supported globally.
@@ -50,19 +49,18 @@
 /// the yaml document.
 ///
 /// Throws a [FormatException] if the configuration is invalid.
-Configuration load(String path, {bool global = false}) {
-  var source = File(path).readAsStringSync();
-  var document = loadYamlNode(source, sourceUrl: p.toUri(path));
+Configuration parse(String content, {Uri? sourceUrl, bool global = false}) {
+  var document = loadYamlNode(content, sourceUrl: sourceUrl);
 
   if (document.value == null) return Configuration.empty;
 
   if (document is! Map) {
     throw SourceSpanFormatException(
-        'The configuration must be a YAML map.', document.span, source);
+        'The configuration must be a YAML map.', document.span, content);
   }
 
   var loader =
-      _ConfigurationLoader(document as YamlMap, source, global: global);
+      _ConfigurationLoader(document as YamlMap, content, global: global);
   return loader.load();
 }
 
@@ -108,7 +106,7 @@
     var basePath =
         p.join(p.dirname(p.fromUri(_document.span.sourceUrl)), includePath);
     try {
-      return self.load(basePath);
+      return Configuration.load(basePath);
     } on FileSystemException catch (error) {
       throw SourceSpanFormatException(
           getErrorMessage(error), includeNode.span, _source);
diff --git a/pkgs/test_core/pubspec.yaml b/pkgs/test_core/pubspec.yaml
index 8605b88..c5862a4 100644
--- a/pkgs/test_core/pubspec.yaml
+++ b/pkgs/test_core/pubspec.yaml
@@ -1,5 +1,5 @@
 name: test_core
-version: 0.3.26
+version: 0.3.27
 description: A basic library for writing tests and running them on the VM.
 homepage: https://github.com/dart-lang/test/blob/master/pkgs/test_core