Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: sdk/lib/_internal/pub/test/test_pub.dart

Issue 354763006: Add a "pub global run" command. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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. 5 /// Test infrastructure for testing pub.
6 /// 6 ///
7 /// Unlike typical unit tests, most pub tests are integration tests that stage 7 /// Unlike typical unit tests, most pub tests are integration tests that stage
8 /// some stuff on the file system, run pub, and then validate the results. This 8 /// some stuff on the file system, run pub, and then validate the results. This
9 /// library provides an API to build tests like that. 9 /// library provides an API to build tests like that.
10 library test_pub; 10 library test_pub;
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 Map<String, List<Map>> _servedPackages; 218 Map<String, List<Map>> _servedPackages;
219 219
220 /// Creates an HTTP server that replicates the structure of pub.dartlang.org. 220 /// Creates an HTTP server that replicates the structure of pub.dartlang.org.
221 /// 221 ///
222 /// [pubspecs] is a list of unserialized pubspecs representing the packages to 222 /// [pubspecs] is a list of unserialized pubspecs representing the packages to
223 /// serve. 223 /// serve.
224 /// 224 ///
225 /// If [replace] is false, subsequent calls to [servePackages] will add to the 225 /// If [replace] is false, subsequent calls to [servePackages] will add to the
226 /// set of packages that are being served. Previous packages will continue to be 226 /// set of packages that are being served. Previous packages will continue to be
227 /// served. Otherwise, the previous packages will no longer be served. 227 /// served. Otherwise, the previous packages will no longer be served.
228 void servePackages(List<Map> pubspecs, {bool replace: false}) { 228 ///
229 /// If [contents] is given, its contents are added to every served
230 /// package.
231 void servePackages(List<Map> pubspecs, {bool replace: false,
232 Iterable<d.Descriptor> contents}) {
229 if (_servedPackages == null || _servedPackageDir == null) { 233 if (_servedPackages == null || _servedPackageDir == null) {
230 _servedPackages = <String, List<Map>>{}; 234 _servedPackages = <String, List<Map>>{};
231 _servedApiPackageDir = d.dir('packages', []); 235 _servedApiPackageDir = d.dir('packages', []);
232 _servedPackageDir = d.dir('packages', []); 236 _servedPackageDir = d.dir('packages', []);
233 serve([ 237 serve([
234 d.dir('api', [_servedApiPackageDir]), 238 d.dir('api', [_servedApiPackageDir]),
235 _servedPackageDir 239 _servedPackageDir
236 ]); 240 ]);
237 241
238 currentSchedule.onComplete.schedule(() { 242 currentSchedule.onComplete.schedule(() {
239 _servedPackages = null; 243 _servedPackages = null;
240 _servedApiPackageDir = null; 244 _servedApiPackageDir = null;
241 _servedPackageDir = null; 245 _servedPackageDir = null;
242 }, 'cleaning up served packages'); 246 }, 'cleaning up served packages');
243 } 247 }
244 248
245 schedule(() { 249 schedule(() {
246 return awaitObject(pubspecs).then((resolvedPubspecs) { 250 return awaitObject(pubspecs).then((resolvedPubspecs) {
247 if (replace) _servedPackages.clear(); 251 if (replace) _servedPackages.clear();
248 252
249 for (var spec in resolvedPubspecs) { 253 for (var pubspec in resolvedPubspecs) {
250 var name = spec['name']; 254 var name = pubspec['name'];
251 var version = spec['version']; 255 var version = pubspec['version'];
252 var versions = _servedPackages.putIfAbsent(name, () => []); 256 var versions = _servedPackages.putIfAbsent(name, () => []);
253 versions.add(spec); 257 versions.add(pubspec);
254 } 258 }
255 259
256 _servedApiPackageDir.contents.clear(); 260 _servedApiPackageDir.contents.clear();
257 _servedPackageDir.contents.clear(); 261 _servedPackageDir.contents.clear();
258 for (var name in _servedPackages.keys) { 262 for (var name in _servedPackages.keys) {
259 _servedApiPackageDir.contents.addAll([ 263 _servedApiPackageDir.contents.addAll([
260 d.file('$name', JSON.encode({ 264 d.file('$name', JSON.encode({
261 'name': name, 265 'name': name,
262 'uploaders': ['nweiz@google.com'], 266 'uploaders': ['nweiz@google.com'],
263 'versions': _servedPackages[name].map(packageVersionApiMap).toList() 267 'versions': _servedPackages[name].map(packageVersionApiMap).toList()
264 })), 268 })),
265 d.dir(name, [ 269 d.dir(name, [
266 d.dir('versions', _servedPackages[name].map((pubspec) { 270 d.dir('versions', _servedPackages[name].map((pubspec) {
267 return d.file(pubspec['version'], JSON.encode( 271 return d.file(pubspec['version'], JSON.encode(
268 packageVersionApiMap(pubspec, full: true))); 272 packageVersionApiMap(pubspec, full: true)));
269 })) 273 }))
270 ]) 274 ])
271 ]); 275 ]);
272 276
273 _servedPackageDir.contents.add(d.dir(name, [ 277 _servedPackageDir.contents.add(d.dir(name, [
274 d.dir('versions', _servedPackages[name].map((pubspec) { 278 d.dir('versions', _servedPackages[name].map((pubspec) {
275 var version = pubspec['version']; 279 var version = pubspec['version'];
276 return d.tar('$version.tar.gz', [ 280
277 d.file('pubspec.yaml', JSON.encode(pubspec)), 281 var archiveContents = [
278 d.libDir(name, '$name $version') 282 d.file('pubspec.yaml', JSON.encode(pubspec)),
279 ]); 283 d.libDir(name, '$name $version')
284 ];
285
286 if (contents != null) {
287 archiveContents.addAll(contents);
288 }
289
290 return d.tar('$version.tar.gz', archiveContents);
280 })) 291 }))
281 ])); 292 ]));
282 } 293 }
283 }); 294 });
284 }, 'initializing the package server'); 295 }, 'initializing the package server');
285 } 296 }
286 297
287 /// Converts [value] into a YAML string. 298 /// Converts [value] into a YAML string.
288 String yaml(value) => JSON.encode(value); 299 String yaml(value) => JSON.encode(value);
289 300
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 void pubGet({Iterable<String> args, output, error, warning, int exitCode}) { 381 void pubGet({Iterable<String> args, output, error, warning, int exitCode}) {
371 pubCommand(RunCommand.get, args: args, output: output, error: error, 382 pubCommand(RunCommand.get, args: args, output: output, error: error,
372 warning: warning, exitCode: exitCode); 383 warning: warning, exitCode: exitCode);
373 } 384 }
374 385
375 void pubUpgrade({Iterable<String> args, output, error, warning, int exitCode}) { 386 void pubUpgrade({Iterable<String> args, output, error, warning, int exitCode}) {
376 pubCommand(RunCommand.upgrade, args: args, output: output, error: error, 387 pubCommand(RunCommand.upgrade, args: args, output: output, error: error,
377 warning: warning, exitCode: exitCode); 388 warning: warning, exitCode: exitCode);
378 } 389 }
379 390
391 /// Schedules starting the "pub [global] run" process and validates the
392 /// expected startup output.
393 ///
394 /// If [global] is `true`, this invokes "pub global run", otherwise it does
395 /// "pub run".
396 ///
397 /// if [transformers] is given, it should contain a list of transformer IDs
398 /// (like "myapp/src/transformer") and this will validate that the output for
399 /// loading those is shown.
400 ///
401 /// Returns the `pub run` process.
402 ScheduledProcess pubRun({bool global: false, Iterable<String> args,
403 Iterable<String> transformers}) {
404 var pubArgs = global ? ["global", "run"] : ["run"];
405 pubArgs.addAll(args);
406 var pub = startPub(args: pubArgs);
407
408 // This isn't normally printed, but the pub test infrastructure runs pub in
409 // verbose mode, which enables this.
410 pub.stdout.expect(startsWith("Loading source assets"));
411
412 if (transformers != null) {
413 for (var transformer in transformers) {
414 pub.stdout.expect(startsWith("Loading $transformer transformers"));
nweiz 2014/07/02 00:12:03 Rather than requiring tests to pass in a list of t
Bob Nystrom 2014/07/02 18:00:53 Done.
415 }
416 }
417 return pub;
418 }
419
380 /// Defines an integration test. 420 /// Defines an integration test.
381 /// 421 ///
382 /// The [body] should schedule a series of operations which will be run 422 /// The [body] should schedule a series of operations which will be run
383 /// asynchronously. 423 /// asynchronously.
384 void integration(String description, void body()) => 424 void integration(String description, void body()) =>
385 _integration(description, body, test); 425 _integration(description, body, test);
386 426
387 /// Like [integration], but causes only this test to run. 427 /// Like [integration], but causes only this test to run.
388 void solo_integration(String description, void body()) => 428 void solo_integration(String description, void body()) =>
389 _integration(description, body, solo_test); 429 _integration(description, body, solo_test);
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 void ensureGit() { 703 void ensureGit() {
664 if (Platform.operatingSystem == "windows") { 704 if (Platform.operatingSystem == "windows") {
665 currentSchedule.timeout = new Duration(seconds: 30); 705 currentSchedule.timeout = new Duration(seconds: 30);
666 } 706 }
667 707
668 if (!gitlib.isInstalled) { 708 if (!gitlib.isInstalled) {
669 throw new Exception("Git must be installed to run this test."); 709 throw new Exception("Git must be installed to run this test.");
670 } 710 }
671 } 711 }
672 712
713 /// Schedules activating a global package [package] without running
714 /// "pub global activate".
715 ///
716 /// This is useful because global packages must be hosted, but the test hosted
717 /// server doesn't serve barback. The other parameters here follow
718 /// [createLockFile].
719 void makeGlobalPackage(String package, String version,
720 Iterable<d.Descriptor> contents, {Iterable<String> pkg,
721 Map<String, String> hosted}) {
722 // Start the server so we know what port to use in the cache directory name.
723 servePackages([]);
724
725 // Create the package in the hosted cache.
726 d.hostedCache([
727 d.dir("$package-$version", contents)
728 ]).create();
729
730 var lockFile = _createLockFile(pkg: pkg, hosted: hosted);
731
732 // Add the root package to the lockfile.
733 var id = new PackageId(package, "hosted", new Version.parse(version),
734 package);
735 lockFile.packages[package] = id;
736
737 // Write the lockfile to the global cache.
738 var sources = new SourceRegistry();
739 sources.register(new HostedSource());
740 sources.register(new PathSource());
741
742 d.dir(cachePath, [
743 d.dir("global_packages", [
744 d.file("$package.lock", lockFile.serialize(null, sources))
745 ])
746 ]).create();
747 }
748
673 /// Creates a lock file for [package] without running `pub get`. 749 /// Creates a lock file for [package] without running `pub get`.
674 /// 750 ///
675 /// [sandbox] is a list of path dependencies to be found in the sandbox 751 /// [sandbox] is a list of path dependencies to be found in the sandbox
676 /// directory. [pkg] is a list of packages in the Dart repo's "pkg" directory; 752 /// directory. [pkg] is a list of packages in the Dart repo's "pkg" directory;
677 /// each package listed here and all its dependencies will be linked to the 753 /// each package listed here and all its dependencies will be linked to the
678 /// version in the Dart repo. 754 /// version in the Dart repo.
679 /// 755 ///
680 /// [hosted] is a list of package names to version strings for dependencies on 756 /// [hosted] is a list of package names to version strings for dependencies on
681 /// hosted packages. 757 /// hosted packages.
682 void createLockFile(String package, {Iterable<String> sandbox, 758 void createLockFile(String package, {Iterable<String> sandbox,
683 Iterable<String> pkg, Map<String, String> hosted}) { 759 Iterable<String> pkg, Map<String, String> hosted}) {
760 var lockFile = _createLockFile(sandbox: sandbox, pkg: pkg, hosted: hosted);
761
762 var sources = new SourceRegistry();
763 sources.register(new HostedSource());
764 sources.register(new PathSource());
765
766 d.file(path.join(package, 'pubspec.lock'),
767 lockFile.serialize(null, sources)).create();
768 }
769
770 /// Creates a lock file for [package] without running `pub get`.
771 ///
772 /// [sandbox] is a list of path dependencies to be found in the sandbox
773 /// directory. [pkg] is a list of packages in the Dart repo's "pkg" directory;
774 /// each package listed here and all its dependencies will be linked to the
775 /// version in the Dart repo.
776 ///
777 /// [hosted] is a list of package names to version strings for dependencies on
778 /// hosted packages.
779 LockFile _createLockFile({Iterable<String> sandbox,
780 Iterable<String> pkg, Map<String, String> hosted}) {
684 var dependencies = {}; 781 var dependencies = {};
685 782
686 if (sandbox != null) { 783 if (sandbox != null) {
687 for (var package in sandbox) { 784 for (var package in sandbox) {
688 dependencies[package] = '../$package'; 785 dependencies[package] = '../$package';
689 } 786 }
690 } 787 }
691 788
692 if (pkg != null) { 789 if (pkg != null) {
693 _addPackage(String package) { 790 _addPackage(String package) {
694 if (dependencies.containsKey(package)) return; 791 if (dependencies.containsKey(package)) return;
695 792
696 var packagePath; 793 var packagePath;
697 if (package == 'barback') { 794 if (package == 'barback') {
698 if (_barbackDir == null) { 795 if (_barbackDir == null) {
699 throw new StateError("createLockFile() can only create a lock file " 796 throw new StateError("createLockFile() can only create a lock file "
700 "with a barback dependency within a withBarbackVersions() " 797 "with a barback dependency within a withBarbackVersions() "
701 "block."); 798 "block.");
nweiz 2014/07/02 00:12:03 Fix this indentation.
Bob Nystrom 2014/07/02 18:00:53 Done.
702 } 799 }
703 packagePath = _barbackDir; 800 packagePath = _barbackDir;
704 } else { 801 } else {
705 packagePath = path.join(pkgPath, package); 802 packagePath = path.join(pkgPath, package);
706 } 803 }
707 804
708 dependencies[package] = packagePath; 805 dependencies[package] = packagePath;
709 var pubspec = loadYaml( 806 var pubspec = loadYaml(
710 readTextFile(path.join(packagePath, 'pubspec.yaml'))); 807 readTextFile(path.join(packagePath, 'pubspec.yaml')));
nweiz 2014/07/02 00:12:02 Also this indentation.
Bob Nystrom 2014/07/02 18:00:53 Done.
711 var packageDeps = pubspec['dependencies']; 808 var packageDeps = pubspec['dependencies'];
712 if (packageDeps == null) return; 809 if (packageDeps == null) return;
713 packageDeps.keys.forEach(_addPackage); 810 packageDeps.keys.forEach(_addPackage);
714 } 811 }
715 812
716 pkg.forEach(_addPackage); 813 pkg.forEach(_addPackage);
717 } 814 }
718 815
719 var lockFile = new LockFile.empty(); 816 var lockFile = new LockFile.empty();
720 dependencies.forEach((name, dependencyPath) { 817 dependencies.forEach((name, dependencyPath) {
721 var id = new PackageId(name, 'path', new Version(0, 0, 0), { 818 var id = new PackageId(name, 'path', new Version(0, 0, 0), {
722 'path': dependencyPath, 819 'path': dependencyPath,
723 'relative': path.isRelative(dependencyPath) 820 'relative': path.isRelative(dependencyPath)
724 }); 821 });
725 lockFile.packages[name] = id; 822 lockFile.packages[name] = id;
726 }); 823 });
727 824
728 if (hosted != null) { 825 if (hosted != null) {
729 hosted.forEach((name, version) { 826 hosted.forEach((name, version) {
730 var id = new PackageId(name, 'hosted', new Version.parse(version), name); 827 var id = new PackageId(name, 'hosted', new Version.parse(version), name);
731 lockFile.packages[name] = id; 828 lockFile.packages[name] = id;
732 }); 829 });
733 } 830 }
734 831
735 var sources = new SourceRegistry(); 832 return lockFile;
736 sources.register(new HostedSource());
737 sources.register(new PathSource());
738
739 d.file(path.join(package, 'pubspec.lock'),
740 lockFile.serialize(null, sources)).create();
741 } 833 }
742 834
743 /// Uses [client] as the mock HTTP client for this test. 835 /// Uses [client] as the mock HTTP client for this test.
744 /// 836 ///
745 /// Note that this will only affect HTTP requests made via http.dart in the 837 /// Note that this will only affect HTTP requests made via http.dart in the
746 /// parent process. 838 /// parent process.
747 void useMockClient(MockClient client) { 839 void useMockClient(MockClient client) {
748 var oldInnerClient = httpClient.inner; 840 var oldInnerClient = httpClient.inner;
749 httpClient.inner = client; 841 httpClient.inner = client;
750 currentSchedule.onComplete.schedule(() { 842 currentSchedule.onComplete.schedule(() {
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 _lastMatcher.matches(item.last, matchState); 1014 _lastMatcher.matches(item.last, matchState);
923 } 1015 }
924 1016
925 Description describe(Description description) { 1017 Description describe(Description description) {
926 return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); 1018 return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]);
927 } 1019 }
928 } 1020 }
929 1021
930 /// A [StreamMatcher] that matches multiple lines of output. 1022 /// A [StreamMatcher] that matches multiple lines of output.
931 StreamMatcher emitsLines(String output) => inOrder(output.split("\n")); 1023 StreamMatcher emitsLines(String output) => inOrder(output.split("\n"));
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698