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 |