| 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 /// Test infrastructure for testing pub. Unlike typical unit tests, most pub | 5 /// Test infrastructure for testing pub. Unlike typical unit tests, most pub |
| 6 /// tests are integration tests that stage some stuff on the file system, run | 6 /// tests are integration tests that stage some stuff on the file system, run |
| 7 /// pub, and then validate the results. This library provides an API to build | 7 /// pub, and then validate the results. This library provides an API to build |
| 8 /// tests like that. | 8 /// tests like that. |
| 9 library test_pub; | 9 library test_pub; |
| 10 | 10 |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 'Pub returned exit code ${result.exitCode}, expected $exitCode.'); | 585 'Pub returned exit code ${result.exitCode}, expected $exitCode.'); |
| 586 } | 586 } |
| 587 | 587 |
| 588 if (failures.length > 0) { | 588 if (failures.length > 0) { |
| 589 if (error == null) { | 589 if (error == null) { |
| 590 // If we aren't validating the error, still show it on failure. | 590 // If we aren't validating the error, still show it on failure. |
| 591 failures.add('Pub stderr:'); | 591 failures.add('Pub stderr:'); |
| 592 failures.addAll(result.stderr.map((line) => '| $line')); | 592 failures.addAll(result.stderr.map((line) => '| $line')); |
| 593 } | 593 } |
| 594 | 594 |
| 595 throw new ExpectException(failures.join('\n')); | 595 throw new TestFailure(failures.join('\n')); |
| 596 } | 596 } |
| 597 | 597 |
| 598 return null; | 598 return null; |
| 599 }); | 599 }); |
| 600 }); | 600 }); |
| 601 } | 601 } |
| 602 | 602 |
| 603 /// Starts a Pub process and returns a [ScheduledProcess] that supports | 603 /// Starts a Pub process and returns a [ScheduledProcess] that supports |
| 604 /// interaction with that process. | 604 /// interaction with that process. |
| 605 /// | 605 /// |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 | 862 |
| 863 /// Validates that at least one file in [dir] matching [name] is valid | 863 /// Validates that at least one file in [dir] matching [name] is valid |
| 864 /// according to [validate]. [validate] should throw or complete to an | 864 /// according to [validate]. [validate] should throw or complete to an |
| 865 /// exception if the input path is invalid. | 865 /// exception if the input path is invalid. |
| 866 Future _validateOneMatch(String dir, Future validate(String entry)) { | 866 Future _validateOneMatch(String dir, Future validate(String entry)) { |
| 867 // Special-case strings to support multi-level names like "myapp/packages". | 867 // Special-case strings to support multi-level names like "myapp/packages". |
| 868 if (name is String) { | 868 if (name is String) { |
| 869 var entry = path.join(dir, name); | 869 var entry = path.join(dir, name); |
| 870 return defer(() { | 870 return defer(() { |
| 871 if (!entryExists(entry)) { | 871 if (!entryExists(entry)) { |
| 872 throw new ExpectException('Entry $entry not found.'); | 872 throw new TestFailure('Entry $entry not found.'); |
| 873 } | 873 } |
| 874 return validate(entry); | 874 return validate(entry); |
| 875 }); | 875 }); |
| 876 } | 876 } |
| 877 | 877 |
| 878 // TODO(nweiz): remove this when issue 4061 is fixed. | 878 // TODO(nweiz): remove this when issue 4061 is fixed. |
| 879 var stackTrace; | 879 var stackTrace; |
| 880 try { | 880 try { |
| 881 throw ""; | 881 throw ""; |
| 882 } catch (_, localStackTrace) { | 882 } catch (_, localStackTrace) { |
| 883 stackTrace = localStackTrace; | 883 stackTrace = localStackTrace; |
| 884 } | 884 } |
| 885 | 885 |
| 886 return listDir(dir).then((files) { | 886 return listDir(dir).then((files) { |
| 887 var matches = files.where((file) => endsWithPattern(file, name)).toList(); | 887 var matches = files.where((file) => endsWithPattern(file, name)).toList(); |
| 888 if (matches.isEmpty) { | 888 if (matches.isEmpty) { |
| 889 throw new ExpectException('No files in $dir match pattern $name.'); | 889 throw new TestFailure('No files in $dir match pattern $name.'); |
| 890 } | 890 } |
| 891 if (matches.length == 1) return validate(matches[0]); | 891 if (matches.length == 1) return validate(matches[0]); |
| 892 | 892 |
| 893 var failures = []; | 893 var failures = []; |
| 894 var successes = 0; | 894 var successes = 0; |
| 895 var completer = new Completer(); | 895 var completer = new Completer(); |
| 896 checkComplete() { | 896 checkComplete() { |
| 897 if (failures.length + successes != matches.length) return; | 897 if (failures.length + successes != matches.length) return; |
| 898 if (successes > 0) { | 898 if (successes > 0) { |
| 899 completer.complete(); | 899 completer.complete(); |
| 900 return; | 900 return; |
| 901 } | 901 } |
| 902 | 902 |
| 903 var error = new StringBuffer(); | 903 var error = new StringBuffer(); |
| 904 error.add("No files named $name in $dir were valid:\n"); | 904 error.add("No files named $name in $dir were valid:\n"); |
| 905 for (var failure in failures) { | 905 for (var failure in failures) { |
| 906 error.add(" $failure\n"); | 906 error.add(" $failure\n"); |
| 907 } | 907 } |
| 908 completer.completeError( | 908 completer.completeError( |
| 909 new ExpectException(error.toString()), stackTrace); | 909 new TestFailure(error.toString()), stackTrace); |
| 910 } | 910 } |
| 911 | 911 |
| 912 for (var match in matches) { | 912 for (var match in matches) { |
| 913 var future = validate(match).then((_) { | 913 var future = validate(match).then((_) { |
| 914 successes++; | 914 successes++; |
| 915 checkComplete(); | 915 checkComplete(); |
| 916 }).catchError((e) { | 916 }).catchError((e) { |
| 917 failures.add(e); | 917 failures.add(e); |
| 918 checkComplete(); | 918 checkComplete(); |
| 919 }); | 919 }); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 946 /// the deletion is done. | 946 /// the deletion is done. |
| 947 Future delete(dir) => | 947 Future delete(dir) => |
| 948 defer(() => deleteFile(path.join(dir, _stringName))); | 948 defer(() => deleteFile(path.join(dir, _stringName))); |
| 949 | 949 |
| 950 /// Validates that this file correctly matches the actual file at [path]. | 950 /// Validates that this file correctly matches the actual file at [path]. |
| 951 Future validate(String path) { | 951 Future validate(String path) { |
| 952 return _validateOneMatch(path, (file) { | 952 return _validateOneMatch(path, (file) { |
| 953 var text = readTextFile(file); | 953 var text = readTextFile(file); |
| 954 if (text == textContents) return null; | 954 if (text == textContents) return null; |
| 955 | 955 |
| 956 throw new ExpectException( | 956 throw new TestFailure( |
| 957 'File $file should contain:\n\n$textContents\n\n' | 957 'File $file should contain:\n\n$textContents\n\n' |
| 958 'but contained:\n\n$text'); | 958 'but contained:\n\n$text'); |
| 959 }); | 959 }); |
| 960 } | 960 } |
| 961 | 961 |
| 962 /// Loads the contents of the file. | 962 /// Loads the contents of the file. |
| 963 ByteStream load(List<String> path) { | 963 ByteStream load(List<String> path) { |
| 964 if (!path.isEmpty) { | 964 if (!path.isEmpty) { |
| 965 throw "Can't load ${path.join('/')} from within $name: not a directory."; | 965 throw "Can't load ${path.join('/')} from within $name: not a directory."; |
| 966 } | 966 } |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1176 /// A descriptor that validates that no file exists with the given name. | 1176 /// A descriptor that validates that no file exists with the given name. |
| 1177 class NothingDescriptor extends Descriptor { | 1177 class NothingDescriptor extends Descriptor { |
| 1178 NothingDescriptor(String name) : super(name); | 1178 NothingDescriptor(String name) : super(name); |
| 1179 | 1179 |
| 1180 Future create(dir) => new Future.immediate(null); | 1180 Future create(dir) => new Future.immediate(null); |
| 1181 Future delete(dir) => new Future.immediate(null); | 1181 Future delete(dir) => new Future.immediate(null); |
| 1182 | 1182 |
| 1183 Future validate(String dir) { | 1183 Future validate(String dir) { |
| 1184 return defer(() { | 1184 return defer(() { |
| 1185 if (entryExists(path.join(dir, name))) { | 1185 if (entryExists(path.join(dir, name))) { |
| 1186 throw new ExpectException('File $name in $dir should not exist.'); | 1186 throw new TestFailure('File $name in $dir should not exist.'); |
| 1187 } | 1187 } |
| 1188 }); | 1188 }); |
| 1189 } | 1189 } |
| 1190 | 1190 |
| 1191 ByteStream load(List<String> path) { | 1191 ByteStream load(List<String> path) { |
| 1192 if (path.isEmpty) { | 1192 if (path.isEmpty) { |
| 1193 throw "Can't load the contents of $name: it doesn't exist."; | 1193 throw "Can't load the contents of $name: it doesn't exist."; |
| 1194 } else { | 1194 } else { |
| 1195 throw "Can't load ${path.join('/')} from within $name: $name doesn't " | 1195 throw "Can't load ${path.join('/')} from within $name: $name doesn't " |
| 1196 "exist."; | 1196 "exist."; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1353 // Sleep for half a second in case _endExpected is set in the next | 1353 // Sleep for half a second in case _endExpected is set in the next |
| 1354 // scheduled event. | 1354 // scheduled event. |
| 1355 return sleep(500).then((_) { | 1355 return sleep(500).then((_) { |
| 1356 if (_endExpected) { | 1356 if (_endExpected) { |
| 1357 _exitCodeCompleter.complete(exitCode); | 1357 _exitCodeCompleter.complete(exitCode); |
| 1358 return; | 1358 return; |
| 1359 } | 1359 } |
| 1360 | 1360 |
| 1361 return _printStreams(); | 1361 return _printStreams(); |
| 1362 }).then((_) { | 1362 }).then((_) { |
| 1363 registerException(new ExpectException("Process $name ended " | 1363 registerException(new TestFailure("Process $name ended " |
| 1364 "earlier than scheduled with exit code $exitCode")); | 1364 "earlier than scheduled with exit code $exitCode")); |
| 1365 }); | 1365 }); |
| 1366 }).catchError((e) => registerException(e.error, e.stackTrace)); | 1366 }).catchError((e) => registerException(e.error, e.stackTrace)); |
| 1367 }); | 1367 }); |
| 1368 | 1368 |
| 1369 _scheduleOnException((_) { | 1369 _scheduleOnException((_) { |
| 1370 if (_process == null) return; | 1370 if (_process == null) return; |
| 1371 | 1371 |
| 1372 if (_exitCode == null) { | 1372 if (_exitCode == null) { |
| 1373 print("\nKilling process $name prematurely."); | 1373 print("\nKilling process $name prematurely."); |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1634 /// calling [completion] is unnecessary. | 1634 /// calling [completion] is unnecessary. |
| 1635 void expectLater(Future actual, matcher, {String reason, | 1635 void expectLater(Future actual, matcher, {String reason, |
| 1636 FailureHandler failureHandler, bool verbose: false}) { | 1636 FailureHandler failureHandler, bool verbose: false}) { |
| 1637 _schedule((_) { | 1637 _schedule((_) { |
| 1638 return actual.then((value) { | 1638 return actual.then((value) { |
| 1639 expect(value, matcher, reason: reason, failureHandler: failureHandler, | 1639 expect(value, matcher, reason: reason, failureHandler: failureHandler, |
| 1640 verbose: false); | 1640 verbose: false); |
| 1641 }); | 1641 }); |
| 1642 }); | 1642 }); |
| 1643 } | 1643 } |
| OLD | NEW |