Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: tools/testing/dart/test_suite.dart

Issue 12608007: Reapply "Update the test runner to use the new dart:io API" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor fixes Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/testing/dart/test_runner.dart ('k') | tools/testing/dart/utils.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 45
46 /** 46 /**
47 * Calls [function] asynchronously. Returns a future that completes with the 47 * Calls [function] asynchronously. Returns a future that completes with the
48 * result of the function. If the function is `null`, returns a future that 48 * result of the function. If the function is `null`, returns a future that
49 * completes immediately with `null`. 49 * completes immediately with `null`.
50 */ 50 */
51 Future asynchronously(function()) { 51 Future asynchronously(function()) {
52 if (function == null) return new Future.immediate(null); 52 if (function == null) return new Future.immediate(null);
53 53
54 var completer = new Completer(); 54 var completer = new Completer();
55 new Timer(0, (_) { 55 Timer.run(() => completer.complete(function()));
56 completer.complete(function());
57 });
58 56
59 return completer.future; 57 return completer.future;
60 } 58 }
61 59
62 /** A completer that waits until all added [Future]s complete. */ 60 /** A completer that waits until all added [Future]s complete. */
63 // TODO(rnystrom): Copied from web_components. Remove from here when it gets 61 // TODO(rnystrom): Copied from web_components. Remove from here when it gets
64 // added to dart:core. (See #6626.) 62 // added to dart:core. (See #6626.)
65 class FutureGroup { 63 class FutureGroup {
66 const _FINISHED = -1; 64 const _FINISHED = -1;
67 int _pending = 0; 65 int _pending = 0;
68 Completer<List> _completer = new Completer<List>(); 66 Completer<List> _completer = new Completer<List>();
69 final List<Future> futures = <Future>[]; 67 final List<Future> futures = <Future>[];
70 bool wasCompleted = false; 68 bool wasCompleted = false;
71 69
72 /** 70 /**
73 * Wait for [task] to complete (assuming this barrier has not already been 71 * Wait for [task] to complete (assuming this barrier has not already been
74 * marked as completed, otherwise you'll get an exception indicating that a 72 * marked as completed, otherwise you'll get an exception indicating that a
75 * future has already been completed). 73 * future has already been completed).
76 */ 74 */
77 void add(Future task) { 75 void add(Future task) {
78 if (_pending == _FINISHED) { 76 if (_pending == _FINISHED) {
79 throw new Exception("FutureFutureAlreadyCompleteException"); 77 throw new Exception("FutureFutureAlreadyCompleteException");
80 } 78 }
81 _pending++; 79 _pending++;
82 var handledTaskFuture = task.catchError((e) { 80 var handledTaskFuture = task.catchError((e) {
83 if (!wasCompleted) { 81 if (!wasCompleted) {
84 _completer.completeError(e.error, task.stackTrace); 82 _completer.completeError(e.error, e.stackTrace);
85 wasCompleted = true; 83 wasCompleted = true;
86 } 84 }
87 }).then((_) { 85 }).then((_) {
88 _pending--; 86 _pending--;
89 if (_pending == 0) { 87 if (_pending == 0) {
90 _pending = _FINISHED; 88 _pending = _FINISHED;
91 if (!wasCompleted) { 89 if (!wasCompleted) {
92 _completer.complete(futures); 90 _completer.complete(futures);
93 wasCompleted = true; 91 wasCompleted = true;
94 } 92 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 */ 135 */
138 String get compilerPath { 136 String get compilerPath {
139 if (configuration['compiler'] == 'none') { 137 if (configuration['compiler'] == 'none') {
140 return null; // No separate compiler for dartium tests. 138 return null; // No separate compiler for dartium tests.
141 } 139 }
142 var name; 140 var name;
143 switch (configuration['compiler']) { 141 switch (configuration['compiler']) {
144 case 'dartc': 142 case 'dartc':
145 case 'new_analyzer': 143 case 'new_analyzer':
146 name = executablePath; 144 name = executablePath;
145 break;
147 case 'dart2js': 146 case 'dart2js':
148 case 'dart2dart': 147 case 'dart2dart':
149 var prefix = 'sdk/bin/'; 148 var prefix = 'sdk/bin/';
150 String suffix = getExecutableSuffix(configuration['compiler']); 149 String suffix = getExecutableSuffix(configuration['compiler']);
151 if (configuration['host_checked']) { 150 if (configuration['host_checked']) {
152 // The script dart2js_developer is not included in the 151 // The script dart2js_developer is not included in the
153 // shipped SDK, that is the script is not installed in 152 // shipped SDK, that is the script is not installed in
154 // "$buildDir/dart-sdk/bin/" 153 // "$buildDir/dart-sdk/bin/"
155 name = '$prefix/dart2js_developer$suffix'; 154 name = '$prefix/dart2js_developer$suffix';
156 } else { 155 } else {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 * cache information about the test suite, so that directories do not need 249 * cache information about the test suite, so that directories do not need
251 * to be listed each time. 250 * to be listed each time.
252 */ 251 */
253 void forEachTest(TestCaseEvent onTest, Map testCache, [VoidFunction onDone]); 252 void forEachTest(TestCaseEvent onTest, Map testCache, [VoidFunction onDone]);
254 } 253 }
255 254
256 255
257 void ccTestLister() { 256 void ccTestLister() {
258 port.receive((String runnerPath, SendPort replyTo) { 257 port.receive((String runnerPath, SendPort replyTo) {
259 Future processFuture = Process.start(runnerPath, ["--list"]); 258 Future processFuture = Process.start(runnerPath, ["--list"]);
260 processFuture.then((p) { 259 processFuture.then((Process p) {
261 // Drain stderr to not leak resources. 260 // Drain stderr to not leak resources.
262 p.stderr.onData = p.stderr.read; 261 p.stderr.listen((_) { });
263 StringInputStream stdoutStream = new StringInputStream(p.stdout); 262 Stream<String> stdoutStream =
263 p.stdout.transform(new StringDecoder())
264 .transform(new LineTransformer());
264 var streamDone = false; 265 var streamDone = false;
265 var processExited = false; 266 var processExited = false;
266 checkDone() { 267 checkDone() {
267 if (streamDone && processExited) { 268 if (streamDone && processExited) {
268 replyTo.send(""); 269 replyTo.send("");
269 } 270 }
270 } 271 }
271 stdoutStream.onLine = () { 272 stdoutStream.listen((String line) {
272 String line = stdoutStream.readLine();
273 replyTo.send(line); 273 replyTo.send(line);
274 }; 274 },
275 stdoutStream.onClosed = () { 275 onDone: () {
276 streamDone = true; 276 streamDone = true;
277 checkDone(); 277 checkDone();
278 }; 278 });
279 p.onExit = (code) { 279
280 p.exitCode.then((code) {
280 if (code < 0) { 281 if (code < 0) {
281 print("Failed to list tests: $runnerPath --list"); 282 print("Failed to list tests: $runnerPath --list");
282 replyTo.send(""); 283 replyTo.send("");
283 } else { 284 } else {
284 processExited = true; 285 processExited = true;
285 checkDone(); 286 checkDone();
286 } 287 }
287 }; 288 });
288 port.close(); 289 port.close();
289 }).catchError((e) { 290 }).catchError((e) {
290 print("Failed to list tests: $runnerPath --list"); 291 print("Failed to list tests: $runnerPath --list");
291 replyTo.send(""); 292 replyTo.send("");
292 return true; 293 return true;
293 }); 294 });
294 }); 295 });
295 } 296 }
296 297
297 298
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 enqueueDirectory(dir, group); 580 enqueueDirectory(dir, group);
580 return group.future; 581 return group.future;
581 } 582 }
582 }); 583 });
583 } 584 }
584 585
585 void enqueueDirectory(Directory dir, FutureGroup group) { 586 void enqueueDirectory(Directory dir, FutureGroup group) {
586 var listCompleter = new Completer(); 587 var listCompleter = new Completer();
587 group.add(listCompleter.future); 588 group.add(listCompleter.future);
588 589
589 var lister = dir.list(recursive: listRecursively); 590 var lister = dir.list(recursive: listRecursively)
590 lister.onFile = (file) => enqueueFile(file, group); 591 .listen((FileSystemEntity fse) {
591 lister.onDone = listCompleter.complete; 592 if (fse is File) enqueueFile(fse.path, group);
593 },
594 onDone: listCompleter.complete);
592 } 595 }
593 596
594 void enqueueFile(String filename, FutureGroup group) { 597 void enqueueFile(String filename, FutureGroup group) {
595 if (!isTestFile(filename)) return; 598 if (!isTestFile(filename)) return;
596 Path filePath = new Path(filename); 599 Path filePath = new Path(filename);
597 600
598 // Only run the tests that match the pattern. 601 // Only run the tests that match the pattern.
599 RegExp pattern = configuration['selectors'][suiteName]; 602 RegExp pattern = configuration['selectors'][suiteName];
600 if (!pattern.hasMatch('$filePath')) return; 603 if (!pattern.hasMatch('$filePath')) return;
601 if (filePath.filename.endsWith('test_config.dart')) return; 604 if (filePath.filename.endsWith('test_config.dart')) return;
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 830
828 var fileString = file.toString(); 831 var fileString = file.toString();
829 if (fileString.startsWith(buildDir.toString())) { 832 if (fileString.startsWith(buildDir.toString())) {
830 var fileRelativeToBuildDir = file.relativeTo(buildDir); 833 var fileRelativeToBuildDir = file.relativeTo(buildDir);
831 return "/$PREFIX_BUILDDIR/$fileRelativeToBuildDir"; 834 return "/$PREFIX_BUILDDIR/$fileRelativeToBuildDir";
832 } else if (fileString.startsWith(dartDir.toString())) { 835 } else if (fileString.startsWith(dartDir.toString())) {
833 var fileRelativeToDartDir = file.relativeTo(dartDir); 836 var fileRelativeToDartDir = file.relativeTo(dartDir);
834 return "/$PREFIX_DARTDIR/$fileRelativeToDartDir"; 837 return "/$PREFIX_DARTDIR/$fileRelativeToDartDir";
835 } 838 }
836 // Unreachable 839 // Unreachable
837 Except.fail('This should be unreachable.'); 840 Expect.fail('This should be unreachable.');
838 } 841 }
839 842
840 void _getUriForBrowserTest(TestInformation info, 843 String _getUriForBrowserTest(TestInformation info,
841 String pathComponent, 844 String pathComponent,
842 subtestNames, 845 subtestNames,
843 subtestIndex) { 846 subtestIndex) {
844 // Note: If we run test.py with the "--list" option, no http servers 847 // Note: If we run test.py with the "--list" option, no http servers
845 // will be started. So we use PORT/CROSS_ORIGIN_PORT instead of real ports. 848 // will be started. So we use PORT/CROSS_ORIGIN_PORT instead of real ports.
846 var serverPort = "PORT"; 849 var serverPort = "PORT";
847 var crossOriginPort = "CROSS_ORIGIN_PORT"; 850 var crossOriginPort = "CROSS_ORIGIN_PORT";
848 if (!configuration['list']) { 851 if (!configuration['list']) {
849 Expect.isTrue(configuration.containsKey('_servers_')); 852 Expect.isTrue(configuration.containsKey('_servers_'));
850 serverPort = configuration['_servers_'].port; 853 serverPort = configuration['_servers_'].port;
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after
1494 if (hasDynamicTypeError) { 1497 if (hasDynamicTypeError) {
1495 // TODO(ahe): Remove this warning when co19 no longer uses this tag. 1498 // TODO(ahe): Remove this warning when co19 no longer uses this tag.
1496 1499
1497 // @dynamic-type-error has been replaced by tests that use 1500 // @dynamic-type-error has been replaced by tests that use
1498 // tests/co19/src/Utils/dynamic_check.dart to dynamically detect 1501 // tests/co19/src/Utils/dynamic_check.dart to dynamically detect
1499 // if a test is running in checked mode or not and change its 1502 // if a test is running in checked mode or not and change its
1500 // expectations accordingly. 1503 // expectations accordingly.
1501 1504
1502 // Using stderr.writeString to avoid breaking dartc/junit_tests 1505 // Using stderr.writeString to avoid breaking dartc/junit_tests
1503 // which parses the output of the --list option. 1506 // which parses the output of the --list option.
1504 stderr.writeString( 1507 stderr.writeln(
1505 "Warning: deprecated @dynamic-type-error tag used in $filePath\n"); 1508 "Warning: deprecated @dynamic-type-error tag used in $filePath");
1506 } 1509 }
1507 1510
1508 return { 1511 return {
1509 "vmOptions": <List>[[]], 1512 "vmOptions": <List>[[]],
1510 "dartOptions": null, 1513 "dartOptions": null,
1511 "packageRoot": null, 1514 "packageRoot": null,
1512 "hasCompileError": hasCompileError, 1515 "hasCompileError": hasCompileError,
1513 "hasRuntimeError": hasRuntimeError, 1516 "hasRuntimeError": hasRuntimeError,
1514 "isStaticClean" : !hasStaticWarning, 1517 "isStaticClean" : !hasStaticWarning,
1515 "otherScripts": <String>[], 1518 "otherScripts": <String>[],
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1619 testClasses = <String>[]; 1622 testClasses = <String>[];
1620 // Do not read the status file. 1623 // Do not read the status file.
1621 // All exclusions are hardcoded in this script, as they are in testcfg.py. 1624 // All exclusions are hardcoded in this script, as they are in testcfg.py.
1622 processDirectory(); 1625 processDirectory();
1623 } 1626 }
1624 1627
1625 void processDirectory() { 1628 void processDirectory() {
1626 directoryPath = '$dartDir/$directoryPath'; 1629 directoryPath = '$dartDir/$directoryPath';
1627 Directory dir = new Directory(directoryPath); 1630 Directory dir = new Directory(directoryPath);
1628 1631
1629 var lister = dir.list(recursive: true); 1632 dir.list(recursive: true).listen((FileSystemEntity fse) {
1630 lister.onFile = processFile; 1633 if (fse is File) processFile(fse.path);
1631 lister.onDone = createTest; 1634 },
1635 onDone: createTest);
1632 } 1636 }
1633 1637
1634 void processFile(String filename) { 1638 void processFile(String filename) {
1635 if (!isTestFile(filename)) return; 1639 if (!isTestFile(filename)) return;
1636 1640
1637 int index = filename.indexOf('compiler/javatests/com/google/dart'); 1641 int index = filename.indexOf('compiler/javatests/com/google/dart');
1638 if (index != -1) { 1642 if (index != -1) {
1639 String testRelativePath = 1643 String testRelativePath =
1640 filename.substring(index + 'compiler/javatests/'.length, 1644 filename.substring(index + 'compiler/javatests/'.length,
1641 filename.length - '.java'.length); 1645 filename.length - '.java'.length);
1642 String testClass = testRelativePath.replaceAll('/', '.'); 1646 String testClass = testRelativePath.replaceAll('/', '.');
1643 testClasses.add(testClass); 1647 testClasses.add(testClass);
1644 } 1648 }
1645 } 1649 }
1646 1650
1647 void createTest(successIgnored) { 1651 void createTest() {
1648 var sdkDir = "$buildDir/dart-sdk".trim(); 1652 var sdkDir = "$buildDir/dart-sdk".trim();
1649 List<String> args = <String>[ 1653 List<String> args = <String>[
1650 '-ea', 1654 '-ea',
1651 '-classpath', classPath, 1655 '-classpath', classPath,
1652 '-Dcom.google.dart.sdk=$sdkDir', 1656 '-Dcom.google.dart.sdk=$sdkDir',
1653 '-Dcom.google.dart.corelib.SharedTests.test_py=$dartDir/tools/test.py', 1657 '-Dcom.google.dart.corelib.SharedTests.test_py=$dartDir/tools/test.py',
1654 'org.junit.runner.JUnitCore']; 1658 'org.junit.runner.JUnitCore'];
1655 args.addAll(testClasses); 1659 args.addAll(testClasses);
1656 1660
1657 // Lengthen the timeout for JUnit tests. It is normal for them 1661 // Lengthen the timeout for JUnit tests. It is normal for them
(...skipping 25 matching lines...) Expand all
1683 '$dartDir/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar', 1687 '$dartDir/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar',
1684 '$dartDir/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar', 1688 '$dartDir/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar',
1685 '$dartDir/third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar', 1689 '$dartDir/third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar',
1686 '$dartDir/third_party/hamcrest/v1_3/hamcrest-library-1.3.0RC2.jar', 1690 '$dartDir/third_party/hamcrest/v1_3/hamcrest-library-1.3.0RC2.jar',
1687 '$dartDir/third_party/junit/v4_8_2/junit.jar'] 1691 '$dartDir/third_party/junit/v4_8_2/junit.jar']
1688 .join(Platform.operatingSystem == 'windows'? ';': ':'); // Path separat or. 1692 .join(Platform.operatingSystem == 'windows'? ';': ':'); // Path separat or.
1689 } 1693 }
1690 } 1694 }
1691 1695
1692 class LastModifiedCache { 1696 class LastModifiedCache {
1693 Map<String, Date> _cache = <String, Date>{}; 1697 Map<String, DateTime> _cache = <String, DateTime>{};
1694 1698
1695 /** 1699 /**
1696 * Returns the last modified date of the given [uri]. 1700 * Returns the last modified date of the given [uri].
1697 * 1701 *
1698 * The return value will be cached for future queries. If [uri] is a local 1702 * The return value will be cached for future queries. If [uri] is a local
1699 * file, it's last modified [Date] will be returned. If the file does not 1703 * file, it's last modified [Date] will be returned. If the file does not
1700 * exist, null will be returned instead. 1704 * exist, null will be returned instead.
1701 * In case [uri] is not a local file, this method will always return 1705 * In case [uri] is not a local file, this method will always return
1702 * the current date. 1706 * the current date.
1703 */ 1707 */
1704 Date getLastModified(Uri uri) { 1708 DateTime getLastModified(Uri uri) {
1705 if (uri.scheme == "file") { 1709 if (uri.scheme == "file") {
1706 if (_cache.containsKey(uri.path)) { 1710 if (_cache.containsKey(uri.path)) {
1707 return _cache[uri.path]; 1711 return _cache[uri.path];
1708 } 1712 }
1709 var file = new File(new Path(uri.path).toNativePath()); 1713 var file = new File(new Path(uri.path).toNativePath());
1710 _cache[uri.path] = file.existsSync() ? file.lastModifiedSync() : null; 1714 _cache[uri.path] = file.existsSync() ? file.lastModifiedSync() : null;
1711 return _cache[uri.path]; 1715 return _cache[uri.path];
1712 } 1716 }
1713 return new Date.now(); 1717 return new Date.now();
1714 } 1718 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1752 Expect.isTrue(dir.existsSync(), "Failed to create ${dir.path}"); 1756 Expect.isTrue(dir.existsSync(), "Failed to create ${dir.path}");
1753 } 1757 }
1754 return dir; 1758 return dir;
1755 } 1759 }
1756 1760
1757 /** 1761 /**
1758 * Copy a [source] file to a new place. 1762 * Copy a [source] file to a new place.
1759 * Assumes that the directory for [dest] already exists. 1763 * Assumes that the directory for [dest] already exists.
1760 */ 1764 */
1761 static Future copyFile(Path source, Path dest) { 1765 static Future copyFile(Path source, Path dest) {
1762 var output = new File.fromPath(dest).openOutputStream(); 1766 return new File.fromPath(source).openRead()
1763 new File.fromPath(source).openInputStream().pipe(output); 1767 .pipe(new File.fromPath(dest).openWrite());
1764 var completer = new Completer();
1765 output.onClosed = (){ completer.complete(null); };
1766 return completer.future;
1767 } 1768 }
1768 1769
1769 static Path debugLogfile() { 1770 static Path debugLogfile() {
1770 return new Path(".debug.log"); 1771 return new Path(".debug.log");
1771 } 1772 }
1772 1773
1773 static String flakyFileName() { 1774 static String flakyFileName() {
1774 // If a flaky test did fail, infos about it (i.e. test name, stdin, stdout) 1775 // If a flaky test did fail, infos about it (i.e. test name, stdin, stdout)
1775 // will be written to this file. This is useful for the debugging of 1776 // will be written to this file. This is useful for the debugging of
1776 // flaky tests. 1777 // flaky tests.
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1960 * $pass tests are expected to pass 1961 * $pass tests are expected to pass
1961 * $failOk tests are expected to fail that we won't fix 1962 * $failOk tests are expected to fail that we won't fix
1962 * $fail tests are expected to fail that we should fix 1963 * $fail tests are expected to fail that we should fix
1963 * $crash tests are expected to crash that we should fix 1964 * $crash tests are expected to crash that we should fix
1964 * $timeout tests are allowed to timeout 1965 * $timeout tests are allowed to timeout
1965 * $compileErrorSkip tests are skipped on browsers due to compile-time error 1966 * $compileErrorSkip tests are skipped on browsers due to compile-time error
1966 """; 1967 """;
1967 print(report); 1968 print(report);
1968 } 1969 }
1969 } 1970 }
OLDNEW
« no previous file with comments | « tools/testing/dart/test_runner.dart ('k') | tools/testing/dart/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698