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 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 versions[version] = yaml(spec); | 182 versions[version] = yaml(spec); |
183 } | 183 } |
184 | 184 |
185 _servedPackageDir.contents.clear(); | 185 _servedPackageDir.contents.clear(); |
186 for (var name in _servedPackages.keys) { | 186 for (var name in _servedPackages.keys) { |
187 var versions = _servedPackages[name].keys.toList(); | 187 var versions = _servedPackages[name].keys.toList(); |
188 _servedPackageDir.contents.addAll([ | 188 _servedPackageDir.contents.addAll([ |
189 file('$name.json', | 189 file('$name.json', |
190 json.stringify({'versions': versions})), | 190 json.stringify({'versions': versions})), |
191 dir(name, [ | 191 dir(name, [ |
192 dir('versions', flatten(versions.mappedBy((version) { | 192 dir('versions', flatten(versions.map((version) { |
193 return [ | 193 return [ |
194 file('$version.yaml', _servedPackages[name][version]), | 194 file('$version.yaml', _servedPackages[name][version]), |
195 tar('$version.tar.gz', [ | 195 tar('$version.tar.gz', [ |
196 file('pubspec.yaml', _servedPackages[name][version]), | 196 file('pubspec.yaml', _servedPackages[name][version]), |
197 libDir(name, '$name $version') | 197 libDir(name, '$name $version') |
198 ]) | 198 ]) |
199 ]; | 199 ]; |
200 }))) | 200 }))) |
201 ]) | 201 ]) |
202 ]); | 202 ]); |
(...skipping 319 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 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 | 920 |
921 /// Creates the file within [dir]. Returns a [Future] that is completed after | 921 /// Creates the file within [dir]. Returns a [Future] that is completed after |
922 /// the creation is done. | 922 /// the creation is done. |
923 Future<Directory> create(parentDir) { | 923 Future<Directory> create(parentDir) { |
924 // Create the directory. | 924 // Create the directory. |
925 return ensureDir(join(parentDir, _stringName)).then((dir) { | 925 return ensureDir(join(parentDir, _stringName)).then((dir) { |
926 if (contents == null) return new Future<Directory>.immediate(dir); | 926 if (contents == null) return new Future<Directory>.immediate(dir); |
927 | 927 |
928 // Recursively create all of its children. | 928 // Recursively create all of its children. |
929 final childFutures = | 929 final childFutures = |
930 contents.mappedBy((child) => child.create(dir)).toList(); | 930 contents.map((child) => child.create(dir)).toList(); |
931 // Only complete once all of the children have been created too. | 931 // Only complete once all of the children have been created too. |
932 return Future.wait(childFutures).then((_) => dir); | 932 return Future.wait(childFutures).then((_) => dir); |
933 }); | 933 }); |
934 } | 934 } |
935 | 935 |
936 /// Deletes the directory within [dir]. Returns a [Future] that is completed | 936 /// Deletes the directory within [dir]. Returns a [Future] that is completed |
937 /// after the deletion is done. | 937 /// after the deletion is done. |
938 Future delete(dir) { | 938 Future delete(dir) { |
939 return deleteDir(join(dir, _stringName)); | 939 return deleteDir(join(dir, _stringName)); |
940 } | 940 } |
941 | 941 |
942 /// Validates that the directory at [path] contains all of the expected | 942 /// Validates that the directory at [path] contains all of the expected |
943 /// contents in this descriptor. Note that this does *not* check that the | 943 /// contents in this descriptor. Note that this does *not* check that the |
944 /// directory doesn't contain other unexpected stuff, just that it *does* | 944 /// directory doesn't contain other unexpected stuff, just that it *does* |
945 /// contain the stuff we do expect. | 945 /// contain the stuff we do expect. |
946 Future validate(String path) { | 946 Future validate(String path) { |
947 return _validateOneMatch(path, (dir) { | 947 return _validateOneMatch(path, (dir) { |
948 // Validate each of the items in this directory. | 948 // Validate each of the items in this directory. |
949 final entryFutures = | 949 final entryFutures = |
950 contents.mappedBy((entry) => entry.validate(dir)).toList(); | 950 contents.map((entry) => entry.validate(dir)).toList(); |
951 | 951 |
952 // If they are all valid, the directory is valid. | 952 // If they are all valid, the directory is valid. |
953 return Future.wait(entryFutures).then((entries) => null); | 953 return Future.wait(entryFutures).then((entries) => null); |
954 }); | 954 }); |
955 } | 955 } |
956 | 956 |
957 /// Loads [path] from within this directory. | 957 /// Loads [path] from within this directory. |
958 ByteStream load(List<String> path) { | 958 ByteStream load(List<String> path) { |
959 if (path.isEmpty) { | 959 if (path.isEmpty) { |
960 throw "Can't load the contents of $name: is a directory."; | 960 throw "Can't load the contents of $name: is a directory."; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1072 TarFileDescriptor(Pattern name, this.contents) | 1072 TarFileDescriptor(Pattern name, this.contents) |
1073 : super(name); | 1073 : super(name); |
1074 | 1074 |
1075 /// Creates the files and directories within this tar file, then archives | 1075 /// Creates the files and directories within this tar file, then archives |
1076 /// them, compresses them, and saves the result to [parentDir]. | 1076 /// them, compresses them, and saves the result to [parentDir]. |
1077 Future<File> create(parentDir) { | 1077 Future<File> create(parentDir) { |
1078 // TODO(rnystrom): Use withTempDir(). | 1078 // TODO(rnystrom): Use withTempDir(). |
1079 var tempDir; | 1079 var tempDir; |
1080 return createTempDir().then((_tempDir) { | 1080 return createTempDir().then((_tempDir) { |
1081 tempDir = _tempDir; | 1081 tempDir = _tempDir; |
1082 return Future.wait(contents.mappedBy((child) => child.create(tempDir))); | 1082 return Future.wait(contents.map((child) => child.create(tempDir))); |
1083 }).then((createdContents) { | 1083 }).then((createdContents) { |
1084 return createTarGz(createdContents, baseDir: tempDir).toBytes(); | 1084 return createTarGz(createdContents, baseDir: tempDir).toBytes(); |
1085 }).then((bytes) { | 1085 }).then((bytes) { |
1086 return new File(join(parentDir, _stringName)).writeAsBytes(bytes); | 1086 return new File(join(parentDir, _stringName)).writeAsBytes(bytes); |
1087 }).then((file) { | 1087 }).then((file) { |
1088 return deleteDir(tempDir).then((_) => file); | 1088 return deleteDir(tempDir).then((_) => file); |
1089 }); | 1089 }); |
1090 } | 1090 } |
1091 | 1091 |
1092 /// Validates that the `.tar.gz` file at [path] contains the expected | 1092 /// Validates that the `.tar.gz` file at [path] contains the expected |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1519 } | 1519 } |
1520 } | 1520 } |
1521 | 1521 |
1522 /// Takes a simple data structure (composed of [Map]s, [List]s, scalar objects, | 1522 /// Takes a simple data structure (composed of [Map]s, [List]s, scalar objects, |
1523 /// and [Future]s) and recursively resolves all the [Future]s contained within. | 1523 /// and [Future]s) and recursively resolves all the [Future]s contained within. |
1524 /// Completes with the fully resolved structure. | 1524 /// Completes with the fully resolved structure. |
1525 Future _awaitObject(object) { | 1525 Future _awaitObject(object) { |
1526 // Unroll nested futures. | 1526 // Unroll nested futures. |
1527 if (object is Future) return object.then(_awaitObject); | 1527 if (object is Future) return object.then(_awaitObject); |
1528 if (object is Collection) { | 1528 if (object is Collection) { |
1529 return Future.wait(object.mappedBy(_awaitObject).toList()); | 1529 return Future.wait(object.map(_awaitObject).toList()); |
1530 } | 1530 } |
1531 if (object is! Map) return new Future.immediate(object); | 1531 if (object is! Map) return new Future.immediate(object); |
1532 | 1532 |
1533 var pairs = <Future<Pair>>[]; | 1533 var pairs = <Future<Pair>>[]; |
1534 object.forEach((key, value) { | 1534 object.forEach((key, value) { |
1535 pairs.add(_awaitObject(value) | 1535 pairs.add(_awaitObject(value) |
1536 .then((resolved) => new Pair(key, resolved))); | 1536 .then((resolved) => new Pair(key, resolved))); |
1537 }); | 1537 }); |
1538 return Future.wait(pairs).then((resolvedPairs) { | 1538 return Future.wait(pairs).then((resolvedPairs) { |
1539 var map = {}; | 1539 var map = {}; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1583 /// calling [completion] is unnecessary. | 1583 /// calling [completion] is unnecessary. |
1584 void expectLater(Future actual, matcher, {String reason, | 1584 void expectLater(Future actual, matcher, {String reason, |
1585 FailureHandler failureHandler, bool verbose: false}) { | 1585 FailureHandler failureHandler, bool verbose: false}) { |
1586 _schedule((_) { | 1586 _schedule((_) { |
1587 return actual.then((value) { | 1587 return actual.then((value) { |
1588 expect(value, matcher, reason: reason, failureHandler: failureHandler, | 1588 expect(value, matcher, reason: reason, failureHandler: failureHandler, |
1589 verbose: false); | 1589 verbose: false); |
1590 }); | 1590 }); |
1591 }); | 1591 }); |
1592 } | 1592 } |
OLD | NEW |