Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013, 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 import 'drt_updater.dart'; | |
| 7 import 'test_suite.dart'; | |
| 8 import 'path.dart'; | |
| 9 import 'compiler_configuration.dart' show CompilerConfiguration; | |
| 10 import 'runtime_configuration.dart' show RuntimeConfiguration; | |
| 11 | |
| 12 const _defaultTestSelectors = const [ | |
| 13 'samples', | |
| 14 'standalone', | |
| 15 'corelib', | |
| 16 'co19', | |
| 17 'language', | |
| 18 'isolate', | |
| 19 'vm', | |
| 20 'html', | |
| 21 'benchmark_smoke', | |
| 22 'utils', | |
| 23 'lib', | |
| 24 'analyze_library', | |
| 25 'service', | |
| 26 'kernel', | |
| 27 'observatory_ui' | |
| 28 ]; | |
| 29 | |
| 30 /// Specifies a single command line option. | |
| 31 /// | |
| 32 /// The name of the specification is used as the key for the option in the Map | |
| 33 /// returned from the [TestOptionParser] parse method. | |
| 34 class _Option { | |
| 35 // TODO(rnystrom): Some string options use "" to mean "no value" and others | |
| 36 // use null. Clean that up. | |
| 37 _Option(this.name, this.description, | |
| 38 {String abbr, List<String> values, String defaultsTo = ""}) | |
| 39 : abbreviation = abbr, | |
| 40 values = values ?? [], | |
| 41 defaultValue = defaultsTo, | |
| 42 type = _OptionValueType.string; | |
| 43 | |
| 44 _Option.bool(this.name, this.description, [this.abbreviation]) | |
| 45 : values = [], | |
| 46 defaultValue = false, | |
| 47 type = _OptionValueType.bool; | |
| 48 | |
| 49 _Option.int(this.name, this.description, {String abbr, int defaultsTo}) | |
| 50 : abbreviation = abbr, | |
| 51 values = [], | |
| 52 defaultValue = defaultsTo, | |
| 53 type = _OptionValueType.int; | |
| 54 | |
| 55 final String name; | |
| 56 final String description; | |
| 57 final String abbreviation; | |
| 58 final List<String> values; | |
| 59 final Object defaultValue; | |
| 60 final _OptionValueType type; | |
| 61 | |
| 62 /// Gets the shortest command line argument used to refer to this option. | |
| 63 String get shortCommand => abbreviation != null ? "-$abbreviation" : command; | |
| 64 | |
| 65 /// Gets the canonical long command line argument used to refer to this | |
| 66 /// option. | |
| 67 String get command => "--${name.replaceAll('_', '-')}"; | |
| 68 } | |
| 69 | |
| 70 enum _OptionValueType { bool, int, string } | |
| 71 | |
| 72 /// Parses command line arguments and produces a test runner configuration. | |
| 73 class OptionsParser { | |
| 74 static final List<_Option> _options = [ | |
| 75 new _Option('mode', 'Mode in which to run the tests.', | |
| 76 abbr: 'm', | |
| 77 values: ['all', 'debug', 'release', 'product'], | |
| 78 defaultsTo: 'debug'), | |
| 79 new _Option( | |
| 80 'compiler', | |
| 81 '''Specify any compilation step (if needed). | |
| 82 | |
| 83 none: Do not compile the Dart code (run native Dart code | |
| 84 on the VM). | |
| 85 (Only valid with runtimes vm, flutter, or drt.) | |
| 86 | |
| 87 precompiler: Compile into AOT snapshot before running the test. | |
| 88 (Only valid with runtime dart_precompiled.) | |
| 89 | |
| 90 dart2js: Compile dart code to JavaScript by running dart2js. | |
| 91 (Only valid with runtimes: d8, drt, chrome, safari, | |
| 92 ie9, ie10, ie11, firefox, opera, chromeOnAndroid, | |
| 93 and none [compile only].) | |
| 94 | |
| 95 dart2analyzer: Perform static analysis on Dart code by running the | |
| 96 analyzer. | |
| 97 (Only valid with runtime none.) | |
| 98 | |
| 99 app_jit: Compile the Dart code into an app snapshot before | |
| 100 running test. | |
| 101 (Only valid with dart_app runtime.) | |
| 102 | |
| 103 dartk: Compile the Dart source into Kernel before running | |
| 104 test. | |
| 105 | |
| 106 dartkp: Compile the Dart source into Kernel and then Kernel | |
| 107 into AOT snapshot before running the test. | |
| 108 (Only valid with runtime dart_precompiled.)''', | |
| 109 abbr: 'c', | |
| 110 values: [ | |
| 111 'none', | |
| 112 'precompiler', | |
| 113 'dart2js', | |
| 114 'dart2analyzer', | |
| 115 'app_jit', | |
| 116 'dartk', | |
| 117 'dartkp' | |
| 118 ], | |
| 119 defaultsTo: 'none'), | |
| 120 new _Option( | |
| 121 'runtime', | |
| 122 '''Where the tests should be run. | |
| 123 vm: Run Dart code on the standalone dart vm. | |
| 124 | |
| 125 flutter: Run Dart code on the flutter engine. | |
| 126 | |
| 127 dart_precompiled: Run a precompiled snapshot on a variant of the | |
| 128 standalone dart VM lacking a JIT. | |
| 129 | |
| 130 d8: Run JavaScript from the command line using v8. | |
| 131 | |
| 132 jsshell: Run JavaScript from the command line using | |
| 133 Firefox js-shell. | |
| 134 | |
| 135 drt: Run Dart or JavaScript in the headless version | |
| 136 of Chrome, Content shell. | |
| 137 | |
| 138 dartium: Run Dart or JavaScript in Dartium. | |
| 139 | |
| 140 ContentShellOnAndroid: Run Dart or JavaScript in Dartium content | |
| 141 shell on Android. | |
| 142 | |
| 143 DartiumOnAndroid: Run Dart or Javascript in Dartium on Android. | |
| 144 | |
| 145 ff: | |
| 146 chrome: | |
| 147 safari: | |
| 148 ie9: | |
| 149 ie10: | |
| 150 ie11: | |
| 151 opera: | |
| 152 chromeOnAndroid: Run JavaScript in the specified browser. | |
| 153 | |
| 154 self_check: Pass each test or its compiled output to every | |
|
Siggi Cherem (dart-lang)
2017/05/25 21:57:19
(optional) I understand this is from before but ho
Bob Nystrom
2017/05/26 18:03:22
I honestly have no idea what this is or how it's u
| |
| 155 file under `pkg` whose name ends with | |
| 156 `_self_check.dart`. Each test is given to the | |
| 157 self_check tester as a filename on stdin using | |
| 158 the batch-mode protocol. | |
| 159 | |
| 160 none: No runtime, compile only. (For example, used | |
| 161 for dart2analyzer static analysis tests).''', | |
| 162 abbr: 'r', | |
| 163 values: [ | |
| 164 'vm', | |
| 165 'flutter', | |
| 166 'dart_precompiled', | |
| 167 'd8', | |
| 168 'jsshell', | |
| 169 'drt', | |
| 170 'dartium', | |
| 171 'ff', | |
| 172 'firefox', | |
| 173 'chrome', | |
| 174 'safari', | |
| 175 'ie9', | |
| 176 'ie10', | |
| 177 'ie11', | |
| 178 'opera', | |
| 179 'chromeOnAndroid', | |
| 180 'safarimobilesim', | |
| 181 'ContentShellOnAndroid', | |
| 182 'DartiumOnAndroid', | |
| 183 'self_check', | |
| 184 'none' | |
| 185 ], | |
| 186 defaultsTo: 'vm'), | |
| 187 new _Option( | |
| 188 'arch', | |
| 189 '''The architecture to run tests for. | |
| 190 | |
| 191 Allowed values are: | |
| 192 all | |
| 193 ia32, x64 | |
| 194 arm, armv6, armv5te, arm64, | |
| 195 simarm, simarmv6, simarmv5te, simarm64, | |
| 196 mips, simmips | |
| 197 simdbc, simdbc64''', | |
| 198 abbr: 'a', | |
| 199 values: [ | |
| 200 'all', | |
| 201 'ia32', | |
| 202 'x64', | |
| 203 'arm', | |
| 204 'armv6', | |
| 205 'armv5te', | |
| 206 'arm64', | |
| 207 'mips', | |
| 208 'simarm', | |
| 209 'simarmv6', | |
| 210 'simarmv5te', | |
| 211 'simarm64', | |
| 212 'simmips', | |
| 213 'simdbc', | |
| 214 'simdbc64', | |
| 215 ], | |
| 216 defaultsTo: 'x64'), | |
| 217 new _Option('system', 'The operating system to run tests on.', | |
| 218 abbr: 's', | |
| 219 values: ['linux', 'macos', 'windows', 'android'], | |
| 220 defaultsTo: Platform.operatingSystem), | |
| 221 new _Option.bool('checked', 'Run tests in checked mode.'), | |
| 222 new _Option.bool('strong', 'Run tests in strong mode.'), | |
| 223 new _Option.bool('host_checked', 'Run compiler in checked mode.'), | |
| 224 new _Option.bool('minified', 'Enable minification in the compiler.'), | |
| 225 new _Option.bool( | |
| 226 'csp', 'Run tests under Content Security Policy restrictions.'), | |
| 227 new _Option.bool('cps_ir', 'Run the compiler with the cps based backend.'), | |
|
Siggi Cherem (dart-lang)
2017/05/25 21:57:19
I believe all uses of this flag are gone, so it is
Bob Nystrom
2017/05/26 18:03:22
Done.
It did show up in a couple of status files,
| |
| 228 new _Option.bool( | |
| 229 'fast_startup', 'Pass the --fast-startup flag to dart2js.'), | |
| 230 new _Option.bool('dart2js_with_kernel', | |
| 231 'Enable the internal pipeline in dart2js to use kernel.'), | |
| 232 new _Option.bool('hot_reload', 'Run hot reload stress tests.'), | |
| 233 new _Option.bool( | |
| 234 'hot_reload_rollback', 'Run hot reload rollback stress tests.'), | |
| 235 new _Option.bool('use_blobs', | |
| 236 'Use mmap instead of shared libraries for precompilation.'), | |
| 237 new _Option.int('timeout', 'Timeout in seconds.', | |
| 238 abbr: 't', defaultsTo: -1), | |
| 239 new _Option( | |
| 240 'progress', | |
| 241 '''Progress indication mode. | |
| 242 | |
| 243 Allowed values are: | |
| 244 compact, color, line, verbose, silent, status, buildbot, diff | |
| 245 ''', | |
| 246 abbr: 'p', | |
| 247 values: [ | |
| 248 'compact', | |
| 249 'color', | |
| 250 'line', | |
| 251 'verbose', | |
| 252 'silent', | |
| 253 'status', | |
| 254 'buildbot', | |
| 255 'diff' | |
| 256 ], | |
| 257 defaultsTo: 'compact'), | |
| 258 new _Option('step_name', 'Step name for use by -pbuildbot.', | |
| 259 defaultsTo: null), | |
| 260 new _Option.bool('report', | |
| 261 'Print a summary report of the number of tests, by expectation.'), | |
| 262 new _Option.int('tasks', 'The number of parallel tasks to run.', | |
| 263 abbr: 'j', defaultsTo: Platform.numberOfProcessors), | |
| 264 new _Option.int('shards', | |
| 265 'The number of instances that the tests will be sharded over.', | |
| 266 defaultsTo: 1), | |
| 267 new _Option.int( | |
| 268 'shard', 'The index of this instance when running in sharded mode.', | |
| 269 defaultsTo: 1), | |
| 270 new _Option.bool('help', 'Print list of options.', 'h'), | |
| 271 new _Option.bool('verbose', 'Verbose output.', 'v'), | |
| 272 new _Option.bool('verify-ir', 'Verify kernel IR.'), | |
| 273 new _Option.bool('no-tree-shake', 'Disable kernel IR tree shaking.'), | |
| 274 new _Option.bool('list', 'List tests only, do not run them.'), | |
| 275 new _Option.bool('report_in_json', | |
| 276 'When listing with --list, output result summary in JSON.'), | |
| 277 new _Option.bool('time', 'Print timing information after running tests.'), | |
| 278 new _Option('dart', 'Path to dart executable.'), | |
| 279 new _Option('flutter', 'Path to flutter executable.'), | |
| 280 new _Option( | |
| 281 'drt', // TODO(antonm): fix the option name. | |
| 282 'Path to content shell executable.'), | |
| 283 new _Option('dartium', 'Path to Dartium Chrome executable.'), | |
| 284 new _Option('firefox', 'Path to firefox browser executable.'), | |
| 285 new _Option('chrome', 'Path to chrome browser executable.'), | |
| 286 new _Option('safari', 'Path to safari browser executable.'), | |
| 287 new _Option.bool( | |
| 288 'use_sdk', | |
| 289 '''Use compiler or runtime from the SDK. | |
| 290 | |
| 291 Normally, the compiler or runtimes in PRODUCT_DIR is tested, with | |
| 292 this option, the compiler or runtime in PRODUCT_DIR/dart-sdk/bin | |
| 293 is tested. | |
| 294 | |
| 295 (Note: currently only implemented for dart2js.)'''), | |
| 296 new _Option('build_directory', | |
| 297 'The name of the build directory, where products are placed.'), | |
| 298 new _Option.bool('noBatch', 'Do not run tests in batch mode.', 'n'), | |
| 299 new _Option.bool('dart2js_batch', 'Run dart2js tests in batch mode.'), | |
| 300 new _Option.bool( | |
| 301 'append_logs', 'Do not delete old logs but rather append to them.'), | |
| 302 new _Option.bool('write_debug_log', | |
| 303 'Don\'t write debug messages to stdout but rather to a logfile.'), | |
| 304 new _Option.bool('write_test_outcome_log', | |
| 305 'Write test outcomes to a "${TestUtils.testOutcomeFileName}" file.'), | |
| 306 new _Option.bool( | |
| 307 'reset_browser_configuration', | |
| 308 '''Browser specific reset of configuration. | |
| 309 | |
| 310 Warning: Using this option may remove your bookmarks and other | |
| 311 settings.'''), | |
| 312 new _Option.bool( | |
| 313 'copy_coredumps', | |
| 314 '''If we see a crash that we did not expect, copy the core dumps to | |
| 315 "/tmp".'''), | |
| 316 new _Option( | |
| 317 'local_ip', | |
| 318 '''IP address the HTTP servers should listen on. This address is also | |
| 319 used for browsers to connect to.''', | |
| 320 defaultsTo: '127.0.0.1'), | |
| 321 new _Option.int('test_server_port', 'Port for test http server.', | |
| 322 defaultsTo: 0), | |
| 323 new _Option.int('test_server_cross_origin_port', | |
| 324 'Port for test http server cross origin.', | |
| 325 defaultsTo: 0), | |
| 326 new _Option.int('test_driver_port', 'Port for http test driver server.', | |
| 327 defaultsTo: 0), | |
| 328 new _Option.int( | |
| 329 'test_driver_error_port', 'Port for http test driver server errors.', | |
| 330 defaultsTo: 0), | |
| 331 new _Option('record_to_file', | |
| 332 'Records all commands to be executed and writes to a file.', | |
| 333 defaultsTo: null), | |
| 334 new _Option( | |
| 335 'replay_from_file', 'Replays a previously recorded list of commands.', | |
| 336 defaultsTo: null), | |
| 337 new _Option( | |
| 338 'builder_tag', | |
| 339 '''Machine specific options that is not captured by the regular test | |
| 340 options. Used to be able to make sane updates to the status files.'''), | |
| 341 new _Option('vm_options', 'Extra options to send to the vm when running.', | |
| 342 defaultsTo: null), | |
| 343 new _Option( | |
| 344 'dart2js_options', 'Extra options for dart2js compilation step.', | |
| 345 defaultsTo: null), | |
| 346 new _Option( | |
| 347 'suite_dir', 'Additional directory to add to the testing matrix.', | |
| 348 defaultsTo: null), | |
| 349 new _Option('package_root', 'The package root to use for testing.', | |
| 350 defaultsTo: null), | |
| 351 new _Option('packages', 'The package spec file to use for testing.', | |
| 352 defaultsTo: null), | |
| 353 new _Option( | |
| 354 'exclude_suite', | |
| 355 '''Exclude suites from default selector, only works when no selector | |
| 356 has been specified on the command line.''', | |
| 357 defaultsTo: null), | |
| 358 new _Option.bool( | |
| 359 'skip-compilation', | |
| 360 ''' | |
| 361 Skip the compilation step, using the compilation artifacts left in | |
| 362 the output folder from a previous run. This flag will often cause | |
| 363 false positves and negatives, but can be useful for quick and | |
| 364 dirty offline testing when not making changes that affect the | |
| 365 compiler.''') | |
| 366 ]; | |
| 367 | |
| 368 /// For printing out reproducing command lines, we don't want to add these | |
| 369 /// options. | |
| 370 static final _blacklistedOptions = [ | |
| 371 'append_logs', | |
| 372 'build_directory', | |
| 373 'chrome', | |
| 374 'copy_coredumps', | |
| 375 'dart', | |
| 376 'flutter', | |
| 377 'dartium', | |
| 378 'drt', | |
| 379 'exclude_suite', | |
| 380 'firefox', | |
| 381 'local_ip', | |
| 382 'progress', | |
| 383 'report', | |
| 384 'safari', | |
| 385 'shard', | |
| 386 'shards', | |
| 387 'step_name', | |
| 388 'tasks', | |
| 389 'time', | |
| 390 'verbose', | |
| 391 'write_debug_log', | |
| 392 'write_test_outcome_log', | |
| 393 ].toSet(); | |
| 394 | |
| 395 /// Parses a list of strings as test options. | |
| 396 /// | |
| 397 /// Returns a list of configurations in which to run the tests. | |
| 398 /// Configurations are maps mapping from option keys to values. When | |
| 399 /// encountering the first non-option string, the rest of the arguments are | |
| 400 /// stored in the returned Map under the 'rest' key. | |
| 401 List<Map> parse(List<String> arguments) { | |
| 402 var configuration = {}; | |
| 403 | |
| 404 // Fill in configuration with arguments passed to the test script. | |
| 405 for (var i = 0; i < arguments.length; i++) { | |
| 406 var arg = arguments[i]; | |
| 407 | |
| 408 // Help supersedes all other arguments. | |
| 409 if (arg == "--help" || arg == "-h") { | |
| 410 _printHelp(); | |
| 411 return null; | |
| 412 } | |
| 413 | |
| 414 // Extract name and value for options. | |
| 415 String command; | |
| 416 String value; | |
| 417 _Option option; | |
| 418 | |
| 419 if (arg.startsWith("--")) { | |
| 420 // A long option name. | |
| 421 var equals = arg.indexOf("="); | |
| 422 if (equals != -1) { | |
| 423 // A long option with a value, like "--arch=ia32". | |
| 424 command = arg.substring(0, equals); | |
| 425 value = arg.substring(equals + 1); | |
| 426 } else { | |
| 427 command = arg; | |
| 428 } | |
| 429 | |
| 430 option = _findByName(command.substring(2)); | |
| 431 } else if (arg.startsWith("-")) { | |
| 432 // An abbreviated option. | |
| 433 if (arg.length == 1) { | |
| 434 _fail('Missing option name after "-".'); | |
| 435 } | |
| 436 | |
| 437 command = arg.substring(0, 2); | |
| 438 | |
| 439 if (arg.length > 2) { | |
| 440 // An abbreviated option followed by a value, like "-aia32". | |
| 441 value = arg.substring(2); | |
| 442 } | |
| 443 | |
| 444 option = _findByAbbreviation(command.substring(1)); | |
| 445 } else { | |
| 446 // The argument does not start with "-" or "--" and is therefore not an | |
| 447 // option. Use it as a test selector pattern. | |
| 448 var patterns = configuration.putIfAbsent("selectors", () => <String>[]); | |
| 449 patterns.add(arg); | |
| 450 continue; | |
| 451 } | |
| 452 | |
| 453 if (option == null) { | |
| 454 _fail('Unknown command line option "$command".'); | |
| 455 } | |
| 456 | |
| 457 // If we need a value, look at the next argument. | |
| 458 if (value == null && option.type != _OptionValueType.bool) { | |
| 459 if (i + 1 >= arguments.length) { | |
| 460 _fail('Missing value for command line option "$command".'); | |
| 461 } | |
| 462 value = arguments[++i]; | |
| 463 } | |
| 464 | |
| 465 // Multiple uses of a flag are an error, because there is no naturally | |
| 466 // correct way to handle conflicting options. | |
| 467 if (configuration.containsKey(option.name)) { | |
| 468 _fail('Already have value for command line option "$command".'); | |
| 469 } | |
| 470 | |
| 471 // Parse the value for the option. | |
| 472 switch (option.type) { | |
| 473 case _OptionValueType.bool: | |
| 474 if (value != null) { | |
| 475 _fail('Boolean flag "$command" does not take a value.'); | |
| 476 } | |
| 477 | |
| 478 configuration[option.name] = true; | |
| 479 break; | |
| 480 | |
| 481 case _OptionValueType.int: | |
| 482 try { | |
| 483 configuration[option.name] = int.parse(value); | |
| 484 } on FormatException { | |
| 485 _fail('Integer value expected for option "$command".'); | |
| 486 } | |
| 487 break; | |
| 488 | |
| 489 case _OptionValueType.string: | |
| 490 // Validate against the allowed values. | |
| 491 if (!option.values.isEmpty) { | |
| 492 for (var v in value.split(",")) { | |
| 493 if (!option.values.contains(v)) { | |
| 494 _fail('Unknown value "$v" for command line option "$command".'); | |
| 495 } | |
| 496 } | |
| 497 } | |
| 498 | |
| 499 // TODO(rnystrom): Store as a list instead of a comma-delimited | |
| 500 // string. | |
| 501 configuration[option.name] = value; | |
| 502 break; | |
| 503 } | |
| 504 } | |
| 505 | |
| 506 // Apply default values for unspecified options. | |
| 507 for (var option in _options) { | |
| 508 if (!configuration.containsKey(option.name)) { | |
| 509 configuration[option.name] = option.defaultValue; | |
| 510 } | |
| 511 } | |
| 512 | |
| 513 var expandedConfigs = _expandConfigurations(configuration); | |
| 514 var result = expandedConfigs.where(_isValidConfig).toList(); | |
| 515 for (var config in result) { | |
| 516 config['_reproducing_arguments_'] = _reproducingCommand(config); | |
| 517 } | |
| 518 | |
| 519 return result.isEmpty ? null : result; | |
| 520 } | |
| 521 | |
| 522 /// Prints [message] and exits with a non-zero exit code. | |
| 523 void _fail(String message) { | |
| 524 print(message); | |
| 525 exit(1); | |
| 526 } | |
| 527 | |
| 528 /// Given a configuration, returns the list of command line arguments that | |
| 529 /// would reproduce that configuration. | |
| 530 List<String> _reproducingCommand(Map config) { | |
| 531 var arguments = <String>[]; | |
| 532 | |
| 533 for (var option in _options) { | |
| 534 var name = option.name; | |
| 535 if (!config.containsKey(name) || _blacklistedOptions.contains(name)) { | |
| 536 continue; | |
| 537 } | |
| 538 | |
| 539 var value = config[name]; | |
| 540 if (config[name] == option.defaultValue || | |
| 541 (name == 'packages' && | |
| 542 value == | |
| 543 TestUtils.dartDirUri.resolve('.packages').toFilePath())) { | |
| 544 continue; | |
| 545 } | |
| 546 | |
| 547 arguments.add(option.shortCommand); | |
| 548 if (option.type != _OptionValueType.bool) { | |
| 549 arguments.add(value.toString()); | |
| 550 } | |
| 551 } | |
| 552 | |
| 553 return arguments; | |
| 554 } | |
| 555 | |
| 556 /// Determines if a particular configuration has a valid combination of | |
| 557 /// compiler and runtime elements. | |
| 558 bool _isValidConfig(Map config) { | |
| 559 var isValid = true; | |
| 560 List<String> validRuntimes; | |
| 561 switch (config['compiler']) { | |
| 562 case 'dart2js': | |
| 563 // Note: by adding 'none' as a configuration, if the user | |
| 564 // runs test.py -c dart2js -r drt,none the dart2js_none and | |
| 565 // dart2js_drt will be duplicating work. If later we don't need 'none' | |
| 566 // with dart2js, we should remove it from here. | |
| 567 validRuntimes = const [ | |
| 568 'd8', | |
| 569 'jsshell', | |
| 570 'drt', | |
| 571 'none', | |
| 572 'dartium', | |
| 573 'ff', | |
| 574 'chrome', | |
| 575 'safari', | |
| 576 'ie9', | |
| 577 'ie10', | |
| 578 'ie11', | |
| 579 'opera', | |
| 580 'chromeOnAndroid', | |
| 581 'safarimobilesim' | |
| 582 ]; | |
| 583 break; | |
| 584 case 'dart2analyzer': | |
| 585 validRuntimes = const ['none']; | |
| 586 break; | |
| 587 case 'app_jit': | |
| 588 case 'dartk': | |
| 589 validRuntimes = const ['vm', 'self_check', 'none']; | |
| 590 break; | |
| 591 case 'precompiler': | |
| 592 case 'dartkp': | |
| 593 validRuntimes = const ['dart_precompiled']; | |
| 594 break; | |
| 595 case 'none': | |
| 596 validRuntimes = const [ | |
| 597 'vm', | |
| 598 'flutter', | |
| 599 'drt', | |
| 600 'dartium', | |
| 601 'ContentShellOnAndroid', | |
| 602 'DartiumOnAndroid' | |
| 603 ]; | |
| 604 break; | |
| 605 } | |
| 606 | |
| 607 if (!validRuntimes.contains(config['runtime'])) { | |
| 608 isValid = false; | |
| 609 print("Warning: combination of compiler '${config['compiler']}' and " | |
| 610 "runtime '${config['runtime']}' is invalid. " | |
| 611 "Skipping this combination."); | |
| 612 } | |
| 613 | |
| 614 if (config['ie'] && Platform.operatingSystem != 'windows') { | |
| 615 isValid = false; | |
| 616 print("Warning: cannot run Internet Explorer on non-Windows operating" | |
| 617 " system."); | |
| 618 } | |
| 619 | |
| 620 if (config['shard'] < 1 || config['shard'] > config['shards']) { | |
| 621 isValid = false; | |
| 622 print("Error: shard index is ${config['shard']} out of " | |
| 623 "${config['shards']} shards"); | |
| 624 } | |
| 625 | |
| 626 if (config['runtime'] == 'flutter' && config['flutter'] == '') { | |
| 627 isValid = false; | |
| 628 print("-rflutter requires the flutter engine executable to " | |
| 629 "be specified using --flutter="); | |
| 630 } | |
| 631 | |
| 632 if (config['runtime'] == 'flutter' && config['arch'] != 'x64') { | |
| 633 isValid = false; | |
| 634 print("-rflutter is applicable only for --arch=x64"); | |
| 635 } | |
| 636 | |
| 637 return isValid; | |
| 638 } | |
| 639 | |
| 640 /// Recursively expands a configuration with multiple values per key into a | |
| 641 /// list of configurations with exactly one value per key. | |
| 642 List<Map> _expandConfigurations(Map configuration) { | |
| 643 // Expand the pseudo-values such as 'all'. | |
| 644 if (configuration['arch'] == 'all') { | |
| 645 configuration['arch'] = 'ia32,x64,simarm,simarm64,simmips,simdbc64'; | |
| 646 } | |
| 647 | |
| 648 if (configuration['mode'] == 'all') { | |
| 649 configuration['mode'] = 'debug,release,product'; | |
| 650 } | |
| 651 | |
| 652 if (configuration['report_in_json']) { | |
| 653 configuration['list'] = true; | |
| 654 configuration['report'] = true; | |
| 655 } | |
| 656 | |
| 657 // Use verbose progress indication for verbose output unless buildbot | |
| 658 // progress indication is requested. | |
| 659 if (configuration['verbose'] && configuration['progress'] != 'buildbot') { | |
| 660 configuration['progress'] = 'verbose'; | |
| 661 } | |
| 662 | |
| 663 // Create the artificial negative options that test status files | |
| 664 // expect. | |
| 665 configuration['unchecked'] = !configuration['checked']; | |
| 666 configuration['host_unchecked'] = !configuration['host_checked']; | |
| 667 configuration['unminified'] = !configuration['minified']; | |
| 668 configuration['nocsp'] = !configuration['csp']; | |
| 669 | |
| 670 String runtime = configuration['runtime']; | |
| 671 if (runtime == 'firefox') { | |
| 672 configuration['runtime'] == 'ff'; | |
| 673 } | |
| 674 | |
| 675 String compiler = configuration['compiler']; | |
| 676 configuration['browser'] = TestUtils.isBrowserRuntime(runtime); | |
| 677 configuration['analyzer'] = TestUtils.isCommandLineAnalyzer(compiler); | |
| 678 | |
| 679 // Set the javascript command line flag for less verbose status files. | |
| 680 configuration['jscl'] = TestUtils.isJsCommandLineRuntime(runtime); | |
| 681 | |
| 682 // Allow suppression that is valid for all ie versions | |
| 683 configuration['ie'] = runtime.startsWith('ie'); | |
| 684 | |
| 685 // Expand the test selectors into a suite name and a simple | |
| 686 // regular expressions to be used on the full path of a test file | |
| 687 // in that test suite. If no selectors are explicitly given use | |
| 688 // the default suite patterns. | |
| 689 var selectors = configuration['selectors']; | |
| 690 if (selectors is! Map) { | |
| 691 if (selectors == null) { | |
| 692 if (configuration['suite_dir'] != null) { | |
| 693 var suite_path = new Path(configuration['suite_dir']); | |
| 694 selectors = [suite_path.filename]; | |
| 695 } else { | |
| 696 selectors = _defaultTestSelectors.toList(); | |
| 697 } | |
| 698 | |
| 699 var excludeSuites = configuration['exclude_suite'] != null | |
| 700 ? configuration['exclude_suite'].split(',') | |
| 701 : []; | |
| 702 for (var exclude in excludeSuites) { | |
| 703 if (selectors.contains(exclude)) { | |
| 704 selectors.remove(exclude); | |
| 705 } else { | |
| 706 print("Warning: default selectors does not contain $exclude"); | |
| 707 } | |
| 708 } | |
| 709 } | |
| 710 var selectorMap = <String, RegExp>{}; | |
| 711 for (var i = 0; i < selectors.length; i++) { | |
| 712 var pattern = selectors[i]; | |
| 713 var suite = pattern; | |
| 714 var slashLocation = pattern.indexOf('/'); | |
| 715 if (slashLocation != -1) { | |
| 716 suite = pattern.substring(0, slashLocation); | |
| 717 pattern = pattern.substring(slashLocation + 1); | |
| 718 pattern = pattern.replaceAll('*', '.*'); | |
| 719 } else { | |
| 720 pattern = ".?"; | |
| 721 } | |
| 722 if (selectorMap.containsKey(suite)) { | |
| 723 print("Error: '$suite/$pattern'. Only one test selection" | |
| 724 " pattern is allowed to start with '$suite/'"); | |
| 725 exit(1); | |
| 726 } | |
| 727 selectorMap[suite] = new RegExp(pattern); | |
| 728 } | |
| 729 configuration['selectors'] = selectorMap; | |
| 730 } | |
| 731 | |
| 732 // Put observatory_ui in a configuration with its own packages override. | |
| 733 // Only one value in the configuration map is mutable: | |
| 734 selectors = configuration['selectors']; | |
| 735 if (selectors.containsKey('observatory_ui')) { | |
| 736 if (selectors.length == 1) { | |
| 737 configuration['packages'] = TestUtils.dartDirUri | |
| 738 .resolve('runtime/observatory/.packages') | |
| 739 .toFilePath(); | |
| 740 } else { | |
| 741 // Make a new configuration whose selectors map only contains | |
| 742 // observatory_ui, and remove the key from the original selectors. | |
| 743 // The only mutable value in the map is the selectors, so a | |
| 744 // shallow copy is safe. | |
| 745 var observatoryConfiguration = new Map.from(configuration); | |
| 746 observatoryConfiguration['selectors'] = { | |
| 747 'observatory_ui': selectors['observatory_ui'] | |
| 748 }; | |
| 749 selectors.remove('observatory_ui'); | |
| 750 | |
| 751 // Set the packages flag. | |
| 752 observatoryConfiguration['packages'] = TestUtils.dartDirUri | |
| 753 .resolve('runtime/observatory/.packages') | |
| 754 .toFilePath(); | |
| 755 | |
| 756 // Return the expansions of both configurations. Neither will reach | |
| 757 // this line in the recursive call to _expandConfigurations. | |
| 758 return _expandConfigurations(configuration) | |
| 759 ..addAll(_expandConfigurations(observatoryConfiguration)); | |
| 760 } | |
| 761 } | |
| 762 | |
| 763 // Set the default package spec explicitly. | |
| 764 if (configuration['package_root'] == null && | |
| 765 configuration['packages'] == null) { | |
| 766 configuration['packages'] = | |
| 767 TestUtils.dartDirUri.resolve('.packages').toFilePath(); | |
| 768 } | |
| 769 | |
| 770 // Expand the architectures. | |
| 771 if (configuration['arch'].contains(',')) { | |
| 772 return _expandHelper('arch', configuration); | |
| 773 } | |
| 774 | |
| 775 // Expand modes. | |
| 776 if (configuration['mode'].contains(',')) { | |
| 777 return _expandHelper('mode', configuration); | |
| 778 } | |
| 779 | |
| 780 // Expand compilers. | |
| 781 if (configuration['compiler'].contains(',')) { | |
| 782 return _expandHelper('compiler', configuration); | |
| 783 } | |
| 784 | |
| 785 // Expand runtimes. | |
| 786 var runtimes = configuration['runtime']; | |
| 787 if (runtimes.contains(',')) { | |
| 788 return _expandHelper('runtime', configuration); | |
| 789 } else { | |
| 790 // All runtimes eventually go through this path, after expansion. | |
| 791 var updater = runtimeUpdater(configuration); | |
| 792 if (updater != null) { | |
| 793 updater.update(); | |
| 794 } | |
| 795 } | |
| 796 | |
| 797 // Adjust default timeout based on mode, compiler, and sometimes runtime. | |
| 798 if (configuration['timeout'] == -1) { | |
| 799 var isReload = | |
| 800 configuration['hot_reload'] || configuration['hot_reload_rollback']; | |
| 801 int compilerMulitiplier = | |
| 802 new CompilerConfiguration(configuration).computeTimeoutMultiplier(); | |
| 803 int runtimeMultiplier = new RuntimeConfiguration(configuration) | |
| 804 .computeTimeoutMultiplier( | |
| 805 mode: configuration['mode'], | |
| 806 isChecked: configuration['checked'], | |
| 807 isReload: isReload, | |
| 808 arch: configuration['arch']); | |
| 809 configuration['timeout'] = 60 * compilerMulitiplier * runtimeMultiplier; | |
| 810 } | |
| 811 | |
| 812 return [configuration]; | |
| 813 } | |
| 814 | |
| 815 /// Helper for _expandConfigurations. Creates a new configuration and adds it | |
| 816 /// to a list, for use in a case when a particular configuration has multiple | |
| 817 /// results (separated by a ','). | |
| 818 /// Arguments: | |
| 819 /// option: The particular test option we are expanding. | |
| 820 /// configuration: The map containing all test configuration information | |
| 821 /// specified. | |
| 822 List<Map> _expandHelper(String option, Map configuration) { | |
| 823 var result = <Map>[]; | |
| 824 var configs = configuration[option]; | |
| 825 for (var config in configs.split(',')) { | |
| 826 var newConfiguration = new Map.from(configuration); | |
| 827 newConfiguration[option] = config; | |
| 828 result.addAll(_expandConfigurations(newConfiguration)); | |
| 829 } | |
| 830 return result; | |
| 831 } | |
| 832 | |
| 833 /// Print out usage information. | |
| 834 void _printHelp() { | |
| 835 var buffer = new StringBuffer(); | |
| 836 | |
| 837 buffer.writeln('''usage: dart test.dart [options] [selector] | |
| 838 | |
| 839 The optional selector limits the tests that will be run. | |
| 840 For example, the selector "language/issue", or equivalently | |
| 841 "language/*issue*", limits to test files matching the regexp | |
| 842 ".*issue.*\\.dart" in the "tests/language" directory. | |
| 843 | |
| 844 Options:'''); | |
| 845 | |
| 846 for (var option in _options) { | |
| 847 if (option.abbreviation != null) { | |
| 848 buffer.write("-${option.abbreviation}, "); | |
| 849 } else { | |
| 850 buffer.write(" "); | |
| 851 } | |
| 852 | |
| 853 buffer.write(option.command); | |
| 854 | |
| 855 switch (option.type) { | |
| 856 case _OptionValueType.bool: | |
| 857 // No value. | |
| 858 break; | |
| 859 case _OptionValueType.int: | |
| 860 buffer.write("=<integer>"); | |
| 861 break; | |
| 862 case _OptionValueType.string: | |
| 863 if (option.values.length > 6) { | |
| 864 // If there are many options, they won't fit nicely in one line and | |
| 865 // should be instead listed in the description. | |
| 866 buffer.write("=<...>"); | |
| 867 } else if (option.values.isNotEmpty) { | |
| 868 buffer.write("=<${option.values.join('|')}>"); | |
| 869 } else { | |
| 870 buffer.write("=<string>"); | |
| 871 } | |
| 872 break; | |
| 873 } | |
| 874 | |
| 875 if (option.type != _OptionValueType.bool && | |
| 876 option.defaultValue != null && | |
| 877 option.defaultValue != "") { | |
| 878 buffer.write(" (defaults to ${option.defaultValue})"); | |
| 879 } | |
| 880 | |
| 881 buffer.writeln(); | |
| 882 buffer | |
| 883 .writeln(" ${option.description.replaceAll('\n', '\n ')}"); | |
| 884 buffer.writeln(); | |
| 885 } | |
| 886 | |
| 887 print(buffer); | |
| 888 } | |
| 889 | |
| 890 _Option _findByAbbreviation(String abbreviation) { | |
| 891 for (var option in _options) { | |
| 892 if (abbreviation == option.abbreviation) return option; | |
| 893 } | |
| 894 | |
| 895 return null; | |
| 896 } | |
| 897 | |
| 898 _Option _findByName(String name) { | |
| 899 for (var option in _options) { | |
| 900 if (name == option.name) return option; | |
| 901 | |
| 902 // Allow hyphens instead of underscores as the separator since they are | |
| 903 // more common for command line flags. | |
| 904 if (name == option.name.replaceAll("_", "-")) return option; | |
| 905 } | |
| 906 | |
| 907 return null; | |
| 908 } | |
| 909 } | |
| OLD | NEW |