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 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 versions[version] = yaml(spec); | 183 versions[version] = yaml(spec); |
184 } | 184 } |
185 | 185 |
186 _servedPackageDir.contents.clear(); | 186 _servedPackageDir.contents.clear(); |
187 for (var name in _servedPackages.keys) { | 187 for (var name in _servedPackages.keys) { |
188 var versions = _servedPackages[name].keys.toList(); | 188 var versions = _servedPackages[name].keys.toList(); |
189 _servedPackageDir.contents.addAll([ | 189 _servedPackageDir.contents.addAll([ |
190 file('$name.json', | 190 file('$name.json', |
191 json.stringify({'versions': versions})), | 191 json.stringify({'versions': versions})), |
192 dir(name, [ | 192 dir(name, [ |
193 dir('versions', flatten(versions.mappedBy((version) { | 193 dir('versions', flatten(versions.map((version) { |
194 return [ | 194 return [ |
195 file('$version.yaml', _servedPackages[name][version]), | 195 file('$version.yaml', _servedPackages[name][version]), |
196 tar('$version.tar.gz', [ | 196 tar('$version.tar.gz', [ |
197 file('pubspec.yaml', _servedPackages[name][version]), | 197 file('pubspec.yaml', _servedPackages[name][version]), |
198 libDir(name, '$name $version') | 198 libDir(name, '$name $version') |
199 ]) | 199 ]) |
200 ]; | 200 ]; |
201 }))) | 201 }))) |
202 ]) | 202 ]) |
203 ]); | 203 ]); |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 | 522 |
523 if (result.exitCode != exitCode) { | 523 if (result.exitCode != exitCode) { |
524 failures.add( | 524 failures.add( |
525 'Pub returned exit code ${result.exitCode}, expected $exitCode.'); | 525 'Pub returned exit code ${result.exitCode}, expected $exitCode.'); |
526 } | 526 } |
527 | 527 |
528 if (failures.length > 0) { | 528 if (failures.length > 0) { |
529 if (error == null) { | 529 if (error == null) { |
530 // If we aren't validating the error, still show it on failure. | 530 // If we aren't validating the error, still show it on failure. |
531 failures.add('Pub stderr:'); | 531 failures.add('Pub stderr:'); |
532 failures.addAll(result.stderr.mappedBy((line) => '| $line')); | 532 failures.addAll(result.stderr.map((line) => '| $line')); |
533 } | 533 } |
534 | 534 |
535 throw new ExpectException(Strings.join(failures, '\n')); | 535 throw new ExpectException(Strings.join(failures, '\n')); |
536 } | 536 } |
537 | 537 |
538 return null; | 538 return null; |
539 }); | 539 }); |
540 }); | 540 }); |
541 } | 541 } |
542 | 542 |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 | 694 |
695 void _validateOutputRegex(List<String> failures, String pipe, | 695 void _validateOutputRegex(List<String> failures, String pipe, |
696 RegExp expected, List<String> actual) { | 696 RegExp expected, List<String> actual) { |
697 var actualText = Strings.join(actual, '\n'); | 697 var actualText = Strings.join(actual, '\n'); |
698 if (actualText.contains(expected)) return; | 698 if (actualText.contains(expected)) return; |
699 | 699 |
700 if (actual.length == 0) { | 700 if (actual.length == 0) { |
701 failures.add('Expected $pipe to match "${expected.pattern}" but got none.'); | 701 failures.add('Expected $pipe to match "${expected.pattern}" but got none.'); |
702 } else { | 702 } else { |
703 failures.add('Expected $pipe to match "${expected.pattern}" but got:'); | 703 failures.add('Expected $pipe to match "${expected.pattern}" but got:'); |
704 failures.addAll(actual.mappedBy((line) => '| $line')); | 704 failures.addAll(actual.map((line) => '| $line')); |
705 } | 705 } |
706 } | 706 } |
707 | 707 |
708 void _validateOutputString(List<String> failures, String pipe, | 708 void _validateOutputString(List<String> failures, String pipe, |
709 String expectedText, List<String> actual) { | 709 String expectedText, List<String> actual) { |
710 final expected = expectedText.split('\n'); | 710 final expected = expectedText.split('\n'); |
711 | 711 |
712 // Strip off the last line. This lets us have expected multiline strings | 712 // Strip off the last line. This lets us have expected multiline strings |
713 // where the closing ''' is on its own line. It also fixes '' expected output | 713 // where the closing ''' is on its own line. It also fixes '' expected output |
714 // to expect zero lines of output, not a single empty line. | 714 // to expect zero lines of output, not a single empty line. |
(...skipping 24 matching lines...) Expand all Loading... |
739 } else { | 739 } else { |
740 // Output is OK, but include it in case other lines are wrong. | 740 // Output is OK, but include it in case other lines are wrong. |
741 results.add('| ${actual[i]}'); | 741 results.add('| ${actual[i]}'); |
742 } | 742 } |
743 } | 743 } |
744 } | 744 } |
745 | 745 |
746 // If any lines mismatched, show the expected and actual. | 746 // If any lines mismatched, show the expected and actual. |
747 if (failed) { | 747 if (failed) { |
748 failures.add('Expected $pipe:'); | 748 failures.add('Expected $pipe:'); |
749 failures.addAll(expected.mappedBy((line) => '| $line')); | 749 failures.addAll(expected.map((line) => '| $line')); |
750 failures.add('Got:'); | 750 failures.add('Got:'); |
751 failures.addAll(results); | 751 failures.addAll(results); |
752 } | 752 } |
753 } | 753 } |
754 | 754 |
755 /// Base class for [FileDescriptor] and [DirectoryDescriptor] so that a | 755 /// Base class for [FileDescriptor] and [DirectoryDescriptor] so that a |
756 /// directory can contain a heterogeneous collection of files and | 756 /// directory can contain a heterogeneous collection of files and |
757 /// subdirectories. | 757 /// subdirectories. |
758 abstract class Descriptor { | 758 abstract class Descriptor { |
759 /// The name of this file or directory. This must be a [String] if the file | 759 /// The name of this file or directory. This must be a [String] if the file |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 | 923 |
924 /// Creates the file within [dir]. Returns a [Future] that is completed after | 924 /// Creates the file within [dir]. Returns a [Future] that is completed after |
925 /// the creation is done. | 925 /// the creation is done. |
926 Future<Directory> create(parentDir) { | 926 Future<Directory> create(parentDir) { |
927 // Create the directory. | 927 // Create the directory. |
928 return ensureDir(join(parentDir, _stringName)).then((dir) { | 928 return ensureDir(join(parentDir, _stringName)).then((dir) { |
929 if (contents == null) return new Future<Directory>.immediate(dir); | 929 if (contents == null) return new Future<Directory>.immediate(dir); |
930 | 930 |
931 // Recursively create all of its children. | 931 // Recursively create all of its children. |
932 final childFutures = | 932 final childFutures = |
933 contents.mappedBy((child) => child.create(dir)).toList(); | 933 contents.map((child) => child.create(dir)).toList(); |
934 // Only complete once all of the children have been created too. | 934 // Only complete once all of the children have been created too. |
935 return Future.wait(childFutures).then((_) => dir); | 935 return Future.wait(childFutures).then((_) => dir); |
936 }); | 936 }); |
937 } | 937 } |
938 | 938 |
939 /// Deletes the directory within [dir]. Returns a [Future] that is completed | 939 /// Deletes the directory within [dir]. Returns a [Future] that is completed |
940 /// after the deletion is done. | 940 /// after the deletion is done. |
941 Future delete(dir) { | 941 Future delete(dir) { |
942 return deleteDir(join(dir, _stringName)); | 942 return deleteDir(join(dir, _stringName)); |
943 } | 943 } |
944 | 944 |
945 /// Validates that the directory at [path] contains all of the expected | 945 /// Validates that the directory at [path] contains all of the expected |
946 /// contents in this descriptor. Note that this does *not* check that the | 946 /// contents in this descriptor. Note that this does *not* check that the |
947 /// directory doesn't contain other unexpected stuff, just that it *does* | 947 /// directory doesn't contain other unexpected stuff, just that it *does* |
948 /// contain the stuff we do expect. | 948 /// contain the stuff we do expect. |
949 Future validate(String path) { | 949 Future validate(String path) { |
950 return _validateOneMatch(path, (dir) { | 950 return _validateOneMatch(path, (dir) { |
951 // Validate each of the items in this directory. | 951 // Validate each of the items in this directory. |
952 final entryFutures = | 952 final entryFutures = |
953 contents.mappedBy((entry) => entry.validate(dir)).toList(); | 953 contents.map((entry) => entry.validate(dir)).toList(); |
954 | 954 |
955 // If they are all valid, the directory is valid. | 955 // If they are all valid, the directory is valid. |
956 return Future.wait(entryFutures).then((entries) => null); | 956 return Future.wait(entryFutures).then((entries) => null); |
957 }); | 957 }); |
958 } | 958 } |
959 | 959 |
960 /// Loads [path] from within this directory. | 960 /// Loads [path] from within this directory. |
961 InputStream load(List<String> path) { | 961 InputStream load(List<String> path) { |
962 if (path.isEmpty) { | 962 if (path.isEmpty) { |
963 throw "Can't load the contents of $name: is a directory."; | 963 throw "Can't load the contents of $name: is a directory."; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 TarFileDescriptor(Pattern name, this.contents) | 1075 TarFileDescriptor(Pattern name, this.contents) |
1076 : super(name); | 1076 : super(name); |
1077 | 1077 |
1078 /// Creates the files and directories within this tar file, then archives | 1078 /// Creates the files and directories within this tar file, then archives |
1079 /// them, compresses them, and saves the result to [parentDir]. | 1079 /// them, compresses them, and saves the result to [parentDir]. |
1080 Future<File> create(parentDir) { | 1080 Future<File> create(parentDir) { |
1081 // TODO(rnystrom): Use withTempDir(). | 1081 // TODO(rnystrom): Use withTempDir(). |
1082 var tempDir; | 1082 var tempDir; |
1083 return createTempDir().then((_tempDir) { | 1083 return createTempDir().then((_tempDir) { |
1084 tempDir = _tempDir; | 1084 tempDir = _tempDir; |
1085 return Future.wait(contents.mappedBy((child) => child.create(tempDir))); | 1085 return Future.wait(contents.map((child) => child.create(tempDir))); |
1086 }).then((createdContents) { | 1086 }).then((createdContents) { |
1087 return consumeInputStream(createTarGz(createdContents, baseDir: tempDir)); | 1087 return consumeInputStream(createTarGz(createdContents, baseDir: tempDir)); |
1088 }).then((bytes) { | 1088 }).then((bytes) { |
1089 return new File(join(parentDir, _stringName)).writeAsBytes(bytes); | 1089 return new File(join(parentDir, _stringName)).writeAsBytes(bytes); |
1090 }).then((file) { | 1090 }).then((file) { |
1091 return deleteDir(tempDir).then((_) => file); | 1091 return deleteDir(tempDir).then((_) => file); |
1092 }); | 1092 }); |
1093 } | 1093 } |
1094 | 1094 |
1095 /// Validates that the `.tar.gz` file at [path] contains the expected | 1095 /// Validates that the `.tar.gz` file at [path] contains the expected |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1486 } | 1486 } |
1487 } | 1487 } |
1488 | 1488 |
1489 /// Takes a simple data structure (composed of [Map]s, [List]s, scalar objects, | 1489 /// Takes a simple data structure (composed of [Map]s, [List]s, scalar objects, |
1490 /// and [Future]s) and recursively resolves all the [Future]s contained within. | 1490 /// and [Future]s) and recursively resolves all the [Future]s contained within. |
1491 /// Completes with the fully resolved structure. | 1491 /// Completes with the fully resolved structure. |
1492 Future _awaitObject(object) { | 1492 Future _awaitObject(object) { |
1493 // Unroll nested futures. | 1493 // Unroll nested futures. |
1494 if (object is Future) return object.then(_awaitObject); | 1494 if (object is Future) return object.then(_awaitObject); |
1495 if (object is Collection) { | 1495 if (object is Collection) { |
1496 return Future.wait(object.mappedBy(_awaitObject).toList()); | 1496 return Future.wait(object.map(_awaitObject).toList()); |
1497 } | 1497 } |
1498 if (object is! Map) return new Future.immediate(object); | 1498 if (object is! Map) return new Future.immediate(object); |
1499 | 1499 |
1500 var pairs = <Future<Pair>>[]; | 1500 var pairs = <Future<Pair>>[]; |
1501 object.forEach((key, value) { | 1501 object.forEach((key, value) { |
1502 pairs.add(_awaitObject(value) | 1502 pairs.add(_awaitObject(value) |
1503 .then((resolved) => new Pair(key, resolved))); | 1503 .then((resolved) => new Pair(key, resolved))); |
1504 }); | 1504 }); |
1505 return Future.wait(pairs).then((resolvedPairs) { | 1505 return Future.wait(pairs).then((resolvedPairs) { |
1506 var map = {}; | 1506 var map = {}; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 /// calling [completion] is unnecessary. | 1550 /// calling [completion] is unnecessary. |
1551 void expectLater(Future actual, matcher, {String reason, | 1551 void expectLater(Future actual, matcher, {String reason, |
1552 FailureHandler failureHandler, bool verbose: false}) { | 1552 FailureHandler failureHandler, bool verbose: false}) { |
1553 _schedule((_) { | 1553 _schedule((_) { |
1554 return actual.then((value) { | 1554 return actual.then((value) { |
1555 expect(value, matcher, reason: reason, failureHandler: failureHandler, | 1555 expect(value, matcher, reason: reason, failureHandler: failureHandler, |
1556 verbose: false); | 1556 verbose: false); |
1557 }); | 1557 }); |
1558 }); | 1558 }); |
1559 } | 1559 } |
OLD | NEW |