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 |
index 299ffaeb0aa5266d3cca177fac0b0349fd67042d..f3a68c6f1c53738a37c249d440ab3c64474f8438 100644 |
--- a/utils/tests/pub/version_solver_test.dart |
+++ b/utils/tests/pub/version_solver_test.dart |
@@ -11,14 +11,20 @@ |
#import('../../pub/pubspec.dart'); |
#import('../../pub/source.dart'); |
#import('../../pub/source_registry.dart'); |
+#import('../../pub/utils.dart'); |
#import('../../pub/version.dart'); |
#import('../../pub/version_solver.dart'); |
#import('../../../lib/unittest/unittest.dart'); |
final noVersion = 'no version'; |
final disjointConstraint = 'disjoint'; |
+final sourceMismatch = 'source mismatch'; |
+final descriptionMismatch = 'description mismatch'; |
final couldNotSolve = 'unsolved'; |
+Source source1; |
+Source source2; |
+ |
main() { |
testResolve('no dependencies', { |
'myapp 0.0.0': {} |
@@ -104,20 +110,7 @@ main() { |
'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); |
+ }, error: sourceMismatch); |
testResolve('no version that matches requirement', { |
'myapp 0.0.0': { |
@@ -157,6 +150,36 @@ main() { |
'shared 4.0.0': {} |
}, error: disjointConstraint); |
+ testResolve('mismatched descriptions', { |
+ 'myapp 0.0.0': { |
+ 'foo': '1.0.0', |
+ 'bar': '1.0.0' |
+ }, |
+ 'foo 1.0.0': { |
+ 'shared-x': '1.0.0' |
+ }, |
+ 'bar 1.0.0': { |
+ 'shared-y': '1.0.0' |
+ }, |
+ 'shared-x 1.0.0': {}, |
+ 'shared-y 1.0.0': {} |
+ }, error: descriptionMismatch); |
+ |
+ testResolve('mismatched sources', { |
+ 'myapp 0.0.0': { |
+ 'foo': '1.0.0', |
+ 'bar': '1.0.0' |
+ }, |
+ 'foo 1.0.0': { |
+ 'shared': '1.0.0' |
+ }, |
+ 'bar 1.0.0': { |
+ 'shared from mock2': '1.0.0' |
+ }, |
+ 'shared 1.0.0': {}, |
+ 'shared 1.0.0 from mock2': {} |
+ }, error: sourceMismatch); |
+ |
testResolve('unstable dependency graph', { |
'myapp 0.0.0': { |
'a': '>=1.0.0' |
@@ -181,16 +204,23 @@ main() { |
testResolve(description, packages, [result, error]) { |
test(description, () { |
var sources = new SourceRegistry(); |
- var source = new MockSource(); |
- sources.register(source); |
- sources.setDefault(source.name); |
+ source1 = new MockSource('mock1'); |
+ source2 = new MockSource('mock2'); |
+ sources.register(source1); |
+ sources.register(source2); |
+ sources.setDefault(source1.name); |
// Build the test package graph. |
var root; |
packages.forEach((nameVersion, dependencies) { |
+ var parsed = parseSource(nameVersion); |
+ nameVersion = parsed.first; |
+ var source = parsed.last; |
+ |
var parts = nameVersion.split(' '); |
var name = parts[0]; |
var version = parts[1]; |
+ |
var package = source.mockPackage(name, version, dependencies); |
if (name == 'myapp') { |
// Don't add the root package to the server, so we can verify that Pub |
@@ -218,6 +248,10 @@ testResolve(description, packages, [result, error]) { |
expect(future, throwsA(new isInstanceOf<NoVersionException>())); |
} else if (error == disjointConstraint) { |
expect(future, throwsA(new isInstanceOf<DisjointConstraintException>())); |
+ } else if (error == sourceMismatch) { |
+ expect(future, throwsA(new isInstanceOf<SourceMismatchException>())); |
+ } else if (error == descriptionMismatch) { |
+ expect(future, throwsA(new isInstanceOf<DescriptionMismatchException>())); |
} else if (error == couldNotSolve) { |
expect(future, throwsA(new isInstanceOf<CouldNotSolveException>())); |
} else { |
@@ -235,22 +269,30 @@ testResolve(description, packages, [result, error]) { |
}); |
} |
+/** |
+ * A source used for testing. This both creates mock package objects and acts as |
+ * a source for them. |
+ * |
+ * In order to support testing packages that have the same name but different |
+ * descriptions, a package's name is calculated by taking the description string |
+ * and stripping off any trailing hyphen followed by non-hyphen characters. |
+ */ |
class MockSource extends Source { |
final Map<String, Map<Version, Package>> _packages; |
- String get name() => 'mock'; |
+ final String name; |
bool get shouldCache() => true; |
- MockSource() |
+ MockSource(this.name) |
: _packages = <Map<Version, Package>>{}; |
Future<List<Version>> getVersions(String name) { |
return fakeAsync(() => _packages[name].getKeys()); |
} |
- Future<Pubspec> describe(String package, Version version) { |
+ Future<Pubspec> describe(PackageId id) { |
return fakeAsync(() { |
- return _packages[package][version].pubspec; |
+ return _packages[id.name][id.version].pubspec; |
}); |
} |
@@ -258,16 +300,18 @@ class MockSource extends Source { |
throw 'no'; |
} |
- Package mockPackage(String name, String version, Map dependencyStrings) { |
+ Package mockPackage(String description, 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 parsed = parseSource(name); |
+ dependencies.add(new PackageRef( |
+ parsed.last, new VersionConstraint.parse(constraint), parsed.first)); |
}); |
var pubspec = new Pubspec(new Version.parse(version), dependencies); |
- return new Package.inMemory(name, pubspec); |
+ return new Package.inMemory(description, pubspec); |
} |
void addPackage(Package package) { |
@@ -275,6 +319,9 @@ class MockSource extends Source { |
_packages[package.name][package.version] = package; |
return package; |
} |
+ |
+ String packageName(String description) => |
+ description.replaceFirst(new RegExp(@"-[^-]+$"), ""); |
} |
Future fakeAsync(callback()) { |
@@ -284,4 +331,13 @@ Future fakeAsync(callback()) { |
}); |
return completer.future; |
-} |
+} |
+ |
+Pair<String, Source> parseSource(String name) { |
+ var match = new RegExp(@"(.*) from (.*)").firstMatch(name); |
+ if (match == null) return new Pair<String, Source>(name, source1); |
+ switch (match[2]) { |
+ case 'mock1': return new Pair<String, Source>(match[1], source1); |
+ case 'mock2': return new Pair<String, Source>(match[1], source2); |
+ } |
+} |