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. | 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 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 warning: warning, exitCode: exitCode); | 347 warning: warning, exitCode: exitCode); |
348 } | 348 } |
349 | 349 |
350 /// Schedules starting the "pub [global] run" process and validates the | 350 /// Schedules starting the "pub [global] run" process and validates the |
351 /// expected startup output. | 351 /// expected startup output. |
352 /// | 352 /// |
353 /// If [global] is `true`, this invokes "pub global run", otherwise it does | 353 /// If [global] is `true`, this invokes "pub global run", otherwise it does |
354 /// "pub run". | 354 /// "pub run". |
355 /// | 355 /// |
356 /// Returns the `pub run` process. | 356 /// Returns the `pub run` process. |
357 ScheduledProcess pubRun({bool shouldGetFirst: false, bool global: false, | 357 ScheduledProcess pubRun({bool global: false, Iterable<String> args}) { |
358 Iterable<String> args}) { | |
359 var pubArgs = global ? ["global", "run"] : ["run"]; | 358 var pubArgs = global ? ["global", "run"] : ["run"]; |
360 pubArgs.addAll(args); | 359 pubArgs.addAll(args); |
361 var pub = startPub(args: pubArgs); | 360 var pub = startPub(args: pubArgs); |
362 | 361 |
363 if (shouldGetFirst) { | |
364 pub.stdout.expect(consumeThrough(anyOf([ | |
365 "Got dependencies!", | |
366 matches(new RegExp(r"^Changed \d+ dependenc")) | |
367 ]))); | |
368 } | |
369 | |
370 // Loading sources and transformers isn't normally printed, but the pub test | 362 // Loading sources and transformers isn't normally printed, but the pub test |
371 // infrastructure runs pub in verbose mode, which enables this. | 363 // infrastructure runs pub in verbose mode, which enables this. |
372 pub.stdout.expect(consumeWhile(startsWith("Loading"))); | 364 pub.stdout.expect(consumeWhile(startsWith("Loading"))); |
373 | 365 |
374 return pub; | 366 return pub; |
375 } | 367 } |
376 | 368 |
377 /// Defines an integration test. | 369 /// Defines an integration test. |
378 /// | 370 /// |
379 /// The [body] should schedule a series of operations which will be run | 371 /// The [body] should schedule a series of operations which will be run |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 /// Gets the absolute path to [relPath], which is a relative path in the test | 493 /// Gets the absolute path to [relPath], which is a relative path in the test |
502 /// sandbox. | 494 /// sandbox. |
503 String _pathInSandbox(String relPath) { | 495 String _pathInSandbox(String relPath) { |
504 return p.join(p.absolute(sandboxDir), relPath); | 496 return p.join(p.absolute(sandboxDir), relPath); |
505 } | 497 } |
506 | 498 |
507 /// Gets the environment variables used to run pub in a test context. | 499 /// Gets the environment variables used to run pub in a test context. |
508 Future<Map> getPubTestEnvironment([String tokenEndpoint]) async { | 500 Future<Map> getPubTestEnvironment([String tokenEndpoint]) async { |
509 var environment = {}; | 501 var environment = {}; |
510 environment['_PUB_TESTING'] = 'true'; | 502 environment['_PUB_TESTING'] = 'true'; |
511 environment['PUB_CACHE'] = _pathInSandbox(cachePath); | 503 environment['PUB_CACHE'] = await schedule(() => _pathInSandbox(cachePath)); |
512 | 504 |
513 // Ensure a known SDK version is set for the tests that rely on that. | 505 // Ensure a known SDK version is set for the tests that rely on that. |
514 environment['_PUB_TEST_SDK_VERSION'] = "0.1.2+3"; | 506 environment['_PUB_TEST_SDK_VERSION'] = "0.1.2+3"; |
515 | 507 |
516 if (tokenEndpoint != null) { | 508 if (tokenEndpoint != null) { |
517 environment['_PUB_TEST_TOKEN_ENDPOINT'] = tokenEndpoint.toString(); | 509 environment['_PUB_TEST_TOKEN_ENDPOINT'] = tokenEndpoint.toString(); |
518 } | 510 } |
519 | 511 |
520 if (_hasServer) { | 512 if (_hasServer) { |
521 return port.then((p) { | 513 environment['PUB_HOSTED_URL'] = "http://localhost:${await port}"; |
522 environment['PUB_HOSTED_URL'] = "http://localhost:$p"; | |
523 return environment; | |
524 }); | |
525 } | 514 } |
526 | 515 |
527 return environment; | 516 return environment; |
528 } | 517 } |
529 | 518 |
530 /// Starts a Pub process and returns a [ScheduledProcess] that supports | 519 /// Starts a Pub process and returns a [ScheduledProcess] that supports |
531 /// interaction with that process. | 520 /// interaction with that process. |
532 /// | 521 /// |
533 /// Any futures in [args] will be resolved before the process is started. | 522 /// Any futures in [args] will be resolved before the process is started. |
534 /// | 523 /// |
535 /// If [environment] is given, any keys in it will override the environment | 524 /// If [environment] is given, any keys in it will override the environment |
536 /// variables passed to the spawned process. | 525 /// variables passed to the spawned process. |
537 ScheduledProcess startPub({List args, Future<String> tokenEndpoint, | 526 ScheduledProcess startPub({List args, Future<String> tokenEndpoint, |
538 Map<String, String> environment}) { | 527 Map<String, String> environment}) { |
539 ensureDir(_pathInSandbox(appPath)); | 528 schedule(() { |
| 529 ensureDir(_pathInSandbox(appPath)); |
| 530 }, "ensuring $appPath exists"); |
540 | 531 |
541 // Find a Dart executable we can use to spawn. Use the same one that was | 532 // Find a Dart executable we can use to spawn. Use the same one that was |
542 // used to run this script itself. | 533 // used to run this script itself. |
543 var dartBin = Platform.executable; | 534 var dartBin = Platform.executable; |
544 | 535 |
545 // If the executable looks like a path, get its full path. That way we | 536 // If the executable looks like a path, get its full path. That way we |
546 // can still find it when we spawn it with a different working directory. | 537 // can still find it when we spawn it with a different working directory. |
547 if (dartBin.contains(Platform.pathSeparator)) { | 538 if (dartBin.contains(Platform.pathSeparator)) { |
548 dartBin = p.absolute(dartBin); | 539 dartBin = p.absolute(dartBin); |
549 } | 540 } |
(...skipping 14 matching lines...) Expand all Loading... |
564 | 555 |
565 if (tokenEndpoint == null) tokenEndpoint = new Future.value(); | 556 if (tokenEndpoint == null) tokenEndpoint = new Future.value(); |
566 var environmentFuture = tokenEndpoint | 557 var environmentFuture = tokenEndpoint |
567 .then((tokenEndpoint) => getPubTestEnvironment(tokenEndpoint)) | 558 .then((tokenEndpoint) => getPubTestEnvironment(tokenEndpoint)) |
568 .then((pubEnvironment) { | 559 .then((pubEnvironment) { |
569 if (environment != null) pubEnvironment.addAll(environment); | 560 if (environment != null) pubEnvironment.addAll(environment); |
570 return pubEnvironment; | 561 return pubEnvironment; |
571 }); | 562 }); |
572 | 563 |
573 return new PubProcess.start(dartBin, dartArgs, environment: environmentFuture, | 564 return new PubProcess.start(dartBin, dartArgs, environment: environmentFuture, |
574 workingDirectory: _pathInSandbox(appPath), | 565 workingDirectory: schedule(() => _pathInSandbox(appPath)), |
575 description: args.isEmpty ? 'pub' : 'pub ${args.first}'); | 566 description: args.isEmpty ? 'pub' : 'pub ${args.first}'); |
576 } | 567 } |
577 | 568 |
578 /// A subclass of [ScheduledProcess] that parses pub's verbose logging output | 569 /// A subclass of [ScheduledProcess] that parses pub's verbose logging output |
579 /// and makes [stdout] and [stderr] work as though pub weren't running in | 570 /// and makes [stdout] and [stderr] work as though pub weren't running in |
580 /// verbose mode. | 571 /// verbose mode. |
581 class PubProcess extends ScheduledProcess { | 572 class PubProcess extends ScheduledProcess { |
582 Stream<Pair<log.Level, String>> _log; | 573 Stream<Pair<log.Level, String>> _log; |
583 Stream<String> _stdout; | 574 Stream<String> _stdout; |
584 Stream<String> _stderr; | 575 Stream<String> _stderr; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 Map<String, String> hosted}) { | 676 Map<String, String> hosted}) { |
686 // Start the server so we know what port to use in the cache directory name. | 677 // Start the server so we know what port to use in the cache directory name. |
687 serveNoPackages(); | 678 serveNoPackages(); |
688 | 679 |
689 // Create the package in the hosted cache. | 680 // Create the package in the hosted cache. |
690 d.hostedCache([ | 681 d.hostedCache([ |
691 d.dir("$package-$version", contents) | 682 d.dir("$package-$version", contents) |
692 ]).create(); | 683 ]).create(); |
693 | 684 |
694 // Write the lockfile to the global cache. | 685 // Write the lockfile to the global cache. |
695 var sources = new SourceRegistry(); | 686 var cache = new SystemCache.withSources( |
696 sources.register(new HostedSource()); | 687 rootDir: p.join(sandboxDir, cachePath)); |
697 sources.register(new PathSource()); | |
698 | 688 |
699 var lockFile = _createLockFile(sources, pkg: pkg, hosted: hosted); | 689 var lockFile = _createLockFile(cache.sources, pkg: pkg, hosted: hosted); |
700 | 690 |
701 // Add the root package to the lockfile. | 691 // Add the root package to the lockfile. |
702 var id = new PackageId(package, "hosted", new Version.parse(version), | 692 var id = new PackageId(package, "hosted", new Version.parse(version), |
703 package); | 693 package); |
704 lockFile = lockFile.setPackage(id); | 694 lockFile = lockFile.setPackage(id); |
705 | 695 |
706 d.dir(cachePath, [ | 696 d.dir(cachePath, [ |
707 d.dir("global_packages", [ | 697 d.dir("global_packages", [ |
708 d.file("$package.lock", lockFile.serialize(null)) | 698 d.dir(package, [ |
| 699 d.file("pubspec.lock", lockFile.serialize(null)), |
| 700 d.file(".packages", lockFile.packagesFile()) |
| 701 ]) |
709 ]) | 702 ]) |
710 ]).create(); | 703 ]).create(); |
711 } | 704 } |
712 | 705 |
713 /// Creates a lock file for [package] without running `pub get`. | 706 /// Creates a lock file for [package] without running `pub get`. |
714 /// | 707 /// |
715 /// [sandbox] is a list of path dependencies to be found in the sandbox | 708 /// [sandbox] is a list of path dependencies to be found in the sandbox |
716 /// directory. [pkg] is a list of packages in the Dart repo's "pkg" directory; | 709 /// directory. [pkg] is a list of packages in the Dart repo's "pkg" directory; |
717 /// each package listed here and all its dependencies will be linked to the | 710 /// each package listed here and all its dependencies will be linked to the |
718 /// version in the Dart repo. | 711 /// version in the Dart repo. |
719 /// | 712 /// |
720 /// [hosted] is a list of package names to version strings for dependencies on | 713 /// [hosted] is a list of package names to version strings for dependencies on |
721 /// hosted packages. | 714 /// hosted packages. |
722 void createLockFile(String package, {Iterable<String> sandbox, | 715 void createLockFile(String package, {Iterable<String> sandbox, |
723 Iterable<String> pkg, Map<String, String> hosted}) { | 716 Iterable<String> pkg, Map<String, String> hosted}) { |
724 var sources = new SourceRegistry(); | 717 var cache = new SystemCache.withSources( |
725 sources.register(new HostedSource()); | 718 rootDir: p.join(sandboxDir, cachePath)); |
726 sources.register(new PathSource()); | |
727 | 719 |
728 var lockFile = _createLockFile(sources, | 720 var lockFile = _createLockFile(cache.sources, |
729 sandbox: sandbox, pkg: pkg, hosted: hosted); | 721 sandbox: sandbox, pkg: pkg, hosted: hosted); |
730 | 722 |
731 d.file(p.join(package, 'pubspec.lock'), lockFile.serialize(null)).create(); | 723 d.dir(package, [ |
| 724 d.file('pubspec.lock', lockFile.serialize(null)), |
| 725 d.file('.packages', lockFile.packagesFile(package)) |
| 726 ]).create(); |
732 } | 727 } |
733 | 728 |
734 /// Creates a lock file for [package] without running `pub get`. | 729 /// Creates a lock file for [package] without running `pub get`. |
735 /// | 730 /// |
736 /// [sandbox] is a list of path dependencies to be found in the sandbox | 731 /// [sandbox] is a list of path dependencies to be found in the sandbox |
737 /// directory. [pkg] is a list of packages in the Dart repo's "pkg" directory; | 732 /// directory. [pkg] is a list of packages in the Dart repo's "pkg" directory; |
738 /// each package listed here and all its dependencies will be linked to the | 733 /// each package listed here and all its dependencies will be linked to the |
739 /// version in the Dart repo. | 734 /// version in the Dart repo. |
740 /// | 735 /// |
741 /// [hosted] is a list of package names to version strings for dependencies on | 736 /// [hosted] is a list of package names to version strings for dependencies on |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 _lastMatcher.matches(item.last, matchState); | 1001 _lastMatcher.matches(item.last, matchState); |
1007 } | 1002 } |
1008 | 1003 |
1009 Description describe(Description description) { | 1004 Description describe(Description description) { |
1010 return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); | 1005 return description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); |
1011 } | 1006 } |
1012 } | 1007 } |
1013 | 1008 |
1014 /// A [StreamMatcher] that matches multiple lines of output. | 1009 /// A [StreamMatcher] that matches multiple lines of output. |
1015 StreamMatcher emitsLines(String output) => inOrder(output.split("\n")); | 1010 StreamMatcher emitsLines(String output) => inOrder(output.split("\n")); |
OLD | NEW |