Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: lib/src/runner/configuration/load.dart

Issue 1649663003: Add basic support for a configuration file. (Closed) Base URL: git@github.com:dart-lang/test@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 import 'dart:io';
6
7 import 'package:path/path.dart' as p;
8 import 'package:source_span/source_span.dart';
9 import 'package:yaml/yaml.dart';
10
11 import '../../utils.dart';
12 import '../../frontend/timeout.dart';
13 import '../../backend/test_platform.dart';
14 import '../configuration.dart';
15 import 'values.dart';
16
17 /// Loads configuration information from a YAML file at [path].
18 ///
19 /// Throws a [FormatException] if the configuration is invalid, and a
20 /// [FileSystemException] if it can't be read.
21 Configuration load(String path) {
22 var source = new File(path).readAsStringSync();
23 var document = loadYamlNode(source, sourceUrl: p.toUri(path));
24
25 if (document.value == null) return new Configuration();
26
27 if (document is! Map) {
28 throw new SourceSpanFormatException(
29 "The configuration must be a YAML map.", document.span, source);
30 }
31
32 var loader = new _ConfigurationLoader(document, source);
33 return loader.load();
34 }
35
36 /// A helper for [load] that tracks the YAML document.
37 class _ConfigurationLoader {
38 /// The parsed configuration document.
39 final YamlMap _document;
40
41 /// The source string for [_document].
42 ///
43 /// Used for error reporting.
44 final String _source;
45
46 _ConfigurationLoader(this._document, this._source);
47
48 /// Loads the configuration in [_document].
49 Configuration load() {
50 var verboseTrace = _getBool("verbose_trace");
51 var jsTrace = _getBool("js_trace");
52
53 var reporter = _getString("reporter");
54 if (reporter != null && !allReporters.contains(reporter)) {
55 _error('Unknown reporter "$reporter".', "reporter");
56 }
57
58 var pubServePort = _getInt("pub_serve");
59 var concurrency = _getInt("concurrency");
60 var timeout = _parseValue("timeout", (value) => new Timeout.parse(value));
61
62 var allPlatformIdentifiers =
63 TestPlatform.all.map((platform) => platform.identifier).toSet();
64 var platforms = _getList("platforms", (platformNode) {
65 _validate(platformNode, "Platforms must be strings.",
66 (value) => value is String);
67 _validate(platformNode, 'Unknown platform "${platformNode.value}".',
68 allPlatformIdentifiers.contains);
69
70 return TestPlatform.find(platformNode.value);
71 });
72
73 // TODO(nweiz): Add support for using globs to define defaults paths to run.
74
75 return new Configuration(
76 verboseTrace: verboseTrace,
77 jsTrace: jsTrace,
78 reporter: reporter,
79 pubServePort: pubServePort,
80 concurrency: concurrency,
81 timeout: timeout,
82 platforms: platforms);
83 }
84
85 /// Throws an exception with [message] if [test] returns `false` when passed
86 /// [node]'s value.
87 void _validate(YamlNode node, String message, bool test(value)) {
88 if (test(node.value)) return;
89 throw new SourceSpanFormatException(message, node.span, _source);
90 }
91
92 /// Returns the value of the node at [field].
93 ///
94 /// If [typeTest] returns `false` for that value, instead throws an error
95 /// complaining that the field is not a [typeName].
96 _getValue(String field, String typeName, bool typeTest(value)) {
97 var value = _document[field];
98 if (value == null || typeTest(value)) return value;
99 _error("$field must be ${a(typeName)}.", field);
100 }
101
102 /// Returns the YAML node at [field].
103 ///
104 /// If [typeTest] returns `false` for that node's value, instead throws an
105 /// error complaining that the field is not a [typeName].
106 YamlNode _getNode(String field, String typeName, bool typeTest(value)) {
107 var node = _document.nodes[field];
108 if (node == null) return null;
109 _validate(node, "$field must be ${a(typeName)}.", typeTest);
110 return node;
111 }
112
113 /// Asserts that [field] is an int and returns its value.
114 int _getInt(String field) =>
115 _getValue(field, "int", (value) => value is int);
116
117 /// Asserts that [field] is a boolean and returns its value.
118 bool _getBool(String field) =>
119 _getValue(field, "boolean", (value) => value is bool);
120
121 /// Asserts that [field] is a string and returns its value.
122 String _getString(String field) =>
123 _getValue(field, "string", (value) => value is String);
124
125 /// Asserts that [field] is a list and runs [forElement] for each element it
126 /// contains.
127 ///
128 /// Returns a list of values returned by [forElement].
129 List _getList(String field, forElement(YamlNode elementNode)) {
130 var node = _getNode(field, "list", (value) => value is List);
131 if (node == null) return [];
132 return node.nodes.map(forElement).toList();
133 }
134
135 /// Asserts that [field] is a string, passes it to [parse], and returns the
136 /// result.
137 ///
138 /// If [parse] throws a [FormatException], it's wrapped to include [field]'s
139 /// span.
140 _parseValue(String field, parse(value)) {
141 var value = _getString(field);
142 if (value == null) return null;
143
144 try {
145 return parse(value);
146 } on FormatException catch (error) {
147 _error('Invalid $field: ${error.message}', field);
148 }
149 }
150
151 /// Throws a [SourceSpanFormatException] with [message] about [field].
152 void _error(String message, String field) {
153 throw new SourceSpanFormatException(
154 message, _document.nodes[field].span, _source);
155 }
156 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698