| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 if (_server == null) return new Future.value(); | 140 if (_server == null) return new Future.value(); |
| 141 _server.close(); | 141 _server.close(); |
| 142 _server = null; | 142 _server = null; |
| 143 _portCompleterCache = null; | 143 _portCompleterCache = null; |
| 144 // TODO(nweiz): Remove this once issue 4155 is fixed. Pumping the event loop | 144 // TODO(nweiz): Remove this once issue 4155 is fixed. Pumping the event loop |
| 145 // *seems* to be enough to ensure that the server is actually closed, but I'm | 145 // *seems* to be enough to ensure that the server is actually closed, but I'm |
| 146 // putting this at 10ms to be safe. | 146 // putting this at 10ms to be safe. |
| 147 return sleep(10); | 147 return sleep(10); |
| 148 } | 148 } |
| 149 | 149 |
| 150 /// The [d.DirectoryDescriptor] describing the server layout of packages that | 150 /// The [d.DirectoryDescriptor] describing the server layout of `/api/packages` |
| 151 /// are being served via [servePackages]. This is `null` if [servePackages] has | 151 /// on the test server. |
| 152 /// not yet been called for this test. | 152 /// |
| 153 /// This contains metadata for packages that are being served via |
| 154 /// [servePackages]. It's `null` if [servePackages] has not yet been called for |
| 155 /// this test. |
| 156 d.DirectoryDescriptor _servedApiPackageDir; |
| 157 |
| 158 /// The [d.DirectoryDescriptor] describing the server layout of `/packages` on |
| 159 /// the test server. |
| 160 /// |
| 161 /// This contains the tarballs for packages that are being served via |
| 162 /// [servePackages]. It's `null` if [servePackages] has not yet been called for |
| 163 /// this test. |
| 153 d.DirectoryDescriptor _servedPackageDir; | 164 d.DirectoryDescriptor _servedPackageDir; |
| 154 | 165 |
| 155 /// A map from package names to version numbers to YAML-serialized pubspecs for | 166 /// A map from package names to parsed pubspec maps for those packages. This |
| 156 /// those packages. This represents the packages currently being served by | 167 /// represents the packages currently being served by [servePackages], and is |
| 157 /// [servePackages], and is `null` if [servePackages] has not yet been called | 168 /// `null` if [servePackages] has not yet been called for this test. |
| 158 /// for this test. | 169 Map<String, List<Map>> _servedPackages; |
| 159 Map<String, Map<String, String>> _servedPackages; | |
| 160 | 170 |
| 161 /// Creates an HTTP server that replicates the structure of pub.dartlang.org. | 171 /// Creates an HTTP server that replicates the structure of pub.dartlang.org. |
| 162 /// [pubspecs] is a list of unserialized pubspecs representing the packages to | 172 /// [pubspecs] is a list of unserialized pubspecs representing the packages to |
| 163 /// serve. | 173 /// serve. |
| 164 /// | 174 /// |
| 165 /// Subsequent calls to [servePackages] will add to the set of packages that | 175 /// Subsequent calls to [servePackages] will add to the set of packages that |
| 166 /// are being served. Previous packages will continue to be served. | 176 /// are being served. Previous packages will continue to be served. |
| 167 void servePackages(List<Map> pubspecs) { | 177 void servePackages(List<Map> pubspecs) { |
| 168 if (_servedPackages == null || _servedPackageDir == null) { | 178 if (_servedPackages == null || _servedPackageDir == null) { |
| 169 _servedPackages = <String, Map<String, String>>{}; | 179 _servedPackages = <String, List<Map>>{}; |
| 180 _servedApiPackageDir = d.dir('packages', []); |
| 170 _servedPackageDir = d.dir('packages', []); | 181 _servedPackageDir = d.dir('packages', []); |
| 171 serve([_servedPackageDir]); | 182 serve([ |
| 183 d.dir('api', [_servedApiPackageDir]), |
| 184 _servedPackageDir |
| 185 ]); |
| 172 | 186 |
| 173 currentSchedule.onComplete.schedule(() { | 187 currentSchedule.onComplete.schedule(() { |
| 174 _servedPackages = null; | 188 _servedPackages = null; |
| 189 _servedApiPackageDir = null; |
| 175 _servedPackageDir = null; | 190 _servedPackageDir = null; |
| 176 }, 'cleaning up served packages'); | 191 }, 'cleaning up served packages'); |
| 177 } | 192 } |
| 178 | 193 |
| 179 schedule(() { | 194 schedule(() { |
| 180 return awaitObject(pubspecs).then((resolvedPubspecs) { | 195 return awaitObject(pubspecs).then((resolvedPubspecs) { |
| 181 for (var spec in resolvedPubspecs) { | 196 for (var spec in resolvedPubspecs) { |
| 182 var name = spec['name']; | 197 var name = spec['name']; |
| 183 var version = spec['version']; | 198 var version = spec['version']; |
| 184 var versions = _servedPackages.putIfAbsent( | 199 var versions = _servedPackages.putIfAbsent(name, () => []); |
| 185 name, () => <String, String>{}); | 200 versions.add(spec); |
| 186 versions[version] = yaml(spec); | |
| 187 } | 201 } |
| 188 | 202 |
| 203 _servedApiPackageDir.contents.clear(); |
| 189 _servedPackageDir.contents.clear(); | 204 _servedPackageDir.contents.clear(); |
| 190 for (var name in _servedPackages.keys) { | 205 for (var name in _servedPackages.keys) { |
| 191 var versions = _servedPackages[name].keys.toList(); | 206 _servedApiPackageDir.contents.addAll([ |
| 192 _servedPackageDir.contents.addAll([ | 207 d.file('$name', json.stringify({ |
| 193 d.file('$name.json', json.stringify({'versions': versions})), | 208 'name': name, |
| 209 'uploaders': ['nweiz@google.com'], |
| 210 'versions': _servedPackages[name].map(packageVersionApiMap).toList() |
| 211 })), |
| 194 d.dir(name, [ | 212 d.dir(name, [ |
| 195 d.dir('versions', flatten(versions.map((version) { | 213 d.dir('versions', _servedPackages[name].map((pubspec) { |
| 196 return [ | 214 return d.file(pubspec['version'], json.stringify( |
| 197 d.file('$version.yaml', _servedPackages[name][version]), | 215 packageVersionApiMap(pubspec, full: true))); |
| 198 d.tar('$version.tar.gz', [ | 216 })) |
| 199 d.file('pubspec.yaml', _servedPackages[name][version]), | |
| 200 d.libDir(name, '$name $version') | |
| 201 ]) | |
| 202 ]; | |
| 203 }))) | |
| 204 ]) | 217 ]) |
| 205 ]); | 218 ]); |
| 219 |
| 220 _servedPackageDir.contents.add(d.dir(name, [ |
| 221 d.dir('versions', _servedPackages[name].map((pubspec) { |
| 222 var version = pubspec['version']; |
| 223 return d.tar('$version.tar.gz', [ |
| 224 d.file('pubspec.yaml', json.stringify(pubspec)), |
| 225 d.libDir(name, '$name $version') |
| 226 ]); |
| 227 })) |
| 228 ])); |
| 206 } | 229 } |
| 207 }); | 230 }); |
| 208 }, 'initializing the package server'); | 231 }, 'initializing the package server'); |
| 209 } | 232 } |
| 210 | 233 |
| 211 /// Converts [value] into a YAML string. | 234 /// Converts [value] into a YAML string. |
| 212 String yaml(value) => json.stringify(value); | 235 String yaml(value) => json.stringify(value); |
| 213 | 236 |
| 214 /// The full path to the created sandbox directory for an integration test. | 237 /// The full path to the created sandbox directory for an integration test. |
| 215 String get sandboxDir => _sandboxDir; | 238 String get sandboxDir => _sandboxDir; |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 return description['name']; | 648 return description['name']; |
| 626 case "path": | 649 case "path": |
| 627 return path.basename(description); | 650 return path.basename(description); |
| 628 case "sdk": | 651 case "sdk": |
| 629 return description; | 652 return description; |
| 630 default: | 653 default: |
| 631 return description; | 654 return description; |
| 632 } | 655 } |
| 633 } | 656 } |
| 634 | 657 |
| 658 /// Returns a Map in the format used by the pub.dartlang.org API to represent a |
| 659 /// package version. |
| 660 /// |
| 661 /// [pubspec] is the parsed pubspec of the package version. If [full] is true, |
| 662 /// this returns the complete map, including metadata that's only included when |
| 663 /// requesting the package version directly. |
| 664 Map packageVersionApiMap(Map pubspec, {bool full: false}) { |
| 665 var name = pubspec['name']; |
| 666 var version = pubspec['version']; |
| 667 var map = { |
| 668 'pubspec': pubspec, |
| 669 'version': version, |
| 670 'url': '/api/packages/$name/versions/$version', |
| 671 'archive_url': '/packages/$name/versions/$version.tar.gz', |
| 672 'new_dartdoc_url': '/api/packages/$name/versions/$version' |
| 673 '/new_dartdoc', |
| 674 'package_url': '/api/packages/$name' |
| 675 }; |
| 676 |
| 677 if (full) { |
| 678 mapAddAll(map, { |
| 679 'downloads': 0, |
| 680 'created': '2012-09-25T18:38:28.685260', |
| 681 'libraries': ['$name.dart'], |
| 682 'uploader': ['nweiz@google.com'] |
| 683 }); |
| 684 } |
| 685 |
| 686 return map; |
| 687 } |
| 688 |
| 635 /// Compares the [actual] output from running pub with [expected]. For [String] | 689 /// Compares the [actual] output from running pub with [expected]. For [String] |
| 636 /// patterns, ignores leading and trailing whitespace differences and tries to | 690 /// patterns, ignores leading and trailing whitespace differences and tries to |
| 637 /// report the offending difference in a nice way. For other [Pattern]s, just | 691 /// report the offending difference in a nice way. For other [Pattern]s, just |
| 638 /// reports whether the output contained the pattern. | 692 /// reports whether the output contained the pattern. |
| 639 void _validateOutput(List<String> failures, String pipe, Pattern expected, | 693 void _validateOutput(List<String> failures, String pipe, Pattern expected, |
| 640 List<String> actual) { | 694 List<String> actual) { |
| 641 if (expected == null) return; | 695 if (expected == null) return; |
| 642 | 696 |
| 643 if (expected is RegExp) { | 697 if (expected is RegExp) { |
| 644 _validateOutputRegex(failures, pipe, expected, actual); | 698 _validateOutputRegex(failures, pipe, expected, actual); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 bool matches(item, MatchState matchState) { | 795 bool matches(item, MatchState matchState) { |
| 742 if (item is! Pair) return false; | 796 if (item is! Pair) return false; |
| 743 return _firstMatcher.matches(item.first, matchState) && | 797 return _firstMatcher.matches(item.first, matchState) && |
| 744 _lastMatcher.matches(item.last, matchState); | 798 _lastMatcher.matches(item.last, matchState); |
| 745 } | 799 } |
| 746 | 800 |
| 747 Description describe(Description description) { | 801 Description describe(Description description) { |
| 748 description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); | 802 description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); |
| 749 } | 803 } |
| 750 } | 804 } |
| OLD | NEW |