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

Unified Diff: test/must_pub_get_test.dart

Issue 1307853004: Improve the heuristics for "pub get" is needed. (Closed) Base URL: git@github.com:dart-lang/pub.git@master
Patch Set: Code review changes Created 5 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/src/io.dart ('k') | test/test_pub.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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");
}
« no previous file with comments | « lib/src/io.dart ('k') | test/test_pub.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698