| 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, |
| 11 * and creating [TestCase]s for those files that meet the relevant criteria. | 11 * and creating [TestCase]s for those files that meet the relevant criteria. |
| 12 * - Preparing tests, including copying files and frameworks to temporary | 12 * - Preparing tests, including copying files and frameworks to temporary |
| 13 * directories, and computing the command line and arguments to be run. | 13 * directories, and computing the command line and arguments to be run. |
| 14 */ | 14 */ |
| 15 library test_suite; | 15 library test_suite; |
| 16 | 16 |
| 17 import "dart:async"; | 17 import "dart:async"; |
| 18 import "dart:convert" show LineSplitter, UTF8; | 18 import "dart:convert" show LineSplitter, UTF8; |
| 19 import "dart:io"; | 19 import "dart:io"; |
| 20 import "dart:isolate"; | |
| 21 import "drt_updater.dart"; | 20 import "drt_updater.dart"; |
| 22 import "multitest.dart"; | 21 import "multitest.dart"; |
| 23 import "status_file_parser.dart"; | 22 import "status_file_parser.dart"; |
| 24 import "test_runner.dart"; | 23 import "test_runner.dart"; |
| 25 import "utils.dart"; | 24 import "utils.dart"; |
| 26 import "http_server.dart" show PREFIX_BUILDDIR, PREFIX_DARTDIR; | 25 import "http_server.dart" show PREFIX_BUILDDIR, PREFIX_DARTDIR; |
| 27 | 26 |
| 28 part "browser_test.dart"; | 27 part "browser_test.dart"; |
| 29 | 28 |
| 30 | 29 |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 } | 319 } |
| 321 | 320 |
| 322 var testName = "$directory"; | 321 var testName = "$directory"; |
| 323 testName = concat(testName, "$filenameWithoutExt"); | 322 testName = concat(testName, "$filenameWithoutExt"); |
| 324 testName = concat(testName, multitestName); | 323 testName = concat(testName, multitestName); |
| 325 return testName; | 324 return testName; |
| 326 } | 325 } |
| 327 } | 326 } |
| 328 | 327 |
| 329 | 328 |
| 330 void ccTestLister() { | 329 Future<Iterable<String>> ccTestLister(String runnerPath) { |
| 331 port.receive((String runnerPath, SendPort replyTo) { | 330 return Process.run(runnerPath, ["--list"]).then((ProcessResult result) { |
| 332 Future processFuture = Process.start(runnerPath, ["--list"]); | 331 if (result.exitCode != 0) { |
| 333 processFuture.then((Process p) { | 332 throw "Failed to list tests: '$runnerPath --list'. " |
| 334 // Drain stderr to not leak resources. | 333 "Process exited with ${result.exitCode}"; |
| 335 p.stderr.listen((_) { }); | 334 } |
| 336 Stream<String> stdoutStream = | 335 return result.stdout |
| 337 p.stdout.transform(UTF8.decoder) | 336 .split('\n') |
| 338 .transform(new LineSplitter()); | 337 .map((line) => line.trim()) |
| 339 var streamDone = false; | 338 .where((name) => name.length > 0); |
| 340 var processExited = false; | |
| 341 checkDone() { | |
| 342 if (streamDone && processExited) { | |
| 343 replyTo.send(""); | |
| 344 } | |
| 345 } | |
| 346 stdoutStream.listen((String line) { | |
| 347 replyTo.send(line); | |
| 348 }, | |
| 349 onDone: () { | |
| 350 streamDone = true; | |
| 351 checkDone(); | |
| 352 }); | |
| 353 | |
| 354 p.exitCode.then((code) { | |
| 355 if (code < 0) { | |
| 356 print("Failed to list tests: $runnerPath --list"); | |
| 357 replyTo.send(""); | |
| 358 } else { | |
| 359 processExited = true; | |
| 360 checkDone(); | |
| 361 } | |
| 362 }); | |
| 363 port.close(); | |
| 364 }).catchError((e) { | |
| 365 print("Failed to list tests: $runnerPath --list"); | |
| 366 replyTo.send(""); | |
| 367 return true; | |
| 368 }); | |
| 369 }); | 339 }); |
| 370 } | 340 } |
| 371 | 341 |
| 372 | 342 |
| 373 /** | 343 /** |
| 374 * A specialized [TestSuite] that runs tests written in C to unit test | 344 * A specialized [TestSuite] that runs tests written in C to unit test |
| 375 * the Dart virtual machine and its API. | 345 * the Dart virtual machine and its API. |
| 376 * | 346 * |
| 377 * The tests are compiled into a monolithic executable by the build step. | 347 * The tests are compiled into a monolithic executable by the build step. |
| 378 * The executable lists its tests when run with the --list command line flag. | 348 * The executable lists its tests when run with the --list command line flag. |
| 379 * Individual tests are run by specifying them on the command line. | 349 * Individual tests are run by specifying them on the command line. |
| 380 */ | 350 */ |
| 381 class CCTestSuite extends TestSuite { | 351 class CCTestSuite extends TestSuite { |
| 382 final String testPrefix; | 352 final String testPrefix; |
| 383 String targetRunnerPath; | 353 String targetRunnerPath; |
| 384 String hostRunnerPath; | 354 String hostRunnerPath; |
| 385 final String dartDir; | 355 final String dartDir; |
| 386 List<String> statusFilePaths; | 356 List<String> statusFilePaths; |
| 387 VoidFunction doDone; | 357 VoidFunction doDone; |
| 388 ReceivePort receiveTestName; | |
| 389 TestExpectations testExpectations; | 358 TestExpectations testExpectations; |
| 390 | 359 |
| 391 CCTestSuite(Map configuration, | 360 CCTestSuite(Map configuration, |
| 392 String suiteName, | 361 String suiteName, |
| 393 String runnerName, | 362 String runnerName, |
| 394 List<String> this.statusFilePaths, | 363 List<String> this.statusFilePaths, |
| 395 {this.testPrefix: ''}) | 364 {this.testPrefix: ''}) |
| 396 : super(configuration, suiteName), | 365 : super(configuration, suiteName), |
| 397 dartDir = TestUtils.dartDir().toNativePath() { | 366 dartDir = TestUtils.dartDir().toNativePath() { |
| 398 // For running the tests we use the given '$runnerName' binary | 367 // For running the tests we use the given '$runnerName' binary |
| 399 targetRunnerPath = '$buildDir/$runnerName'; | 368 targetRunnerPath = '$buildDir/$runnerName'; |
| 400 | 369 |
| 401 // For listing the tests we use the '$runnerName.host' binary if it exists | 370 // For listing the tests we use the '$runnerName.host' binary if it exists |
| 402 // and use '$runnerName' if it doesn't. | 371 // and use '$runnerName' if it doesn't. |
| 403 var binarySuffix = Platform.operatingSystem == 'windows' ? '.exe' : ''; | 372 var binarySuffix = Platform.operatingSystem == 'windows' ? '.exe' : ''; |
| 404 var hostBinary = '$targetRunnerPath.host$binarySuffix'; | 373 var hostBinary = '$targetRunnerPath.host$binarySuffix'; |
| 405 if (new File(hostBinary).existsSync()) { | 374 if (new File(hostBinary).existsSync()) { |
| 406 hostRunnerPath = hostBinary; | 375 hostRunnerPath = hostBinary; |
| 407 } else { | 376 } else { |
| 408 hostRunnerPath = targetRunnerPath; | 377 hostRunnerPath = targetRunnerPath; |
| 409 } | 378 } |
| 410 } | 379 } |
| 411 | 380 |
| 412 void testNameHandler(String testName, ignore) { | 381 void testNameHandler(String testName) { |
| 413 if (testName == "") { | 382 // Only run the tests that match the pattern. Use the name |
| 414 receiveTestName.close(); | 383 // "suiteName/testName" for cc tests. |
| 384 String constructedName = '$suiteName/$testPrefix$testName'; |
| 415 | 385 |
| 416 if (doDone != null) doDone(); | 386 var expectations = testExpectations.expectations( |
| 417 } else { | 387 '$testPrefix$testName'); |
| 418 // Only run the tests that match the pattern. Use the name | |
| 419 // "suiteName/testName" for cc tests. | |
| 420 String constructedName = '$suiteName/$testPrefix$testName'; | |
| 421 | 388 |
| 422 var expectations = testExpectations.expectations( | 389 var args = TestUtils.standardOptions(configuration); |
| 423 '$testPrefix$testName'); | 390 args.add(testName); |
| 424 | 391 |
| 425 var args = TestUtils.standardOptions(configuration); | 392 var command = CommandBuilder.instance.getCommand( |
| 426 args.add(testName); | 393 'run_vm_unittest', targetRunnerPath, args, configurationDir); |
| 427 | 394 enqueueNewTestCase( |
| 428 var command = CommandBuilder.instance.getCommand( | 395 new TestCase(constructedName, [command], configuration, expectations)); |
| 429 'run_vm_unittest', targetRunnerPath, args, configurationDir); | |
| 430 enqueueNewTestCase( | |
| 431 new TestCase(constructedName, | |
| 432 [command], | |
| 433 configuration, | |
| 434 expectations)); | |
| 435 } | |
| 436 } | 396 } |
| 437 | 397 |
| 438 void forEachTest(Function onTest, Map testCache, [VoidFunction onDone]) { | 398 void forEachTest(Function onTest, Map testCache, [VoidFunction onDone]) { |
| 439 doTest = onTest; | 399 doTest = onTest; |
| 440 doDone = onDone; | 400 doDone = onDone; |
| 441 | 401 |
| 442 var filesRead = 0; | 402 var filesRead = 0; |
| 443 void statusFileRead() { | 403 void statusFileRead() { |
| 444 filesRead++; | 404 filesRead++; |
| 445 if (filesRead == statusFilePaths.length) { | 405 if (filesRead == statusFilePaths.length) { |
| 446 receiveTestName = new ReceivePort(); | 406 ccTestLister(hostRunnerPath).then((Iterable<String> names) { |
| 447 var port = spawnFunction(ccTestLister); | 407 names.forEach(testNameHandler); |
| 448 port.send(hostRunnerPath, receiveTestName.toSendPort()); | 408 onDone(); |
| 449 receiveTestName.receive(testNameHandler); | 409 }).catchError((error) { |
| 410 print("Fatal error occured: $error"); |
| 411 exit(1); |
| 412 }); |
| 450 } | 413 } |
| 451 } | 414 } |
| 452 | 415 |
| 453 testExpectations = new TestExpectations(); | 416 testExpectations = new TestExpectations(); |
| 454 for (var statusFilePath in statusFilePaths) { | 417 for (var statusFilePath in statusFilePaths) { |
| 455 ReadTestExpectationsInto(testExpectations, | 418 ReadTestExpectationsInto(testExpectations, |
| 456 '$dartDir/$statusFilePath', | 419 '$dartDir/$statusFilePath', |
| 457 configuration, | 420 configuration, |
| 458 statusFileRead); | 421 statusFileRead); |
| 459 } | 422 } |
| (...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1226 if (!optionsName.isEmpty) { | 1189 if (!optionsName.isEmpty) { |
| 1227 testUniqueName = '$testUniqueName-$optionsName'; | 1190 testUniqueName = '$testUniqueName-$optionsName'; |
| 1228 } | 1191 } |
| 1229 | 1192 |
| 1230 Path generatedTestPath = new Path(buildDir) | 1193 Path generatedTestPath = new Path(buildDir) |
| 1231 .append('generated_$name') | 1194 .append('generated_$name') |
| 1232 .append(dirname) | 1195 .append(dirname) |
| 1233 .append(testUniqueName); | 1196 .append(testUniqueName); |
| 1234 | 1197 |
| 1235 TestUtils.mkdirRecursive(new Path('.'), generatedTestPath); | 1198 TestUtils.mkdirRecursive(new Path('.'), generatedTestPath); |
| 1236 return new File(generatedTestPath.toNativePath()).fullPathSync() | 1199 return new File(generatedTestPath.toNativePath()).absolute.path |
| 1237 .replaceAll('\\', '/'); | 1200 .replaceAll('\\', '/'); |
| 1238 } | 1201 } |
| 1239 | 1202 |
| 1240 String get scriptType { | 1203 String get scriptType { |
| 1241 switch (configuration['compiler']) { | 1204 switch (configuration['compiler']) { |
| 1242 case 'none': | 1205 case 'none': |
| 1243 case 'dart2dart': | 1206 case 'dart2dart': |
| 1244 return 'application/dart'; | 1207 return 'application/dart'; |
| 1245 case 'dart2js': | 1208 case 'dart2js': |
| 1246 case 'dartanalyzer': | 1209 case 'dartanalyzer': |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1702 | 1665 |
| 1703 // Lengthen the timeout for JUnit tests. It is normal for them | 1666 // Lengthen the timeout for JUnit tests. It is normal for them |
| 1704 // to run for a few minutes. | 1667 // to run for a few minutes. |
| 1705 Map updatedConfiguration = new Map(); | 1668 Map updatedConfiguration = new Map(); |
| 1706 configuration.forEach((key, value) { | 1669 configuration.forEach((key, value) { |
| 1707 updatedConfiguration[key] = value; | 1670 updatedConfiguration[key] = value; |
| 1708 }); | 1671 }); |
| 1709 updatedConfiguration['timeout'] *= 3; | 1672 updatedConfiguration['timeout'] *= 3; |
| 1710 var command = CommandBuilder.instance.getCommand( | 1673 var command = CommandBuilder.instance.getCommand( |
| 1711 'junit_test', 'java', args, configurationDir); | 1674 'junit_test', 'java', args, configurationDir); |
| 1712 enqueueNewTestCase(new TestCase(suiteName, | 1675 enqueueNewTestCase( |
| 1713 [command], | 1676 new TestCase(suiteName, |
| 1714 updatedConfiguration, | 1677 [command], |
| 1715 new Set<String>.from([PASS]))); | 1678 updatedConfiguration, |
| 1679 new Set<Expectation>.from([Expectation.PASS]))); |
| 1716 doDone(); | 1680 doDone(); |
| 1717 } | 1681 } |
| 1718 | 1682 |
| 1719 void computeClassPath() { | 1683 void computeClassPath() { |
| 1720 classPath = | 1684 classPath = |
| 1721 ['$buildDir/analyzer/util/analyzer/dart_analyzer.jar', | 1685 ['$buildDir/analyzer/util/analyzer/dart_analyzer.jar', |
| 1722 '$buildDir/analyzer/dart_analyzer_tests.jar', | 1686 '$buildDir/analyzer/dart_analyzer_tests.jar', |
| 1723 // Third party libraries. | 1687 // Third party libraries. |
| 1724 '$dartDir/third_party/args4j/2.0.12/args4j-2.0.12.jar', | 1688 '$dartDir/third_party/args4j/2.0.12/args4j-2.0.12.jar', |
| 1725 '$dartDir/third_party/guava/r13/guava-13.0.1.jar', | 1689 '$dartDir/third_party/guava/r13/guava-13.0.1.jar', |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1758 } | 1722 } |
| 1759 } | 1723 } |
| 1760 | 1724 |
| 1761 class TestUtils { | 1725 class TestUtils { |
| 1762 /** | 1726 /** |
| 1763 * The libraries in this directory relies on finding various files | 1727 * The libraries in this directory relies on finding various files |
| 1764 * relative to the 'test.dart' script in '.../dart/tools/test.dart'. If | 1728 * relative to the 'test.dart' script in '.../dart/tools/test.dart'. If |
| 1765 * the main script using 'test_suite.dart' is not there, the main | 1729 * the main script using 'test_suite.dart' is not there, the main |
| 1766 * script must set this to '.../dart/tools/test.dart'. | 1730 * script must set this to '.../dart/tools/test.dart'. |
| 1767 */ | 1731 */ |
| 1768 static String testScriptPath = new Options().script; | 1732 static String testScriptPath = Platform.script.path; |
| 1769 static LastModifiedCache lastModifiedCache = new LastModifiedCache(); | 1733 static LastModifiedCache lastModifiedCache = new LastModifiedCache(); |
| 1770 static Path currentWorkingDirectory = | 1734 static Path currentWorkingDirectory = |
| 1771 new Path(Directory.current.path); | 1735 new Path(Directory.current.path); |
| 1772 /** | 1736 /** |
| 1773 * Creates a directory using a [relativePath] to an existing | 1737 * Creates a directory using a [relativePath] to an existing |
| 1774 * [base] directory if that [relativePath] does not already exist. | 1738 * [base] directory if that [relativePath] does not already exist. |
| 1775 */ | 1739 */ |
| 1776 static Directory mkdirRecursive(Path base, Path relativePath) { | 1740 static Directory mkdirRecursive(Path base, Path relativePath) { |
| 1777 if (relativePath.isAbsolute) { | 1741 if (relativePath.isAbsolute) { |
| 1778 base = new Path('/'); | 1742 base = new Path('/'); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1840 } else if (system == 'macos') { | 1804 } else if (system == 'macos') { |
| 1841 result = 'xcodebuild/'; | 1805 result = 'xcodebuild/'; |
| 1842 } else if (system == 'windows') { | 1806 } else if (system == 'windows') { |
| 1843 result = 'build/'; | 1807 result = 'build/'; |
| 1844 } | 1808 } |
| 1845 return result; | 1809 return result; |
| 1846 } | 1810 } |
| 1847 | 1811 |
| 1848 static Path dartDir() { | 1812 static Path dartDir() { |
| 1849 File scriptFile = new File(testScriptPath); | 1813 File scriptFile = new File(testScriptPath); |
| 1850 Path scriptPath = new Path(scriptFile.fullPathSync()); | 1814 Path scriptPath = new Path(scriptFile.absolute.path); |
| 1851 return scriptPath.directoryPath.directoryPath; | 1815 return scriptPath.directoryPath.directoryPath; |
| 1852 } | 1816 } |
| 1853 | 1817 |
| 1854 static List<String> standardOptions(Map configuration) { | 1818 static List<String> standardOptions(Map configuration) { |
| 1855 List args = ["--ignore-unrecognized-flags"]; | 1819 List args = ["--ignore-unrecognized-flags"]; |
| 1856 if (configuration["checked"]) { | 1820 if (configuration["checked"]) { |
| 1857 args.add('--enable_asserts'); | 1821 args.add('--enable_asserts'); |
| 1858 args.add("--enable_type_checks"); | 1822 args.add("--enable_type_checks"); |
| 1859 } | 1823 } |
| 1860 String compiler = configuration["compiler"]; | 1824 String compiler = configuration["compiler"]; |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2024 * $pass tests are expected to pass | 1988 * $pass tests are expected to pass |
| 2025 * $failOk tests are expected to fail that we won't fix | 1989 * $failOk tests are expected to fail that we won't fix |
| 2026 * $fail tests are expected to fail that we should fix | 1990 * $fail tests are expected to fail that we should fix |
| 2027 * $crash tests are expected to crash that we should fix | 1991 * $crash tests are expected to crash that we should fix |
| 2028 * $timeout tests are allowed to timeout | 1992 * $timeout tests are allowed to timeout |
| 2029 * $compileErrorSkip tests are skipped on browsers due to compile-time error | 1993 * $compileErrorSkip tests are skipped on browsers due to compile-time error |
| 2030 """; | 1994 """; |
| 2031 print(report); | 1995 print(report); |
| 2032 } | 1996 } |
| 2033 } | 1997 } |
| OLD | NEW |