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

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

Issue 12417004: 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: 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
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 new Timer(new Duration(seconds: 0), () => completer.complete(function()));
kustermann 2013/03/13 13:37:56 Why not use 'Timer.run' (is there a difference to
Søren Gjesse 2013/03/13 15:17:18 Done.
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 644 matching lines...) Expand 10 before | Expand all | Expand 10 after
1495 if (hasDynamicTypeError) { 1498 if (hasDynamicTypeError) {
1496 // TODO(ahe): Remove this warning when co19 no longer uses this tag. 1499 // TODO(ahe): Remove this warning when co19 no longer uses this tag.
1497 1500
1498 // @dynamic-type-error has been replaced by tests that use 1501 // @dynamic-type-error has been replaced by tests that use
1499 // tests/co19/src/Utils/dynamic_check.dart to dynamically detect 1502 // tests/co19/src/Utils/dynamic_check.dart to dynamically detect
1500 // if a test is running in checked mode or not and change its 1503 // if a test is running in checked mode or not and change its
1501 // expectations accordingly. 1504 // expectations accordingly.
1502 1505
1503 // Using stderr.writeString to avoid breaking dartc/junit_tests 1506 // Using stderr.writeString to avoid breaking dartc/junit_tests
1504 // which parses the output of the --list option. 1507 // which parses the output of the --list option.
1505 stderr.writeString( 1508 stderr.writeln(
1506 "Warning: deprecated @dynamic-type-error tag used in $filePath\n"); 1509 "Warning: deprecated @dynamic-type-error tag used in $filePath");
1507 } 1510 }
1508 1511
1509 return { 1512 return {
1510 "vmOptions": <List>[[]], 1513 "vmOptions": <List>[[]],
1511 "dartOptions": null, 1514 "dartOptions": null,
1512 "packageRoot": null, 1515 "packageRoot": null,
1513 "hasCompileError": hasCompileError, 1516 "hasCompileError": hasCompileError,
1514 "hasRuntimeError": hasRuntimeError, 1517 "hasRuntimeError": hasRuntimeError,
1515 "isStaticClean" : !hasStaticWarning, 1518 "isStaticClean" : !hasStaticWarning,
1516 "otherScripts": <String>[], 1519 "otherScripts": <String>[],
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1620 testClasses = <String>[]; 1623 testClasses = <String>[];
1621 // Do not read the status file. 1624 // Do not read the status file.
1622 // All exclusions are hardcoded in this script, as they are in testcfg.py. 1625 // All exclusions are hardcoded in this script, as they are in testcfg.py.
1623 processDirectory(); 1626 processDirectory();
1624 } 1627 }
1625 1628
1626 void processDirectory() { 1629 void processDirectory() {
1627 directoryPath = '$dartDir/$directoryPath'; 1630 directoryPath = '$dartDir/$directoryPath';
1628 Directory dir = new Directory(directoryPath); 1631 Directory dir = new Directory(directoryPath);
1629 1632
1630 var lister = dir.list(recursive: true); 1633 dir.list(recursive: true).listen((FileSystemEntity fse) {
1631 lister.onFile = processFile; 1634 if (fse is File) processFile(fse.path);
1632 lister.onDone = createTest; 1635 },
1636 onDone: createTest);
1633 } 1637 }
1634 1638
1635 void processFile(String filename) { 1639 void processFile(String filename) {
1636 if (!isTestFile(filename)) return; 1640 if (!isTestFile(filename)) return;
1637 1641
1638 int index = filename.indexOf('compiler/javatests/com/google/dart'); 1642 int index = filename.indexOf('compiler/javatests/com/google/dart');
1639 if (index != -1) { 1643 if (index != -1) {
1640 String testRelativePath = 1644 String testRelativePath =
1641 filename.substring(index + 'compiler/javatests/'.length, 1645 filename.substring(index + 'compiler/javatests/'.length,
1642 filename.length - '.java'.length); 1646 filename.length - '.java'.length);
1643 String testClass = testRelativePath.replaceAll('/', '.'); 1647 String testClass = testRelativePath.replaceAll('/', '.');
1644 testClasses.add(testClass); 1648 testClasses.add(testClass);
1645 } 1649 }
1646 } 1650 }
1647 1651
1648 void createTest(successIgnored) { 1652 void createTest() {
1649 var sdkDir = "$buildDir/dart-sdk".trim(); 1653 var sdkDir = "$buildDir/dart-sdk".trim();
1650 List<String> args = <String>[ 1654 List<String> args = <String>[
1651 '-ea', 1655 '-ea',
1652 '-classpath', classPath, 1656 '-classpath', classPath,
1653 '-Dcom.google.dart.sdk=$sdkDir', 1657 '-Dcom.google.dart.sdk=$sdkDir',
1654 '-Dcom.google.dart.corelib.SharedTests.test_py=$dartDir/tools/test.py', 1658 '-Dcom.google.dart.corelib.SharedTests.test_py=$dartDir/tools/test.py',
1655 'org.junit.runner.JUnitCore']; 1659 'org.junit.runner.JUnitCore'];
1656 args.addAll(testClasses); 1660 args.addAll(testClasses);
1657 1661
1658 // Lengthen the timeout for JUnit tests. It is normal for them 1662 // Lengthen the timeout for JUnit tests. It is normal for them
(...skipping 25 matching lines...) Expand all
1684 '$dartDir/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar', 1688 '$dartDir/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar',
1685 '$dartDir/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar', 1689 '$dartDir/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar',
1686 '$dartDir/third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar', 1690 '$dartDir/third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar',
1687 '$dartDir/third_party/hamcrest/v1_3/hamcrest-library-1.3.0RC2.jar', 1691 '$dartDir/third_party/hamcrest/v1_3/hamcrest-library-1.3.0RC2.jar',
1688 '$dartDir/third_party/junit/v4_8_2/junit.jar'] 1692 '$dartDir/third_party/junit/v4_8_2/junit.jar']
1689 .join(Platform.operatingSystem == 'windows'? ';': ':'); // Path separat or. 1693 .join(Platform.operatingSystem == 'windows'? ';': ':'); // Path separat or.
1690 } 1694 }
1691 } 1695 }
1692 1696
1693 class LastModifiedCache { 1697 class LastModifiedCache {
1694 Map<String, Date> _cache = <String, Date>{}; 1698 Map<String, DateTime> _cache = <String, DateTime>{};
1695 1699
1696 /** 1700 /**
1697 * Returns the last modified date of the given [uri]. 1701 * Returns the last modified date of the given [uri].
1698 * 1702 *
1699 * The return value will be cached for future queries. If [uri] is a local 1703 * The return value will be cached for future queries. If [uri] is a local
1700 * file, it's last modified [Date] will be returned. If the file does not 1704 * file, it's last modified [Date] will be returned. If the file does not
1701 * exist, null will be returned instead. 1705 * exist, null will be returned instead.
1702 * In case [uri] is not a local file, this method will always return 1706 * In case [uri] is not a local file, this method will always return
1703 * the current date. 1707 * the current date.
1704 */ 1708 */
1705 Date getLastModified(Uri uri) { 1709 DateTime getLastModified(Uri uri) {
1706 if (uri.scheme == "file") { 1710 if (uri.scheme == "file") {
1707 if (_cache.containsKey(uri.path)) { 1711 if (_cache.containsKey(uri.path)) {
1708 return _cache[uri.path]; 1712 return _cache[uri.path];
1709 } 1713 }
1710 var file = new File(new Path(uri.path).toNativePath()); 1714 var file = new File(new Path(uri.path).toNativePath());
1711 _cache[uri.path] = file.existsSync() ? file.lastModifiedSync() : null; 1715 _cache[uri.path] = file.existsSync() ? file.lastModifiedSync() : null;
1712 return _cache[uri.path]; 1716 return _cache[uri.path];
1713 } 1717 }
1714 return new Date.now(); 1718 return new Date.now();
1715 } 1719 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1753 Expect.isTrue(dir.existsSync(), "Failed to create ${dir.path}"); 1757 Expect.isTrue(dir.existsSync(), "Failed to create ${dir.path}");
1754 } 1758 }
1755 return dir; 1759 return dir;
1756 } 1760 }
1757 1761
1758 /** 1762 /**
1759 * Copy a [source] file to a new place. 1763 * Copy a [source] file to a new place.
1760 * Assumes that the directory for [dest] already exists. 1764 * Assumes that the directory for [dest] already exists.
1761 */ 1765 */
1762 static Future copyFile(Path source, Path dest) { 1766 static Future copyFile(Path source, Path dest) {
1763 var output = new File.fromPath(dest).openOutputStream(); 1767 return new File.fromPath(source).openRead()
1764 new File.fromPath(source).openInputStream().pipe(output); 1768 .pipe(new File.fromPath(dest).openWrite());
1765 var completer = new Completer();
1766 output.onClosed = (){ completer.complete(null); };
1767 return completer.future;
1768 } 1769 }
1769 1770
1770 static Path debugLogfile() { 1771 static Path debugLogfile() {
1771 return new Path(".debug.log"); 1772 return new Path(".debug.log");
1772 } 1773 }
1773 1774
1774 static String flakyFileName() { 1775 static String flakyFileName() {
1775 // If a flaky test did fail, infos about it (i.e. test name, stdin, stdout) 1776 // If a flaky test did fail, infos about it (i.e. test name, stdin, stdout)
1776 // will be written to this file. This is useful for the debugging of 1777 // will be written to this file. This is useful for the debugging of
1777 // flaky tests. 1778 // flaky tests.
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1961 * $pass tests are expected to pass 1962 * $pass tests are expected to pass
1962 * $failOk tests are expected to fail that we won't fix 1963 * $failOk tests are expected to fail that we won't fix
1963 * $fail tests are expected to fail that we should fix 1964 * $fail tests are expected to fail that we should fix
1964 * $crash tests are expected to crash that we should fix 1965 * $crash tests are expected to crash that we should fix
1965 * $timeout tests are allowed to timeout 1966 * $timeout tests are allowed to timeout
1966 * $compileErrorSkip tests are skipped on browsers due to compile-time error 1967 * $compileErrorSkip tests are skipped on browsers due to compile-time error
1967 """; 1968 """;
1968 print(report); 1969 print(report);
1969 } 1970 }
1970 } 1971 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698