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