| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:io'; | 5 import 'dart:io'; |
| 6 | 6 |
| 7 import 'package:collection/collection.dart'; |
| 7 import 'package:glob/glob.dart'; | 8 import 'package:glob/glob.dart'; |
| 8 import 'package:path/path.dart' as p; | 9 import 'package:path/path.dart' as p; |
| 9 | 10 |
| 10 import '../frontend/timeout.dart'; | 11 import '../frontend/timeout.dart'; |
| 11 import '../backend/metadata.dart'; | 12 import '../backend/metadata.dart'; |
| 12 import '../backend/test_platform.dart'; | 13 import '../backend/test_platform.dart'; |
| 13 import '../util/io.dart'; | 14 import '../util/io.dart'; |
| 15 import '../utils.dart'; |
| 14 import 'configuration/args.dart' as args; | 16 import 'configuration/args.dart' as args; |
| 15 import 'configuration/load.dart'; | 17 import 'configuration/load.dart'; |
| 16 import 'configuration/values.dart'; | 18 import 'configuration/values.dart'; |
| 17 | 19 |
| 18 /// A class that encapsulates the command-line configuration of the test runner. | 20 /// A class that encapsulates the command-line configuration of the test runner. |
| 19 class Configuration { | 21 class Configuration { |
| 20 /// The usage string for the command-line arguments. | 22 /// The usage string for the command-line arguments. |
| 21 static String get usage => args.usage; | 23 static String get usage => args.usage; |
| 22 | 24 |
| 23 /// Whether `--help` was passed. | 25 /// Whether `--help` was passed. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 | 90 |
| 89 /// The set of platforms on which to run tests. | 91 /// The set of platforms on which to run tests. |
| 90 List<TestPlatform> get platforms => _platforms ?? [TestPlatform.vm]; | 92 List<TestPlatform> get platforms => _platforms ?? [TestPlatform.vm]; |
| 91 final List<TestPlatform> _platforms; | 93 final List<TestPlatform> _platforms; |
| 92 | 94 |
| 93 /// Restricts the set of tests to a set of tags. | 95 /// Restricts the set of tests to a set of tags. |
| 94 /// | 96 /// |
| 95 /// If this is empty, it applies no restrictions. | 97 /// If this is empty, it applies no restrictions. |
| 96 /// | 98 /// |
| 97 /// When [merge]d, this is unioned with the other configuration's tags. | 99 /// When [merge]d, this is unioned with the other configuration's tags. |
| 98 final Set<String> tags; | 100 final Set<String> includeTags; |
| 99 | 101 |
| 100 /// Does not run tests with tags from this set. | 102 /// Does not run tests with tags from this set. |
| 101 /// | 103 /// |
| 102 /// If this is empty, it applies no restrictions. | 104 /// If this is empty, it applies no restrictions. |
| 103 /// | 105 /// |
| 104 /// When [merge]d, this is unioned with the other configuration's excluded | 106 /// When [merge]d, this is unioned with the other configuration's excluded |
| 105 /// tags. | 107 /// tags. |
| 106 final Set<String> excludeTags; | 108 final Set<String> excludeTags; |
| 107 | 109 |
| 110 /// Configuration for particular tags. |
| 111 /// |
| 112 /// The keys are tag names, and the values are configuration for those tags. |
| 113 /// The configuration should only contain test-level configuration fields, but |
| 114 /// that isn't enforced. |
| 115 final Map<String, Configuration> tags; |
| 116 |
| 108 /// The global test metadata derived from this configuration. | 117 /// The global test metadata derived from this configuration. |
| 109 Metadata get metadata => | 118 Metadata get metadata => new Metadata( |
| 110 new Metadata(timeout: timeout, verboseTrace: verboseTrace); | 119 timeout: timeout, |
| 120 verboseTrace: verboseTrace, |
| 121 forTag: mapMap(tags, value: (_, config) => config.metadata)); |
| 122 |
| 123 /// The set of tags that have been declaredin any way in this configuration. |
| 124 Set<String> get knownTags { |
| 125 if (_knownTags != null) return _knownTags; |
| 126 |
| 127 var known = includeTags.union(excludeTags); |
| 128 tags.forEach((tag, config) { |
| 129 known.add(tag); |
| 130 known.addAll(config.knownTags); |
| 131 }); |
| 132 |
| 133 _knownTags = new UnmodifiableSetView(known); |
| 134 return _knownTags; |
| 135 } |
| 136 Set<String> _knownTags; |
| 111 | 137 |
| 112 /// Parses the configuration from [args]. | 138 /// Parses the configuration from [args]. |
| 113 /// | 139 /// |
| 114 /// Throws a [FormatException] if [args] are invalid. | 140 /// Throws a [FormatException] if [args] are invalid. |
| 115 factory Configuration.parse(List<String> arguments) => args.parse(arguments); | 141 factory Configuration.parse(List<String> arguments) => args.parse(arguments); |
| 116 | 142 |
| 117 /// Loads the configuration from [path]. | 143 /// Loads the configuration from [path]. |
| 118 /// | 144 /// |
| 119 /// Throws an [IOException] if [path] does not exist or cannot be read. Throws | 145 /// Throws an [IOException] if [path] does not exist or cannot be read. Throws |
| 120 /// a [FormatException] if its contents are invalid. | 146 /// a [FormatException] if its contents are invalid. |
| 121 factory Configuration.load(String path) => load(path); | 147 factory Configuration.load(String path) => load(path); |
| 122 | 148 |
| 123 Configuration({bool help, bool version, bool verboseTrace, bool jsTrace, | 149 Configuration({bool help, bool version, bool verboseTrace, bool jsTrace, |
| 124 bool pauseAfterLoad, bool color, String packageRoot, String reporter, | 150 bool pauseAfterLoad, bool color, String packageRoot, String reporter, |
| 125 int pubServePort, int concurrency, Timeout timeout, this.pattern, | 151 int pubServePort, int concurrency, Timeout timeout, this.pattern, |
| 126 Iterable<TestPlatform> platforms, Iterable<String> paths, | 152 Iterable<TestPlatform> platforms, Iterable<String> paths, |
| 127 Glob filename, Iterable<String> tags, Iterable<String> excludeTags}) | 153 Glob filename, Iterable<String> includeTags, |
| 154 Iterable<String> excludeTags, Map<String, Configuration> tags}) |
| 128 : _help = help, | 155 : _help = help, |
| 129 _version = version, | 156 _version = version, |
| 130 _verboseTrace = verboseTrace, | 157 _verboseTrace = verboseTrace, |
| 131 _jsTrace = jsTrace, | 158 _jsTrace = jsTrace, |
| 132 _pauseAfterLoad = pauseAfterLoad, | 159 _pauseAfterLoad = pauseAfterLoad, |
| 133 _color = color, | 160 _color = color, |
| 134 _packageRoot = packageRoot, | 161 _packageRoot = packageRoot, |
| 135 _reporter = reporter, | 162 _reporter = reporter, |
| 136 pubServeUrl = pubServePort == null | 163 pubServeUrl = pubServePort == null |
| 137 ? null | 164 ? null |
| 138 : Uri.parse("http://localhost:$pubServePort"), | 165 : Uri.parse("http://localhost:$pubServePort"), |
| 139 _concurrency = concurrency, | 166 _concurrency = concurrency, |
| 140 timeout = (pauseAfterLoad ?? false) | 167 timeout = (pauseAfterLoad ?? false) |
| 141 ? Timeout.none | 168 ? Timeout.none |
| 142 : (timeout == null ? new Timeout.factor(1) : timeout), | 169 : (timeout == null ? new Timeout.factor(1) : timeout), |
| 143 _platforms = _list(platforms), | 170 _platforms = _list(platforms), |
| 144 _paths = _list(paths), | 171 _paths = _list(paths), |
| 145 _filename = filename, | 172 _filename = filename, |
| 146 tags = tags?.toSet() ?? new Set(), | 173 includeTags = includeTags?.toSet() ?? new Set(), |
| 147 excludeTags = excludeTags?.toSet() ?? new Set() { | 174 excludeTags = excludeTags?.toSet() ?? new Set(), |
| 175 tags = tags == null ? const {} : new Map.unmodifiable(tags) { |
| 148 if (_filename != null && _filename.context.style != p.style) { | 176 if (_filename != null && _filename.context.style != p.style) { |
| 149 throw new ArgumentError( | 177 throw new ArgumentError( |
| 150 "filename's context must match the current operating system, was " | 178 "filename's context must match the current operating system, was " |
| 151 "${_filename.context.style}."); | 179 "${_filename.context.style}."); |
| 152 } | 180 } |
| 153 } | 181 } |
| 154 | 182 |
| 155 /// Returns a [input] as a list or `null`. | 183 /// Returns a [input] as a list or `null`. |
| 156 /// | 184 /// |
| 157 /// If [input] is `null` or empty, this returns `null`. Otherwise, it returns | 185 /// If [input] is `null` or empty, this returns `null`. Otherwise, it returns |
| 158 /// `input.toList()`. | 186 /// `input.toList()`. |
| 159 static List _list(Iterable input) { | 187 static List _list(Iterable input) { |
| 160 if (input == null) return null; | 188 if (input == null) return null; |
| 161 input = input.toList(); | 189 input = input.toList(); |
| 162 if (input.isEmpty) return null; | 190 if (input.isEmpty) return null; |
| 163 return input; | 191 return input; |
| 164 } | 192 } |
| 165 | 193 |
| 166 /// Merges this with [other]. | 194 /// Merges this with [other]. |
| 167 /// | 195 /// |
| 168 /// For most fields, if both configurations have values set, [other]'s value | 196 /// For most fields, if both configurations have values set, [other]'s value |
| 169 /// takes precedence. However, certain fields are merged together instead. | 197 /// takes precedence. However, certain fields are merged together instead. |
| 170 /// This is indicated in those fields' documentation. | 198 /// This is indicated in those fields' documentation. |
| 171 Configuration merge(Configuration other) => new Configuration( | 199 Configuration merge(Configuration other) { |
| 172 help: other._help ?? _help, | 200 return new Configuration( |
| 173 version: other._version ?? _version, | 201 help: other._help ?? _help, |
| 174 verboseTrace: other._verboseTrace ?? _verboseTrace, | 202 version: other._version ?? _version, |
| 175 jsTrace: other._jsTrace ?? _jsTrace, | 203 verboseTrace: other._verboseTrace ?? _verboseTrace, |
| 176 pauseAfterLoad: other._pauseAfterLoad ?? _pauseAfterLoad, | 204 jsTrace: other._jsTrace ?? _jsTrace, |
| 177 color: other._color ?? _color, | 205 pauseAfterLoad: other._pauseAfterLoad ?? _pauseAfterLoad, |
| 178 packageRoot: other._packageRoot ?? _packageRoot, | 206 color: other._color ?? _color, |
| 179 reporter: other._reporter ?? _reporter, | 207 packageRoot: other._packageRoot ?? _packageRoot, |
| 180 pubServePort: (other.pubServeUrl ?? pubServeUrl)?.port, | 208 reporter: other._reporter ?? _reporter, |
| 181 concurrency: other._concurrency ?? _concurrency, | 209 pubServePort: (other.pubServeUrl ?? pubServeUrl)?.port, |
| 182 timeout: timeout.merge(other.timeout), | 210 concurrency: other._concurrency ?? _concurrency, |
| 183 pattern: other.pattern ?? pattern, | 211 timeout: timeout.merge(other.timeout), |
| 184 platforms: other._platforms ?? _platforms, | 212 pattern: other.pattern ?? pattern, |
| 185 paths: other._paths ?? _paths, | 213 platforms: other._platforms ?? _platforms, |
| 186 filename: other._filename ?? _filename, | 214 paths: other._paths ?? _paths, |
| 187 tags: other.tags.union(tags), | 215 filename: other._filename ?? _filename, |
| 188 excludeTags: other.excludeTags.union(excludeTags)); | 216 includeTags: other.includeTags.union(includeTags), |
| 217 excludeTags: other.excludeTags.union(excludeTags), |
| 218 tags: mergeMaps(tags, other.tags, |
| 219 value: (config1, config2) => config1.merge(config2))); |
| 220 } |
| 189 } | 221 } |
| OLD | NEW |