| Index: lib/src/runner/configuration/load.dart
|
| diff --git a/lib/src/runner/configuration/load.dart b/lib/src/runner/configuration/load.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d2def18469e06f6540022fee732263844aec1fd4
|
| --- /dev/null
|
| +++ b/lib/src/runner/configuration/load.dart
|
| @@ -0,0 +1,156 @@
|
| +// Copyright (c) 2016, 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 file.
|
| +
|
| +import 'dart:io';
|
| +
|
| +import 'package:path/path.dart' as p;
|
| +import 'package:source_span/source_span.dart';
|
| +import 'package:yaml/yaml.dart';
|
| +
|
| +import '../../utils.dart';
|
| +import '../../frontend/timeout.dart';
|
| +import '../../backend/test_platform.dart';
|
| +import '../configuration.dart';
|
| +import 'values.dart';
|
| +
|
| +/// Loads configuration information from a YAML file at [path].
|
| +///
|
| +/// Throws a [FormatException] if the configuration is invalid, and a
|
| +/// [FileSystemException] if it can't be read.
|
| +Configuration load(String path) {
|
| + var source = new File(path).readAsStringSync();
|
| + var document = loadYamlNode(source, sourceUrl: p.toUri(path));
|
| +
|
| + if (document.value == null) return new Configuration();
|
| +
|
| + if (document is! Map) {
|
| + throw new SourceSpanFormatException(
|
| + "The configuration must be a YAML map.", document.span, source);
|
| + }
|
| +
|
| + var loader = new _ConfigurationLoader(document, source);
|
| + return loader.load();
|
| +}
|
| +
|
| +/// A helper for [load] that tracks the YAML document.
|
| +class _ConfigurationLoader {
|
| + /// The parsed configuration document.
|
| + final YamlMap _document;
|
| +
|
| + /// The source string for [_document].
|
| + ///
|
| + /// Used for error reporting.
|
| + final String _source;
|
| +
|
| + _ConfigurationLoader(this._document, this._source);
|
| +
|
| + /// Loads the configuration in [_document].
|
| + Configuration load() {
|
| + var verboseTrace = _getBool("verbose_trace");
|
| + var jsTrace = _getBool("js_trace");
|
| +
|
| + var reporter = _getString("reporter");
|
| + if (reporter != null && !allReporters.contains(reporter)) {
|
| + _error('Unknown reporter "$reporter".', "reporter");
|
| + }
|
| +
|
| + var pubServePort = _getInt("pub_serve");
|
| + var concurrency = _getInt("concurrency");
|
| + var timeout = _parseValue("timeout", (value) => new Timeout.parse(value));
|
| +
|
| + var allPlatformIdentifiers =
|
| + TestPlatform.all.map((platform) => platform.identifier).toSet();
|
| + var platforms = _getList("platforms", (platformNode) {
|
| + _validate(platformNode, "Platforms must be strings.",
|
| + (value) => value is String);
|
| + _validate(platformNode, 'Unknown platform "${platformNode.value}".',
|
| + allPlatformIdentifiers.contains);
|
| +
|
| + return TestPlatform.find(platformNode.value);
|
| + });
|
| +
|
| + // TODO(nweiz): Add support for using globs to define defaults paths to run.
|
| +
|
| + return new Configuration(
|
| + verboseTrace: verboseTrace,
|
| + jsTrace: jsTrace,
|
| + reporter: reporter,
|
| + pubServePort: pubServePort,
|
| + concurrency: concurrency,
|
| + timeout: timeout,
|
| + platforms: platforms);
|
| + }
|
| +
|
| + /// Throws an exception with [message] if [test] returns `false` when passed
|
| + /// [node]'s value.
|
| + void _validate(YamlNode node, String message, bool test(value)) {
|
| + if (test(node.value)) return;
|
| + throw new SourceSpanFormatException(message, node.span, _source);
|
| + }
|
| +
|
| + /// Returns the value of the node at [field].
|
| + ///
|
| + /// If [typeTest] returns `false` for that value, instead throws an error
|
| + /// complaining that the field is not a [typeName].
|
| + _getValue(String field, String typeName, bool typeTest(value)) {
|
| + var value = _document[field];
|
| + if (value == null || typeTest(value)) return value;
|
| + _error("$field must be ${a(typeName)}.", field);
|
| + }
|
| +
|
| + /// Returns the YAML node at [field].
|
| + ///
|
| + /// If [typeTest] returns `false` for that node's value, instead throws an
|
| + /// error complaining that the field is not a [typeName].
|
| + YamlNode _getNode(String field, String typeName, bool typeTest(value)) {
|
| + var node = _document.nodes[field];
|
| + if (node == null) return null;
|
| + _validate(node, "$field must be ${a(typeName)}.", typeTest);
|
| + return node;
|
| + }
|
| +
|
| + /// Asserts that [field] is an int and returns its value.
|
| + int _getInt(String field) =>
|
| + _getValue(field, "int", (value) => value is int);
|
| +
|
| + /// Asserts that [field] is a boolean and returns its value.
|
| + bool _getBool(String field) =>
|
| + _getValue(field, "boolean", (value) => value is bool);
|
| +
|
| + /// Asserts that [field] is a string and returns its value.
|
| + String _getString(String field) =>
|
| + _getValue(field, "string", (value) => value is String);
|
| +
|
| + /// Asserts that [field] is a list and runs [forElement] for each element it
|
| + /// contains.
|
| + ///
|
| + /// Returns a list of values returned by [forElement].
|
| + List _getList(String field, forElement(YamlNode elementNode)) {
|
| + var node = _getNode(field, "list", (value) => value is List);
|
| + if (node == null) return [];
|
| + return node.nodes.map(forElement).toList();
|
| + }
|
| +
|
| + /// Asserts that [field] is a string, passes it to [parse], and returns the
|
| + /// result.
|
| + ///
|
| + /// If [parse] throws a [FormatException], it's wrapped to include [field]'s
|
| + /// span.
|
| + _parseValue(String field, parse(value)) {
|
| + var value = _getString(field);
|
| + if (value == null) return null;
|
| +
|
| + try {
|
| + return parse(value);
|
| + } on FormatException catch (error) {
|
| + _error('Invalid $field: ${error.message}', field);
|
| + }
|
| + }
|
| +
|
| + /// Throws a [SourceSpanFormatException] with [message] about [field].
|
| + void _error(String message, String field) {
|
| + throw new SourceSpanFormatException(
|
| + message, _document.nodes[field].span, _source);
|
| + }
|
| +}
|
|
|