OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2017, 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 /// Runs the tests in a batch on the various configurations used on the bots. |
| 6 |
| 7 import 'dart:async'; |
| 8 import 'dart:io'; |
| 9 |
| 10 import 'package:args/args.dart'; |
| 11 import 'package:path/path.dart' as p; |
| 12 |
| 13 import 'package:migration/src/fork.dart'; |
| 14 import 'package:migration/src/log.dart'; |
| 15 |
| 16 const appJit = "--compiler=app_jit"; |
| 17 const dart2js = "--compiler=dart2js"; |
| 18 const dartdevc = "--compiler=dartdevc"; |
| 19 const noCompiler = "--compiler=none"; |
| 20 const precompiler = "--compiler=precompiler"; |
| 21 const analyzer = "--compiler=dart2analyzer"; |
| 22 |
| 23 const chrome = "--runtime=chrome"; |
| 24 const precompiled = "--runtime=dart_precompiled"; |
| 25 const noRuntime = "--runtime=none"; |
| 26 const vm = "--runtime=vm"; |
| 27 |
| 28 const checked = "--checked"; |
| 29 const dart2jsBatch = "--dart2js-batch"; |
| 30 const useSdk = "--use-sdk"; |
| 31 const productMode = "--mode=product"; |
| 32 const strong = "--strong"; |
| 33 |
| 34 /// Maps configuration names to a corresponding set of test.dart command line |
| 35 /// arguments. |
| 36 /// |
| 37 /// Each configuration name starts with the name of a column on the buildbot |
| 38 /// waterfall (except for "dartjs-linux" which is just called "dart2js" here) |
| 39 /// possibly followed by some modifier for a specific bot or annotated step on |
| 40 /// a bot. The configs here are ordered the same order as the waterfall. |
| 41 final allConfigs = { |
| 42 "vm": [noCompiler, vm], |
| 43 "vm-checked": [noCompiler, vm, checked], |
| 44 "vm-app": [appJit, vm], |
| 45 "vm-app-product": [productMode, appJit, vm], |
| 46 // TODO(rnystrom): What build target do we need to get this to work? |
| 47 // "vm-precomp": [precompiler, precompiled], |
| 48 "vm-product": [productMode, noCompiler, vm], |
| 49 // TODO(rnystrom): Add dart2js-d8-hostchecked, dart2js-d8-minified, or |
| 50 // dart2js-jsshell? |
| 51 "analyzer": [analyzer, noRuntime, useSdk], |
| 52 "analyzer-checked": [analyzer, noRuntime, checked, useSdk], |
| 53 "dart2js": [dart2js, chrome, useSdk, dart2jsBatch], |
| 54 // TODO(rnystrom): Is it worth running dart2js on Firefox too? |
| 55 "dartdevc": [dartdevc, chrome, useSdk, strong] |
| 56 }; |
| 57 |
| 58 final buildSteps = [ |
| 59 // The SDK, which also builds the VM. |
| 60 ["--mode=release", "create_sdk"], |
| 61 // Product version of the runtime and precompiled runtime. |
| 62 ["--mode=product", "runtime", "runtime_precompiled"], |
| 63 // Dartdevc and its dependencies. |
| 64 ["--mode=release", "dartdevc_test"], |
| 65 ]; |
| 66 |
| 67 Future<Null> main(List<String> arguments) async { |
| 68 var argParser = new ArgParser(allowTrailingOptions: true); |
| 69 argParser.addFlag("build", help: "Build runtimes before running tests."); |
| 70 argParser.addOption("config", |
| 71 abbr: "c", allowMultiple: true, help: "Which configurations to run."); |
| 72 argParser.addFlag("help"); |
| 73 |
| 74 var argResults = argParser.parse(arguments); |
| 75 if (argResults["help"] as bool) { |
| 76 usage(argParser); |
| 77 return; |
| 78 } |
| 79 |
| 80 if (argResults.rest.length != 2) { |
| 81 usage(argParser); |
| 82 exit(1); |
| 83 } |
| 84 |
| 85 var build = argResults["build"] as bool; |
| 86 var configs = argResults["config"] as List<String>; |
| 87 if (configs.isEmpty) configs = allConfigs.keys.toList(); |
| 88 |
| 89 var tests = scanTests(); |
| 90 |
| 91 var startIndex = findFork(tests, argResults.rest[0]); |
| 92 var endIndex = findFork(tests, argResults.rest[1]); |
| 93 |
| 94 if (startIndex == null || endIndex == null) exit(1); |
| 95 |
| 96 tests = tests.sublist(startIndex, endIndex + 1); |
| 97 |
| 98 if (tests.isEmpty) { |
| 99 print("No tests in range."); |
| 100 return; |
| 101 } |
| 102 |
| 103 // Build any needed targets first. |
| 104 if (build) { |
| 105 for (var steps in buildSteps) { |
| 106 var command = "tools/build.py ${steps.join(' ')}"; |
| 107 print("Building ${bold(command)}:"); |
| 108 var exitCode = await run("tools/build.py", steps); |
| 109 if (exitCode != 0) { |
| 110 print(red("Build failed: $command")); |
| 111 } |
| 112 } |
| 113 } |
| 114 |
| 115 // Splits the tests into selectors and patterns. |
| 116 var selectors = <String, List<String>>{}; |
| 117 for (var test in tests) { |
| 118 var parts = p.split(p.withoutExtension(test.twoPath)); |
| 119 var selector = parts[0]; |
| 120 var path = parts.skip(1).join("/"); |
| 121 selectors.putIfAbsent(selector, () => []).add(path); |
| 122 } |
| 123 |
| 124 var failed = <String>[]; |
| 125 var passed = <String>[]; |
| 126 for (var name in configs) { |
| 127 var configArgs = allConfigs[name]; |
| 128 print("${bold(name)} ${configArgs.join(' ')}:"); |
| 129 |
| 130 var args = [ |
| 131 "--progress=color", |
| 132 ]; |
| 133 |
| 134 args.addAll(configArgs); |
| 135 |
| 136 if (!args.any((arg) => arg.startsWith("--mode"))) { |
| 137 args.add("--mode=release"); |
| 138 } |
| 139 |
| 140 selectors.forEach((selector, paths) { |
| 141 args.add("$selector/${paths.join('|')}"); |
| 142 }); |
| 143 |
| 144 var exitCode = await run("tools/test.py", args); |
| 145 if (exitCode != 0) { |
| 146 print(red("Configuration failed: $name")); |
| 147 failed.add(name); |
| 148 } else { |
| 149 passed.add(name); |
| 150 } |
| 151 } |
| 152 |
| 153 if (failed.length == 0) { |
| 154 var s = passed.length == 1 ? "" : "s"; |
| 155 print("${green('PASSED')} all ${bold(passed.length)} configuration$s!"); |
| 156 } else { |
| 157 if (passed.length > 0) { |
| 158 var s = passed == 1 ? "" : "s"; |
| 159 print("${green('PASSED')} ${bold(passed.length)} configuration$s:"); |
| 160 for (var config in passed) { |
| 161 print("- ${bold(config)}"); |
| 162 } |
| 163 } |
| 164 |
| 165 var s = failed == 1 ? "" : "s"; |
| 166 print("${red("FAILED")} ${bold(failed.length)} configuration$s:"); |
| 167 for (var config in failed) { |
| 168 print("- ${bold(config)}"); |
| 169 } |
| 170 } |
| 171 } |
| 172 |
| 173 void usage(ArgParser parser) { |
| 174 print("Usage: dart run_tests.dart [--build] [--configs=...] " |
| 175 "<first file> <last file>"); |
| 176 print("\n"); |
| 177 print("Example:"); |
| 178 print("\n"); |
| 179 print(" \$ dart run_tests.dart map_to_string queue"); |
| 180 print("\n"); |
| 181 print(parser.usage); |
| 182 } |
| 183 |
| 184 Future<int> run(String executable, List<String> arguments) async { |
| 185 var process = await Process.start(executable, arguments); |
| 186 process.stdout.listen((bytes) { |
| 187 stdout.add(bytes); |
| 188 }); |
| 189 |
| 190 process.stderr.listen((bytes) { |
| 191 stderr.add(bytes); |
| 192 }); |
| 193 |
| 194 return await process.exitCode; |
| 195 } |
OLD | NEW |