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

Side by Side Diff: utils/tests/pub/version_solver_test.dart

Issue 11445034: Better error messages for dependency conflicts. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tweak error messages. Created 8 years 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/pub/version_solver.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library pub_update_test; 5 library pub_update_test;
6 6
7 import 'dart:io'; 7 import 'dart:io';
8 import 'dart:isolate'; 8 import 'dart:isolate';
9 9
10 import '../../pub/lock_file.dart'; 10 import '../../pub/lock_file.dart';
11 import '../../pub/package.dart'; 11 import '../../pub/package.dart';
12 import '../../pub/pubspec.dart'; 12 import '../../pub/pubspec.dart';
13 import '../../pub/root_source.dart'; 13 import '../../pub/root_source.dart';
14 import '../../pub/source.dart'; 14 import '../../pub/source.dart';
15 import '../../pub/source_registry.dart'; 15 import '../../pub/source_registry.dart';
16 import '../../pub/system_cache.dart'; 16 import '../../pub/system_cache.dart';
17 import '../../pub/utils.dart'; 17 import '../../pub/utils.dart';
18 import '../../pub/version.dart'; 18 import '../../pub/version.dart';
19 import '../../pub/version_solver.dart'; 19 import '../../pub/version_solver.dart';
20 import '../../../pkg/unittest/lib/unittest.dart'; 20 import '../../../pkg/unittest/lib/unittest.dart';
21 21
22 final noVersion = 'no version'; 22 Matcher noVersion(List<String> packages) {
23 final disjointConstraint = 'disjoint'; 23 return predicate((x) {
24 final sourceMismatch = 'source mismatch'; 24 if (x is! NoVersionException) return false;
25 final descriptionMismatch = 'description mismatch'; 25
26 final couldNotSolve = 'unsolved'; 26 // Make sure the error string mentions the conflicting dependers.
27 var message = x.toString();
28 return packages.every((package) => message.contains(package));
29 }, "is a NoVersionException");
30 }
31
32 Matcher disjointConstraint(List<String> packages) {
33 return predicate((x) {
34 if (x is! DisjointConstraintException) return false;
35
36 // Make sure the error string mentions the conflicting dependers.
37 var message = x.toString();
38 return packages.every((package) => message.contains(package));
39 }, "is a DisjointConstraintException");
40 }
41
42 Matcher descriptionMismatch(String package1, String package2) {
43 return predicate((x) {
44 if (x is! DescriptionMismatchException) return false;
45
46 // Make sure the error string mentions the conflicting dependers.
47 if (!x.toString().contains(package1)) return false;
48 if (!x.toString().contains(package2)) return false;
49
50 return true;
51 }, "is a DescriptionMismatchException");
52 }
53
54 final couldNotSolve = predicate((x) => x is CouldNotSolveException,
55 "is a CouldNotSolveException");
56
57 Matcher sourceMismatch(String package1, String package2) {
58 return predicate((x) {
59 if (x is! SourceMismatchException) return false;
60
61 // Make sure the error string mentions the conflicting dependers.
62 if (!x.toString().contains(package1)) return false;
63 if (!x.toString().contains(package2)) return false;
64
65 return true;
66 }, "is a SourceMismatchException");
67 }
27 68
28 MockSource source1; 69 MockSource source1;
29 MockSource source2; 70 MockSource source2;
30 Source versionlessSource; 71 Source versionlessSource;
31 Source rootSource; 72 Source rootSource;
32 73
33 main() { 74 main() {
34 testResolve('no dependencies', { 75 testResolve('no dependencies', {
35 'myapp 0.0.0': {} 76 'myapp 0.0.0': {}
36 }, result: { 77 }, result: {
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 'myapp 1.0.0': { 272 'myapp 1.0.0': {
232 'foo': '1.0.0', 273 'foo': '1.0.0',
233 'bar': '1.0.0' 274 'bar': '1.0.0'
234 }, 275 },
235 'foo 1.0.0': { 276 'foo 1.0.0': {
236 'myapp': '>=1.0.0' 277 'myapp': '>=1.0.0'
237 }, 278 },
238 'bar 1.0.0': { 279 'bar 1.0.0': {
239 'myapp from mock2': '>=1.0.0' 280 'myapp from mock2': '>=1.0.0'
240 } 281 }
241 }, error: sourceMismatch); 282 }, error: sourceMismatch('foo', 'bar'));
242 283
243 testResolve('dependency back onto root package with wrong version', { 284 testResolve('dependency back onto root package with wrong version', {
244 'myapp 1.0.0': { 285 'myapp 1.0.0': {
245 'foo': '1.0.0' 286 'foo': '1.0.0'
246 }, 287 },
247 'foo 1.0.0': { 288 'foo 1.0.0': {
248 'myapp': '<1.0.0' 289 'myapp': '<1.0.0'
249 } 290 }
250 }, error: disjointConstraint); 291 }, error: disjointConstraint(['foo']));
251 292
252 testResolve('no version that matches requirement', { 293 testResolve('no version that matches requirement', {
253 'myapp 0.0.0': { 294 'myapp 0.0.0': {
254 'foo': '>=1.0.0 <2.0.0' 295 'foo': '>=1.0.0 <2.0.0'
255 }, 296 },
256 'foo 2.0.0': {}, 297 'foo 2.0.0': {},
257 'foo 2.1.3': {} 298 'foo 2.1.3': {}
258 }, error: noVersion); 299 }, error: noVersion(['myapp']));
259 300
260 testResolve('no version that matches combined constraint', { 301 testResolve('no version that matches combined constraint', {
261 'myapp 0.0.0': { 302 'myapp 0.0.0': {
262 'foo': '1.0.0', 303 'foo': '1.0.0',
263 'bar': '1.0.0' 304 'bar': '1.0.0'
264 }, 305 },
265 'foo 1.0.0': { 306 'foo 1.0.0': {
266 'shared': '>=2.0.0 <3.0.0' 307 'shared': '>=2.0.0 <3.0.0'
267 }, 308 },
268 'bar 1.0.0': { 309 'bar 1.0.0': {
269 'shared': '>=2.9.0 <4.0.0' 310 'shared': '>=2.9.0 <4.0.0'
270 }, 311 },
271 'shared 2.5.0': {}, 312 'shared 2.5.0': {},
272 'shared 3.5.0': {} 313 'shared 3.5.0': {}
273 }, error: noVersion); 314 }, error: noVersion(['foo', 'bar']));
274 315
275 testResolve('disjoint constraints', { 316 testResolve('disjoint constraints', {
276 'myapp 0.0.0': { 317 'myapp 0.0.0': {
277 'foo': '1.0.0', 318 'foo': '1.0.0',
278 'bar': '1.0.0' 319 'bar': '1.0.0'
279 }, 320 },
280 'foo 1.0.0': { 321 'foo 1.0.0': {
281 'shared': '<=2.0.0' 322 'shared': '<=2.0.0'
282 }, 323 },
283 'bar 1.0.0': { 324 'bar 1.0.0': {
284 'shared': '>3.0.0' 325 'shared': '>3.0.0'
285 }, 326 },
286 'shared 2.0.0': {}, 327 'shared 2.0.0': {},
287 'shared 4.0.0': {} 328 'shared 4.0.0': {}
288 }, error: disjointConstraint); 329 }, error: disjointConstraint(['foo', 'bar']));
289 330
290 testResolve('mismatched descriptions', { 331 testResolve('mismatched descriptions', {
291 'myapp 0.0.0': { 332 'myapp 0.0.0': {
292 'foo': '1.0.0', 333 'foo': '1.0.0',
293 'bar': '1.0.0' 334 'bar': '1.0.0'
294 }, 335 },
295 'foo 1.0.0': { 336 'foo 1.0.0': {
296 'shared-x': '1.0.0' 337 'shared-x': '1.0.0'
297 }, 338 },
298 'bar 1.0.0': { 339 'bar 1.0.0': {
299 'shared-y': '1.0.0' 340 'shared-y': '1.0.0'
300 }, 341 },
301 'shared-x 1.0.0': {}, 342 'shared-x 1.0.0': {},
302 'shared-y 1.0.0': {} 343 'shared-y 1.0.0': {}
303 }, error: descriptionMismatch); 344 }, error: descriptionMismatch('foo', 'bar'));
304 345
305 testResolve('mismatched sources', { 346 testResolve('mismatched sources', {
306 'myapp 0.0.0': { 347 'myapp 0.0.0': {
307 'foo': '1.0.0', 348 'foo': '1.0.0',
308 'bar': '1.0.0' 349 'bar': '1.0.0'
309 }, 350 },
310 'foo 1.0.0': { 351 'foo 1.0.0': {
311 'shared': '1.0.0' 352 'shared': '1.0.0'
312 }, 353 },
313 'bar 1.0.0': { 354 'bar 1.0.0': {
314 'shared from mock2': '1.0.0' 355 'shared from mock2': '1.0.0'
315 }, 356 },
316 'shared 1.0.0': {}, 357 'shared 1.0.0': {},
317 'shared 1.0.0 from mock2': {} 358 'shared 1.0.0 from mock2': {}
318 }, error: sourceMismatch); 359 }, error: sourceMismatch('foo', 'bar'));
319 360
320 testResolve('unstable dependency graph', { 361 testResolve('unstable dependency graph', {
321 'myapp 0.0.0': { 362 'myapp 0.0.0': {
322 'a': '>=1.0.0' 363 'a': '>=1.0.0'
323 }, 364 },
324 'a 1.0.0': {}, 365 'a 1.0.0': {},
325 'a 2.0.0': { 366 'a 2.0.0': {
326 'b': '1.0.0' 367 'b': '1.0.0'
327 }, 368 },
328 'b 1.0.0': { 369 'b 1.0.0': {
329 'a': '1.0.0' 370 'a': '1.0.0'
330 } 371 }
331 }, error: couldNotSolve); 372 }, error: couldNotSolve);
332 373
333 // TODO(rnystrom): More stuff to test: 374 // TODO(rnystrom): More stuff to test:
334 // - Two packages depend on the same package, but from different sources. Should
335 // fail.
336 // - Depending on a non-existent package. 375 // - Depending on a non-existent package.
337 // - Test that only a certain number requests are sent to the mock source so we 376 // - Test that only a certain number requests are sent to the mock source so we
338 // can keep track of server traffic. 377 // can keep track of server traffic.
339 } 378 }
340 379
341 testResolve(description, packages, {lockfile, result, error}) { 380 testResolve(description, packages, {lockfile, result, Matcher error}) {
342 test(description, () { 381 test(description, () {
343 var isNoVersionException = predicate((x)=> x is NoVersionException,
344 "is a NoVersionException");
345 var isDisjointConstraintException =
346 predicate((x)=> x is DisjointConstraintException,
347 " is a DisjointConstraintException");
348 var isSourceMismatchException =
349 predicate((x)=> x is SourceMismatchException,
350 "is a SourceMismatchException");
351 var isDescriptionMismatchException =
352 predicate((x)=> x is DescriptionMismatchException,
353 "is a DescriptionMismatchException");
354 var isCouldNotSolveException = predicate((x)=> x is CouldNotSolveException,
355 "is a CouldNotSolveException");
356
357 var cache = new SystemCache('.'); 382 var cache = new SystemCache('.');
358 source1 = new MockSource('mock1'); 383 source1 = new MockSource('mock1');
359 source2 = new MockSource('mock2'); 384 source2 = new MockSource('mock2');
360 versionlessSource = new MockVersionlessSource(); 385 versionlessSource = new MockVersionlessSource();
361 cache.register(source1); 386 cache.register(source1);
362 cache.register(source2); 387 cache.register(source2);
363 cache.register(versionlessSource); 388 cache.register(versionlessSource);
364 cache.sources.setDefault(source1.name); 389 cache.sources.setDefault(source1.name);
365 390
366 // Build the test package graph. 391 // Build the test package graph.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 439
415 if (result != null) { 440 if (result != null) {
416 expect(future, completion(predicate((actualResult) { 441 expect(future, completion(predicate((actualResult) {
417 for (var actualId in actualResult) { 442 for (var actualId in actualResult) {
418 if (!result.containsKey(actualId.name)) return false; 443 if (!result.containsKey(actualId.name)) return false;
419 var expectedId = result.remove(actualId.name); 444 var expectedId = result.remove(actualId.name);
420 if (actualId != expectedId) return false; 445 if (actualId != expectedId) return false;
421 } 446 }
422 return result.isEmpty; 447 return result.isEmpty;
423 }, 'packages to match $result'))); 448 }, 'packages to match $result')));
424 } else if (error == noVersion) { 449 } else if (error != null) {
425 expect(future, throwsA(isNoVersionException));
426 } else if (error == disjointConstraint) {
427 expect(future, throwsA(isDisjointConstraintException));
428 } else if (error == sourceMismatch) {
429 expect(future, throwsA(isSourceMismatchException));
430 } else if (error == descriptionMismatch) {
431 expect(future, throwsA(isDescriptionMismatchException));
432 } else if (error == couldNotSolve) {
433 expect(future, throwsA(isCouldNotSolveException));
434 } else {
435 expect(future, throwsA(error)); 450 expect(future, throwsA(error));
436 } 451 }
437 452
438 // If we aren't expecting an error, print some debugging info if we get one. 453 // If we aren't expecting an error, print some debugging info if we get one.
439 if (error == null) { 454 if (error == null) {
440 future.handleException((ex) { 455 future.handleException((ex) {
441 print(ex); 456 print(ex);
442 print(future.stackTrace); 457 print(future.stackTrace);
443 return true; 458 return true;
444 }); 459 });
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 var match = new RegExp(r"(.*) from (.*)").firstMatch(name); 554 var match = new RegExp(r"(.*) from (.*)").firstMatch(name);
540 if (match == null) return new Pair<String, Source>(name, source1); 555 if (match == null) return new Pair<String, Source>(name, source1);
541 switch (match[2]) { 556 switch (match[2]) {
542 case 'mock1': return new Pair<String, Source>(match[1], source1); 557 case 'mock1': return new Pair<String, Source>(match[1], source1);
543 case 'mock2': return new Pair<String, Source>(match[1], source2); 558 case 'mock2': return new Pair<String, Source>(match[1], source2);
544 case 'root': return new Pair<String, Source>(match[1], rootSource); 559 case 'root': return new Pair<String, Source>(match[1], rootSource);
545 case 'versionless': 560 case 'versionless':
546 return new Pair<String, Source>(match[1], versionlessSource); 561 return new Pair<String, Source>(match[1], versionlessSource);
547 } 562 }
548 } 563 }
OLDNEW
« no previous file with comments | « utils/pub/version_solver.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698