Chromium Code Reviews| OLD | NEW |
|---|---|
| (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:args/args.dart'; | |
| 8 | |
| 9 import '../../frontend/timeout.dart'; | |
| 10 import '../../backend/test_platform.dart'; | |
| 11 import '../../utils.dart'; | |
| 12 import '../configuration.dart'; | |
| 13 import 'values.dart'; | |
| 14 | |
| 15 /// The parser used to parse the command-line arguments. | |
| 16 final ArgParser _parser = (() { | |
| 17 var parser = new ArgParser(allowTrailingOptions: true); | |
| 18 | |
| 19 var allPlatforms = TestPlatform.all.toList(); | |
| 20 if (!Platform.isMacOS) allPlatforms.remove(TestPlatform.safari); | |
| 21 if (!Platform.isWindows) allPlatforms.remove(TestPlatform.internetExplorer); | |
| 22 | |
| 23 parser.addFlag("help", abbr: "h", negatable: false, | |
| 24 help: "Shows this usage information."); | |
| 25 parser.addFlag("version", negatable: false, | |
| 26 help: "Shows the package's version."); | |
| 27 parser.addOption("package-root", hide: true); | |
| 28 | |
| 29 // Note that defaultsTo declarations here are only for documentation purposes. | |
| 30 // We pass null values rather than defaults to [new Configuration] so that it | |
| 31 // merges properly with the config file. | |
| 32 | |
| 33 parser.addSeparator("======== Selecting Tests"); | |
| 34 parser.addOption("name", | |
| 35 abbr: 'n', | |
| 36 help: 'A substring of the name of the test to run.\n' | |
| 37 'Regular expression syntax is supported.'); | |
| 38 parser.addOption("plain-name", | |
| 39 abbr: 'N', | |
| 40 help: 'A plain-text substring of the name of the test to run.'); | |
| 41 // TODO(nweiz): Support the full platform-selector syntax for choosing which | |
| 42 // tags to run. In the shorter term, disallow non-"identifier" tags. | |
| 43 parser.addOption("tags", | |
| 44 abbr: 't', | |
| 45 help: 'Run only tests with all of the specified tags.', | |
| 46 allowMultiple: true); | |
| 47 parser.addOption("tag", hide: true, allowMultiple: true); | |
| 48 parser.addOption("exclude-tags", | |
| 49 abbr: 'x', | |
| 50 help: "Don't run tests with any of the specified tags.", | |
| 51 allowMultiple: true); | |
| 52 parser.addOption("exclude-tag", hide: true, allowMultiple: true); | |
| 53 | |
| 54 parser.addSeparator("======== Running Tests"); | |
| 55 parser.addOption("platform", | |
| 56 abbr: 'p', | |
| 57 help: 'The platform(s) on which to run the tests.', | |
| 58 defaultsTo: 'vm', | |
| 59 allowed: allPlatforms.map((platform) => platform.identifier).toList(), | |
| 60 allowMultiple: true); | |
| 61 parser.addOption("concurrency", | |
| 62 abbr: 'j', | |
| 63 help: 'The number of concurrent test suites run.', | |
| 64 defaultsTo: defaultConcurrency, | |
|
kevmoo
2016/02/03 23:01:56
defaultConcurrency must be a String
| |
| 65 valueHelp: 'threads'); | |
| 66 parser.addOption("pub-serve", | |
| 67 help: 'The port of a pub serve instance serving "test/".', | |
| 68 valueHelp: 'port'); | |
| 69 parser.addOption("timeout", | |
| 70 help: 'The default test timeout. For example: 15s, 2x, none', | |
| 71 defaultsTo: '30s'); | |
| 72 parser.addFlag("pause-after-load", | |
| 73 help: 'Pauses for debugging before any tests execute.\n' | |
| 74 'Implies --concurrency=1 and --timeout=none.\n' | |
| 75 'Currently only supported for browser tests.', | |
| 76 negatable: false); | |
| 77 | |
| 78 parser.addSeparator("======== Output"); | |
| 79 parser.addOption("reporter", | |
| 80 abbr: 'r', | |
| 81 help: 'The runner used to print test results.', | |
| 82 defaultsTo: defaultReporter, | |
| 83 allowed: allReporters, | |
| 84 allowedHelp: { | |
| 85 'compact': 'A single line, updated continuously.', | |
| 86 'expanded': 'A separate line for each update.', | |
| 87 'json': 'A machine-readable format (see https://goo.gl/0HRhdZ).' | |
| 88 }); | |
| 89 parser.addFlag("verbose-trace", negatable: false, | |
| 90 help: 'Whether to emit stack traces with core library frames.'); | |
| 91 parser.addFlag("js-trace", negatable: false, | |
| 92 help: 'Whether to emit raw JavaScript stack traces for browser tests.'); | |
| 93 parser.addFlag("color", | |
| 94 help: 'Whether to use terminal colors.\n(auto-detected by default)'); | |
| 95 | |
| 96 return parser; | |
| 97 })(); | |
| 98 | |
| 99 /// The usage string for the command-line arguments. | |
| 100 String get usage => _parser.usage; | |
| 101 | |
| 102 /// Parses the configuration from [args]. | |
| 103 /// | |
| 104 /// Throws a [FormatException] if [args] are invalid. | |
| 105 Configuration parse(List<String> args) { | |
| 106 var options = _parser.parse(args); | |
| 107 | |
| 108 var pattern; | |
| 109 if (options['name'] != null) { | |
| 110 if (options["plain-name"] != null) { | |
| 111 throw new FormatException( | |
| 112 "--name and --plain-name may not both be passed."); | |
| 113 } | |
| 114 | |
| 115 pattern = _wrapFormatException( | |
| 116 options, 'name', (value) => new RegExp(value)); | |
| 117 } else if (options['plain-name'] != null) { | |
| 118 pattern = options['plain-name']; | |
| 119 } | |
| 120 | |
| 121 var tags = new Set(); | |
| 122 tags.addAll(options['tags'] ?? []); | |
| 123 tags.addAll(options['tag'] ?? []); | |
| 124 | |
| 125 var excludeTags = new Set(); | |
| 126 excludeTags.addAll(options['exclude-tags'] ?? []); | |
| 127 excludeTags.addAll(options['exclude-tag'] ?? []); | |
| 128 | |
| 129 var tagIntersection = tags.intersection(excludeTags); | |
| 130 if (tagIntersection.isNotEmpty) { | |
| 131 throw new FormatException( | |
| 132 'The ${pluralize('tag', tagIntersection.length)} ' | |
| 133 '${toSentence(tagIntersection)} ' | |
| 134 '${pluralize('was', tagIntersection.length, plural: 'were')} ' | |
| 135 'both included and excluded.'); | |
| 136 } | |
| 137 | |
| 138 // If the user hasn't explicitly chosen a value, we want to pass null values | |
| 139 // to [new Configuration] so that it considers those fields unset when merging | |
| 140 // with configuration from the config file. | |
| 141 ifParsed(name) => options.wasParsed(name) ? options[name] : null; | |
| 142 | |
| 143 return new Configuration( | |
| 144 help: ifParsed('help'), | |
| 145 version: ifParsed('version'), | |
| 146 verboseTrace: ifParsed('verbose-trace'), | |
| 147 jsTrace: ifParsed('js-trace'), | |
| 148 pauseAfterLoad: ifParsed('pause-after-load'), | |
| 149 color: ifParsed('color'), | |
| 150 packageRoot: ifParsed('package-root'), | |
| 151 reporter: ifParsed('reporter'), | |
| 152 pubServePort: _wrapFormatException(options, 'pub-serve', int.parse), | |
| 153 concurrency: _wrapFormatException(options, 'concurrency', int.parse), | |
| 154 timeout: _wrapFormatException(options, 'timeout', | |
| 155 (value) => new Timeout.parse(value)), | |
| 156 pattern: pattern, | |
| 157 platforms: ifParsed('platform')?.map(TestPlatform.find), | |
| 158 paths: options.rest.isEmpty ? null : options.rest, | |
| 159 tags: tags, | |
| 160 excludeTags: excludeTags); | |
| 161 } | |
| 162 | |
| 163 /// Runs [parse] on the value of the option [name], and wraps any | |
| 164 /// [FormatException] it throws with additional information. | |
| 165 _wrapFormatException(ArgResults options, String name, parse(value)) { | |
| 166 if (!options.wasParsed(name)) return null; | |
| 167 | |
| 168 var value = options[name]; | |
| 169 if (value == null) return null; | |
| 170 | |
| 171 try { | |
| 172 return parse(value); | |
| 173 } on FormatException catch (error) { | |
| 174 throw new FormatException('Couldn\'t parse --$name "${options[name]}": ' | |
| 175 '${error.message}'); | |
| 176 } | |
| 177 } | |
| OLD | NEW |