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 |