| Index: test/must_pub_get_test.dart
|
| diff --git a/test/must_pub_get_test.dart b/test/must_pub_get_test.dart
|
| index 5a10d82dcb87fe12a0553e0f943a2ffb1129f06a..981d9ff13a417373f5be50ef0f2445b17785c52a 100644
|
| --- a/test/must_pub_get_test.dart
|
| +++ b/test/must_pub_get_test.dart
|
| @@ -4,39 +4,42 @@
|
|
|
| import 'dart:async';
|
| import 'dart:convert';
|
| +import 'dart:io';
|
|
|
| import 'package:path/path.dart' as p;
|
| import 'package:pub/src/exit_codes.dart' as exit_codes;
|
| import 'package:pub/src/io.dart';
|
| +import 'package:scheduled_test/scheduled_stream.dart';
|
| import 'package:scheduled_test/scheduled_test.dart';
|
|
|
| import 'descriptor.dart' as d;
|
| import 'test_pub.dart';
|
|
|
| main() {
|
| - group("requires the user to run pub get first if", () {
|
| - setUp(() {
|
| - d.dir(appPath, [
|
| - d.appPubspec(),
|
| - d.dir("web", []),
|
| - d.dir("bin", [
|
| - d.file("script.dart", "main() => print('hello!');")
|
| - ])
|
| - ]).create();
|
| + setUp(() {
|
| + servePackages((builder) {
|
| + builder.serve("foo", "1.0.0");
|
| + builder.serve("foo", "2.0.0");
|
| + });
|
|
|
| - pubGet();
|
| + d.dir(appPath, [
|
| + d.appPubspec(),
|
| + d.dir("web", []),
|
| + d.dir("bin", [
|
| + d.file("script.dart", "main() => print('hello!');")
|
| + ])
|
| + ]).create();
|
|
|
| - // Delay a bit to make sure the modification times are noticeably
|
| - // different. 1s seems to be the finest granularity that dart:io reports.
|
| - schedule(() => new Future.delayed(new Duration(seconds: 1)));
|
| - });
|
| + pubGet();
|
| + });
|
|
|
| + group("requires the user to run pub get first if", () {
|
| group("there's no lockfile", () {
|
| setUp(() {
|
| schedule(() => deleteEntry(p.join(sandboxDir, "myapp/pubspec.lock")));
|
| });
|
|
|
| - _forEveryCommand(
|
| + _requiresPubGet(
|
| 'No pubspec.lock file found, please run "pub get" first.');
|
| });
|
|
|
| @@ -45,55 +48,335 @@ main() {
|
| schedule(() => deleteEntry(p.join(sandboxDir, "myapp/.packages")));
|
| });
|
|
|
| - _forEveryCommand('No .packages file found, please run "pub get" first.');
|
| + _requiresPubGet('No .packages file found, please run "pub get" first.');
|
| + });
|
| +
|
| + group("the pubspec has a new dependency", () {
|
| + setUp(() {
|
| + d.dir("foo", [
|
| + d.libPubspec("foo", "1.0.0")
|
| + ]).create();
|
| +
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": {"path": "../foo"}})
|
| + ]).create();
|
| +
|
| + // Ensure that the pubspec looks newer than the lockfile.
|
| + _touch("pubspec.yaml");
|
| + });
|
| +
|
| + _requiresPubGet('The pubspec.yaml file has changed since the '
|
| + 'pubspec.lock file was generated, please run "pub get" again.');
|
| + });
|
| +
|
| + group("the lockfile has a dependency from the wrong source", () {
|
| + setUp(() {
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": "1.0.0"})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + createLockFile(appPath, sandbox: ["foo"]);
|
| +
|
| + // Ensure that the pubspec looks newer than the lockfile.
|
| + _touch("pubspec.yaml");
|
| + });
|
| +
|
| + _requiresPubGet('The pubspec.yaml file has changed since the '
|
| + 'pubspec.lock file was generated, please run "pub get" again.');
|
| });
|
|
|
| - group("the pubspec is newer than the package spec", () {
|
| + group("the lockfile has a dependency from an unknown source", () {
|
| setUp(() {
|
| - schedule(() => _touch("pubspec.yaml"));
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": "1.0.0"})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + d.dir(appPath, [
|
| + d.file("pubspec.lock", yaml({
|
| + "packages": {
|
| + "foo": {
|
| + "description": "foo",
|
| + "version": "1.0.0",
|
| + "source": "sdk"
|
| + }
|
| + }
|
| + }))
|
| + ]).create();
|
| +
|
| + // Ensure that the pubspec looks newer than the lockfile.
|
| + _touch("pubspec.yaml");
|
| });
|
|
|
| - _forEveryCommand('The pubspec.yaml file has changed since the .packages '
|
| + _requiresPubGet('The pubspec.yaml file has changed since the '
|
| + 'pubspec.lock file was generated, please run "pub get" again.');
|
| + });
|
| +
|
| + group("the lockfile has a dependency with the wrong description", () {
|
| + setUp(() {
|
| + d.dir("bar", [
|
| + d.libPubspec("foo", "1.0.0")
|
| + ]).create();
|
| +
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": {"path": "../bar"}})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + createLockFile(appPath, sandbox: ["foo"]);
|
| +
|
| + // Ensure that the pubspec looks newer than the lockfile.
|
| + _touch("pubspec.yaml");
|
| + });
|
| +
|
| + _requiresPubGet('The pubspec.yaml file has changed since the '
|
| + 'pubspec.lock file was generated, please run "pub get" again.');
|
| + });
|
| +
|
| + group("the pubspec has an incompatible version of a dependency", () {
|
| + setUp(() {
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": "1.0.0"})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": "2.0.0"})
|
| + ]).create();
|
| +
|
| + // Ensure that the pubspec looks newer than the lockfile.
|
| + _touch("pubspec.yaml");
|
| + });
|
| +
|
| + _requiresPubGet('The pubspec.yaml file has changed since the '
|
| + 'pubspec.lock file was generated, please run "pub get" again.');
|
| + });
|
| +
|
| + group("the lockfile is pointing to an unavailable package with a newer "
|
| + "pubspec", () {
|
| + setUp(() {
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": "1.0.0"})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + schedule(() => deleteEntry(p.join(sandboxDir, cachePath)));
|
| +
|
| + // Ensure that the pubspec looks newer than the lockfile.
|
| + _touch("pubspec.yaml");
|
| + });
|
| +
|
| + _requiresPubGet('The pubspec.yaml file has changed since the '
|
| + 'pubspec.lock file was generated, please run "pub get" again.');
|
| + });
|
| +
|
| + group("the lockfile is pointing to an unavailable package with an older "
|
| + ".packages", () {
|
| + setUp(() {
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": "1.0.0"})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + schedule(() => deleteEntry(p.join(sandboxDir, cachePath)));
|
| +
|
| + // Ensure that the lockfile looks newer than the .packages file.
|
| + _touch("pubspec.lock");
|
| + });
|
| +
|
| + _requiresPubGet('The pubspec.lock file has changed since the .packages '
|
| 'file was generated, please run "pub get" again.');
|
| });
|
|
|
| - group("the lockfile is newer than the package spec", () {
|
| + group("the lockfile has a package that the .packages file doesn't", () {
|
| setUp(() {
|
| - schedule(() => _touch("pubspec.lock"));
|
| + d.dir("foo", [
|
| + d.libPubspec("foo", "1.0.0")
|
| + ]).create();
|
| +
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": {"path": "../foo"}})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + createPackagesFile(appPath);
|
| +
|
| + // Ensure that the pubspec looks newer than the lockfile.
|
| + _touch("pubspec.lock");
|
| });
|
|
|
| - _forEveryCommand('The pubspec.lock file has changed since the .packages '
|
| + _requiresPubGet('The pubspec.lock file has changed since the .packages '
|
| 'file was generated, please run "pub get" again.');
|
| });
|
| +
|
| + group("the .packages file has a package with a non-file URI", () {
|
| + setUp(() {
|
| + d.dir("foo", [
|
| + d.libPubspec("foo", "1.0.0")
|
| + ]).create();
|
| +
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": {"path": "../foo"}})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + d.dir(appPath, [
|
| + d.file(".packages", """
|
| +myapp:lib
|
| +foo:http://example.com/
|
| +""")
|
| + ]).create();
|
| +
|
| + // Ensure that the pubspec looks newer than the lockfile.
|
| + _touch("pubspec.lock");
|
| + });
|
| +
|
| + _requiresPubGet('The pubspec.lock file has changed since the .packages '
|
| + 'file was generated, please run "pub get" again.');
|
| + });
|
| +
|
| + group("the .packages file points to the wrong place", () {
|
| + setUp(() {
|
| + d.dir("bar", [
|
| + d.libPubspec("foo", "1.0.0")
|
| + ]).create();
|
| +
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": {"path": "../bar"}})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + createPackagesFile(appPath, sandbox: ["foo"]);
|
| +
|
| + // Ensure that the pubspec looks newer than the lockfile.
|
| + _touch("pubspec.lock");
|
| + });
|
| +
|
| + _requiresPubGet('The pubspec.lock file has changed since the .packages '
|
| + 'file was generated, please run "pub get" again.');
|
| + });
|
| + });
|
| +
|
| + group("doesn't require the user to run pub get first if", () {
|
| + group("the pubspec is older than the lockfile which is older than the "
|
| + "packages file, even if the contents are wrong", () {
|
| + setUp(() {
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": "1.0.0"})
|
| + ]).create();
|
| +
|
| + _touch("pubspec.lock");
|
| + _touch(".packages");
|
| + });
|
| +
|
| + _runsSuccessfully(runDeps: false);
|
| + });
|
| +
|
| + group("the pubspec is newer than the lockfile, but they're up-to-date", () {
|
| + setUp(() {
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": "1.0.0"})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + _touch("pubspec.yaml");
|
| + });
|
| +
|
| + _runsSuccessfully();
|
| + });
|
| +
|
| + group("the lockfile is newer than .packages, but they're up-to-date", () {
|
| + setUp(() {
|
| + d.dir(appPath, [
|
| + d.appPubspec({"foo": "1.0.0"})
|
| + ]).create();
|
| +
|
| + pubGet();
|
| +
|
| + _touch("pubspec.lock");
|
| + });
|
| +
|
| + _runsSuccessfully();
|
| + });
|
| });
|
| }
|
|
|
| /// Runs every command that care about the world being up-to-date, and asserts
|
| /// that it prints [message] as part of its error.
|
| -void _forEveryCommand(String message) {
|
| +void _requiresPubGet(String message) {
|
| for (var command in ["build", "serve", "run", "deps"]) {
|
| integration("for pub $command", () {
|
| var args = [command];
|
| if (command == "run") args.add("script");
|
|
|
| - var output;
|
| - var error;
|
| - if (command == "list-package-dirs") {
|
| - output = contains(JSON.encode(message));
|
| - } else {
|
| - error = contains(message);
|
| - }
|
| -
|
| schedulePub(
|
| args: args,
|
| - output: output,
|
| - error: error,
|
| + error: contains(message),
|
| exitCode: exit_codes.DATA);
|
| });
|
| }
|
| }
|
|
|
| +/// Ensures that pub doesn't require "pub get" for the current package.
|
| +///
|
| +/// If [runDeps] is false, `pub deps` isn't included in the test. This is
|
| +/// sometimes not desirable, since it uses slightly stronger checks for pubspec
|
| +/// and lockfile consistency.
|
| +void _runsSuccessfully({bool runDeps: true}) {
|
| + var commands = ["build", "serve", "run"];
|
| + if (runDeps) commands.add("deps");
|
| +
|
| + for (var command in commands) {
|
| + integration("for pub $command", () {
|
| + var args = [command];
|
| + if (command == "run") args.add("bin/script.dart");
|
| + if (command == "serve") ;
|
| +
|
| + if (command != "serve") {
|
| + schedulePub(args: args);
|
| + } else {
|
| + var pub = startPub(args: ["serve", "--port=0"]);
|
| + pub.stdout.expect(consumeThrough(startsWith("Serving myapp web")));
|
| + pub.kill();
|
| + }
|
| +
|
| + schedule(() {
|
| + // If pub determines that everything is up-to-date, it should set the
|
| + // mtimes to indicate that.
|
| + var pubspecModified = new File(p.join(sandboxDir, "myapp/pubspec.yaml"))
|
| + .lastModifiedSync();
|
| + var lockFileModified =
|
| + new File(p.join(sandboxDir, "myapp/pubspec.lock"))
|
| + .lastModifiedSync();
|
| + var packagesModified = new File(p.join(sandboxDir, "myapp/.packages"))
|
| + .lastModifiedSync();
|
| +
|
| + expect(!pubspecModified.isAfter(lockFileModified), isTrue);
|
| + expect(!lockFileModified.isAfter(packagesModified), isTrue);
|
| + }, "testing last-modified times");
|
| + });
|
| + }
|
| +}
|
| +
|
| +/// Schedules a non-semantic modification to [path].
|
| void _touch(String path) {
|
| - path = p.join(sandboxDir, "myapp", path);
|
| - writeTextFile(path, readTextFile(path) + " ");
|
| + schedule(() async {
|
| + // Delay a bit to make sure the modification times are noticeably different.
|
| + // 1s seems to be the finest granularity that dart:io reports.
|
| + await new Future.delayed(new Duration(seconds: 1));
|
| +
|
| + path = p.join(sandboxDir, "myapp", path);
|
| + touch(path);
|
| + }, "touching $path");
|
| }
|
|
|