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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « utils/tests/pub/pubspec_test.dart ('k') | utils/tests/pub/version_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
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.
4
5 #library('pub_update_test');
6
7 #import('dart:io');
8
9 #import('../../pub/package.dart');
10 #import('../../pub/pubspec.dart');
11 #import('../../pub/source.dart');
12 #import('../../pub/source_registry.dart');
13 #import('../../pub/version.dart');
14 #import('../../pub/version_solver.dart');
15 #import('../../../lib/unittest/unittest.dart');
16
17 final noVersion = 'no version';
18 final disjointConstraint = 'disjoint';
19 final couldNotSolve = 'unsolved';
20
21 main() {
22 testResolve('no dependencies', {
23 'myapp 0.0.0': {}
24 }, result: {
25 'myapp': '0.0.0'
26 });
27
28 testResolve('simple dependency tree', {
29 'myapp 0.0.0': {
30 'a': '1.0.0',
31 'b': '1.0.0'
32 },
33 'a 1.0.0': {
34 'aa': '1.0.0',
35 'ab': '1.0.0'
36 },
37 'aa 1.0.0': {},
38 'ab 1.0.0': {},
39 'b 1.0.0': {
40 'ba': '1.0.0',
41 'bb': '1.0.0'
42 },
43 'ba 1.0.0': {},
44 'bb 1.0.0': {}
45 }, result: {
46 'myapp': '0.0.0',
47 'a': '1.0.0',
48 'aa': '1.0.0',
49 'ab': '1.0.0',
50 'b': '1.0.0',
51 'ba': '1.0.0',
52 'bb': '1.0.0'
53 });
54
55 testResolve('shared dependency with overlapping constraints', {
56 'myapp 0.0.0': {
57 'a': '1.0.0',
58 'b': '1.0.0'
59 },
60 'a 1.0.0': {
61 'shared': '>=2.0.0 <4.0.0'
62 },
63 'b 1.0.0': {
64 'shared': '>=3.0.0 <5.0.0'
65 },
66 'shared 2.0.0': {},
67 'shared 3.0.0': {},
68 'shared 3.6.9': {},
69 'shared 4.0.0': {},
70 'shared 5.0.0': {},
71 }, result: {
72 'myapp': '0.0.0',
73 'a': '1.0.0',
74 'b': '1.0.0',
75 'shared': '3.6.9'
76 });
77
78 testResolve('shared dependency where dependent version in turn affects '
79 'other dependencies', {
80 'myapp 0.0.0': {
81 'foo': '<=1.0.2',
82 'bar': '1.0.0'
83 },
84 'foo 1.0.0': {},
85 'foo 1.0.1': { 'bang': '1.0.0' },
86 'foo 1.0.2': { 'whoop': '1.0.0' },
87 'foo 1.0.3': { 'zoop': '1.0.0' },
88 'bar 1.0.0': { 'foo': '<=1.0.1' },
89 'bang 1.0.0': {},
90 'whoop 1.0.0': {},
91 'zoop 1.0.0': {}
92 }, result: {
93 'myapp': '0.0.0',
94 'foo': '1.0.1',
95 'bar': '1.0.0',
96 'bang': '1.0.0'
97 });
98
99 testResolve('dependency back onto root package', {
100 'myapp 1.0.0': {
101 'foo': '1.0.0'
102 },
103 'foo 1.0.0': {
104 'myapp': '>=1.0.0'
105 }
106 }, result: {
107 'myapp': '1.0.0',
108 'foo': '1.0.0'
109 });
110
111 testResolve("dependency back onto root package that doesn't contain root's "
112 "version", {
113 'myapp 1.0.0': {
114 'foo': '1.0.0'
115 },
116 'foo 1.0.0': {
117 'myapp': '>=2.0.0'
118 }
119 }, error: disjointConstraint);
120
121 testResolve('no version that matches requirement', {
122 'myapp 0.0.0': {
123 'foo': '>=1.0.0 <2.0.0'
124 },
125 'foo 2.0.0': {},
126 'foo 2.1.3': {}
127 }, error: noVersion);
128
129 testResolve('no version that matches combined constraint', {
130 'myapp 0.0.0': {
131 'foo': '1.0.0',
132 'bar': '1.0.0'
133 },
134 'foo 1.0.0': {
135 'shared': '>=2.0.0 <3.0.0'
136 },
137 'bar 1.0.0': {
138 'shared': '>=2.9.0 <4.0.0'
139 },
140 'shared 2.5.0': {},
141 'shared 3.5.0': {}
142 }, error: noVersion);
143
144 testResolve('disjoint constraints', {
145 'myapp 0.0.0': {
146 'foo': '1.0.0',
147 'bar': '1.0.0'
148 },
149 'foo 1.0.0': {
150 'shared': '<=2.0.0'
151 },
152 'bar 1.0.0': {
153 'shared': '>3.0.0'
154 },
155 'shared 2.0.0': {},
156 'shared 4.0.0': {}
157 }, error: disjointConstraint);
158
159 testResolve('unstable dependency graph', {
160 'myapp 0.0.0': {
161 'a': '>=1.0.0'
162 },
163 'a 1.0.0': {},
164 'a 2.0.0': {
165 'b': '1.0.0'
166 },
167 'b 1.0.0': {
168 'a': '1.0.0'
169 }
170 }, error: couldNotSolve);
171
172 // TODO(rnystrom): More stuff to test:
173 // - Two packages depend on the same package, but from different sources. Should
174 // fail.
175 // - Depending on a non-existent package.
176 // - Test that only a certain number requests are sent to the mock source so we
177 // can keep track of server traffic.
178 }
179
180 testResolve(description, packages, [result, error]) {
181 test(description, () {
182 var sources = new SourceRegistry();
183 var source = new MockSource();
184 sources.register(source);
185 sources.setDefault(source.name);
186
187 // Build the test package graph.
188 var root;
189 packages.forEach((nameVersion, dependencies) {
190 var parts = nameVersion.split(' ');
191 var name = parts[0];
192 var version = parts[1];
193 var package = source.mockPackage(name, version, dependencies);
194 if (name == 'myapp') root = package;
195 });
196
197 // Clean up the expectation.
198 if (result != null) {
199 result.forEach((name, version) {
200 result[name] = new Version.parse(version);
201 });
202 }
203
204 // Resolve the versions.
205 var future = resolveVersions(sources, root);
206
207 if (result != null) {
208 expect(future, completion(recursivelyMatches(result)));
209 } else if (error == noVersion) {
210 expect(future, throwsA(new isInstanceOf<NoVersionException>()));
211 } else if (error == disjointConstraint) {
212 expect(future, throwsA(new isInstanceOf<DisjointConstraintException>()));
213 } else if (error == couldNotSolve) {
214 expect(future, throwsA(new isInstanceOf<CouldNotSolveException>()));
215 } else {
216 expect(future, throwsA(error));
217 }
218
219 // If we aren't expecting an error, print some debugging info if we get one.
220 if (error == null) {
221 future.handleException((ex) {
222 print(ex);
223 print(future.stackTrace);
224 return true;
225 });
226 }
227 });
228 }
229
230 class MockSource extends Source {
231 final Map<String, Map<Version, Package>> _packages;
232
233 String get name() => 'mock';
234 bool get shouldCache() => true;
235
236 MockSource()
237 : _packages = <Map<Version, Package>>{};
238
239 Future<List<Version>> getVersions(String name) {
240 return fakeAsync(() => _packages[name].getKeys());
241 }
242
243 Future<Pubspec> describe(String package, Version version) {
244 return fakeAsync(() {
245 return _packages[package][version].pubspec;
246 });
247 }
248
249 Future<bool> install(PackageId id, String path) {
250 throw 'no';
251 }
252
253 Package mockPackage(String name, String version, Map dependencyStrings) {
254 // Build the pubspec dependencies.
255 var dependencies = <PackageRef>[];
256 dependencyStrings.forEach((name, constraint) {
257 dependencies.add(new PackageRef(name, this,
258 new VersionConstraint.parse(constraint), name));
259 });
260
261 var pubspec = new Pubspec(new Version.parse(version), dependencies);
262 var package = new Package.inMemory(name, pubspec);
263
264 _packages.putIfAbsent(name, () => new Map<Version, Package>());
265 _packages[name][package.version] = package;
266 return package;
267 }
268 }
269
270 Future fakeAsync(callback()) {
271 var completer = new Completer();
272 new Timer(0, (_) {
273 completer.complete(callback());
274 });
275
276 return completer.future;
277 }
OLDNEW
« 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