OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library test.runner.configuration; |
| 6 |
| 7 import 'dart:io'; |
| 8 import 'dart:math' as math; |
| 9 |
| 10 import 'package:args/args.dart'; |
| 11 import 'package:path/path.dart' as p; |
| 12 |
| 13 import '../frontend/timeout.dart'; |
| 14 import '../backend/metadata.dart'; |
| 15 import '../backend/test_platform.dart'; |
| 16 import '../util/io.dart'; |
| 17 |
| 18 /// The default number of test suites to run at once. |
| 19 /// |
| 20 /// This defaults to half the available processors, since presumably some of |
| 21 /// them will be used for the OS and other processes. |
| 22 final _defaultConcurrency = math.max(1, Platform.numberOfProcessors ~/ 2); |
| 23 |
| 24 /// A class that encapsulates the command-line configuration of the test runner. |
| 25 class Configuration { |
| 26 /// The parser used to parse the command-line arguments. |
| 27 static final ArgParser _parser = (() { |
| 28 var parser = new ArgParser(allowTrailingOptions: true); |
| 29 |
| 30 var allPlatforms = TestPlatform.all.toList(); |
| 31 if (!Platform.isMacOS) allPlatforms.remove(TestPlatform.safari); |
| 32 if (!Platform.isWindows) allPlatforms.remove(TestPlatform.internetExplorer); |
| 33 |
| 34 parser.addFlag("help", abbr: "h", negatable: false, |
| 35 help: "Shows this usage information."); |
| 36 parser.addFlag("version", negatable: false, |
| 37 help: "Shows the package's version."); |
| 38 parser.addOption("package-root", hide: true); |
| 39 parser.addOption("name", |
| 40 abbr: 'n', |
| 41 help: 'A substring of the name of the test to run.\n' |
| 42 'Regular expression syntax is supported.'); |
| 43 parser.addOption("plain-name", |
| 44 abbr: 'N', |
| 45 help: 'A plain-text substring of the name of the test to run.'); |
| 46 parser.addOption("platform", |
| 47 abbr: 'p', |
| 48 help: 'The platform(s) on which to run the tests.', |
| 49 allowed: allPlatforms.map((platform) => platform.identifier).toList(), |
| 50 defaultsTo: 'vm', |
| 51 allowMultiple: true); |
| 52 parser.addOption("concurrency", |
| 53 abbr: 'j', |
| 54 help: 'The number of concurrent test suites run.\n' |
| 55 '(defaults to $_defaultConcurrency)', |
| 56 valueHelp: 'threads'); |
| 57 parser.addOption("pub-serve", |
| 58 help: 'The port of a pub serve instance serving "test/".', |
| 59 valueHelp: 'port'); |
| 60 parser.addFlag("pause-after-load", |
| 61 help: 'Pauses for debugging before any tests execute.\n' |
| 62 'Implies --concurrency=1.\n' |
| 63 'Currently only supported for browser tests.', |
| 64 negatable: false); |
| 65 parser.addOption("reporter", |
| 66 abbr: 'r', |
| 67 help: 'The runner used to print test results.', |
| 68 allowed: ['compact', 'expanded'], |
| 69 defaultsTo: Platform.isWindows ? 'expanded' : 'compact', |
| 70 allowedHelp: { |
| 71 'compact': 'A single line, updated continuously.', |
| 72 'expanded': 'A separate line for each update.' |
| 73 }); |
| 74 parser.addFlag("verbose-trace", negatable: false, |
| 75 help: 'Whether to emit stack traces with core library frames.'); |
| 76 parser.addFlag("js-trace", negatable: false, |
| 77 help: 'Whether to emit raw JavaScript stack traces for browser tests.'); |
| 78 parser.addFlag("color", defaultsTo: null, |
| 79 help: 'Whether to use terminal colors.\n(auto-detected by default)'); |
| 80 |
| 81 return parser; |
| 82 })(); |
| 83 |
| 84 /// The usage string for the command-line arguments. |
| 85 static String get usage => _parser.usage; |
| 86 |
| 87 /// Whether `--help` was passed. |
| 88 final bool help; |
| 89 |
| 90 /// Whether `--version` was passed. |
| 91 final bool version; |
| 92 |
| 93 /// Whether stack traces should be presented as-is or folded to remove |
| 94 /// irrelevant packages. |
| 95 final bool verboseTrace; |
| 96 |
| 97 /// Whether JavaScript stack traces should be left as-is or converted to |
| 98 /// Dart-like traces. |
| 99 final bool jsTrace; |
| 100 |
| 101 /// Whether to pause for debugging after loading each test suite. |
| 102 final bool pauseAfterLoad; |
| 103 |
| 104 /// The package root for resolving "package:" URLs. |
| 105 final String packageRoot; |
| 106 |
| 107 /// The name of the reporter to use to display results. |
| 108 final String reporter; |
| 109 |
| 110 /// The URL for the `pub serve` instance from which to load tests, or `null` |
| 111 /// if tests should be loaded from the filesystem. |
| 112 final Uri pubServeUrl; |
| 113 |
| 114 /// Whether to use command-line color escapes. |
| 115 final bool color; |
| 116 |
| 117 /// How many tests to run concurrently. |
| 118 final int concurrency; |
| 119 |
| 120 /// The from which to load tests. |
| 121 final List<String> paths; |
| 122 |
| 123 /// Whether the load paths were passed explicitly or the default was used. |
| 124 final bool explicitPaths; |
| 125 |
| 126 /// The pattern to match against test names to decide which to run, or `null` |
| 127 /// if all tests should be run. |
| 128 final Pattern pattern; |
| 129 |
| 130 /// The set of platforms on which to run tests. |
| 131 final List<TestPlatform> platforms; |
| 132 |
| 133 /// The global test metadata derived from this configuration. |
| 134 Metadata get metadata => |
| 135 new Metadata( |
| 136 timeout: pauseAfterLoad ? Timeout.none : null, |
| 137 verboseTrace: verboseTrace); |
| 138 |
| 139 /// Parses the configuration from [args]. |
| 140 /// |
| 141 /// Throws a [FormatException] if [args] are invalid. |
| 142 factory Configuration.parse(List<String> args) { |
| 143 var options = _parser.parse(args); |
| 144 |
| 145 var pattern; |
| 146 if (options['name'] != null) { |
| 147 if (options["plain-name"] != null) { |
| 148 throw new FormatException( |
| 149 "--name and --plain-name may not both be passed."); |
| 150 } |
| 151 |
| 152 pattern = _wrapFormatException( |
| 153 options, 'name', (value) => new RegExp(value)); |
| 154 } else if (options['plain-name'] != null) { |
| 155 pattern = options['plain-name']; |
| 156 } |
| 157 |
| 158 return new Configuration( |
| 159 help: options['help'], |
| 160 version: options['version'], |
| 161 verboseTrace: options['verbose-trace'], |
| 162 jsTrace: options['js-trace'], |
| 163 pauseAfterLoad: options['pause-after-load'], |
| 164 color: options['color'], |
| 165 packageRoot: options['package-root'], |
| 166 reporter: options['reporter'], |
| 167 pubServePort: _wrapFormatException(options, 'pub-serve', int.parse), |
| 168 concurrency: _wrapFormatException(options, 'concurrency', int.parse, |
| 169 orElse: () => _defaultConcurrency), |
| 170 pattern: pattern, |
| 171 platforms: options['platform'].map(TestPlatform.find), |
| 172 paths: options.rest.isEmpty ? null : options.rest); |
| 173 } |
| 174 |
| 175 /// Runs [parse] on the value of the option [name], and wraps any |
| 176 /// [FormatException] it throws with additional information. |
| 177 static _wrapFormatException(ArgResults options, String name, parse(value), |
| 178 {orElse()}) { |
| 179 var value = options[name]; |
| 180 if (value == null) return orElse == null ? null : orElse(); |
| 181 |
| 182 try { |
| 183 return parse(value); |
| 184 } on FormatException catch (error) { |
| 185 throw new FormatException('Couldn\'t parse --$name "${options[name]}": ' |
| 186 '${error.message}'); |
| 187 } |
| 188 } |
| 189 |
| 190 Configuration({this.help: false, this.version: false, |
| 191 this.verboseTrace: false, this.jsTrace: false, |
| 192 bool pauseAfterLoad: false, bool color, String packageRoot, |
| 193 String reporter, int pubServePort, int concurrency, this.pattern, |
| 194 Iterable<TestPlatform> platforms, Iterable<String> paths}) |
| 195 : pauseAfterLoad = pauseAfterLoad, |
| 196 color = color == null ? canUseSpecialChars : color, |
| 197 packageRoot = packageRoot == null |
| 198 ? p.join(p.current, 'packages') |
| 199 : packageRoot, |
| 200 reporter = reporter == null ? 'compact' : reporter, |
| 201 pubServeUrl = pubServePort == null |
| 202 ? null |
| 203 : Uri.parse("http://localhost:$pubServePort"), |
| 204 concurrency = pauseAfterLoad |
| 205 ? 1 |
| 206 : (concurrency == null ? _defaultConcurrency : concurrency), |
| 207 platforms = platforms == null ? [TestPlatform.vm] : platforms.toList(), |
| 208 paths = paths == null ? ["test"] : paths.toList(), |
| 209 explicitPaths = paths != null; |
| 210 } |
OLD | NEW |