| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 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 | 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:args/args.dart'; | 7 import 'package:args/args.dart'; |
| 8 import 'package:boolean_selector/boolean_selector.dart'; |
| 8 | 9 |
| 9 import '../../backend/test_platform.dart'; | 10 import '../../backend/test_platform.dart'; |
| 10 import '../../frontend/timeout.dart'; | 11 import '../../frontend/timeout.dart'; |
| 11 import '../../utils.dart'; | |
| 12 import '../configuration.dart'; | 12 import '../configuration.dart'; |
| 13 import 'values.dart'; | 13 import 'values.dart'; |
| 14 | 14 |
| 15 /// The parser used to parse the command-line arguments. | 15 /// The parser used to parse the command-line arguments. |
| 16 final ArgParser _parser = (() { | 16 final ArgParser _parser = (() { |
| 17 var parser = new ArgParser(allowTrailingOptions: true); | 17 var parser = new ArgParser(allowTrailingOptions: true); |
| 18 | 18 |
| 19 var allPlatforms = TestPlatform.all.toList(); | 19 var allPlatforms = TestPlatform.all.toList(); |
| 20 if (!Platform.isMacOS) allPlatforms.remove(TestPlatform.safari); | 20 if (!Platform.isMacOS) allPlatforms.remove(TestPlatform.safari); |
| 21 if (!Platform.isWindows) allPlatforms.remove(TestPlatform.internetExplorer); | 21 if (!Platform.isWindows) allPlatforms.remove(TestPlatform.internetExplorer); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 35 abbr: 'n', | 35 abbr: 'n', |
| 36 help: 'A substring of the name of the test to run.\n' | 36 help: 'A substring of the name of the test to run.\n' |
| 37 'Regular expression syntax is supported.'); | 37 'Regular expression syntax is supported.'); |
| 38 parser.addOption("plain-name", | 38 parser.addOption("plain-name", |
| 39 abbr: 'N', | 39 abbr: 'N', |
| 40 help: 'A plain-text substring of the name of the test to run.'); | 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 | 41 // TODO(nweiz): Support the full platform-selector syntax for choosing which |
| 42 // tags to run. In the shorter term, disallow non-"identifier" tags. | 42 // tags to run. In the shorter term, disallow non-"identifier" tags. |
| 43 parser.addOption("tags", | 43 parser.addOption("tags", |
| 44 abbr: 't', | 44 abbr: 't', |
| 45 help: 'Run only tests with all of the specified tags.', | 45 help: 'Run only tests with all of the specified tags.\n' |
| 46 'Supports boolean selector syntax.', |
| 46 allowMultiple: true); | 47 allowMultiple: true); |
| 47 parser.addOption("tag", hide: true, allowMultiple: true); | 48 parser.addOption("tag", hide: true, allowMultiple: true); |
| 48 parser.addOption("exclude-tags", | 49 parser.addOption("exclude-tags", |
| 49 abbr: 'x', | 50 abbr: 'x', |
| 50 help: "Don't run tests with any of the specified tags.", | 51 help: "Don't run tests with any of the specified tags.\n" |
| 52 "Supports boolean selector syntax.", |
| 51 allowMultiple: true); | 53 allowMultiple: true); |
| 52 parser.addOption("exclude-tag", hide: true, allowMultiple: true); | 54 parser.addOption("exclude-tag", hide: true, allowMultiple: true); |
| 53 | 55 |
| 54 parser.addSeparator("======== Running Tests"); | 56 parser.addSeparator("======== Running Tests"); |
| 55 parser.addOption("platform", | 57 parser.addOption("platform", |
| 56 abbr: 'p', | 58 abbr: 'p', |
| 57 help: 'The platform(s) on which to run the tests.', | 59 help: 'The platform(s) on which to run the tests.', |
| 58 defaultsTo: 'vm', | 60 defaultsTo: 'vm', |
| 59 allowed: allPlatforms.map((platform) => platform.identifier).toList(), | 61 allowed: allPlatforms.map((platform) => platform.identifier).toList(), |
| 60 allowMultiple: true); | 62 allowMultiple: true); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 throw new FormatException( | 113 throw new FormatException( |
| 112 "--name and --plain-name may not both be passed."); | 114 "--name and --plain-name may not both be passed."); |
| 113 } | 115 } |
| 114 | 116 |
| 115 pattern = _wrapFormatException( | 117 pattern = _wrapFormatException( |
| 116 options, 'name', (value) => new RegExp(value)); | 118 options, 'name', (value) => new RegExp(value)); |
| 117 } else if (options['plain-name'] != null) { | 119 } else if (options['plain-name'] != null) { |
| 118 pattern = options['plain-name']; | 120 pattern = options['plain-name']; |
| 119 } | 121 } |
| 120 | 122 |
| 121 var tags = new Set(); | 123 var includeTagSet = new Set.from(options['tags'] ?? []) |
| 122 tags.addAll(options['tags'] ?? []); | 124 ..addAll(options['tag'] ?? []); |
| 123 tags.addAll(options['tag'] ?? []); | |
| 124 | 125 |
| 125 var excludeTags = new Set(); | 126 var includeTags = includeTagSet.fold(BooleanSelector.all, (selector, tag) { |
| 126 excludeTags.addAll(options['exclude-tags'] ?? []); | 127 var tagSelector = new BooleanSelector.parse(tag); |
| 127 excludeTags.addAll(options['exclude-tag'] ?? []); | 128 return selector.intersection(tagSelector); |
| 129 }); |
| 128 | 130 |
| 129 var tagIntersection = tags.intersection(excludeTags); | 131 var excludeTagSet = new Set.from(options['exclude-tags'] ?? []) |
| 130 if (tagIntersection.isNotEmpty) { | 132 ..addAll(options['exclude-tag'] ?? []); |
| 131 throw new FormatException( | 133 |
| 132 'The ${pluralize('tag', tagIntersection.length)} ' | 134 var excludeTags = excludeTagSet.fold(BooleanSelector.none, (selector, tag) { |
| 133 '${toSentence(tagIntersection)} ' | 135 var tagSelector = new BooleanSelector.parse(tag); |
| 134 '${pluralize('was', tagIntersection.length, plural: 'were')} ' | 136 return selector.union(tagSelector); |
| 135 'both included and excluded.'); | 137 }); |
| 136 } | |
| 137 | 138 |
| 138 // If the user hasn't explicitly chosen a value, we want to pass null values | 139 // 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 // to [new Configuration] so that it considers those fields unset when merging |
| 140 // with configuration from the config file. | 141 // with configuration from the config file. |
| 141 ifParsed(name) => options.wasParsed(name) ? options[name] : null; | 142 ifParsed(name) => options.wasParsed(name) ? options[name] : null; |
| 142 | 143 |
| 143 return new Configuration( | 144 return new Configuration( |
| 144 help: ifParsed('help'), | 145 help: ifParsed('help'), |
| 145 version: ifParsed('version'), | 146 version: ifParsed('version'), |
| 146 verboseTrace: ifParsed('verbose-trace'), | 147 verboseTrace: ifParsed('verbose-trace'), |
| 147 jsTrace: ifParsed('js-trace'), | 148 jsTrace: ifParsed('js-trace'), |
| 148 pauseAfterLoad: ifParsed('pause-after-load'), | 149 pauseAfterLoad: ifParsed('pause-after-load'), |
| 149 color: ifParsed('color'), | 150 color: ifParsed('color'), |
| 150 packageRoot: ifParsed('package-root'), | 151 packageRoot: ifParsed('package-root'), |
| 151 reporter: ifParsed('reporter'), | 152 reporter: ifParsed('reporter'), |
| 152 pubServePort: _wrapFormatException(options, 'pub-serve', int.parse), | 153 pubServePort: _wrapFormatException(options, 'pub-serve', int.parse), |
| 153 concurrency: _wrapFormatException(options, 'concurrency', int.parse), | 154 concurrency: _wrapFormatException(options, 'concurrency', int.parse), |
| 154 timeout: _wrapFormatException(options, 'timeout', | 155 timeout: _wrapFormatException(options, 'timeout', |
| 155 (value) => new Timeout.parse(value)), | 156 (value) => new Timeout.parse(value)), |
| 156 pattern: pattern, | 157 pattern: pattern, |
| 157 platforms: ifParsed('platform')?.map(TestPlatform.find), | 158 platforms: ifParsed('platform')?.map(TestPlatform.find), |
| 158 paths: options.rest.isEmpty ? null : options.rest, | 159 paths: options.rest.isEmpty ? null : options.rest, |
| 159 includeTags: tags, | 160 includeTags: includeTags, |
| 160 excludeTags: excludeTags); | 161 excludeTags: excludeTags); |
| 161 } | 162 } |
| 162 | 163 |
| 163 /// Runs [parse] on the value of the option [name], and wraps any | 164 /// Runs [parse] on the value of the option [name], and wraps any |
| 164 /// [FormatException] it throws with additional information. | 165 /// [FormatException] it throws with additional information. |
| 165 _wrapFormatException(ArgResults options, String name, parse(value)) { | 166 _wrapFormatException(ArgResults options, String name, parse(value)) { |
| 166 if (!options.wasParsed(name)) return null; | 167 if (!options.wasParsed(name)) return null; |
| 167 | 168 |
| 168 var value = options[name]; | 169 var value = options[name]; |
| 169 if (value == null) return null; | 170 if (value == null) return null; |
| 170 | 171 |
| 171 try { | 172 try { |
| 172 return parse(value); | 173 return parse(value); |
| 173 } on FormatException catch (error) { | 174 } on FormatException catch (error) { |
| 174 throw new FormatException('Couldn\'t parse --$name "${options[name]}": ' | 175 throw new FormatException('Couldn\'t parse --$name "${options[name]}": ' |
| 175 '${error.message}'); | 176 '${error.message}'); |
| 176 } | 177 } |
| 177 } | 178 } |
| OLD | NEW |