| OLD | NEW |
| 1 #!/usr/bin/env dart | 1 #!/usr/bin/env dart |
| 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
| 4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
| 5 | 5 |
| 6 /** | 6 /** |
| 7 * This file is the entrypoint of the dart test suite. This suite is used | 7 * This file is the entrypoint of the dart test suite. This suite is used |
| 8 * to test: | 8 * to test: |
| 9 * | 9 * |
| 10 * 1. the dart vm | 10 * 1. the dart vm |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 * | 23 * |
| 24 * The default test directory layout is documented in | 24 * The default test directory layout is documented in |
| 25 * "tools/testing/dart/test_suite.dart", above | 25 * "tools/testing/dart/test_suite.dart", above |
| 26 * "factory StandardTestSuite.forDirectory". | 26 * "factory StandardTestSuite.forDirectory". |
| 27 */ | 27 */ |
| 28 | 28 |
| 29 library test; | 29 library test; |
| 30 | 30 |
| 31 import "dart:async"; | 31 import "dart:async"; |
| 32 import "dart:io"; | 32 import "dart:io"; |
| 33 import "dart:math" as math; | 33 import "testing/dart/test_configurations.dart"; |
| 34 import "testing/dart/browser_controller.dart"; | |
| 35 import "testing/dart/http_server.dart"; | |
| 36 import "testing/dart/test_options.dart"; | 34 import "testing/dart/test_options.dart"; |
| 37 import "testing/dart/test_progress.dart"; | 35 import "testing/dart/test_progress.dart"; |
| 38 import "testing/dart/test_runner.dart"; | |
| 39 import "testing/dart/test_suite.dart"; | 36 import "testing/dart/test_suite.dart"; |
| 40 import "testing/dart/utils.dart"; | 37 import "testing/dart/utils.dart"; |
| 41 | 38 |
| 42 import "testing/dart/vm_test_config.dart"; | 39 Future _deleteTemporaryDartDirectories() { |
| 43 import "testing/dart/co19_test_config.dart"; | |
| 44 | |
| 45 /** | |
| 46 * The directories that contain test suites which follow the conventions | |
| 47 * required by [StandardTestSuite]'s forDirectory constructor. | |
| 48 * New test suites should follow this convention because it makes it much | |
| 49 * simpler to add them to test.dart. Existing test suites should be | |
| 50 * moved to here, if possible. | |
| 51 */ | |
| 52 final TEST_SUITE_DIRECTORIES = [ | |
| 53 new Path('pkg'), | |
| 54 new Path('runtime/tests/vm'), | |
| 55 new Path('runtime/bin/vmservice'), | |
| 56 new Path('samples'), | |
| 57 new Path('samples-dev'), | |
| 58 new Path('tests/benchmark_smoke'), | |
| 59 new Path('tests/chrome'), | |
| 60 new Path('tests/compiler/dart2js'), | |
| 61 new Path('tests/compiler/dart2js_extra'), | |
| 62 new Path('tests/compiler/dart2js_native'), | |
| 63 new Path('tests/corelib'), | |
| 64 new Path('tests/html'), | |
| 65 new Path('tests/isolate'), | |
| 66 new Path('tests/language'), | |
| 67 new Path('tests/lib'), | |
| 68 new Path('tests/standalone'), | |
| 69 new Path('tests/try'), | |
| 70 new Path('tests/utils'), | |
| 71 new Path('utils/tests/css'), | |
| 72 new Path('utils/tests/peg'), | |
| 73 ]; | |
| 74 | |
| 75 void testConfigurations(List<Map> configurations) { | |
| 76 var startTime = new DateTime.now(); | |
| 77 // Extract global options from first configuration. | |
| 78 var firstConf = configurations[0]; | |
| 79 var maxProcesses = firstConf['tasks']; | |
| 80 var progressIndicator = firstConf['progress']; | |
| 81 // TODO(kustermann): Remove this option once the buildbots don't use it | |
| 82 // anymore. | |
| 83 var failureSummary = firstConf['failure-summary']; | |
| 84 BuildbotProgressIndicator.stepName = firstConf['step_name']; | |
| 85 var verbose = firstConf['verbose']; | |
| 86 var printTiming = firstConf['time']; | |
| 87 var listTests = firstConf['list']; | |
| 88 | |
| 89 var recordingPath = firstConf['record_to_file']; | |
| 90 var recordingOutputPath = firstConf['replay_from_file']; | |
| 91 | |
| 92 Browser.deleteCache = firstConf['clear_browser_cache']; | |
| 93 | |
| 94 if (recordingPath != null && recordingOutputPath != null) { | |
| 95 print("Fatal: Can't have the '--record_to_file' and '--replay_from_file'" | |
| 96 "at the same time. Exiting ..."); | |
| 97 exit(1); | |
| 98 } | |
| 99 | |
| 100 if (!firstConf['append_logs']) { | |
| 101 var files = [new File(TestUtils.flakyFileName()), | |
| 102 new File(TestUtils.testOutcomeFileName())]; | |
| 103 for (var file in files) { | |
| 104 if (file.existsSync()) { | |
| 105 file.deleteSync(); | |
| 106 } | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 DebugLogger.init(firstConf['write_debug_log'] ? | |
| 111 TestUtils.debugLogfile() : null, append: firstConf['append_logs']); | |
| 112 | |
| 113 // Print the configurations being run by this execution of | |
| 114 // test.dart. However, don't do it if the silent progress indicator | |
| 115 // is used. This is only needed because of the junit tests. | |
| 116 if (progressIndicator != 'silent') { | |
| 117 List output_words = configurations.length > 1 ? | |
| 118 ['Test configurations:'] : ['Test configuration:']; | |
| 119 for (Map conf in configurations) { | |
| 120 List settings = ['compiler', 'runtime', 'mode', 'arch'] | |
| 121 .map((name) => conf[name]).toList(); | |
| 122 if (conf['checked']) settings.add('checked'); | |
| 123 output_words.add(settings.join('_')); | |
| 124 } | |
| 125 print(output_words.join(' ')); | |
| 126 } | |
| 127 | |
| 128 var runningBrowserTests = configurations.any((config) { | |
| 129 return TestUtils.isBrowserRuntime(config['runtime']); | |
| 130 }); | |
| 131 | |
| 132 List<Future> serverFutures = []; | |
| 133 var testSuites = new List<TestSuite>(); | |
| 134 var maxBrowserProcesses = maxProcesses; | |
| 135 if (configurations.length > 1 && | |
| 136 (configurations[0]['test_server_port'] != 0 || | |
| 137 configurations[0]['test_server_cross_origin_port'] != 0)) { | |
| 138 print("If the http server ports are specified, only one configuration" | |
| 139 " may be run at a time"); | |
| 140 exit(1); | |
| 141 } | |
| 142 for (var conf in configurations) { | |
| 143 Map<String, RegExp> selectors = conf['selectors']; | |
| 144 var useContentSecurityPolicy = conf['csp']; | |
| 145 if (!listTests && runningBrowserTests) { | |
| 146 // Start global http servers that serve the entire dart repo. | |
| 147 // The http server is available on window.location.port, and a second | |
| 148 // server for cross-domain tests can be found by calling | |
| 149 // getCrossOriginPortNumber(). | |
| 150 var servers = new TestingServers(new Path(TestUtils.buildDir(conf)), | |
| 151 useContentSecurityPolicy, | |
| 152 conf['runtime'], | |
| 153 null, | |
| 154 conf['package_root']); | |
| 155 serverFutures.add(servers.startServers(conf['local_ip'], | |
| 156 port: conf['test_server_port'], | |
| 157 crossOriginPort: conf['test_server_cross_origin_port'])); | |
| 158 conf['_servers_'] = servers; | |
| 159 if (verbose) { | |
| 160 serverFutures.last.then((_) { | |
| 161 var commandline = servers.httpServerCommandline(); | |
| 162 print('Started HttpServers: $commandline'); | |
| 163 }); | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 if (conf['runtime'].startsWith('ie')) { | |
| 168 // NOTE: We've experienced random timeouts of tests on ie9/ie10. The | |
| 169 // underlying issue has not been determined yet. Our current hypothesis | |
| 170 // is that windows does not handle the IE processes independently. | |
| 171 // If we have more than one browser and kill a browser we are seeing | |
| 172 // issues with starting up a new browser just after killing the hanging | |
| 173 // browser. | |
| 174 maxBrowserProcesses = 1; | |
| 175 } else if (conf['runtime'].startsWith('safari')) { | |
| 176 // Safari does not allow us to run from a fresh profile, so we can only | |
| 177 // use one browser. Additionally, you can not start two simulators | |
| 178 // for mobile safari simultainiously. | |
| 179 maxBrowserProcesses = 1; | |
| 180 } else if (conf['runtime'] == 'chrome' && | |
| 181 Platform.operatingSystem == 'macos') { | |
| 182 // Chrome on mac results in random timeouts. | |
| 183 maxBrowserProcesses = math.max(1, maxBrowserProcesses ~/ 2); | |
| 184 } | |
| 185 | |
| 186 // If we specifically pass in a suite only run that. | |
| 187 if (conf['suite_dir'] != null) { | |
| 188 var suite_path = new Path(conf['suite_dir']); | |
| 189 testSuites.add(new PKGTestSuite(conf, suite_path)); | |
| 190 } else { | |
| 191 for (String key in selectors.keys) { | |
| 192 if (key == 'co19') { | |
| 193 testSuites.add(new Co19TestSuite(conf)); | |
| 194 } else if (conf['compiler'] == 'none' && | |
| 195 conf['runtime'] == 'vm' && | |
| 196 key == 'vm') { | |
| 197 // vm tests contain both cc tests (added here) and dart tests (added | |
| 198 // in [TEST_SUITE_DIRECTORIES]). | |
| 199 testSuites.add(new VMTestSuite(conf)); | |
| 200 } else if (conf['analyzer']) { | |
| 201 if (key == 'analyze_library') { | |
| 202 testSuites.add(new AnalyzeLibraryTestSuite(conf)); | |
| 203 } | |
| 204 } else if (conf['compiler'] == 'none' && | |
| 205 conf['runtime'] == 'vm' && | |
| 206 key == 'pkgbuild') { | |
| 207 if (!conf['use_repository_packages'] && | |
| 208 !conf['use_public_packages']) { | |
| 209 print("You need to use either --use-repository-packages or " | |
| 210 "--use-public-packages with the pkgbuild test suite!"); | |
| 211 exit(1); | |
| 212 } | |
| 213 if (!conf['use_sdk']) { | |
| 214 print("Running the 'pkgbuild' test suite requires " | |
| 215 "passing the '--use-sdk' to test.py"); | |
| 216 exit(1); | |
| 217 } | |
| 218 testSuites.add( | |
| 219 new PkgBuildTestSuite(conf, 'pkgbuild', 'pkg/pkgbuild.status')); | |
| 220 } else if (key == 'pub') { | |
| 221 // TODO(rnystrom): Move pub back into TEST_SUITE_DIRECTORIES once | |
| 222 // #104 is fixed. | |
| 223 testSuites.add(new StandardTestSuite(conf, 'pub', | |
| 224 new Path('sdk/lib/_internal/pub_generated'), | |
| 225 ['sdk/lib/_internal/pub/pub.status'], | |
| 226 isTestFilePredicate: (file) => file.endsWith('_test.dart'), | |
| 227 recursive: true)); | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 for (final testSuiteDir in TEST_SUITE_DIRECTORIES) { | |
| 232 final name = testSuiteDir.filename; | |
| 233 if (selectors.containsKey(name)) { | |
| 234 testSuites.add( | |
| 235 new StandardTestSuite.forDirectory(conf, testSuiteDir)); | |
| 236 } | |
| 237 } | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 void allTestsFinished() { | |
| 242 for (var conf in configurations) { | |
| 243 if (conf.containsKey('_servers_')) { | |
| 244 conf['_servers_'].stopServers(); | |
| 245 } | |
| 246 } | |
| 247 DebugLogger.close(); | |
| 248 } | |
| 249 | |
| 250 var eventListener = []; | |
| 251 if (progressIndicator != 'silent') { | |
| 252 var printFailures = true; | |
| 253 var formatter = new Formatter(); | |
| 254 if (progressIndicator == 'color') { | |
| 255 progressIndicator = 'compact'; | |
| 256 formatter = new ColorFormatter(); | |
| 257 } | |
| 258 if (progressIndicator == 'diff') { | |
| 259 progressIndicator = 'compact'; | |
| 260 formatter = new ColorFormatter(); | |
| 261 printFailures = false; | |
| 262 eventListener.add(new StatusFileUpdatePrinter()); | |
| 263 } | |
| 264 eventListener.add(new SummaryPrinter()); | |
| 265 eventListener.add(new FlakyLogWriter()); | |
| 266 if (printFailures) { | |
| 267 // The buildbot has it's own failure summary since it needs to wrap it | |
| 268 // into '@@@'-annotated sections. | |
| 269 var printFailureSummary = progressIndicator != 'buildbot'; | |
| 270 eventListener.add(new TestFailurePrinter(printFailureSummary, formatter)); | |
| 271 } | |
| 272 eventListener.add(progressIndicatorFromName(progressIndicator, | |
| 273 startTime, | |
| 274 formatter)); | |
| 275 if (printTiming) { | |
| 276 eventListener.add(new TimingPrinter(startTime)); | |
| 277 } | |
| 278 eventListener.add(new SkippedCompilationsPrinter()); | |
| 279 eventListener.add(new LeftOverTempDirPrinter()); | |
| 280 } | |
| 281 if (firstConf['write_test_outcome_log']) { | |
| 282 eventListener.add(new TestOutcomeLogWriter()); | |
| 283 } | |
| 284 if (firstConf['copy_coredumps']) { | |
| 285 eventListener.add(new UnexpectedCrashDumpArchiver()); | |
| 286 } | |
| 287 | |
| 288 eventListener.add(new ExitCodeSetter()); | |
| 289 | |
| 290 void startProcessQueue() { | |
| 291 // [firstConf] is needed here, since the ProcessQueue needs to know the | |
| 292 // settings of 'noBatch' and 'local_ip' | |
| 293 new ProcessQueue(firstConf, | |
| 294 maxProcesses, | |
| 295 maxBrowserProcesses, | |
| 296 startTime, | |
| 297 testSuites, | |
| 298 eventListener, | |
| 299 allTestsFinished, | |
| 300 verbose, | |
| 301 recordingPath, | |
| 302 recordingOutputPath); | |
| 303 } | |
| 304 | |
| 305 // Start all the HTTP servers required before starting the process queue. | |
| 306 if (serverFutures.isEmpty) { | |
| 307 startProcessQueue(); | |
| 308 } else { | |
| 309 Future.wait(serverFutures).then((_) => startProcessQueue()); | |
| 310 } | |
| 311 } | |
| 312 | |
| 313 Future deleteTemporaryDartDirectories() { | |
| 314 var completer = new Completer(); | 40 var completer = new Completer(); |
| 315 var environment = Platform.environment; | 41 var environment = Platform.environment; |
| 316 if (environment['DART_TESTING_DELETE_TEMPORARY_DIRECTORIES'] == '1') { | 42 if (environment['DART_TESTING_DELETE_TEMPORARY_DIRECTORIES'] == '1') { |
| 317 LeftOverTempDirPrinter.getLeftOverTemporaryDirectories().listen( | 43 LeftOverTempDirPrinter.getLeftOverTemporaryDirectories().listen( |
| 318 (Directory tempDirectory) { | 44 (Directory tempDirectory) { |
| 319 try { | 45 try { |
| 320 tempDirectory.deleteSync(recursive: true); | 46 tempDirectory.deleteSync(recursive: true); |
| 321 } catch (error) { | 47 } catch (error) { |
| 322 DebugLogger.error(error); | 48 DebugLogger.error(error); |
| 323 } | 49 } |
| 324 }, onDone: completer.complete); | 50 }, onDone: completer.complete); |
| 325 } else { | 51 } else { |
| 326 completer.complete(); | 52 completer.complete(); |
| 327 } | 53 } |
| 328 return completer.future; | 54 return completer.future; |
| 329 } | 55 } |
| 330 | 56 |
| 331 void main(List<String> arguments) { | 57 void main(List<String> arguments) { |
| 332 // This script is in [dart]/tools. | 58 // This script is in [dart]/tools. |
| 333 TestUtils.setDartDirUri(Platform.script.resolve('..')); | 59 TestUtils.setDartDirUri(Platform.script.resolve('..')); |
| 334 deleteTemporaryDartDirectories().then((_) { | 60 _deleteTemporaryDartDirectories().then((_) { |
| 335 var optionsParser = new TestOptionsParser(); | 61 var optionsParser = new TestOptionsParser(); |
| 336 var configurations = optionsParser.parse(arguments); | 62 var configurations = optionsParser.parse(arguments); |
| 337 if (configurations != null && configurations.length > 0) { | 63 if (configurations != null && configurations.length > 0) { |
| 338 testConfigurations(configurations); | 64 testConfigurations(configurations); |
| 339 } | 65 } |
| 340 }); | 66 }); |
| 341 } | 67 } |
| 342 | |
| OLD | NEW |