| 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:async'; | 7 import 'dart:async'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 | 9 |
| 10 import '../../../pkg/unittest/lib/unittest.dart'; |
| 11 |
| 10 import '../../pub/lock_file.dart'; | 12 import '../../pub/lock_file.dart'; |
| 11 import '../../pub/package.dart'; | 13 import '../../pub/package.dart'; |
| 12 import '../../pub/pubspec.dart'; | 14 import '../../pub/pubspec.dart'; |
| 13 import '../../pub/source.dart'; | 15 import '../../pub/source.dart'; |
| 14 import '../../pub/source_registry.dart'; | 16 import '../../pub/source_registry.dart'; |
| 15 import '../../pub/system_cache.dart'; | 17 import '../../pub/system_cache.dart'; |
| 16 import '../../pub/utils.dart'; | 18 import '../../pub/utils.dart'; |
| 17 import '../../pub/version.dart'; | 19 import '../../pub/version.dart'; |
| 18 import '../../pub/version_solver.dart'; | 20 import '../../pub/version_solver.dart'; |
| 19 import '../../../pkg/unittest/lib/unittest.dart'; | 21 import 'test_pub.dart'; |
| 20 | 22 |
| 21 Matcher noVersion(List<String> packages) { | 23 Matcher noVersion(List<String> packages) { |
| 22 return predicate((x) { | 24 return predicate((x) { |
| 23 if (x is! NoVersionException) return false; | 25 if (x is! NoVersionException) return false; |
| 24 | 26 |
| 25 // Make sure the error string mentions the conflicting dependers. | 27 // Make sure the error string mentions the conflicting dependers. |
| 26 var message = x.toString(); | 28 var message = x.toString(); |
| 27 return packages.every((package) => message.contains(package)); | 29 return packages.every((package) => message.contains(package)); |
| 28 }, "is a NoVersionException"); | 30 }, "is a NoVersionException"); |
| 29 } | 31 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 | 65 |
| 64 return true; | 66 return true; |
| 65 }, "is a SourceMismatchException"); | 67 }, "is a SourceMismatchException"); |
| 66 } | 68 } |
| 67 | 69 |
| 68 MockSource source1; | 70 MockSource source1; |
| 69 MockSource source2; | 71 MockSource source2; |
| 70 Source versionlessSource; | 72 Source versionlessSource; |
| 71 | 73 |
| 72 main() { | 74 main() { |
| 75 initConfig(); |
| 76 |
| 73 testResolve('no dependencies', { | 77 testResolve('no dependencies', { |
| 74 'myapp 0.0.0': {} | 78 'myapp 0.0.0': {} |
| 75 }, result: { | 79 }, result: { |
| 76 'myapp from root': '0.0.0' | 80 'myapp from root': '0.0.0' |
| 77 }); | 81 }); |
| 78 | 82 |
| 79 testResolve('simple dependency tree', { | 83 testResolve('simple dependency tree', { |
| 80 'myapp 0.0.0': { | 84 'myapp 0.0.0': { |
| 81 'a': '1.0.0', | 85 'a': '1.0.0', |
| 82 'b': '1.0.0' | 86 'b': '1.0.0' |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 }, | 366 }, |
| 363 'a 1.0.0': {}, | 367 'a 1.0.0': {}, |
| 364 'a 2.0.0': { | 368 'a 2.0.0': { |
| 365 'b': '1.0.0' | 369 'b': '1.0.0' |
| 366 }, | 370 }, |
| 367 'b 1.0.0': { | 371 'b 1.0.0': { |
| 368 'a': '1.0.0' | 372 'a': '1.0.0' |
| 369 } | 373 } |
| 370 }, error: couldNotSolve); | 374 }, error: couldNotSolve); |
| 371 | 375 |
| 376 group('dev dependencies', () { |
| 377 testResolve("includes root package's dev dependencies", { |
| 378 'myapp 1.0.0': { |
| 379 '(dev) foo': '1.0.0', |
| 380 '(dev) bar': '1.0.0' |
| 381 }, |
| 382 'foo 1.0.0': {}, |
| 383 'bar 1.0.0': {} |
| 384 }, result: { |
| 385 'myapp from root': '1.0.0', |
| 386 'foo': '1.0.0', |
| 387 'bar': '1.0.0' |
| 388 }); |
| 389 |
| 390 testResolve("includes dev dependency's transitive dependencies", { |
| 391 'myapp 1.0.0': { |
| 392 '(dev) foo': '1.0.0' |
| 393 }, |
| 394 'foo 1.0.0': { |
| 395 'bar': '1.0.0' |
| 396 }, |
| 397 'bar 1.0.0': {} |
| 398 }, result: { |
| 399 'myapp from root': '1.0.0', |
| 400 'foo': '1.0.0', |
| 401 'bar': '1.0.0' |
| 402 }); |
| 403 |
| 404 testResolve("ignores transitive dependency's dev dependencies", { |
| 405 'myapp 1.0.0': { |
| 406 'foo': '1.0.0' |
| 407 }, |
| 408 'foo 1.0.0': { |
| 409 '(dev) bar': '1.0.0' |
| 410 }, |
| 411 'bar 1.0.0': {} |
| 412 }, result: { |
| 413 'myapp from root': '1.0.0', |
| 414 'foo': '1.0.0' |
| 415 }); |
| 416 }); |
| 417 } |
| 418 |
| 372 // TODO(rnystrom): More stuff to test: | 419 // TODO(rnystrom): More stuff to test: |
| 373 // - Depending on a non-existent package. | 420 // - Depending on a non-existent package. |
| 374 // - Test that only a certain number requests are sent to the mock source so we | 421 // - Test that only a certain number requests are sent to the mock source so we |
| 375 // can keep track of server traffic. | 422 // can keep track of server traffic. |
| 376 } | |
| 377 | 423 |
| 378 testResolve(description, packages, {lockfile, result, Matcher error}) { | 424 testResolve(description, packages, {lockfile, result, Matcher error}) { |
| 379 test(description, () { | 425 test(description, () { |
| 380 var cache = new SystemCache('.'); | 426 var cache = new SystemCache('.'); |
| 381 source1 = new MockSource('mock1'); | 427 source1 = new MockSource('mock1'); |
| 382 source2 = new MockSource('mock2'); | 428 source2 = new MockSource('mock2'); |
| 383 versionlessSource = new MockVersionlessSource(); | 429 versionlessSource = new MockVersionlessSource(); |
| 384 cache.register(source1); | 430 cache.register(source1); |
| 385 cache.register(source2); | 431 cache.register(source2); |
| 386 cache.register(versionlessSource); | 432 cache.register(versionlessSource); |
| 387 cache.sources.setDefault(source1.name); | 433 cache.sources.setDefault(source1.name); |
| 388 | 434 |
| 389 // Build the test package graph. | 435 // Build the test package graph. |
| 390 var root; | 436 var root; |
| 391 packages.forEach((nameVersion, dependencies) { | 437 packages.forEach((nameVersion, dependencies) { |
| 392 var parsed = parseSource(nameVersion); | 438 var parsed = parseSource(nameVersion, (isDev, nameVersion, source) { |
| 393 nameVersion = parsed.first; | 439 var parts = nameVersion.split(' '); |
| 394 var source = parsed.last; | 440 var name = parts[0]; |
| 441 var version = parts[1]; |
| 395 | 442 |
| 396 var parts = nameVersion.split(' '); | 443 var package = source1.mockPackage(name, version, dependencies); |
| 397 var name = parts[0]; | 444 if (name == 'myapp') { |
| 398 var version = parts[1]; | 445 // Don't add the root package to the server, so we can verify that Pub |
| 399 | 446 // doesn't try to look up information about the local package on the |
| 400 var package = source1.mockPackage(name, version, dependencies); | 447 // remote server. |
| 401 if (name == 'myapp') { | 448 root = package; |
| 402 // Don't add the root package to the server, so we can verify that Pub | 449 } else { |
| 403 // doesn't try to look up information about the local package on the | 450 source.addPackage(package); |
| 404 // remote server. | 451 } |
| 405 root = package; | 452 }); |
| 406 } else { | |
| 407 source.addPackage(package); | |
| 408 } | |
| 409 }); | 453 }); |
| 410 | 454 |
| 411 // Clean up the expectation. | 455 // Clean up the expectation. |
| 412 if (result != null) { | 456 if (result != null) { |
| 413 var newResult = {}; | 457 var newResult = {}; |
| 414 result.forEach((name, version) { | 458 result.forEach((name, version) { |
| 415 var parsed = parseSource(name); | 459 parseSource(name, (isDev, name, source) { |
| 416 name = parsed.first; | 460 version = new Version.parse(version); |
| 417 var source = parsed.last; | 461 newResult[name] = new PackageId(name, source, version, name); |
| 418 version = new Version.parse(version); | 462 }); |
| 419 newResult[name] = new PackageId(name, source, version, name); | |
| 420 }); | 463 }); |
| 421 result = newResult; | 464 result = newResult; |
| 422 } | 465 } |
| 423 | 466 |
| 424 var realLockFile = new LockFile.empty(); | 467 var realLockFile = new LockFile.empty(); |
| 425 if (lockfile != null) { | 468 if (lockfile != null) { |
| 426 lockfile.forEach((name, version) { | 469 lockfile.forEach((name, version) { |
| 427 version = new Version.parse(version); | 470 version = new Version.parse(version); |
| 428 realLockFile.packages[name] = | 471 realLockFile.packages[name] = |
| 429 new PackageId(name, source1, version, name); | 472 new PackageId(name, source1, version, name); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 } | 518 } |
| 476 | 519 |
| 477 Future<bool> install(PackageId id, String path) { | 520 Future<bool> install(PackageId id, String path) { |
| 478 throw 'no'; | 521 throw 'no'; |
| 479 } | 522 } |
| 480 | 523 |
| 481 Package mockPackage(String description, String version, | 524 Package mockPackage(String description, String version, |
| 482 Map dependencyStrings) { | 525 Map dependencyStrings) { |
| 483 // Build the pubspec dependencies. | 526 // Build the pubspec dependencies. |
| 484 var dependencies = <PackageRef>[]; | 527 var dependencies = <PackageRef>[]; |
| 528 var devDependencies = <PackageRef>[]; |
| 529 |
| 485 dependencyStrings.forEach((name, constraint) { | 530 dependencyStrings.forEach((name, constraint) { |
| 486 var parsed = parseSource(name); | 531 parseSource(name, (isDev, name, source) { |
| 487 var description = parsed.first; | 532 var packageName = name.replaceFirst(new RegExp(r"-[^-]+$"), ""); |
| 488 var packageName = description.replaceFirst(new RegExp(r"-[^-]+$"), ""); | 533 var ref = new PackageRef(packageName, source, |
| 489 dependencies.add(new PackageRef(packageName, parsed.last, | 534 new VersionConstraint.parse(constraint), name); |
| 490 new VersionConstraint.parse(constraint), description)); | 535 |
| 536 if (isDev) { |
| 537 devDependencies.add(ref); |
| 538 } else { |
| 539 dependencies.add(ref); |
| 540 } |
| 541 }); |
| 491 }); | 542 }); |
| 492 | 543 |
| 493 var pubspec = new Pubspec( | 544 var pubspec = new Pubspec( |
| 494 description, new Version.parse(version), dependencies, | 545 description, new Version.parse(version), dependencies, devDependencies, |
| 495 new PubspecEnvironment()); | 546 new PubspecEnvironment()); |
| 496 return new Package.inMemory(pubspec); | 547 return new Package.inMemory(pubspec); |
| 497 } | 548 } |
| 498 | 549 |
| 499 void addPackage(Package package) { | 550 void addPackage(Package package) { |
| 500 _packages.putIfAbsent(package.name, () => new Map<Version, Package>()); | 551 _packages.putIfAbsent(package.name, () => new Map<Version, Package>()); |
| 501 _packages[package.name][package.version] = package; | 552 _packages[package.name][package.version] = package; |
| 502 } | 553 } |
| 503 } | 554 } |
| 504 | 555 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 519 | 570 |
| 520 Future<Pubspec> describe(PackageId id) { | 571 Future<Pubspec> describe(PackageId id) { |
| 521 return new Future<Pubspec>.immediate(_packages[id.description].pubspec); | 572 return new Future<Pubspec>.immediate(_packages[id.description].pubspec); |
| 522 } | 573 } |
| 523 | 574 |
| 524 void addPackage(Package package) { | 575 void addPackage(Package package) { |
| 525 _packages[package.name] = package; | 576 _packages[package.name] = package; |
| 526 } | 577 } |
| 527 } | 578 } |
| 528 | 579 |
| 529 Pair<String, Source> parseSource(String name) { | 580 void parseSource(String description, |
| 530 var match = new RegExp(r"(.*) from (.*)").firstMatch(name); | 581 callback(bool isDev, String name, Source source)) { |
| 531 if (match == null) return new Pair<String, Source>(name, source1); | 582 var isDev = false; |
| 532 switch (match[2]) { | 583 |
| 533 case 'mock1': return new Pair<String, Source>(match[1], source1); | 584 if (description.startsWith("(dev) ")) { |
| 534 case 'mock2': return new Pair<String, Source>(match[1], source2); | 585 description = description.substring("(dev) ".length); |
| 535 case 'root': return new Pair<String, Source>(match[1], null); | 586 isDev = true; |
| 536 case 'versionless': | |
| 537 return new Pair<String, Source>(match[1], versionlessSource); | |
| 538 } | 587 } |
| 588 |
| 589 var name = description; |
| 590 var source = source1; |
| 591 |
| 592 var sourceNames = { |
| 593 'mock1': source1, |
| 594 'mock2': source2, |
| 595 'root': null, |
| 596 'versionless': versionlessSource |
| 597 }; |
| 598 |
| 599 var match = new RegExp(r"(.*) from (.*)").firstMatch(description); |
| 600 if (match != null) { |
| 601 name = match[1]; |
| 602 source = sourceNames[match[2]]; |
| 603 } |
| 604 |
| 605 callback(isDev, name, source); |
| 539 } | 606 } |
| OLD | NEW |