| 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 |