OLD | NEW |
---|---|
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) { |
nweiz
2012/12/06 00:58:55
I think the unittest style would have this be "isN
| |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |