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

Unified Diff: utils/tests/pub/version_solver_test.dart

Issue 10540151: First pass at version constraint solver. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Request all versions from the source, and not just the best. Created 8 years, 6 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 | « utils/tests/pub/pubspec_test.dart ('k') | utils/tests/pub/version_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utils/tests/pub/version_solver_test.dart
diff --git a/utils/tests/pub/version_solver_test.dart b/utils/tests/pub/version_solver_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4c86ecfaaf973aad1e6a6a8e58c3eb5ba4bff371
--- /dev/null
+++ b/utils/tests/pub/version_solver_test.dart
@@ -0,0 +1,277 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#library('pub_update_test');
+
+#import('dart:io');
+
+#import('../../pub/package.dart');
+#import('../../pub/pubspec.dart');
+#import('../../pub/source.dart');
+#import('../../pub/source_registry.dart');
+#import('../../pub/version.dart');
+#import('../../pub/version_solver.dart');
+#import('../../../lib/unittest/unittest.dart');
+
+final noVersion = 'no version';
+final disjointConstraint = 'disjoint';
+final couldNotSolve = 'unsolved';
+
+main() {
+ testResolve('no dependencies', {
+ 'myapp 0.0.0': {}
+ }, result: {
+ 'myapp': '0.0.0'
+ });
+
+ testResolve('simple dependency tree', {
+ 'myapp 0.0.0': {
+ 'a': '1.0.0',
+ 'b': '1.0.0'
+ },
+ 'a 1.0.0': {
+ 'aa': '1.0.0',
+ 'ab': '1.0.0'
+ },
+ 'aa 1.0.0': {},
+ 'ab 1.0.0': {},
+ 'b 1.0.0': {
+ 'ba': '1.0.0',
+ 'bb': '1.0.0'
+ },
+ 'ba 1.0.0': {},
+ 'bb 1.0.0': {}
+ }, result: {
+ 'myapp': '0.0.0',
+ 'a': '1.0.0',
+ 'aa': '1.0.0',
+ 'ab': '1.0.0',
+ 'b': '1.0.0',
+ 'ba': '1.0.0',
+ 'bb': '1.0.0'
+ });
+
+ testResolve('shared dependency with overlapping constraints', {
+ 'myapp 0.0.0': {
+ 'a': '1.0.0',
+ 'b': '1.0.0'
+ },
+ 'a 1.0.0': {
+ 'shared': '>=2.0.0 <4.0.0'
+ },
+ 'b 1.0.0': {
+ 'shared': '>=3.0.0 <5.0.0'
+ },
+ 'shared 2.0.0': {},
+ 'shared 3.0.0': {},
+ 'shared 3.6.9': {},
+ 'shared 4.0.0': {},
+ 'shared 5.0.0': {},
+ }, result: {
+ 'myapp': '0.0.0',
+ 'a': '1.0.0',
+ 'b': '1.0.0',
+ 'shared': '3.6.9'
+ });
+
+ testResolve('shared dependency where dependent version in turn affects '
+ 'other dependencies', {
+ 'myapp 0.0.0': {
+ 'foo': '<=1.0.2',
+ 'bar': '1.0.0'
+ },
+ 'foo 1.0.0': {},
+ 'foo 1.0.1': { 'bang': '1.0.0' },
+ 'foo 1.0.2': { 'whoop': '1.0.0' },
+ 'foo 1.0.3': { 'zoop': '1.0.0' },
+ 'bar 1.0.0': { 'foo': '<=1.0.1' },
+ 'bang 1.0.0': {},
+ 'whoop 1.0.0': {},
+ 'zoop 1.0.0': {}
+ }, result: {
+ 'myapp': '0.0.0',
+ 'foo': '1.0.1',
+ 'bar': '1.0.0',
+ 'bang': '1.0.0'
+ });
+
+ testResolve('dependency back onto root package', {
+ 'myapp 1.0.0': {
+ 'foo': '1.0.0'
+ },
+ 'foo 1.0.0': {
+ 'myapp': '>=1.0.0'
+ }
+ }, result: {
+ 'myapp': '1.0.0',
+ 'foo': '1.0.0'
+ });
+
+ testResolve("dependency back onto root package that doesn't contain root's "
+ "version", {
+ 'myapp 1.0.0': {
+ 'foo': '1.0.0'
+ },
+ 'foo 1.0.0': {
+ 'myapp': '>=2.0.0'
+ }
+ }, error: disjointConstraint);
+
+ testResolve('no version that matches requirement', {
+ 'myapp 0.0.0': {
+ 'foo': '>=1.0.0 <2.0.0'
+ },
+ 'foo 2.0.0': {},
+ 'foo 2.1.3': {}
+ }, error: noVersion);
+
+ testResolve('no version that matches combined constraint', {
+ 'myapp 0.0.0': {
+ 'foo': '1.0.0',
+ 'bar': '1.0.0'
+ },
+ 'foo 1.0.0': {
+ 'shared': '>=2.0.0 <3.0.0'
+ },
+ 'bar 1.0.0': {
+ 'shared': '>=2.9.0 <4.0.0'
+ },
+ 'shared 2.5.0': {},
+ 'shared 3.5.0': {}
+ }, error: noVersion);
+
+ testResolve('disjoint constraints', {
+ 'myapp 0.0.0': {
+ 'foo': '1.0.0',
+ 'bar': '1.0.0'
+ },
+ 'foo 1.0.0': {
+ 'shared': '<=2.0.0'
+ },
+ 'bar 1.0.0': {
+ 'shared': '>3.0.0'
+ },
+ 'shared 2.0.0': {},
+ 'shared 4.0.0': {}
+ }, error: disjointConstraint);
+
+ testResolve('unstable dependency graph', {
+ 'myapp 0.0.0': {
+ 'a': '>=1.0.0'
+ },
+ 'a 1.0.0': {},
+ 'a 2.0.0': {
+ 'b': '1.0.0'
+ },
+ 'b 1.0.0': {
+ 'a': '1.0.0'
+ }
+ }, error: couldNotSolve);
+
+// TODO(rnystrom): More stuff to test:
+// - Two packages depend on the same package, but from different sources. Should
+// fail.
+// - Depending on a non-existent package.
+// - Test that only a certain number requests are sent to the mock source so we
+// can keep track of server traffic.
+}
+
+testResolve(description, packages, [result, error]) {
+ test(description, () {
+ var sources = new SourceRegistry();
+ var source = new MockSource();
+ sources.register(source);
+ sources.setDefault(source.name);
+
+ // Build the test package graph.
+ var root;
+ packages.forEach((nameVersion, dependencies) {
+ var parts = nameVersion.split(' ');
+ var name = parts[0];
+ var version = parts[1];
+ var package = source.mockPackage(name, version, dependencies);
+ if (name == 'myapp') root = package;
+ });
+
+ // Clean up the expectation.
+ if (result != null) {
+ result.forEach((name, version) {
+ result[name] = new Version.parse(version);
+ });
+ }
+
+ // Resolve the versions.
+ var future = resolveVersions(sources, root);
+
+ if (result != null) {
+ expect(future, completion(recursivelyMatches(result)));
+ } else if (error == noVersion) {
+ expect(future, throwsA(new isInstanceOf<NoVersionException>()));
+ } else if (error == disjointConstraint) {
+ expect(future, throwsA(new isInstanceOf<DisjointConstraintException>()));
+ } else if (error == couldNotSolve) {
+ expect(future, throwsA(new isInstanceOf<CouldNotSolveException>()));
+ } else {
+ expect(future, throwsA(error));
+ }
+
+ // If we aren't expecting an error, print some debugging info if we get one.
+ if (error == null) {
+ future.handleException((ex) {
+ print(ex);
+ print(future.stackTrace);
+ return true;
+ });
+ }
+ });
+}
+
+class MockSource extends Source {
+ final Map<String, Map<Version, Package>> _packages;
+
+ String get name() => 'mock';
+ bool get shouldCache() => true;
+
+ MockSource()
+ : _packages = <Map<Version, Package>>{};
+
+ Future<List<Version>> getVersions(String name) {
+ return fakeAsync(() => _packages[name].getKeys());
+ }
+
+ Future<Pubspec> describe(String package, Version version) {
+ return fakeAsync(() {
+ return _packages[package][version].pubspec;
+ });
+ }
+
+ Future<bool> install(PackageId id, String path) {
+ throw 'no';
+ }
+
+ Package mockPackage(String name, String version, Map dependencyStrings) {
+ // Build the pubspec dependencies.
+ var dependencies = <PackageRef>[];
+ dependencyStrings.forEach((name, constraint) {
+ dependencies.add(new PackageRef(name, this,
+ new VersionConstraint.parse(constraint), name));
+ });
+
+ var pubspec = new Pubspec(new Version.parse(version), dependencies);
+ var package = new Package.inMemory(name, pubspec);
+
+ _packages.putIfAbsent(name, () => new Map<Version, Package>());
+ _packages[name][package.version] = package;
+ return package;
+ }
+}
+
+Future fakeAsync(callback()) {
+ var completer = new Completer();
+ new Timer(0, (_) {
+ completer.complete(callback());
+ });
+
+ return completer.future;
+}
« no previous file with comments | « utils/tests/pub/pubspec_test.dart ('k') | utils/tests/pub/version_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698