Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * Classes and methods for enumerating and preparing tests. | 6 * Classes and methods for enumerating and preparing tests. |
| 7 * | 7 * |
| 8 * This library includes: | 8 * This library includes: |
| 9 * | 9 * |
| 10 * - Creating tests by listing all the Dart files in certain directories, | 10 * - Creating tests by listing all the Dart files in certain directories, |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 typedef void CreateTest(Path filePath, | 33 typedef void CreateTest(Path filePath, |
| 34 bool hasCompileError, | 34 bool hasCompileError, |
| 35 bool hasRuntimeError, | 35 bool hasRuntimeError, |
| 36 {bool isNegativeIfChecked, | 36 {bool isNegativeIfChecked, |
| 37 bool hasFatalTypeErrors, | 37 bool hasFatalTypeErrors, |
| 38 Set<String> multitestOutcome}); | 38 Set<String> multitestOutcome}); |
| 39 | 39 |
| 40 typedef void VoidFunction(); | 40 typedef void VoidFunction(); |
| 41 | 41 |
| 42 /** | 42 /** |
| 43 * Calls [function] asynchronously. If [function] is `null`, does nothing. | |
| 44 */ | |
| 45 void asynchronously(VoidFunction function) { | |
| 46 if (function == null) return; | |
| 47 new Timer(0, (_) => function()); | |
| 48 } | |
| 49 | |
| 50 /** A completer that waits until all added [Future]s complete. */ | |
| 51 // TODO(rnystrom): Copied from web_components. Remove from here when it gets | |
| 52 // added to dart:core. (See #6626.) | |
| 53 class FutureGroup { | |
| 54 const _FINISHED = -1; | |
| 55 int _pending = 0; | |
| 56 Completer<List> _completer = new Completer<List>(); | |
| 57 final List<Future> futures = <Future>[]; | |
| 58 | |
| 59 /** | |
| 60 * Wait for [task] to complete (assuming this barrier has not already been | |
| 61 * marked as completed, otherwise you'll get an exception indicating that a | |
| 62 * future has already been completed). | |
| 63 */ | |
| 64 void add(Future task) { | |
| 65 if (_pending == _FINISHED) { | |
| 66 throw new FutureAlreadyCompleteException(); | |
| 67 } | |
| 68 _pending++; | |
| 69 futures.add(task); | |
| 70 task.handleException( | |
| 71 (e) => _completer.completeException(e, task.stackTrace)); | |
| 72 task.then((_) { | |
| 73 _pending--; | |
| 74 if (_pending == 0) { | |
| 75 _pending = _FINISHED; | |
| 76 _completer.complete(futures); | |
| 77 } | |
| 78 }); | |
| 79 } | |
| 80 | |
| 81 Future<List> get future => _completer.future; | |
| 82 } | |
| 83 | |
| 84 /** | |
| 43 * A TestSuite represents a collection of tests. It creates a [TestCase] | 85 * A TestSuite represents a collection of tests. It creates a [TestCase] |
| 44 * object for each test to be run, and passes the test cases to a callback. | 86 * object for each test to be run, and passes the test cases to a callback. |
| 45 * | 87 * |
| 46 * Most TestSuites represent a directory or directory tree containing tests, | 88 * Most TestSuites represent a directory or directory tree containing tests, |
| 47 * and a status file containing the expected results when these tests are run. | 89 * and a status file containing the expected results when these tests are run. |
| 48 */ | 90 */ |
| 49 abstract class TestSuite { | 91 abstract class TestSuite { |
| 92 final Map configuration; | |
| 93 final String suiteName; | |
| 94 | |
| 95 TestSuite(this.configuration, this.suiteName); | |
| 96 | |
| 97 /** | |
| 98 * The output directory for this suite's configuration. | |
| 99 */ | |
| 100 String get buildDir { | |
| 101 var mode = (configuration['mode'] == 'debug') ? 'Debug' : 'Release'; | |
| 102 var arch = configuration['arch'].toUpperCase(); | |
| 103 return "${TestUtils.outputDir(configuration)}$mode$arch"; | |
| 104 } | |
| 105 | |
| 106 /** | |
| 107 * The path to the compiler for this suite's configuration. Returns `null` if | |
| 108 * no compiler should be used. | |
| 109 */ | |
| 110 String get compilerPath { | |
| 111 if (configuration['compiler'] == 'none') { | |
| 112 return null; // No separate compiler for dartium tests. | |
| 113 } | |
| 114 var name = '$buildDir/${compilerName}'; | |
| 115 if (!(new File(name)).existsSync() && !configuration['list']) { | |
| 116 throw "Executable '$name' does not exist"; | |
| 117 } | |
| 118 return name; | |
| 119 } | |
| 120 | |
| 121 /** | |
| 122 * The name of the compiler for this suite's configuration. Throws an error | |
| 123 * if the configuration does not use a compiler. | |
| 124 */ | |
| 125 String get compilerName { | |
| 126 switch (configuration['compiler']) { | |
| 127 case 'dartc': | |
| 128 case 'dart2js': | |
| 129 case 'dart2dart': | |
| 130 return executableName; | |
| 131 default: | |
| 132 throw "Unknown compiler for: ${configuration['compiler']}"; | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 /** | |
| 137 * The file name of the executable used to run this suite's tests. | |
| 138 */ | |
| 139 String get executableName { | |
| 140 String suffix = getExecutableSuffix(configuration['compiler']); | |
| 141 switch (configuration['compiler']) { | |
| 142 case 'none': | |
| 143 return 'dart$suffix'; | |
| 144 case 'dartc': | |
| 145 return 'analyzer/bin/dart_analyzer$suffix'; | |
| 146 case 'dart2js': | |
| 147 case 'dart2dart': | |
| 148 var prefix = ''; | |
| 149 if (configuration['use_sdk']) { | |
| 150 prefix = 'dart-sdk/bin/'; | |
| 151 } | |
| 152 if (configuration['host_checked']) { | |
| 153 // The script dart2js_developer is not in the SDK. | |
| 154 return 'dart2js_developer$suffix'; | |
| 155 } else { | |
| 156 return '${prefix}dart2js$suffix'; | |
| 157 } | |
| 158 break; | |
| 159 default: | |
| 160 throw "Unknown executable for: ${configuration['compiler']}"; | |
| 161 } | |
| 162 } | |
| 163 | |
| 164 /** | |
| 165 * The file name of the d8 executable. | |
| 166 */ | |
| 167 String get d8FileName { | |
| 168 var suffix = getExecutableSuffix('d8'); | |
| 169 var d8 = '$buildDir/d8$suffix'; | |
| 170 TestUtils.ensureExists(d8, configuration); | |
| 171 return d8; | |
| 172 } | |
| 173 | |
| 174 String get dartShellFileName { | |
| 175 var name = configuration['dart']; | |
| 176 if (name == '') { | |
| 177 name = '$buildDir/$executableName'; | |
| 178 } | |
| 179 TestUtils.ensureExists(name, configuration); | |
| 180 return name; | |
| 181 } | |
| 182 | |
| 183 String get jsShellFileName { | |
| 184 var executableSuffix = getExecutableSuffix('jsshell'); | |
| 185 var executable = 'jsshell$executableSuffix'; | |
| 186 var jsshellDir = '${TestUtils.dartDir()}/tools/testing/bin'; | |
| 187 return '$jsshellDir/$executable'; | |
| 188 } | |
| 189 | |
| 190 /** | |
| 191 * The file name of the Dart VM executable. | |
| 192 */ | |
| 193 String get vmFileName { | |
| 194 var suffix = getExecutableSuffix('vm'); | |
| 195 var vm = '$buildDir/dart$suffix'; | |
| 196 TestUtils.ensureExists(vm, configuration); | |
| 197 return vm; | |
| 198 } | |
| 199 | |
| 200 /** | |
| 201 * The file extension (if any) that should be added to the given executable | |
| 202 * name for the current platform. | |
| 203 */ | |
| 204 String getExecutableSuffix(String executable) { | |
| 205 if (Platform.operatingSystem == 'windows') { | |
| 206 if (executable == 'd8' || executable == 'vm' || executable == 'none') { | |
| 207 return '.exe'; | |
| 208 } else { | |
| 209 return '.bat'; | |
| 210 } | |
| 211 } | |
| 212 return ''; | |
| 213 } | |
| 214 | |
| 50 /** | 215 /** |
| 51 * Call the callback function onTest with a [TestCase] argument for each | 216 * Call the callback function onTest with a [TestCase] argument for each |
| 52 * test in the suite. When all tests have been processed, call [onDone]. | 217 * test in the suite. When all tests have been processed, call [onDone]. |
| 53 * | 218 * |
| 54 * The [testCache] argument provides a persistent store that can be used to | 219 * The [testCache] argument provides a persistent store that can be used to |
| 55 * cache information about the test suite, so that directories do not need | 220 * cache information about the test suite, so that directories do not need |
| 56 * to be listed each time. | 221 * to be listed each time. |
| 57 */ | 222 */ |
| 58 void forEachTest(TestCaseEvent onTest, Map testCache, [VoidFunction onDone]); | 223 void forEachTest(TestCaseEvent onTest, Map testCache, [VoidFunction onDone]); |
| 59 } | 224 } |
| 60 | 225 |
| 61 | 226 |
| 62 // TODO(1030): remove once in the corelib. | |
|
Emily Fortuna
2012/11/09 01:41:44
:-)
| |
| 63 bool Contains(element, collection) => collection.indexOf(element) >= 0; | |
| 64 | |
| 65 | |
| 66 void ccTestLister() { | 227 void ccTestLister() { |
| 67 port.receive((String runnerPath, SendPort replyTo) { | 228 port.receive((String runnerPath, SendPort replyTo) { |
| 68 Future processFuture = Process.start(runnerPath, ["--list"]); | 229 Future processFuture = Process.start(runnerPath, ["--list"]); |
| 69 processFuture.then((p) { | 230 processFuture.then((p) { |
| 70 // Drain stderr to not leak resources. | 231 // Drain stderr to not leak resources. |
| 71 p.stderr.onData = p.stderr.read; | 232 p.stderr.onData = p.stderr.read; |
| 72 StringInputStream stdoutStream = new StringInputStream(p.stdout); | 233 StringInputStream stdoutStream = new StringInputStream(p.stdout); |
| 73 var streamDone = false; | 234 var streamDone = false; |
| 74 var processExited = false; | 235 var processExited = false; |
| 75 checkDone() { | 236 checkDone() { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 106 | 267 |
| 107 | 268 |
| 108 /** | 269 /** |
| 109 * A specialized [TestSuite] that runs tests written in C to unit test | 270 * A specialized [TestSuite] that runs tests written in C to unit test |
| 110 * the Dart virtual machine and its API. | 271 * the Dart virtual machine and its API. |
| 111 * | 272 * |
| 112 * The tests are compiled into a monolithic executable by the build step. | 273 * The tests are compiled into a monolithic executable by the build step. |
| 113 * The executable lists its tests when run with the --list command line flag. | 274 * The executable lists its tests when run with the --list command line flag. |
| 114 * Individual tests are run by specifying them on the command line. | 275 * Individual tests are run by specifying them on the command line. |
| 115 */ | 276 */ |
| 116 class CCTestSuite implements TestSuite { | 277 class CCTestSuite extends TestSuite { |
| 117 Map configuration; | |
| 118 final String suiteName; | |
| 119 final String testPrefix; | 278 final String testPrefix; |
| 120 String runnerPath; | 279 String runnerPath; |
| 121 final String dartDir; | 280 final String dartDir; |
| 122 List<String> statusFilePaths; | 281 List<String> statusFilePaths; |
| 123 TestCaseEvent doTest; | 282 TestCaseEvent doTest; |
| 124 VoidFunction doDone; | 283 VoidFunction doDone; |
| 125 ReceivePort receiveTestName; | 284 ReceivePort receiveTestName; |
| 126 TestExpectations testExpectations; | 285 TestExpectations testExpectations; |
| 127 | 286 |
| 128 CCTestSuite(Map this.configuration, | 287 CCTestSuite(Map configuration, |
| 129 String this.suiteName, | 288 String suiteName, |
| 130 String runnerName, | 289 String runnerName, |
| 131 List<String> this.statusFilePaths, | 290 List<String> this.statusFilePaths, |
| 132 {this.testPrefix: ''}) | 291 {this.testPrefix: ''}) |
| 133 : dartDir = TestUtils.dartDir().toNativePath() { | 292 : super(configuration, suiteName), |
| 134 runnerPath = '${TestUtils.buildDir(configuration)}/$runnerName'; | 293 dartDir = TestUtils.dartDir().toNativePath() { |
| 294 runnerPath = '$buildDir/$runnerName'; | |
| 135 } | 295 } |
| 136 | 296 |
| 137 void testNameHandler(String testName, ignore) { | 297 void testNameHandler(String testName, ignore) { |
| 138 if (testName == "") { | 298 if (testName == "") { |
| 139 receiveTestName.close(); | 299 receiveTestName.close(); |
| 140 doDone(); | 300 |
| 301 if (doDone != null) doDone(); | |
| 141 } else { | 302 } else { |
| 142 // Only run the tests that match the pattern. Use the name | 303 // Only run the tests that match the pattern. Use the name |
| 143 // "suiteName/testName" for cc tests. | 304 // "suiteName/testName" for cc tests. |
| 144 RegExp pattern = configuration['selectors'][suiteName]; | 305 RegExp pattern = configuration['selectors'][suiteName]; |
| 145 String constructedName = '$suiteName/$testPrefix$testName'; | 306 String constructedName = '$suiteName/$testPrefix$testName'; |
| 146 if (!pattern.hasMatch(constructedName)) return; | 307 if (!pattern.hasMatch(constructedName)) return; |
| 147 | 308 |
| 148 var expectations = testExpectations.expectations( | 309 var expectations = testExpectations.expectations( |
| 149 '$testPrefix$testName'); | 310 '$testPrefix$testName'); |
| 150 | 311 |
| 151 if (configuration["report"]) { | 312 if (configuration["report"]) { |
| 152 SummaryReport.add(expectations); | 313 SummaryReport.add(expectations); |
| 153 } | 314 } |
| 154 | 315 |
| 155 if (expectations.contains(SKIP)) return; | 316 if (expectations.contains(SKIP)) return; |
| 156 | 317 |
| 157 var args = TestUtils.standardOptions(configuration); | 318 var args = TestUtils.standardOptions(configuration); |
| 158 args.add(testName); | 319 args.add(testName); |
| 159 | 320 |
| 160 doTest(new TestCase(constructedName, | 321 doTest(new TestCase(constructedName, |
| 161 [new Command(runnerPath, args)], | 322 [new Command(runnerPath, args)], |
| 162 configuration, | 323 configuration, |
| 163 completeHandler, | 324 completeHandler, |
| 164 expectations)); | 325 expectations)); |
| 165 } | 326 } |
| 166 } | 327 } |
| 167 | 328 |
| 168 void forEachTest(TestCaseEvent onTest, Map testCache, [VoidFunction onDone]) { | 329 void forEachTest(TestCaseEvent onTest, Map testCache, [VoidFunction onDone]) { |
| 169 doTest = onTest; | 330 doTest = onTest; |
| 170 doDone = () => (onDone != null) ? onDone() : null; | 331 doDone = onDone; |
| 171 | 332 |
| 172 var filesRead = 0; | 333 var filesRead = 0; |
| 173 void statusFileRead() { | 334 void statusFileRead() { |
| 174 filesRead++; | 335 filesRead++; |
| 175 if (filesRead == statusFilePaths.length) { | 336 if (filesRead == statusFilePaths.length) { |
| 176 receiveTestName = new ReceivePort(); | 337 receiveTestName = new ReceivePort(); |
| 177 var port = spawnFunction(ccTestLister); | 338 var port = spawnFunction(ccTestLister); |
| 178 port.send(runnerPath, receiveTestName.toSendPort()); | 339 port.send(runnerPath, receiveTestName.toSendPort()); |
| 179 receiveTestName.receive(testNameHandler); | 340 receiveTestName.receive(testNameHandler); |
| 180 } | 341 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 209 this.multitestOutcome) { | 370 this.multitestOutcome) { |
| 210 Expect.isTrue(filePath.isAbsolute); | 371 Expect.isTrue(filePath.isAbsolute); |
| 211 } | 372 } |
| 212 } | 373 } |
| 213 | 374 |
| 214 | 375 |
| 215 /** | 376 /** |
| 216 * A standard [TestSuite] implementation that searches for tests in a | 377 * A standard [TestSuite] implementation that searches for tests in a |
| 217 * directory, and creates [TestCase]s that compile and/or run them. | 378 * directory, and creates [TestCase]s that compile and/or run them. |
| 218 */ | 379 */ |
| 219 class StandardTestSuite implements TestSuite { | 380 class StandardTestSuite extends TestSuite { |
| 220 Map configuration; | 381 final Path suiteDir; |
| 221 String suiteName; | 382 final List<String> statusFilePaths; |
| 222 Path suiteDir; | |
| 223 List<String> statusFilePaths; | |
| 224 TestCaseEvent doTest; | 383 TestCaseEvent doTest; |
| 225 VoidFunction doDone; | |
| 226 int activeTestGenerators = 0; | |
| 227 bool listingDone = false; | |
| 228 TestExpectations testExpectations; | 384 TestExpectations testExpectations; |
| 229 List<TestInformation> cachedTests; | 385 List<TestInformation> cachedTests; |
| 230 final Path dartDir; | 386 final Path dartDir; |
| 231 Predicate<String> isTestFilePredicate; | 387 Predicate<String> isTestFilePredicate; |
| 232 bool _listRecursive; | 388 final bool listRecursively; |
| 233 | 389 |
| 234 StandardTestSuite(this.configuration, | 390 StandardTestSuite(Map configuration, |
| 235 this.suiteName, | 391 String suiteName, |
| 236 Path suiteDirectory, | 392 Path suiteDirectory, |
| 237 this.statusFilePaths, | 393 this.statusFilePaths, |
| 238 {this.isTestFilePredicate, | 394 {this.isTestFilePredicate, |
| 239 bool recursive: false}) | 395 bool recursive: false}) |
| 240 : dartDir = TestUtils.dartDir(), _listRecursive = recursive, | 396 : super(configuration, suiteName), |
| 397 dartDir = TestUtils.dartDir(), | |
| 398 listRecursively = recursive, | |
| 241 suiteDir = TestUtils.dartDir().join(suiteDirectory); | 399 suiteDir = TestUtils.dartDir().join(suiteDirectory); |
| 242 | 400 |
| 243 /** | 401 /** |
| 244 * Creates a test suite whose file organization matches an expected structure. | 402 * Creates a test suite whose file organization matches an expected structure. |
| 245 * To use this, your suite should look like: | 403 * To use this, your suite should look like: |
| 246 * | 404 * |
| 247 * dart/ | 405 * dart/ |
| 248 * path/ | 406 * path/ |
| 249 * to/ | 407 * to/ |
| 250 * mytestsuite/ | 408 * mytestsuite/ |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 * The default implementation assumes a file is a test if | 440 * The default implementation assumes a file is a test if |
| 283 * it ends in "Test.dart". | 441 * it ends in "Test.dart". |
| 284 */ | 442 */ |
| 285 bool isTestFile(String filename) { | 443 bool isTestFile(String filename) { |
| 286 // Use the specified predicate, if provided. | 444 // Use the specified predicate, if provided. |
| 287 if (isTestFilePredicate != null) return isTestFilePredicate(filename); | 445 if (isTestFilePredicate != null) return isTestFilePredicate(filename); |
| 288 | 446 |
| 289 return filename.endsWith("Test.dart"); | 447 return filename.endsWith("Test.dart"); |
| 290 } | 448 } |
| 291 | 449 |
| 292 bool listRecursively() => _listRecursive; | |
| 293 | |
| 294 String shellPath() => TestUtils.dartShellFileName(configuration); | |
| 295 | |
| 296 List<String> additionalOptions(Path filePath) => []; | 450 List<String> additionalOptions(Path filePath) => []; |
| 297 | 451 |
| 298 void forEachTest(TestCaseEvent onTest, Map testCache, [VoidFunction onDone]) { | 452 void forEachTest(TestCaseEvent onTest, Map testCache, [VoidFunction onDone]) { |
| 299 // If DumpRenderTree/Dartium is required, and not yet updated, | 453 waitForDartium().chain((_) { |
| 300 // wait for update. | 454 doTest = onTest; |
| 455 | |
| 456 return readExpectations(); | |
| 457 }).chain((expectations) { | |
| 458 testExpectations = expectations; | |
| 459 | |
| 460 // Checked if we have already found and generated the tests for | |
| 461 // this suite. | |
| 462 if (!testCache.containsKey(suiteName)) { | |
| 463 cachedTests = testCache[suiteName] = []; | |
| 464 return enqueueTests(); | |
| 465 } else { | |
| 466 // We rely on enqueueing completing asynchronously. | |
| 467 return asynchronously(() { | |
| 468 for (var info in testCache[suiteName]) { | |
| 469 enqueueTestCaseFromTestInformation(info); | |
| 470 } | |
| 471 }); | |
| 472 } | |
| 473 }).then((_) { | |
| 474 if (onDone != null) onDone(); | |
| 475 }); | |
| 476 } | |
| 477 | |
| 478 /** | |
| 479 * If DumpRenderTree/Dartium is required, and not yet updated, waits for | |
| 480 * the update then completes. Otherwise completes immediately. | |
| 481 */ | |
| 482 Future waitForDartium() { | |
|
Emily Fortuna
2012/11/09 01:41:44
nit: maybe just call this updateDartium since in n
Bob Nystrom
2012/11/09 20:56:26
Done.
| |
| 483 var completer = new Completer(); | |
| 301 var updater = runtimeUpdater(configuration); | 484 var updater = runtimeUpdater(configuration); |
| 302 if (updater !== null && !updater.updated) { | 485 if (updater == null || updater.updated) { |
| 303 Expect.isTrue(updater.isActive); | 486 return new Future.immediate(null); |
| 304 updater.onUpdated.add(() { | |
| 305 forEachTest(onTest, testCache, onDone); | |
| 306 }); | |
| 307 return; | |
| 308 } | 487 } |
| 309 | 488 |
| 310 doTest = onTest; | 489 Expect.isTrue(updater.isActive); |
| 311 doDone = (onDone != null) ? onDone : (() => null); | 490 updater.onUpdated.add(completer.complete); |
| 491 | |
| 492 return completer.future; | |
| 493 } | |
| 494 | |
| 495 /** | |
| 496 * Reads the status files and completes with the parsed expectations. | |
| 497 */ | |
| 498 Future<TestExpectations> readExpectations() { | |
| 499 var completer = new Completer(); | |
| 500 var expectations = new TestExpectations(); | |
| 312 | 501 |
| 313 var filesRead = 0; | 502 var filesRead = 0; |
| 314 void statusFileRead() { | 503 void statusFileRead() { |
| 315 filesRead++; | 504 filesRead++; |
| 316 if (filesRead == statusFilePaths.length) { | 505 if (filesRead == statusFilePaths.length) { |
| 317 // Checked if we have already found and generated the tests for | 506 completer.complete(expectations); |
| 318 // this suite. | |
| 319 if (!testCache.containsKey(suiteName)) { | |
| 320 cachedTests = testCache[suiteName] = []; | |
| 321 processDirectory(); | |
| 322 } else { | |
| 323 // We rely on enqueueing completing asynchronously so use a | |
| 324 // timer to make it so. | |
| 325 void enqueueCachedTests(Timer ignore) { | |
| 326 for (var info in testCache[suiteName]) { | |
| 327 enqueueTestCaseFromTestInformation(info); | |
| 328 } | |
| 329 doDone(); | |
| 330 } | |
| 331 new Timer(0, enqueueCachedTests); | |
| 332 } | |
| 333 } | 507 } |
| 334 } | 508 } |
| 335 | 509 |
| 336 // Read test expectations from status files. | |
| 337 testExpectations = new TestExpectations(); | |
| 338 for (var statusFilePath in statusFilePaths) { | 510 for (var statusFilePath in statusFilePaths) { |
| 339 // [forDirectory] adds name_dart2js.status for all tests suites, use it if | 511 // [forDirectory] adds name_dart2js.status for all tests suites. Use it |
| 340 // it exists, but otherwise skip it and don't fail. | 512 // if it exists, but otherwise skip it and don't fail. |
| 341 if (statusFilePath.endsWith('_dart2js.status')) { | 513 if (statusFilePath.endsWith('_dart2js.status')) { |
| 342 File file = new File.fromPath(dartDir.append(statusFilePath)); | 514 var file = new File.fromPath(dartDir.append(statusFilePath)); |
| 343 if (!file.existsSync()) { | 515 if (!file.existsSync()) { |
| 344 filesRead++; | 516 filesRead++; |
| 345 continue; | 517 continue; |
| 346 } | 518 } |
| 347 } | 519 } |
| 348 ReadTestExpectationsInto(testExpectations, | 520 |
| 521 ReadTestExpectationsInto(expectations, | |
| 349 dartDir.append(statusFilePath).toNativePath(), | 522 dartDir.append(statusFilePath).toNativePath(), |
| 350 configuration, | 523 configuration, statusFileRead); |
| 351 statusFileRead); | |
| 352 } | 524 } |
| 525 | |
| 526 return completer.future; | |
| 353 } | 527 } |
| 354 | 528 |
| 355 void processDirectory() { | 529 Future enqueueTests() { |
| 356 Directory dir = new Directory.fromPath(suiteDir); | 530 Directory dir = new Directory.fromPath(suiteDir); |
| 357 dir.exists().then((exists) { | 531 return dir.exists().chain((exists) { |
| 358 if (!exists) { | 532 if (!exists) { |
| 359 print('Directory containing tests not found: $suiteDir'); | 533 print('Directory containing tests not found: $suiteDir'); |
| 360 directoryListingDone(false); | 534 return new Future.immediate(null); |
| 361 } else { | 535 } else { |
| 362 var lister = dir.list(recursive: listRecursively()); | 536 var group = new FutureGroup(); |
| 363 lister.onFile = processFile; | 537 enqueueDirectory(dir, group); |
| 364 lister.onDone = directoryListingDone; | 538 return group.future; |
| 365 } | 539 } |
| 366 }); | 540 }); |
| 367 } | 541 } |
| 368 | 542 |
| 543 Future enqueueDirectory(Directory dir, FutureGroup group) { | |
| 544 var listCompleter = new Completer(); | |
| 545 group.add(listCompleter.future); | |
| 546 | |
| 547 var lister = dir.list(recursive: listRecursively); | |
| 548 lister.onFile = (file) => enqueueFile(file, group); | |
| 549 lister.onDone = listCompleter.complete; | |
| 550 } | |
| 551 | |
| 552 void enqueueFile(String filename, FutureGroup group) { | |
| 553 if (!isTestFile(filename)) return; | |
| 554 Path filePath = new Path.fromNative(filename); | |
| 555 | |
| 556 // Only run the tests that match the pattern. | |
| 557 RegExp pattern = configuration['selectors'][suiteName]; | |
| 558 if (!pattern.hasMatch('$filePath')) return; | |
| 559 if (filePath.filename.endsWith('test_config.dart')) return; | |
| 560 | |
| 561 var optionsFromFile = readOptionsFromFile(filePath); | |
| 562 CreateTest createTestCase = makeTestCaseCreator(optionsFromFile); | |
| 563 | |
| 564 if (optionsFromFile['isMultitest']) { | |
| 565 group.add(doMultitest(filePath, buildDir, suiteDir, createTestCase)); | |
| 566 } else { | |
| 567 createTestCase(filePath, | |
| 568 optionsFromFile['hasCompileError'], | |
| 569 optionsFromFile['hasRuntimeError']); | |
| 570 } | |
| 571 } | |
| 572 | |
| 369 void enqueueTestCaseFromTestInformation(TestInformation info) { | 573 void enqueueTestCaseFromTestInformation(TestInformation info) { |
| 370 var filePath = info.filePath; | 574 var filePath = info.filePath; |
| 371 var optionsFromFile = info.optionsFromFile; | 575 var optionsFromFile = info.optionsFromFile; |
| 372 var isNegative = info.hasCompileError; | 576 var isNegative = info.hasCompileError; |
| 373 if (info.hasRuntimeError && hasRuntime) { | 577 if (info.hasRuntimeError && hasRuntime) { |
| 374 isNegative = true; | 578 isNegative = true; |
| 375 } | 579 } |
| 376 | 580 |
| 377 // Look up expectations in status files using a test name generated | 581 // Look up expectations in status files using a test name generated |
| 378 // from the test file's path. | 582 // from the test file's path. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 466 info: info)); | 670 info: info)); |
| 467 } | 671 } |
| 468 } | 672 } |
| 469 | 673 |
| 470 List<Command> makeCommands(TestInformation info, var vmOptions, var args) { | 674 List<Command> makeCommands(TestInformation info, var vmOptions, var args) { |
| 471 switch (configuration['compiler']) { | 675 switch (configuration['compiler']) { |
| 472 case 'dart2js': | 676 case 'dart2js': |
| 473 args = new List.from(args); | 677 args = new List.from(args); |
| 474 String tempDir = createOutputDirectory(info.filePath, ''); | 678 String tempDir = createOutputDirectory(info.filePath, ''); |
| 475 args.add('--out=$tempDir/out.js'); | 679 args.add('--out=$tempDir/out.js'); |
| 476 List<Command> commands = <Command>[new Command(shellPath(), args)]; | 680 List<Command> commands = <Command>[new Command(dartShellFileName, args)]; |
| 477 if (info.hasCompileError) { | 681 if (info.hasCompileError) { |
| 478 // Do not attempt to run the compiled result. A compilation | 682 // Do not attempt to run the compiled result. A compilation |
| 479 // error should be reported by the compilation command. | 683 // error should be reported by the compilation command. |
| 480 } else if (configuration['runtime'] == 'd8') { | 684 } else if (configuration['runtime'] == 'd8') { |
| 481 var d8 = TestUtils.d8FileName(configuration); | 685 commands.add(new Command(d8FileName, ['$tempDir/out.js'])); |
| 482 commands.add(new Command(d8, ['$tempDir/out.js'])); | |
| 483 } else if (configuration['runtime'] == 'jsshell') { | 686 } else if (configuration['runtime'] == 'jsshell') { |
| 484 var jsshell = TestUtils.jsshellFileName(configuration); | 687 commands.add(new Command(jsShellFileName, ['$tempDir/out.js'])); |
| 485 commands.add(new Command(jsshell, ['$tempDir/out.js'])); | |
| 486 } | 688 } |
| 487 return commands; | 689 return commands; |
| 488 | 690 |
| 489 case 'dart2dart': | 691 case 'dart2dart': |
| 490 var compilerArguments = new List.from(args); | 692 var compilerArguments = new List.from(args); |
| 491 var additionalFlags = | 693 var additionalFlags = |
| 492 configuration['additional-compiler-flags'].split(' '); | 694 configuration['additional-compiler-flags'].split(' '); |
| 493 for (final flag in additionalFlags) { | 695 for (final flag in additionalFlags) { |
| 494 if (flag.isEmpty) continue; | 696 if (flag.isEmpty) continue; |
| 495 compilerArguments.add(flag); | 697 compilerArguments.add(flag); |
| 496 } | 698 } |
| 497 compilerArguments.add('--output-type=dart'); | 699 compilerArguments.add('--output-type=dart'); |
| 498 String tempDir = createOutputDirectory(info.filePath, ''); | 700 String tempDir = createOutputDirectory(info.filePath, ''); |
| 499 compilerArguments.add('--out=$tempDir/out.dart'); | 701 compilerArguments.add('--out=$tempDir/out.dart'); |
| 500 List<Command> commands = | 702 List<Command> commands = |
| 501 <Command>[new Command(shellPath(), compilerArguments)]; | 703 <Command>[new Command(dartShellFileName, compilerArguments)]; |
| 502 if (info.hasCompileError) { | 704 if (info.hasCompileError) { |
| 503 // Do not attempt to run the compiled result. A compilation | 705 // Do not attempt to run the compiled result. A compilation |
| 504 // error should be reported by the compilation command. | 706 // error should be reported by the compilation command. |
| 505 } else if (configuration['runtime'] == 'vm') { | 707 } else if (configuration['runtime'] == 'vm') { |
| 506 // TODO(antonm): support checked. | 708 // TODO(antonm): support checked. |
| 507 var vmArguments = new List.from(vmOptions); | 709 var vmArguments = new List.from(vmOptions); |
| 508 vmArguments.addAll([ | 710 vmArguments.addAll([ |
| 509 '--ignore-unrecognized-flags', '$tempDir/out.dart']); | 711 '--ignore-unrecognized-flags', '$tempDir/out.dart']); |
| 510 commands.add(new Command( | 712 commands.add(new Command(vmFileName, vmArguments)); |
| 511 TestUtils.vmFileName(configuration), | |
| 512 vmArguments)); | |
| 513 } else { | 713 } else { |
| 514 throw 'Unsupported runtime ${configuration["runtime"]} for dart2dart'; | 714 throw 'Unsupported runtime ${configuration["runtime"]} for dart2dart'; |
| 515 } | 715 } |
| 516 return commands; | 716 return commands; |
| 517 | 717 |
| 518 case 'none': | 718 case 'none': |
| 519 case 'dartc': | 719 case 'dartc': |
| 520 var arguments = new List.from(vmOptions); | 720 var arguments = new List.from(vmOptions); |
| 521 arguments.addAll(args); | 721 arguments.addAll(args); |
| 522 return <Command>[new Command(shellPath(), arguments)]; | 722 return <Command>[new Command(dartShellFileName, arguments)]; |
| 523 | 723 |
| 524 default: | 724 default: |
| 525 throw 'Unknown compiler ${configuration["compiler"]}'; | 725 throw 'Unknown compiler ${configuration["compiler"]}'; |
| 526 } | 726 } |
| 527 } | 727 } |
| 528 | 728 |
| 529 CreateTest makeTestCaseCreator(Map optionsFromFile) { | 729 CreateTest makeTestCaseCreator(Map optionsFromFile) { |
| 530 return (Path filePath, | 730 return (Path filePath, |
| 531 bool hasCompileError, | 731 bool hasCompileError, |
| 532 bool hasRuntimeError, | 732 bool hasRuntimeError, |
| 533 {bool isNegativeIfChecked: false, | 733 {bool isNegativeIfChecked: false, |
| 534 bool hasFatalTypeErrors: false, | 734 bool hasFatalTypeErrors: false, |
| 535 Set<String> multitestOutcome: null}) { | 735 Set<String> multitestOutcome: null}) { |
| 536 // Cache the test information for each test case. | 736 // Cache the test information for each test case. |
| 537 var info = new TestInformation(filePath, | 737 var info = new TestInformation(filePath, |
| 538 optionsFromFile, | 738 optionsFromFile, |
| 539 hasCompileError, | 739 hasCompileError, |
| 540 hasRuntimeError, | 740 hasRuntimeError, |
| 541 isNegativeIfChecked, | 741 isNegativeIfChecked, |
| 542 hasFatalTypeErrors, | 742 hasFatalTypeErrors, |
| 543 multitestOutcome); | 743 multitestOutcome); |
| 544 cachedTests.add(info); | 744 cachedTests.add(info); |
| 545 enqueueTestCaseFromTestInformation(info); | 745 enqueueTestCaseFromTestInformation(info); |
| 546 }; | 746 }; |
| 547 } | 747 } |
| 548 | 748 |
| 549 void processFile(String filename) { | |
| 550 if (!isTestFile(filename)) return; | |
| 551 Path filePath = new Path.fromNative(filename); | |
| 552 | |
| 553 // Only run the tests that match the pattern. | |
| 554 RegExp pattern = configuration['selectors'][suiteName]; | |
| 555 if (!pattern.hasMatch('$filePath')) return; | |
| 556 if (filePath.filename.endsWith('test_config.dart')) return; | |
| 557 | |
| 558 var optionsFromFile = readOptionsFromFile(filePath); | |
| 559 CreateTest createTestCase = makeTestCaseCreator(optionsFromFile); | |
| 560 | |
| 561 if (optionsFromFile['isMultitest']) { | |
| 562 testGeneratorStarted(); | |
| 563 DoMultitest(filePath, | |
| 564 TestUtils.buildDir(configuration), | |
| 565 suiteDir, | |
| 566 createTestCase, | |
| 567 testGeneratorDone); | |
| 568 } else { | |
| 569 createTestCase(filePath, | |
| 570 optionsFromFile['hasCompileError'], | |
| 571 optionsFromFile['hasRuntimeError']); | |
| 572 } | |
| 573 } | |
| 574 | |
| 575 /** | 749 /** |
| 576 * The [StandardTestSuite] has support for tests that | 750 * The [StandardTestSuite] has support for tests that |
| 577 * compile a test from Dart to JavaScript, and then run the resulting | 751 * compile a test from Dart to JavaScript, and then run the resulting |
| 578 * JavaScript. This function creates a working directory to hold the | 752 * JavaScript. This function creates a working directory to hold the |
| 579 * JavaScript version of the test, and copies the appropriate framework | 753 * JavaScript version of the test, and copies the appropriate framework |
| 580 * files to that directory. It creates a [BrowserTestCase], which has | 754 * files to that directory. It creates a [BrowserTestCase], which has |
| 581 * two sequential steps to be run by the [ProcessQueue] when the test is | 755 * two sequential steps to be run by the [ProcessQueue] when the test is |
| 582 * executed: a compilation | 756 * executed: a compilation |
| 583 * step and an execution step, both with the appropriate executable and | 757 * step and an execution step, both with the appropriate executable and |
| 584 * arguments. | 758 * arguments. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 743 var testCase = new BrowserTestCase('$suiteName/$testName', | 917 var testCase = new BrowserTestCase('$suiteName/$testName', |
| 744 commands, configuration, completeHandler, expectations, | 918 commands, configuration, completeHandler, expectations, |
| 745 info, info.hasCompileError || info.hasRuntimeError); | 919 info, info.hasCompileError || info.hasRuntimeError); |
| 746 doTest(testCase); | 920 doTest(testCase); |
| 747 } | 921 } |
| 748 } | 922 } |
| 749 | 923 |
| 750 /** Helper to create a compilation command for a single input file. */ | 924 /** Helper to create a compilation command for a single input file. */ |
| 751 Command _compileCommand(String inputFile, String outputFile, | 925 Command _compileCommand(String inputFile, String outputFile, |
| 752 String compiler, String dir, var vmOptions) { | 926 String compiler, String dir, var vmOptions) { |
| 753 String executable = TestUtils.compilerPath(configuration); | 927 String executable = compilerPath; |
| 754 List<String> args = TestUtils.standardOptions(configuration); | 928 List<String> args = TestUtils.standardOptions(configuration); |
| 755 switch (compiler) { | 929 switch (compiler) { |
| 756 case 'dart2js': | 930 case 'dart2js': |
| 757 case 'dart2dart': | 931 case 'dart2dart': |
| 758 if (compiler == 'dart2dart') args.add('--out=$outputFile'); | 932 if (compiler == 'dart2dart') args.add('--out=$outputFile'); |
| 759 args.add('--out=$outputFile'); | 933 args.add('--out=$outputFile'); |
| 760 args.add(inputFile); | 934 args.add(inputFile); |
| 761 break; | 935 break; |
| 762 default: | 936 default: |
| 763 Expect.fail('unimplemented compiler $compiler'); | 937 Expect.fail('unimplemented compiler $compiler'); |
| 764 } | 938 } |
| 765 if (executable.endsWith('.dart')) { | 939 if (executable.endsWith('.dart')) { |
| 766 // Run the compiler script via the Dart VM. | 940 // Run the compiler script via the Dart VM. |
| 767 args.insertRange(0, 1, executable); | 941 args.insertRange(0, 1, executable); |
| 768 executable = TestUtils.dartShellFileName(configuration); | 942 executable = dartShellFileName; |
| 769 } | 943 } |
| 770 return new Command(executable, args); | 944 return new Command(executable, args); |
| 771 } | 945 } |
| 772 | 946 |
| 773 /** | 947 /** |
| 774 * Create a directory for the generated test. If a Dart language test | 948 * Create a directory for the generated test. If a Dart language test |
| 775 * needs to be run in a browser, the Dart test needs to be embedded in | 949 * needs to be run in a browser, the Dart test needs to be embedded in |
| 776 * an HTML page, with a testing framework based on scripting and DOM events. | 950 * an HTML page, with a testing framework based on scripting and DOM events. |
| 777 * These scripts and pages are written to a generated_test directory | 951 * These scripts and pages are written to a generated_test directory |
| 778 * inside the build directory of the checkout. | 952 * inside the build directory of the checkout. |
| 779 * | 953 * |
| 780 * Those tests which are already HTML web applications (web tests), with | 954 * Those tests which are already HTML web applications (web tests), with |
| 781 * resources including CSS files and HTML files, need to be compiled into | 955 * resources including CSS files and HTML files, need to be compiled into |
| 782 * a work directory where the relative URLS to the resources work. | 956 * a work directory where the relative URLS to the resources work. |
| 783 * We use a subdirectory of the build directory that is the same number | 957 * We use a subdirectory of the build directory that is the same number |
| 784 * of levels down in the checkout as the original path of the web test. | 958 * of levels down in the checkout as the original path of the web test. |
| 785 */ | 959 */ |
| 786 String createOutputDirectory(Path testPath, String optionsName) { | 960 String createOutputDirectory(Path testPath, String optionsName) { |
| 787 Path relative = testPath.relativeTo(TestUtils.dartDir()); | 961 Path relative = testPath.relativeTo(TestUtils.dartDir()); |
| 788 relative = relative.directoryPath.append(relative.filenameWithoutExtension); | 962 relative = relative.directoryPath.append(relative.filenameWithoutExtension); |
| 789 String testUniqueName = relative.toString().replaceAll('/', '_'); | 963 String testUniqueName = relative.toString().replaceAll('/', '_'); |
| 790 if (!optionsName.isEmpty) { | 964 if (!optionsName.isEmpty) { |
| 791 testUniqueName = '$testUniqueName-$optionsName'; | 965 testUniqueName = '$testUniqueName-$optionsName'; |
| 792 } | 966 } |
| 793 | 967 |
| 794 // Create '[build dir]/generated_tests/$compiler-$runtime/$testUniqueName', | 968 // Create '[build dir]/generated_tests/$compiler-$runtime/$testUniqueName', |
| 795 // including any intermediate directories that don't exist. | 969 // including any intermediate directories that don't exist. |
| 796 var generatedTestPath = Strings.join( | 970 var generatedTestPath = Strings.join([ |
| 797 [TestUtils.buildDir(configuration), | 971 buildDir, |
| 798 'generated_tests', | 972 'generated_tests', |
| 799 "${configuration['compiler']}-${configuration['runtime']}", | 973 "${configuration['compiler']}-${configuration['runtime']}", |
| 800 testUniqueName], '/'); | 974 testUniqueName |
| 975 ], '/'); | |
| 801 | 976 |
| 802 TestUtils.mkdirRecursive(new Path('.'), new Path(generatedTestPath)); | 977 TestUtils.mkdirRecursive(new Path('.'), new Path(generatedTestPath)); |
| 803 return new File(generatedTestPath).fullPathSync().replaceAll('\\', '/'); | 978 return new File(generatedTestPath).fullPathSync().replaceAll('\\', '/'); |
| 804 } | 979 } |
| 805 | 980 |
| 806 String get scriptType { | 981 String get scriptType { |
| 807 switch (configuration['compiler']) { | 982 switch (configuration['compiler']) { |
| 808 case 'none': | 983 case 'none': |
| 809 case 'dart2dart': | 984 case 'dart2dart': |
| 810 return 'application/dart'; | 985 return 'application/dart'; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 851 if (configuration['dartium'] != '') { | 1026 if (configuration['dartium'] != '') { |
| 852 return configuration['dartium']; | 1027 return configuration['dartium']; |
| 853 } | 1028 } |
| 854 if (Platform.operatingSystem == 'macos') { | 1029 if (Platform.operatingSystem == 'macos') { |
| 855 return dartDir.append('client/tests/dartium/Chromium.app/Contents/' | 1030 return dartDir.append('client/tests/dartium/Chromium.app/Contents/' |
| 856 'MacOS/Chromium').toNativePath(); | 1031 'MacOS/Chromium').toNativePath(); |
| 857 } | 1032 } |
| 858 return dartDir.append('client/tests/dartium/chrome').toNativePath(); | 1033 return dartDir.append('client/tests/dartium/chrome').toNativePath(); |
| 859 } | 1034 } |
| 860 | 1035 |
| 861 void testGeneratorStarted() { | |
| 862 ++activeTestGenerators; | |
| 863 } | |
| 864 | |
| 865 void testGeneratorDone() { | |
| 866 --activeTestGenerators; | |
| 867 if (activeTestGenerators == 0 && listingDone) { | |
| 868 doDone(); | |
| 869 } | |
| 870 } | |
| 871 | |
| 872 void directoryListingDone(ignore) { | |
| 873 listingDone = true; | |
| 874 if (activeTestGenerators == 0) { | |
| 875 doDone(); | |
| 876 } | |
| 877 } | |
| 878 | |
| 879 void completeHandler(TestCase testCase) { | 1036 void completeHandler(TestCase testCase) { |
| 880 } | 1037 } |
| 881 | 1038 |
| 882 List<String> commonArgumentsFromFile(Path filePath, Map optionsFromFile) { | 1039 List<String> commonArgumentsFromFile(Path filePath, Map optionsFromFile) { |
| 883 List args = TestUtils.standardOptions(configuration); | 1040 List args = TestUtils.standardOptions(configuration); |
| 884 args.addAll(additionalOptions(filePath)); | 1041 args.addAll(additionalOptions(filePath)); |
| 885 if (configuration['compiler'] == 'dartc') { | 1042 if (configuration['compiler'] == 'dartc') { |
| 886 args.add('--error_format'); | 1043 args.add('--error_format'); |
| 887 args.add('machine'); | 1044 args.add('machine'); |
| 888 } | 1045 } |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1060 "containsLeadingHash": containsLeadingHash, | 1217 "containsLeadingHash": containsLeadingHash, |
| 1061 "isolateStubs": isolateStubs, | 1218 "isolateStubs": isolateStubs, |
| 1062 "containsDomImport": containsDomImport, | 1219 "containsDomImport": containsDomImport, |
| 1063 "isLibraryDefinition": isLibraryDefinition, | 1220 "isLibraryDefinition": isLibraryDefinition, |
| 1064 "containsSourceOrImport": containsSourceOrImport, | 1221 "containsSourceOrImport": containsSourceOrImport, |
| 1065 "numStaticTypeAnnotations": numStaticTypeAnnotations, | 1222 "numStaticTypeAnnotations": numStaticTypeAnnotations, |
| 1066 "numCompileTimeAnnotations": numCompileTimeAnnotations }; | 1223 "numCompileTimeAnnotations": numCompileTimeAnnotations }; |
| 1067 } | 1224 } |
| 1068 | 1225 |
| 1069 List<List<String>> getVmOptions(Map optionsFromFile) { | 1226 List<List<String>> getVmOptions(Map optionsFromFile) { |
| 1070 bool needsVmOptions = Contains(configuration['compiler'], | 1227 var COMPILERS = const ['none', 'dart2dart', 'dartc']; |
| 1071 const ['none', 'dart2dart', 'dartc']) && | 1228 var RUNTIMES = const ['none', 'vm', 'drt', 'dartium']; |
| 1072 Contains(configuration['runtime'], | 1229 var needsVmOptions = COMPILERS.contains(configuration['compiler']) && |
| 1073 const ['none', 'vm', 'drt', 'dartium']); | 1230 RUNTIMES.contains(configuration['runtime']); |
| 1074 if (!needsVmOptions) return [[]]; | 1231 if (!needsVmOptions) return [[]]; |
| 1075 return optionsFromFile['vmOptions']; | 1232 return optionsFromFile['vmOptions']; |
| 1076 } | 1233 } |
| 1077 } | 1234 } |
| 1078 | 1235 |
| 1079 | 1236 |
| 1080 class DartcCompilationTestSuite extends StandardTestSuite { | 1237 class DartcCompilationTestSuite extends StandardTestSuite { |
| 1081 List<String> _testDirs; | 1238 List<String> _testDirs; |
| 1082 int activityCount = 0; | |
| 1083 | 1239 |
| 1084 DartcCompilationTestSuite(Map configuration, | 1240 DartcCompilationTestSuite(Map configuration, |
| 1085 String suiteName, | 1241 String suiteName, |
| 1086 String directoryPath, | 1242 String directoryPath, |
| 1087 List<String> this._testDirs, | 1243 List<String> this._testDirs, |
| 1088 List<String> expectations) | 1244 List<String> expectations) |
| 1089 : super(configuration, | 1245 : super(configuration, |
| 1090 suiteName, | 1246 suiteName, |
| 1091 new Path.fromNative(directoryPath), | 1247 new Path.fromNative(directoryPath), |
| 1092 expectations); | 1248 expectations); |
| 1093 | 1249 |
| 1094 void activityStarted() { ++activityCount; } | |
| 1095 | |
| 1096 void activityCompleted() { | |
| 1097 if (--activityCount == 0) { | |
| 1098 directoryListingDone(true); | |
| 1099 } | |
| 1100 } | |
| 1101 | |
| 1102 String shellPath() => TestUtils.compilerPath(configuration); | |
| 1103 | |
| 1104 List<String> additionalOptions(Path filePath) { | 1250 List<String> additionalOptions(Path filePath) { |
| 1105 return ['--fatal-warnings', '--fatal-type-errors']; | 1251 return ['--fatal-warnings', '--fatal-type-errors']; |
| 1106 } | 1252 } |
| 1107 | 1253 |
| 1108 void processDirectory() { | 1254 Future enqueueTests() { |
| 1109 // Enqueueing the directory listers is an activity. | 1255 var group = new FutureGroup(); |
| 1110 activityStarted(); | 1256 |
| 1257 var listCompleter = new Completer(); | |
| 1258 group.add(listCompleter.future); | |
| 1259 | |
| 1111 for (String testDir in _testDirs) { | 1260 for (String testDir in _testDirs) { |
| 1112 Directory dir = new Directory.fromPath(suiteDir.append(testDir)); | 1261 Directory dir = new Directory.fromPath(suiteDir.append(testDir)); |
| 1113 if (dir.existsSync()) { | 1262 if (dir.existsSync()) { |
| 1114 activityStarted(); | 1263 enqueueDirectory(dir, group); |
| 1115 var lister = dir.list(recursive: listRecursively()); | |
| 1116 lister.onFile = processFile; | |
| 1117 lister.onDone = (ignore) => activityCompleted(); | |
| 1118 } | 1264 } |
| 1119 } | 1265 } |
| 1120 // Completed the enqueueing of listers. | 1266 |
| 1121 activityCompleted(); | 1267 return group.future; |
| 1122 } | 1268 } |
| 1123 } | 1269 } |
| 1124 | 1270 |
| 1125 | 1271 |
| 1126 class JUnitTestSuite implements TestSuite { | 1272 class JUnitTestSuite extends TestSuite { |
| 1127 Map configuration; | |
| 1128 String suiteName; | |
| 1129 String directoryPath; | 1273 String directoryPath; |
| 1130 String statusFilePath; | 1274 String statusFilePath; |
| 1131 final String dartDir; | 1275 final String dartDir; |
| 1132 String buildDir; | |
| 1133 String classPath; | 1276 String classPath; |
| 1134 List<String> testClasses; | 1277 List<String> testClasses; |
| 1135 TestCaseEvent doTest; | 1278 TestCaseEvent doTest; |
| 1136 VoidFunction doDone; | 1279 VoidFunction doDone; |
| 1137 TestExpectations testExpectations; | 1280 TestExpectations testExpectations; |
| 1138 | 1281 |
| 1139 JUnitTestSuite(Map this.configuration, | 1282 JUnitTestSuite(Map configuration, |
| 1140 String this.suiteName, | 1283 String suiteName, |
| 1141 String this.directoryPath, | 1284 String this.directoryPath, |
| 1142 String this.statusFilePath) | 1285 String this.statusFilePath) |
| 1143 : dartDir = TestUtils.dartDir().toNativePath(); | 1286 : super(configuration, suiteName), |
| 1287 dartDir = TestUtils.dartDir().toNativePath(); | |
| 1144 | 1288 |
| 1145 bool isTestFile(String filename) => filename.endsWith("Tests.java") && | 1289 bool isTestFile(String filename) => filename.endsWith("Tests.java") && |
| 1146 !filename.contains('com/google/dart/compiler/vm') && | 1290 !filename.contains('com/google/dart/compiler/vm') && |
| 1147 !filename.contains('com/google/dart/corelib/SharedTests.java'); | 1291 !filename.contains('com/google/dart/corelib/SharedTests.java'); |
| 1148 | 1292 |
| 1149 void forEachTest(TestCaseEvent onTest, | 1293 void forEachTest(TestCaseEvent onTest, |
| 1150 Map testCacheIgnored, | 1294 Map testCacheIgnored, |
| 1151 [VoidFunction onDone]) { | 1295 [VoidFunction onDone]) { |
| 1152 doTest = onTest; | 1296 doTest = onTest; |
| 1153 doDone = (onDone != null) ? onDone : (() => null); | 1297 doDone = onDone; |
| 1154 | 1298 |
| 1155 if (configuration['compiler'] != 'dartc') { | 1299 if (configuration['compiler'] != 'dartc') { |
| 1156 // Do nothing. Asynchronously report that the suite is enqueued. | 1300 // Do nothing. Asynchronously report that the suite is enqueued. |
| 1157 new Timer(0, (timerUnused){ doDone(); }); | 1301 asynchronously(doDone); |
| 1158 return; | 1302 return; |
| 1159 } | 1303 } |
| 1160 RegExp pattern = configuration['selectors']['dartc']; | 1304 RegExp pattern = configuration['selectors']['dartc']; |
| 1161 if (!pattern.hasMatch('junit_tests')) { | 1305 if (!pattern.hasMatch('junit_tests')) { |
| 1162 new Timer(0, (timerUnused){ doDone(); }); | 1306 asynchronously(doDone); |
| 1163 return; | 1307 return; |
| 1164 } | 1308 } |
| 1165 | 1309 |
| 1166 buildDir = TestUtils.buildDir(configuration); | |
| 1167 computeClassPath(); | 1310 computeClassPath(); |
| 1168 testClasses = <String>[]; | 1311 testClasses = <String>[]; |
| 1169 // Do not read the status file. | 1312 // Do not read the status file. |
| 1170 // All exclusions are hardcoded in this script, as they are in testcfg.py. | 1313 // All exclusions are hardcoded in this script, as they are in testcfg.py. |
| 1171 processDirectory(); | 1314 processDirectory(); |
| 1172 } | 1315 } |
| 1173 | 1316 |
| 1174 void processDirectory() { | 1317 void processDirectory() { |
| 1175 directoryPath = '$dartDir/$directoryPath'; | 1318 directoryPath = '$dartDir/$directoryPath'; |
| 1176 Directory dir = new Directory(directoryPath); | 1319 Directory dir = new Directory(directoryPath); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1231 '$dartDir/third_party/rhino/1_7R3/js.jar', | 1374 '$dartDir/third_party/rhino/1_7R3/js.jar', |
| 1232 '$dartDir/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar', | 1375 '$dartDir/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar', |
| 1233 '$dartDir/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar', | 1376 '$dartDir/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar', |
| 1234 '$dartDir/third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar', | 1377 '$dartDir/third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar', |
| 1235 '$dartDir/third_party/hamcrest/v1_3/hamcrest-library-1.3.0RC2.jar', | 1378 '$dartDir/third_party/hamcrest/v1_3/hamcrest-library-1.3.0RC2.jar', |
| 1236 '$dartDir/third_party/junit/v4_8_2/junit.jar'], | 1379 '$dartDir/third_party/junit/v4_8_2/junit.jar'], |
| 1237 Platform.operatingSystem == 'windows'? ';': ':'); // Path separator. | 1380 Platform.operatingSystem == 'windows'? ';': ':'); // Path separator. |
| 1238 } | 1381 } |
| 1239 } | 1382 } |
| 1240 | 1383 |
| 1241 | |
| 1242 class TestUtils { | 1384 class TestUtils { |
| 1243 /** | 1385 /** |
| 1244 * The libraries in this directory relies on finding various files | 1386 * The libraries in this directory relies on finding various files |
| 1245 * relative to the 'test.dart' script in '.../dart/tools/test.dart'. If | 1387 * relative to the 'test.dart' script in '.../dart/tools/test.dart'. If |
| 1246 * the main script using 'test_suite.dart' is not there, the main | 1388 * the main script using 'test_suite.dart' is not there, the main |
| 1247 * script must set this to '.../dart/tools/test.dart'. | 1389 * script must set this to '.../dart/tools/test.dart'. |
| 1248 */ | 1390 */ |
| 1249 static String testScriptPath = new Options().script; | 1391 static String testScriptPath = new Options().script; |
| 1250 | 1392 |
| 1251 /** | 1393 /** |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1273 * Assumes that the directory for [dest] already exists. | 1415 * Assumes that the directory for [dest] already exists. |
| 1274 */ | 1416 */ |
| 1275 static Future copyFile(Path source, Path dest) { | 1417 static Future copyFile(Path source, Path dest) { |
| 1276 var output = new File.fromPath(dest).openOutputStream(); | 1418 var output = new File.fromPath(dest).openOutputStream(); |
| 1277 new File.fromPath(source).openInputStream().pipe(output); | 1419 new File.fromPath(source).openInputStream().pipe(output); |
| 1278 var completer = new Completer(); | 1420 var completer = new Completer(); |
| 1279 output.onClosed = (){ completer.complete(null); }; | 1421 output.onClosed = (){ completer.complete(null); }; |
| 1280 return completer.future; | 1422 return completer.future; |
| 1281 } | 1423 } |
| 1282 | 1424 |
| 1283 static String executableSuffix(String executable) { | |
| 1284 if (Platform.operatingSystem == 'windows') { | |
| 1285 if (executable == 'd8' || executable == 'vm' || executable == 'none') { | |
| 1286 return '.exe'; | |
| 1287 } else { | |
| 1288 return '.bat'; | |
| 1289 } | |
| 1290 } | |
| 1291 return ''; | |
| 1292 } | |
| 1293 | |
| 1294 static String executableName(Map configuration) { | |
| 1295 String suffix = executableSuffix(configuration['compiler']); | |
| 1296 switch (configuration['compiler']) { | |
| 1297 case 'none': | |
| 1298 return 'dart$suffix'; | |
| 1299 case 'dartc': | |
| 1300 return 'analyzer/bin/dart_analyzer$suffix'; | |
| 1301 case 'dart2js': | |
| 1302 case 'dart2dart': | |
| 1303 var prefix = ''; | |
| 1304 if (configuration['use_sdk']) { | |
| 1305 prefix = 'dart-sdk/bin/'; | |
| 1306 } | |
| 1307 if (configuration['host_checked']) { | |
| 1308 // The script dart2js_developer is not in the SDK. | |
| 1309 return 'dart2js_developer$suffix'; | |
| 1310 } else { | |
| 1311 return '${prefix}dart2js$suffix'; | |
| 1312 } | |
| 1313 break; | |
| 1314 default: | |
| 1315 throw "Unknown executable for: ${configuration['compiler']}"; | |
| 1316 } | |
| 1317 } | |
| 1318 | |
| 1319 static String compilerName(Map configuration) { | |
| 1320 String suffix = executableSuffix(configuration['compiler']); | |
| 1321 switch (configuration['compiler']) { | |
| 1322 case 'dartc': | |
| 1323 case 'dart2js': | |
| 1324 case 'dart2dart': | |
| 1325 return executableName(configuration); | |
| 1326 default: | |
| 1327 throw "Unknown compiler for: ${configuration['compiler']}"; | |
| 1328 } | |
| 1329 } | |
| 1330 | |
| 1331 static String dartShellFileName(Map configuration) { | |
| 1332 var name = configuration['dart']; | |
| 1333 if (name == '') { | |
| 1334 name = '${buildDir(configuration)}/${executableName(configuration)}'; | |
| 1335 } | |
| 1336 ensureExists(name, configuration); | |
| 1337 return name; | |
| 1338 } | |
| 1339 | |
| 1340 static String d8FileName(Map configuration) { | |
| 1341 var suffix = executableSuffix('d8'); | |
| 1342 var d8 = '${buildDir(configuration)}/d8$suffix'; | |
| 1343 ensureExists(d8, configuration); | |
| 1344 return d8; | |
| 1345 } | |
| 1346 | |
| 1347 static String vmFileName(Map configuration) { | |
| 1348 var suffix = executableSuffix('vm'); | |
| 1349 var vm = '${buildDir(configuration)}/dart$suffix'; | |
| 1350 ensureExists(vm, configuration); | |
| 1351 return vm; | |
| 1352 } | |
| 1353 | |
| 1354 static void ensureExists(String filename, Map configuration) { | 1425 static void ensureExists(String filename, Map configuration) { |
| 1355 if (!configuration['list'] && !(new File(filename).existsSync())) { | 1426 if (!configuration['list'] && !(new File(filename).existsSync())) { |
| 1356 throw "Executable '$filename' does not exist"; | 1427 throw "Executable '$filename' does not exist"; |
| 1357 } | 1428 } |
| 1358 } | 1429 } |
| 1359 | 1430 |
| 1360 static String compilerPath(Map configuration) { | |
| 1361 if (configuration['compiler'] == 'none') { | |
| 1362 return null; // No separate compiler for dartium tests. | |
| 1363 } | |
| 1364 var name = '${buildDir(configuration)}/${compilerName(configuration)}'; | |
| 1365 if (!(new File(name)).existsSync() && !configuration['list']) { | |
| 1366 throw "Executable '$name' does not exist"; | |
| 1367 } | |
| 1368 return name; | |
| 1369 } | |
| 1370 | |
| 1371 static String outputDir(Map configuration) { | 1431 static String outputDir(Map configuration) { |
| 1372 var result = ''; | 1432 var result = ''; |
| 1373 var system = configuration['system']; | 1433 var system = configuration['system']; |
| 1374 if (system == 'linux') { | 1434 if (system == 'linux') { |
| 1375 result = 'out/'; | 1435 result = 'out/'; |
| 1376 } else if (system == 'macos') { | 1436 } else if (system == 'macos') { |
| 1377 result = 'xcodebuild/'; | 1437 result = 'xcodebuild/'; |
| 1378 } else if (system == 'windows') { | 1438 } else if (system == 'windows') { |
| 1379 result = 'build/'; | 1439 result = 'build/'; |
| 1380 } | 1440 } |
| 1381 return result; | 1441 return result; |
| 1382 } | 1442 } |
| 1383 | 1443 |
| 1384 static String buildDir(Map configuration) { | |
| 1385 String mode = (configuration['mode'] == 'debug') ? 'Debug' : 'Release'; | |
| 1386 String arch = configuration['arch'].toUpperCase(); | |
| 1387 return "${outputDir(configuration)}$mode$arch"; | |
| 1388 } | |
| 1389 | |
| 1390 static Path dartDir() { | 1444 static Path dartDir() { |
| 1391 File scriptFile = new File(testScriptPath); | 1445 File scriptFile = new File(testScriptPath); |
| 1392 Path scriptPath = new Path.fromNative(scriptFile.fullPathSync()); | 1446 Path scriptPath = new Path.fromNative(scriptFile.fullPathSync()); |
| 1393 return scriptPath.directoryPath.directoryPath; | 1447 return scriptPath.directoryPath.directoryPath; |
| 1394 } | 1448 } |
| 1395 | 1449 |
| 1396 static List<String> standardOptions(Map configuration) { | 1450 static List<String> standardOptions(Map configuration) { |
| 1397 List args = ["--ignore-unrecognized-flags"]; | 1451 List args = ["--ignore-unrecognized-flags"]; |
| 1398 if (configuration["checked"]) { | 1452 if (configuration["checked"]) { |
| 1399 args.add('--enable_asserts'); | 1453 args.add('--enable_asserts'); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1411 } | 1465 } |
| 1412 } | 1466 } |
| 1413 // TODO(riocw): Unify our minification calling convention between dart2js | 1467 // TODO(riocw): Unify our minification calling convention between dart2js |
| 1414 // and dart2dart. | 1468 // and dart2dart. |
| 1415 if (compiler == "dart2js" && configuration["minified"]) { | 1469 if (compiler == "dart2js" && configuration["minified"]) { |
| 1416 args.add("--minify"); | 1470 args.add("--minify"); |
| 1417 } | 1471 } |
| 1418 return args; | 1472 return args; |
| 1419 } | 1473 } |
| 1420 | 1474 |
| 1421 static String jsshellFileName(Map configuration) { | 1475 static bool usesWebDriver(String runtime) { |
| 1422 var executableSuffix = executableSuffix('jsshell'); | 1476 const BROWSERS = const [ |
| 1423 var executable = 'jsshell$executableSuffix'; | 1477 'dartium', |
| 1424 var jsshellDir = '${dartDir()}/tools/testing/bin'; | 1478 'ie9', |
| 1425 return '$jsshellDir/$executable'; | 1479 'ie10', |
| 1480 'safari', | |
| 1481 'opera', | |
| 1482 'chrome', | |
| 1483 'ff' | |
| 1484 ]; | |
| 1485 return BROWSERS.contains(runtime); | |
| 1426 } | 1486 } |
| 1427 | 1487 |
| 1428 static bool usesWebDriver(String runtime) => Contains( | |
| 1429 runtime, const <String>['dartium', | |
| 1430 'ie9', | |
| 1431 'ie10', | |
| 1432 'safari', | |
| 1433 'opera', | |
| 1434 'chrome', | |
| 1435 'ff']); | |
| 1436 | |
| 1437 static bool isBrowserRuntime(String runtime) => | 1488 static bool isBrowserRuntime(String runtime) => |
| 1438 runtime == 'drt' || TestUtils.usesWebDriver(runtime); | 1489 runtime == 'drt' || TestUtils.usesWebDriver(runtime); |
| 1439 | 1490 |
| 1440 static bool isJsCommandLineRuntime(String runtime) => | 1491 static bool isJsCommandLineRuntime(String runtime) => |
| 1441 Contains(runtime, const <String>['d8', 'jsshell']); | 1492 const ['d8', 'jsshell'].contains(runtime); |
| 1442 | 1493 |
| 1443 } | 1494 } |
| 1444 | 1495 |
| 1445 class SummaryReport { | 1496 class SummaryReport { |
| 1446 static int total = 0; | 1497 static int total = 0; |
| 1447 static int skipped = 0; | 1498 static int skipped = 0; |
| 1448 static int noCrash = 0; | 1499 static int noCrash = 0; |
| 1449 static int pass = 0; | 1500 static int pass = 0; |
| 1450 static int failOk = 0; | 1501 static int failOk = 0; |
| 1451 static int fail = 0; | 1502 static int fail = 0; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1493 * $pass tests are expected to pass | 1544 * $pass tests are expected to pass |
| 1494 * $failOk tests are expected to fail that we won't fix | 1545 * $failOk tests are expected to fail that we won't fix |
| 1495 * $fail tests are expected to fail that we should fix | 1546 * $fail tests are expected to fail that we should fix |
| 1496 * $crash tests are expected to crash that we should fix | 1547 * $crash tests are expected to crash that we should fix |
| 1497 * $timeout tests are allowed to timeout | 1548 * $timeout tests are allowed to timeout |
| 1498 * $compileErrorSkip tests are skipped on browsers due to compile-time error | 1549 * $compileErrorSkip tests are skipped on browsers due to compile-time error |
| 1499 """; | 1550 """; |
| 1500 print(report); | 1551 print(report); |
| 1501 } | 1552 } |
| 1502 } | 1553 } |
| OLD | NEW |