| 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_upgrade_test; | 5 library pub_upgrade_test; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:pub_semver/pub_semver.dart'; | 9 import 'package:pub_semver/pub_semver.dart'; |
| 10 import 'package:unittest/unittest.dart'; | 10 import 'package:unittest/unittest.dart'; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 'shared 3.6.9': {}, | 96 'shared 3.6.9': {}, |
| 97 'shared 4.0.0': {}, | 97 'shared 4.0.0': {}, |
| 98 'shared 5.0.0': {}, | 98 'shared 5.0.0': {}, |
| 99 }, result: { | 99 }, result: { |
| 100 'myapp from root': '0.0.0', | 100 'myapp from root': '0.0.0', |
| 101 'a': '1.0.0', | 101 'a': '1.0.0', |
| 102 'b': '1.0.0', | 102 'b': '1.0.0', |
| 103 'shared': '3.6.9' | 103 'shared': '3.6.9' |
| 104 }); | 104 }); |
| 105 | 105 |
| 106 testResolve('shared dependency where dependent version in turn affects ' | 106 testResolve( |
| 107 'other dependencies', { | 107 'shared dependency where dependent version in turn affects ' |
| 108 'other dependencies', |
| 109 { |
| 108 'myapp 0.0.0': { | 110 'myapp 0.0.0': { |
| 109 'foo': '<=1.0.2', | 111 'foo': '<=1.0.2', |
| 110 'bar': '1.0.0' | 112 'bar': '1.0.0' |
| 111 }, | 113 }, |
| 112 'foo 1.0.0': {}, | 114 'foo 1.0.0': {}, |
| 113 'foo 1.0.1': { 'bang': '1.0.0' }, | 115 'foo 1.0.1': { |
| 114 'foo 1.0.2': { 'whoop': '1.0.0' }, | 116 'bang': '1.0.0' |
| 115 'foo 1.0.3': { 'zoop': '1.0.0' }, | 117 }, |
| 116 'bar 1.0.0': { 'foo': '<=1.0.1' }, | 118 'foo 1.0.2': { |
| 119 'whoop': '1.0.0' |
| 120 }, |
| 121 'foo 1.0.3': { |
| 122 'zoop': '1.0.0' |
| 123 }, |
| 124 'bar 1.0.0': { |
| 125 'foo': '<=1.0.1' |
| 126 }, |
| 117 'bang 1.0.0': {}, | 127 'bang 1.0.0': {}, |
| 118 'whoop 1.0.0': {}, | 128 'whoop 1.0.0': {}, |
| 119 'zoop 1.0.0': {} | 129 'zoop 1.0.0': {} |
| 120 }, result: { | 130 }, result: { |
| 121 'myapp from root': '0.0.0', | 131 'myapp from root': '0.0.0', |
| 122 'foo': '1.0.1', | 132 'foo': '1.0.1', |
| 123 'bar': '1.0.0', | 133 'bar': '1.0.0', |
| 124 'bang': '1.0.0' | 134 'bang': '1.0.0' |
| 125 }, maxTries: 2); | 135 }, maxTries: 2); |
| 126 | 136 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 139 'foo': '1.0.0', | 149 'foo': '1.0.0', |
| 140 'bar': '1.0.0' | 150 'bar': '1.0.0' |
| 141 }); | 151 }); |
| 142 } | 152 } |
| 143 | 153 |
| 144 withLockFile() { | 154 withLockFile() { |
| 145 testResolve('with compatible locked dependency', { | 155 testResolve('with compatible locked dependency', { |
| 146 'myapp 0.0.0': { | 156 'myapp 0.0.0': { |
| 147 'foo': 'any' | 157 'foo': 'any' |
| 148 }, | 158 }, |
| 149 'foo 1.0.0': { 'bar': '1.0.0' }, | 159 'foo 1.0.0': { |
| 150 'foo 1.0.1': { 'bar': '1.0.1' }, | 160 'bar': '1.0.0' |
| 151 'foo 1.0.2': { 'bar': '1.0.2' }, | 161 }, |
| 162 'foo 1.0.1': { |
| 163 'bar': '1.0.1' |
| 164 }, |
| 165 'foo 1.0.2': { |
| 166 'bar': '1.0.2' |
| 167 }, |
| 152 'bar 1.0.0': {}, | 168 'bar 1.0.0': {}, |
| 153 'bar 1.0.1': {}, | 169 'bar 1.0.1': {}, |
| 154 'bar 1.0.2': {} | 170 'bar 1.0.2': {} |
| 155 }, lockfile: { | 171 }, lockfile: { |
| 156 'foo': '1.0.1' | 172 'foo': '1.0.1' |
| 157 }, result: { | 173 }, result: { |
| 158 'myapp from root': '0.0.0', | 174 'myapp from root': '0.0.0', |
| 159 'foo': '1.0.1', | 175 'foo': '1.0.1', |
| 160 'bar': '1.0.1' | 176 'bar': '1.0.1' |
| 161 }); | 177 }); |
| 162 | 178 |
| 163 testResolve('with incompatible locked dependency', { | 179 testResolve('with incompatible locked dependency', { |
| 164 'myapp 0.0.0': { | 180 'myapp 0.0.0': { |
| 165 'foo': '>1.0.1' | 181 'foo': '>1.0.1' |
| 166 }, | 182 }, |
| 167 'foo 1.0.0': { 'bar': '1.0.0' }, | 183 'foo 1.0.0': { |
| 168 'foo 1.0.1': { 'bar': '1.0.1' }, | 184 'bar': '1.0.0' |
| 169 'foo 1.0.2': { 'bar': '1.0.2' }, | 185 }, |
| 186 'foo 1.0.1': { |
| 187 'bar': '1.0.1' |
| 188 }, |
| 189 'foo 1.0.2': { |
| 190 'bar': '1.0.2' |
| 191 }, |
| 170 'bar 1.0.0': {}, | 192 'bar 1.0.0': {}, |
| 171 'bar 1.0.1': {}, | 193 'bar 1.0.1': {}, |
| 172 'bar 1.0.2': {} | 194 'bar 1.0.2': {} |
| 173 }, lockfile: { | 195 }, lockfile: { |
| 174 'foo': '1.0.1' | 196 'foo': '1.0.1' |
| 175 }, result: { | 197 }, result: { |
| 176 'myapp from root': '0.0.0', | 198 'myapp from root': '0.0.0', |
| 177 'foo': '1.0.2', | 199 'foo': '1.0.2', |
| 178 'bar': '1.0.2' | 200 'bar': '1.0.2' |
| 179 }); | 201 }); |
| 180 | 202 |
| 181 testResolve('with unrelated locked dependency', { | 203 testResolve('with unrelated locked dependency', { |
| 182 'myapp 0.0.0': { | 204 'myapp 0.0.0': { |
| 183 'foo': 'any' | 205 'foo': 'any' |
| 184 }, | 206 }, |
| 185 'foo 1.0.0': { 'bar': '1.0.0' }, | 207 'foo 1.0.0': { |
| 186 'foo 1.0.1': { 'bar': '1.0.1' }, | 208 'bar': '1.0.0' |
| 187 'foo 1.0.2': { 'bar': '1.0.2' }, | 209 }, |
| 210 'foo 1.0.1': { |
| 211 'bar': '1.0.1' |
| 212 }, |
| 213 'foo 1.0.2': { |
| 214 'bar': '1.0.2' |
| 215 }, |
| 188 'bar 1.0.0': {}, | 216 'bar 1.0.0': {}, |
| 189 'bar 1.0.1': {}, | 217 'bar 1.0.1': {}, |
| 190 'bar 1.0.2': {}, | 218 'bar 1.0.2': {}, |
| 191 'baz 1.0.0': {} | 219 'baz 1.0.0': {} |
| 192 }, lockfile: { | 220 }, lockfile: { |
| 193 'baz': '1.0.0' | 221 'baz': '1.0.0' |
| 194 }, result: { | 222 }, result: { |
| 195 'myapp from root': '0.0.0', | 223 'myapp from root': '0.0.0', |
| 196 'foo': '1.0.2', | 224 'foo': '1.0.2', |
| 197 'bar': '1.0.2' | 225 'bar': '1.0.2' |
| 198 }); | 226 }); |
| 199 | 227 |
| 200 testResolve('unlocks dependencies if necessary to ensure that a new ' | 228 testResolve( |
| 201 'dependency is satisfied', { | 229 'unlocks dependencies if necessary to ensure that a new ' |
| 230 'dependency is satisfied', |
| 231 { |
| 202 'myapp 0.0.0': { | 232 'myapp 0.0.0': { |
| 203 'foo': 'any', | 233 'foo': 'any', |
| 204 'newdep': 'any' | 234 'newdep': 'any' |
| 205 }, | 235 }, |
| 206 'foo 1.0.0': { 'bar': '<2.0.0' }, | 236 'foo 1.0.0': { |
| 207 'bar 1.0.0': { 'baz': '<2.0.0' }, | 237 'bar': '<2.0.0' |
| 208 'baz 1.0.0': { 'qux': '<2.0.0' }, | 238 }, |
| 239 'bar 1.0.0': { |
| 240 'baz': '<2.0.0' |
| 241 }, |
| 242 'baz 1.0.0': { |
| 243 'qux': '<2.0.0' |
| 244 }, |
| 209 'qux 1.0.0': {}, | 245 'qux 1.0.0': {}, |
| 210 'foo 2.0.0': { 'bar': '<3.0.0' }, | 246 'foo 2.0.0': { |
| 211 'bar 2.0.0': { 'baz': '<3.0.0' }, | 247 'bar': '<3.0.0' |
| 212 'baz 2.0.0': { 'qux': '<3.0.0' }, | 248 }, |
| 249 'bar 2.0.0': { |
| 250 'baz': '<3.0.0' |
| 251 }, |
| 252 'baz 2.0.0': { |
| 253 'qux': '<3.0.0' |
| 254 }, |
| 213 'qux 2.0.0': {}, | 255 'qux 2.0.0': {}, |
| 214 'newdep 2.0.0': { 'baz': '>=1.5.0' } | 256 'newdep 2.0.0': { |
| 257 'baz': '>=1.5.0' |
| 258 } |
| 215 }, lockfile: { | 259 }, lockfile: { |
| 216 'foo': '1.0.0', | 260 'foo': '1.0.0', |
| 217 'bar': '1.0.0', | 261 'bar': '1.0.0', |
| 218 'baz': '1.0.0', | 262 'baz': '1.0.0', |
| 219 'qux': '1.0.0' | 263 'qux': '1.0.0' |
| 220 }, result: { | 264 }, result: { |
| 221 'myapp from root': '0.0.0', | 265 'myapp from root': '0.0.0', |
| 222 'foo': '2.0.0', | 266 'foo': '2.0.0', |
| 223 'bar': '2.0.0', | 267 'bar': '2.0.0', |
| 224 'baz': '2.0.0', | 268 'baz': '2.0.0', |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 "angular 0.9.11": { | 474 "angular 0.9.11": { |
| 431 "di": ">=0.0.32 <0.1.0", | 475 "di": ">=0.0.32 <0.1.0", |
| 432 "collection": ">=0.9.1 <1.0.0" | 476 "collection": ">=0.9.1 <1.0.0" |
| 433 }, | 477 }, |
| 434 "angular 0.9.10": { | 478 "angular 0.9.10": { |
| 435 "di": ">=0.0.32 <0.1.0", | 479 "di": ">=0.0.32 <0.1.0", |
| 436 "collection": ">=0.9.1 <1.0.0" | 480 "collection": ">=0.9.1 <1.0.0" |
| 437 }, | 481 }, |
| 438 "collection 0.9.0": {}, | 482 "collection 0.9.0": {}, |
| 439 "collection 0.9.1": {}, | 483 "collection 0.9.1": {}, |
| 440 "di 0.0.37": {"analyzer": ">=0.13.0 <0.14.0"}, | 484 "di 0.0.37": { |
| 441 "di 0.0.36": {"analyzer": ">=0.13.0 <0.14.0"} | 485 "analyzer": ">=0.13.0 <0.14.0" |
| 486 }, |
| 487 "di 0.0.36": { |
| 488 "analyzer": ">=0.13.0 <0.14.0" |
| 489 } |
| 442 }, error: noVersion(['myapp', 'angular', 'collection']), maxTries: 9); | 490 }, error: noVersion(['myapp', 'angular', 'collection']), maxTries: 9); |
| 443 } | 491 } |
| 444 | 492 |
| 445 badSource() { | 493 badSource() { |
| 446 testResolve('fail if the root package has a bad source in dep', { | 494 testResolve('fail if the root package has a bad source in dep', { |
| 447 'myapp 0.0.0': { | 495 'myapp 0.0.0': { |
| 448 'foo from bad': 'any' | 496 'foo from bad': 'any' |
| 449 }, | 497 }, |
| 450 }, error: unknownSource('myapp', 'foo', 'bad')); | 498 }, error: unknownSource('myapp', 'foo', 'bad')); |
| 451 | 499 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 531 }, result: { | 579 }, result: { |
| 532 'myapp from root': '0.0.0', | 580 'myapp from root': '0.0.0', |
| 533 'a': '2.0.0', | 581 'a': '2.0.0', |
| 534 'b': '1.0.0', | 582 'b': '1.0.0', |
| 535 'c': '2.0.0' | 583 'c': '2.0.0' |
| 536 }, maxTries: 2); | 584 }, maxTries: 2); |
| 537 | 585 |
| 538 // Only one version of baz, so foo and bar will have to downgrade until they | 586 // Only one version of baz, so foo and bar will have to downgrade until they |
| 539 // reach it. | 587 // reach it. |
| 540 testResolve('simple transitive', { | 588 testResolve('simple transitive', { |
| 541 'myapp 0.0.0': {'foo': 'any'}, | 589 'myapp 0.0.0': { |
| 542 'foo 1.0.0': {'bar': '1.0.0'}, | 590 'foo': 'any' |
| 543 'foo 2.0.0': {'bar': '2.0.0'}, | 591 }, |
| 544 'foo 3.0.0': {'bar': '3.0.0'}, | 592 'foo 1.0.0': { |
| 545 'bar 1.0.0': {'baz': 'any'}, | 593 'bar': '1.0.0' |
| 546 'bar 2.0.0': {'baz': '2.0.0'}, | 594 }, |
| 547 'bar 3.0.0': {'baz': '3.0.0'}, | 595 'foo 2.0.0': { |
| 596 'bar': '2.0.0' |
| 597 }, |
| 598 'foo 3.0.0': { |
| 599 'bar': '3.0.0' |
| 600 }, |
| 601 'bar 1.0.0': { |
| 602 'baz': 'any' |
| 603 }, |
| 604 'bar 2.0.0': { |
| 605 'baz': '2.0.0' |
| 606 }, |
| 607 'bar 3.0.0': { |
| 608 'baz': '3.0.0' |
| 609 }, |
| 548 'baz 1.0.0': {} | 610 'baz 1.0.0': {} |
| 549 }, result: { | 611 }, result: { |
| 550 'myapp from root': '0.0.0', | 612 'myapp from root': '0.0.0', |
| 551 'foo': '1.0.0', | 613 'foo': '1.0.0', |
| 552 'bar': '1.0.0', | 614 'bar': '1.0.0', |
| 553 'baz': '1.0.0' | 615 'baz': '1.0.0' |
| 554 }, maxTries: 3); | 616 }, maxTries: 3); |
| 555 | 617 |
| 556 // This ensures it doesn't exhaustively search all versions of b when it's | 618 // This ensures it doesn't exhaustively search all versions of b when it's |
| 557 // a-2.0.0 whose dependency on c-2.0.0-nonexistent led to the problem. We | 619 // a-2.0.0 whose dependency on c-2.0.0-nonexistent led to the problem. We |
| 558 // make sure b has more versions than a so that the solver tries a first | 620 // make sure b has more versions than a so that the solver tries a first |
| 559 // since it sorts sibling dependencies by number of versions. | 621 // since it sorts sibling dependencies by number of versions. |
| 560 testResolve('backjump to nearer unsatisfied package', { | 622 testResolve('backjump to nearer unsatisfied package', { |
| 561 'myapp 0.0.0': { | 623 'myapp 0.0.0': { |
| 562 'a': 'any', | 624 'a': 'any', |
| 563 'b': 'any' | 625 'b': 'any' |
| 564 }, | 626 }, |
| 565 'a 1.0.0': { 'c': '1.0.0' }, | 627 'a 1.0.0': { |
| 566 'a 2.0.0': { 'c': '2.0.0-nonexistent' }, | 628 'c': '1.0.0' |
| 629 }, |
| 630 'a 2.0.0': { |
| 631 'c': '2.0.0-nonexistent' |
| 632 }, |
| 567 'b 1.0.0': {}, | 633 'b 1.0.0': {}, |
| 568 'b 2.0.0': {}, | 634 'b 2.0.0': {}, |
| 569 'b 3.0.0': {}, | 635 'b 3.0.0': {}, |
| 570 'c 1.0.0': {}, | 636 'c 1.0.0': {}, |
| 571 }, result: { | 637 }, result: { |
| 572 'myapp from root': '0.0.0', | 638 'myapp from root': '0.0.0', |
| 573 'a': '1.0.0', | 639 'a': '1.0.0', |
| 574 'b': '3.0.0', | 640 'b': '3.0.0', |
| 575 'c': '1.0.0' | 641 'c': '1.0.0' |
| 576 }, maxTries: 2); | 642 }, maxTries: 2); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 // Dependencies are ordered so that packages with fewer versions are tried | 749 // Dependencies are ordered so that packages with fewer versions are tried |
| 684 // first. Here, there are two valid solutions (either a or b must be | 750 // first. Here, there are two valid solutions (either a or b must be |
| 685 // downgraded once). The chosen one depends on which dep is traversed first. | 751 // downgraded once). The chosen one depends on which dep is traversed first. |
| 686 // Since b has fewer versions, it will be traversed first, which means a will | 752 // Since b has fewer versions, it will be traversed first, which means a will |
| 687 // come later. Since later selections are revised first, a gets downgraded. | 753 // come later. Since later selections are revised first, a gets downgraded. |
| 688 testResolve('traverse into package with fewer versions first', { | 754 testResolve('traverse into package with fewer versions first', { |
| 689 'myapp 0.0.0': { | 755 'myapp 0.0.0': { |
| 690 'a': 'any', | 756 'a': 'any', |
| 691 'b': 'any' | 757 'b': 'any' |
| 692 }, | 758 }, |
| 693 'a 1.0.0': {'c': 'any'}, | 759 'a 1.0.0': { |
| 694 'a 2.0.0': {'c': 'any'}, | 760 'c': 'any' |
| 695 'a 3.0.0': {'c': 'any'}, | 761 }, |
| 696 'a 4.0.0': {'c': 'any'}, | 762 'a 2.0.0': { |
| 697 'a 5.0.0': {'c': '1.0.0'}, | 763 'c': 'any' |
| 698 'b 1.0.0': {'c': 'any'}, | 764 }, |
| 699 'b 2.0.0': {'c': 'any'}, | 765 'a 3.0.0': { |
| 700 'b 3.0.0': {'c': 'any'}, | 766 'c': 'any' |
| 701 'b 4.0.0': {'c': '2.0.0'}, | 767 }, |
| 768 'a 4.0.0': { |
| 769 'c': 'any' |
| 770 }, |
| 771 'a 5.0.0': { |
| 772 'c': '1.0.0' |
| 773 }, |
| 774 'b 1.0.0': { |
| 775 'c': 'any' |
| 776 }, |
| 777 'b 2.0.0': { |
| 778 'c': 'any' |
| 779 }, |
| 780 'b 3.0.0': { |
| 781 'c': 'any' |
| 782 }, |
| 783 'b 4.0.0': { |
| 784 'c': '2.0.0' |
| 785 }, |
| 702 'c 1.0.0': {}, | 786 'c 1.0.0': {}, |
| 703 'c 2.0.0': {}, | 787 'c 2.0.0': {}, |
| 704 }, result: { | 788 }, result: { |
| 705 'myapp from root': '0.0.0', | 789 'myapp from root': '0.0.0', |
| 706 'a': '4.0.0', | 790 'a': '4.0.0', |
| 707 'b': '4.0.0', | 791 'b': '4.0.0', |
| 708 'c': '2.0.0' | 792 'c': '2.0.0' |
| 709 }, maxTries: 2); | 793 }, maxTries: 2); |
| 710 | 794 |
| 711 // This is similar to the above test. When getting the number of versions of | 795 // This is similar to the above test. When getting the number of versions of |
| 712 // a package to determine which to traverse first, versions that are | 796 // a package to determine which to traverse first, versions that are |
| 713 // disallowed by the root package's constraints should not be considered. | 797 // disallowed by the root package's constraints should not be considered. |
| 714 // Here, foo has more versions of bar in total (4), but fewer that meet | 798 // Here, foo has more versions of bar in total (4), but fewer that meet |
| 715 // myapp's constraints (only 2). There is no solution, but we will do less | 799 // myapp's constraints (only 2). There is no solution, but we will do less |
| 716 // backtracking if foo is tested first. | 800 // backtracking if foo is tested first. |
| 717 testResolve('take root package constraints into counting versions', { | 801 testResolve('take root package constraints into counting versions', { |
| 718 "myapp 0.0.0": { | 802 "myapp 0.0.0": { |
| 719 "foo": ">2.0.0", | 803 "foo": ">2.0.0", |
| 720 "bar": "any" | 804 "bar": "any" |
| 721 }, | 805 }, |
| 722 "foo 1.0.0": {"none": "2.0.0"}, | 806 "foo 1.0.0": { |
| 723 "foo 2.0.0": {"none": "2.0.0"}, | 807 "none": "2.0.0" |
| 724 "foo 3.0.0": {"none": "2.0.0"}, | 808 }, |
| 725 "foo 4.0.0": {"none": "2.0.0"}, | 809 "foo 2.0.0": { |
| 810 "none": "2.0.0" |
| 811 }, |
| 812 "foo 3.0.0": { |
| 813 "none": "2.0.0" |
| 814 }, |
| 815 "foo 4.0.0": { |
| 816 "none": "2.0.0" |
| 817 }, |
| 726 "bar 1.0.0": {}, | 818 "bar 1.0.0": {}, |
| 727 "bar 2.0.0": {}, | 819 "bar 2.0.0": {}, |
| 728 "bar 3.0.0": {}, | 820 "bar 3.0.0": {}, |
| 729 "none 1.0.0": {} | 821 "none 1.0.0": {} |
| 730 }, error: noVersion(["foo", "none"]), maxTries: 2); | 822 }, error: noVersion(["foo", "none"]), maxTries: 2); |
| 731 | 823 |
| 732 // This sets up a hundred versions of foo and bar, 0.0.0 through 9.9.0. Each | 824 // This sets up a hundred versions of foo and bar, 0.0.0 through 9.9.0. Each |
| 733 // version of foo depends on a baz with the same major version. Each version | 825 // version of foo depends on a baz with the same major version. Each version |
| 734 // of bar depends on a baz with the same minor version. There is only one | 826 // of bar depends on a baz with the same minor version. There is only one |
| 735 // version of baz, 0.0.0, so only older versions of foo and bar will | 827 // version of baz, 0.0.0, so only older versions of foo and bar will |
| 736 // satisfy it. | 828 // satisfy it. |
| 737 var map = { | 829 var map = { |
| 738 'myapp 0.0.0': { | 830 'myapp 0.0.0': { |
| 739 'foo': 'any', | 831 'foo': 'any', |
| 740 'bar': 'any' | 832 'bar': 'any' |
| 741 }, | 833 }, |
| 742 'baz 0.0.0': {} | 834 'baz 0.0.0': {} |
| 743 }; | 835 }; |
| 744 | 836 |
| 745 for (var i = 0; i < 10; i++) { | 837 for (var i = 0; i < 10; i++) { |
| 746 for (var j = 0; j < 10; j++) { | 838 for (var j = 0; j < 10; j++) { |
| 747 map['foo $i.$j.0'] = {'baz': '$i.0.0'}; | 839 map['foo $i.$j.0'] = { |
| 748 map['bar $i.$j.0'] = {'baz': '0.$j.0'}; | 840 'baz': '$i.0.0' |
| 841 }; |
| 842 map['bar $i.$j.0'] = { |
| 843 'baz': '0.$j.0' |
| 844 }; |
| 749 } | 845 } |
| 750 } | 846 } |
| 751 | 847 |
| 752 testResolve('complex backtrack', map, result: { | 848 testResolve('complex backtrack', map, result: { |
| 753 'myapp from root': '0.0.0', | 849 'myapp from root': '0.0.0', |
| 754 'foo': '0.9.0', | 850 'foo': '0.9.0', |
| 755 'bar': '9.0.0', | 851 'bar': '9.0.0', |
| 756 'baz': '0.0.0' | 852 'baz': '0.0.0' |
| 757 }, maxTries: 100); | 853 }, maxTries: 100); |
| 758 | 854 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 786 // would backtrack over the failed package instead of trying different | 882 // would backtrack over the failed package instead of trying different |
| 787 // versions of it. | 883 // versions of it. |
| 788 testResolve("finds solution with less strict constraint", { | 884 testResolve("finds solution with less strict constraint", { |
| 789 "myapp 1.0.0": { | 885 "myapp 1.0.0": { |
| 790 "a": "any", | 886 "a": "any", |
| 791 "c": "any", | 887 "c": "any", |
| 792 "d": "any" | 888 "d": "any" |
| 793 }, | 889 }, |
| 794 "a 2.0.0": {}, | 890 "a 2.0.0": {}, |
| 795 "a 1.0.0": {}, | 891 "a 1.0.0": {}, |
| 796 "b 1.0.0": {"a": "1.0.0"}, | 892 "b 1.0.0": { |
| 797 "c 1.0.0": {"b": "any"}, | 893 "a": "1.0.0" |
| 798 "d 2.0.0": {"myapp": "any"}, | 894 }, |
| 799 "d 1.0.0": {"myapp": "<1.0.0"} | 895 "c 1.0.0": { |
| 896 "b": "any" |
| 897 }, |
| 898 "d 2.0.0": { |
| 899 "myapp": "any" |
| 900 }, |
| 901 "d 1.0.0": { |
| 902 "myapp": "<1.0.0" |
| 903 } |
| 800 }, result: { | 904 }, result: { |
| 801 'myapp from root': '1.0.0', | 905 'myapp from root': '1.0.0', |
| 802 'a': '1.0.0', | 906 'a': '1.0.0', |
| 803 'b': '1.0.0', | 907 'b': '1.0.0', |
| 804 'c': '1.0.0', | 908 'c': '1.0.0', |
| 805 'd': '2.0.0' | 909 'd': '2.0.0' |
| 806 }, maxTries: 3); | 910 }, maxTries: 3); |
| 807 } | 911 } |
| 808 | 912 |
| 809 sdkConstraint() { | 913 sdkConstraint() { |
| 810 var badVersion = '0.0.0-nope'; | 914 var badVersion = '0.0.0-nope'; |
| 811 var goodVersion = sdk.version.toString(); | 915 var goodVersion = sdk.version.toString(); |
| 812 | 916 |
| 813 testResolve('root matches SDK', { | 917 testResolve('root matches SDK', { |
| 814 'myapp 0.0.0': {'sdk': goodVersion } | 918 'myapp 0.0.0': { |
| 919 'sdk': goodVersion |
| 920 } |
| 815 }, result: { | 921 }, result: { |
| 816 'myapp from root': '0.0.0' | 922 'myapp from root': '0.0.0' |
| 817 }); | 923 }); |
| 818 | 924 |
| 819 testResolve('root does not match SDK', { | 925 testResolve('root does not match SDK', { |
| 820 'myapp 0.0.0': {'sdk': badVersion } | 926 'myapp 0.0.0': { |
| 927 'sdk': badVersion |
| 928 } |
| 821 }, error: couldNotSolve); | 929 }, error: couldNotSolve); |
| 822 | 930 |
| 823 testResolve('dependency does not match SDK', { | 931 testResolve('dependency does not match SDK', { |
| 824 'myapp 0.0.0': {'foo': 'any'}, | 932 'myapp 0.0.0': { |
| 825 'foo 0.0.0': {'sdk': badVersion } | 933 'foo': 'any' |
| 934 }, |
| 935 'foo 0.0.0': { |
| 936 'sdk': badVersion |
| 937 } |
| 826 }, error: couldNotSolve); | 938 }, error: couldNotSolve); |
| 827 | 939 |
| 828 testResolve('transitive dependency does not match SDK', { | 940 testResolve('transitive dependency does not match SDK', { |
| 829 'myapp 0.0.0': {'foo': 'any'}, | 941 'myapp 0.0.0': { |
| 830 'foo 0.0.0': {'bar': 'any'}, | 942 'foo': 'any' |
| 831 'bar 0.0.0': {'sdk': badVersion } | 943 }, |
| 944 'foo 0.0.0': { |
| 945 'bar': 'any' |
| 946 }, |
| 947 'bar 0.0.0': { |
| 948 'sdk': badVersion |
| 949 } |
| 832 }, error: couldNotSolve); | 950 }, error: couldNotSolve); |
| 833 | 951 |
| 834 testResolve('selects a dependency version that allows the SDK', { | 952 testResolve('selects a dependency version that allows the SDK', { |
| 835 'myapp 0.0.0': {'foo': 'any'}, | 953 'myapp 0.0.0': { |
| 836 'foo 1.0.0': {'sdk': goodVersion }, | 954 'foo': 'any' |
| 837 'foo 2.0.0': {'sdk': goodVersion }, | 955 }, |
| 838 'foo 3.0.0': {'sdk': badVersion }, | 956 'foo 1.0.0': { |
| 839 'foo 4.0.0': {'sdk': badVersion } | 957 'sdk': goodVersion |
| 958 }, |
| 959 'foo 2.0.0': { |
| 960 'sdk': goodVersion |
| 961 }, |
| 962 'foo 3.0.0': { |
| 963 'sdk': badVersion |
| 964 }, |
| 965 'foo 4.0.0': { |
| 966 'sdk': badVersion |
| 967 } |
| 840 }, result: { | 968 }, result: { |
| 841 'myapp from root': '0.0.0', | 969 'myapp from root': '0.0.0', |
| 842 'foo': '2.0.0' | 970 'foo': '2.0.0' |
| 843 }, maxTries: 3); | 971 }, maxTries: 3); |
| 844 | 972 |
| 845 testResolve('selects a transitive dependency version that allows the SDK', { | 973 testResolve('selects a transitive dependency version that allows the SDK', { |
| 846 'myapp 0.0.0': {'foo': 'any'}, | 974 'myapp 0.0.0': { |
| 847 'foo 1.0.0': {'bar': 'any'}, | 975 'foo': 'any' |
| 848 'bar 1.0.0': {'sdk': goodVersion }, | 976 }, |
| 849 'bar 2.0.0': {'sdk': goodVersion }, | 977 'foo 1.0.0': { |
| 850 'bar 3.0.0': {'sdk': badVersion }, | 978 'bar': 'any' |
| 851 'bar 4.0.0': {'sdk': badVersion } | 979 }, |
| 980 'bar 1.0.0': { |
| 981 'sdk': goodVersion |
| 982 }, |
| 983 'bar 2.0.0': { |
| 984 'sdk': goodVersion |
| 985 }, |
| 986 'bar 3.0.0': { |
| 987 'sdk': badVersion |
| 988 }, |
| 989 'bar 4.0.0': { |
| 990 'sdk': badVersion |
| 991 } |
| 852 }, result: { | 992 }, result: { |
| 853 'myapp from root': '0.0.0', | 993 'myapp from root': '0.0.0', |
| 854 'foo': '1.0.0', | 994 'foo': '1.0.0', |
| 855 'bar': '2.0.0' | 995 'bar': '2.0.0' |
| 856 }, maxTries: 3); | 996 }, maxTries: 3); |
| 857 | 997 |
| 858 testResolve('selects a dependency version that allows a transitive ' | 998 testResolve( |
| 859 'dependency that allows the SDK', { | 999 'selects a dependency version that allows a transitive ' |
| 860 'myapp 0.0.0': {'foo': 'any'}, | 1000 'dependency that allows the SDK', |
| 861 'foo 1.0.0': {'bar': '1.0.0'}, | 1001 { |
| 862 'foo 2.0.0': {'bar': '2.0.0'}, | 1002 'myapp 0.0.0': { |
| 863 'foo 3.0.0': {'bar': '3.0.0'}, | 1003 'foo': 'any' |
| 864 'foo 4.0.0': {'bar': '4.0.0'}, | 1004 }, |
| 865 'bar 1.0.0': {'sdk': goodVersion }, | 1005 'foo 1.0.0': { |
| 866 'bar 2.0.0': {'sdk': goodVersion }, | 1006 'bar': '1.0.0' |
| 867 'bar 3.0.0': {'sdk': badVersion }, | 1007 }, |
| 868 'bar 4.0.0': {'sdk': badVersion } | 1008 'foo 2.0.0': { |
| 1009 'bar': '2.0.0' |
| 1010 }, |
| 1011 'foo 3.0.0': { |
| 1012 'bar': '3.0.0' |
| 1013 }, |
| 1014 'foo 4.0.0': { |
| 1015 'bar': '4.0.0' |
| 1016 }, |
| 1017 'bar 1.0.0': { |
| 1018 'sdk': goodVersion |
| 1019 }, |
| 1020 'bar 2.0.0': { |
| 1021 'sdk': goodVersion |
| 1022 }, |
| 1023 'bar 3.0.0': { |
| 1024 'sdk': badVersion |
| 1025 }, |
| 1026 'bar 4.0.0': { |
| 1027 'sdk': badVersion |
| 1028 } |
| 869 }, result: { | 1029 }, result: { |
| 870 'myapp from root': '0.0.0', | 1030 'myapp from root': '0.0.0', |
| 871 'foo': '2.0.0', | 1031 'foo': '2.0.0', |
| 872 'bar': '2.0.0' | 1032 'bar': '2.0.0' |
| 873 }, maxTries: 3); | 1033 }, maxTries: 3); |
| 874 } | 1034 } |
| 875 | 1035 |
| 876 void prerelease() { | 1036 void prerelease() { |
| 877 testResolve('prefer stable versions over unstable', { | 1037 testResolve('prefer stable versions over unstable', { |
| 878 'myapp 0.0.0': { | 1038 'myapp 0.0.0': { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 }, result: { | 1154 }, result: { |
| 995 'myapp from root': '0.0.0', | 1155 'myapp from root': '0.0.0', |
| 996 'a': '1.0.0', | 1156 'a': '1.0.0', |
| 997 'shared': '2.0.0' | 1157 'shared': '2.0.0' |
| 998 }, maxTries: 2); | 1158 }, maxTries: 2); |
| 999 | 1159 |
| 1000 testResolve('override compatible with locked dependency', { | 1160 testResolve('override compatible with locked dependency', { |
| 1001 'myapp 0.0.0': { | 1161 'myapp 0.0.0': { |
| 1002 'foo': 'any' | 1162 'foo': 'any' |
| 1003 }, | 1163 }, |
| 1004 'foo 1.0.0': { 'bar': '1.0.0' }, | 1164 'foo 1.0.0': { |
| 1005 'foo 1.0.1': { 'bar': '1.0.1' }, | 1165 'bar': '1.0.0' |
| 1006 'foo 1.0.2': { 'bar': '1.0.2' }, | 1166 }, |
| 1167 'foo 1.0.1': { |
| 1168 'bar': '1.0.1' |
| 1169 }, |
| 1170 'foo 1.0.2': { |
| 1171 'bar': '1.0.2' |
| 1172 }, |
| 1007 'bar 1.0.0': {}, | 1173 'bar 1.0.0': {}, |
| 1008 'bar 1.0.1': {}, | 1174 'bar 1.0.1': {}, |
| 1009 'bar 1.0.2': {} | 1175 'bar 1.0.2': {} |
| 1010 }, lockfile: { | 1176 }, lockfile: { |
| 1011 'foo': '1.0.1' | 1177 'foo': '1.0.1' |
| 1012 }, overrides: { | 1178 }, overrides: { |
| 1013 'foo': '<1.0.2' | 1179 'foo': '<1.0.2' |
| 1014 }, result: { | 1180 }, result: { |
| 1015 'myapp from root': '0.0.0', | 1181 'myapp from root': '0.0.0', |
| 1016 'foo': '1.0.1', | 1182 'foo': '1.0.1', |
| 1017 'bar': '1.0.1' | 1183 'bar': '1.0.1' |
| 1018 }); | 1184 }); |
| 1019 | 1185 |
| 1020 testResolve('override incompatible with locked dependency', { | 1186 testResolve('override incompatible with locked dependency', { |
| 1021 'myapp 0.0.0': { | 1187 'myapp 0.0.0': { |
| 1022 'foo': 'any' | 1188 'foo': 'any' |
| 1023 }, | 1189 }, |
| 1024 'foo 1.0.0': { 'bar': '1.0.0' }, | 1190 'foo 1.0.0': { |
| 1025 'foo 1.0.1': { 'bar': '1.0.1' }, | 1191 'bar': '1.0.0' |
| 1026 'foo 1.0.2': { 'bar': '1.0.2' }, | 1192 }, |
| 1193 'foo 1.0.1': { |
| 1194 'bar': '1.0.1' |
| 1195 }, |
| 1196 'foo 1.0.2': { |
| 1197 'bar': '1.0.2' |
| 1198 }, |
| 1027 'bar 1.0.0': {}, | 1199 'bar 1.0.0': {}, |
| 1028 'bar 1.0.1': {}, | 1200 'bar 1.0.1': {}, |
| 1029 'bar 1.0.2': {} | 1201 'bar 1.0.2': {} |
| 1030 }, lockfile: { | 1202 }, lockfile: { |
| 1031 'foo': '1.0.1' | 1203 'foo': '1.0.1' |
| 1032 }, overrides: { | 1204 }, overrides: { |
| 1033 'foo': '>1.0.1' | 1205 'foo': '>1.0.1' |
| 1034 }, result: { | 1206 }, result: { |
| 1035 'myapp from root': '0.0.0', | 1207 'myapp from root': '0.0.0', |
| 1036 'foo': '1.0.2', | 1208 'foo': '1.0.2', |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1067 'foo 2.0.0-dev': {}, | 1239 'foo 2.0.0-dev': {}, |
| 1068 'foo 2.0.0': {}, | 1240 'foo 2.0.0': {}, |
| 1069 'foo 2.1.0': {} | 1241 'foo 2.1.0': {} |
| 1070 }, lockfile: { | 1242 }, lockfile: { |
| 1071 'foo': '2.1.0' | 1243 'foo': '2.1.0' |
| 1072 }, result: { | 1244 }, result: { |
| 1073 'myapp from root': '0.0.0', | 1245 'myapp from root': '0.0.0', |
| 1074 'foo': '2.0.0' | 1246 'foo': '2.0.0' |
| 1075 }, downgrade: true); | 1247 }, downgrade: true); |
| 1076 | 1248 |
| 1077 testResolve('use earliest allowed prerelease if no stable versions match ' | 1249 testResolve( |
| 1078 'while downgrading', { | 1250 'use earliest allowed prerelease if no stable versions match ' |
| 1251 'while downgrading', |
| 1252 { |
| 1079 'myapp 0.0.0': { | 1253 'myapp 0.0.0': { |
| 1080 'a': '>=2.0.0-dev.1 <3.0.0' | 1254 'a': '>=2.0.0-dev.1 <3.0.0' |
| 1081 }, | 1255 }, |
| 1082 'a 1.0.0': {}, | 1256 'a 1.0.0': {}, |
| 1083 'a 2.0.0-dev.1': {}, | 1257 'a 2.0.0-dev.1': {}, |
| 1084 'a 2.0.0-dev.2': {}, | 1258 'a 2.0.0-dev.2': {}, |
| 1085 'a 2.0.0-dev.3': {} | 1259 'a 2.0.0-dev.3': {} |
| 1086 }, result: { | 1260 }, result: { |
| 1087 'myapp from root': '0.0.0', | 1261 'myapp from root': '0.0.0', |
| 1088 'a': '2.0.0-dev.1' | 1262 'a': '2.0.0-dev.1' |
| 1089 }, downgrade: true); | 1263 }, downgrade: true); |
| 1090 } | 1264 } |
| 1091 | 1265 |
| 1092 testResolve(String description, Map packages, { | 1266 testResolve(String description, Map packages, {Map lockfile, Map overrides, |
| 1093 Map lockfile, Map overrides, Map result, FailMatcherBuilder error, | 1267 Map result, FailMatcherBuilder error, int maxTries, bool downgrade: false})
{ |
| 1094 int maxTries, bool downgrade: false}) { | 1268 _testResolve( |
| 1095 _testResolve(test, description, packages, lockfile: lockfile, | 1269 test, |
| 1096 overrides: overrides, result: result, error: error, maxTries: maxTries, | 1270 description, |
| 1271 packages, |
| 1272 lockfile: lockfile, |
| 1273 overrides: overrides, |
| 1274 result: result, |
| 1275 error: error, |
| 1276 maxTries: maxTries, |
| 1097 downgrade: downgrade); | 1277 downgrade: downgrade); |
| 1098 } | 1278 } |
| 1099 | 1279 |
| 1100 solo_testResolve(String description, Map packages, { | 1280 solo_testResolve(String description, Map packages, {Map lockfile, Map overrides, |
| 1101 Map lockfile, Map overrides, Map result, FailMatcherBuilder error, | 1281 Map result, FailMatcherBuilder error, int maxTries, bool downgrade: false})
{ |
| 1102 int maxTries, bool downgrade: false}) { | |
| 1103 log.verbosity = log.Verbosity.SOLVER; | 1282 log.verbosity = log.Verbosity.SOLVER; |
| 1104 _testResolve(solo_test, description, packages, lockfile: lockfile, | 1283 _testResolve( |
| 1105 overrides: overrides, result: result, error: error, maxTries: maxTries, | 1284 solo_test, |
| 1285 description, |
| 1286 packages, |
| 1287 lockfile: lockfile, |
| 1288 overrides: overrides, |
| 1289 result: result, |
| 1290 error: error, |
| 1291 maxTries: maxTries, |
| 1106 downgrade: downgrade); | 1292 downgrade: downgrade); |
| 1107 } | 1293 } |
| 1108 | 1294 |
| 1109 _testResolve(void testFn(String description, Function body), | 1295 _testResolve(void testFn(String description, Function body), String description, |
| 1110 String description, Map packages, { | 1296 Map packages, {Map lockfile, Map overrides, Map result, |
| 1111 Map lockfile, Map overrides, Map result, FailMatcherBuilder error, | 1297 FailMatcherBuilder error, int maxTries, bool downgrade: false}) { |
| 1112 int maxTries, bool downgrade: false}) { | |
| 1113 if (maxTries == null) maxTries = 1; | 1298 if (maxTries == null) maxTries = 1; |
| 1114 | 1299 |
| 1115 testFn(description, () { | 1300 testFn(description, () { |
| 1116 var cache = new SystemCache('.'); | 1301 var cache = new SystemCache('.'); |
| 1117 source1 = new MockSource('mock1'); | 1302 source1 = new MockSource('mock1'); |
| 1118 source2 = new MockSource('mock2'); | 1303 source2 = new MockSource('mock2'); |
| 1119 cache.register(source1); | 1304 cache.register(source1); |
| 1120 cache.register(source2); | 1305 cache.register(source2); |
| 1121 cache.sources.setDefault(source1.name); | 1306 cache.sources.setDefault(source1.name); |
| 1122 | 1307 |
| 1123 // Build the test package graph. | 1308 // Build the test package graph. |
| 1124 var root; | 1309 var root; |
| 1125 packages.forEach((description, dependencies) { | 1310 packages.forEach((description, dependencies) { |
| 1126 var id = parseSpec(description); | 1311 var id = parseSpec(description); |
| 1127 var package = mockPackage(id, dependencies, | 1312 var package = |
| 1128 id.name == 'myapp' ? overrides : null); | 1313 mockPackage(id, dependencies, id.name == 'myapp' ? overrides : null); |
| 1129 if (id.name == 'myapp') { | 1314 if (id.name == 'myapp') { |
| 1130 // Don't add the root package to the server, so we can verify that Pub | 1315 // Don't add the root package to the server, so we can verify that Pub |
| 1131 // doesn't try to look up information about the local package on the | 1316 // doesn't try to look up information about the local package on the |
| 1132 // remote server. | 1317 // remote server. |
| 1133 root = package; | 1318 root = package; |
| 1134 } else { | 1319 } else { |
| 1135 (cache.sources[id.source] as MockSource).addPackage( | 1320 (cache.sources[id.source] as MockSource).addPackage( |
| 1136 id.description, package); | 1321 id.description, |
| 1322 package); |
| 1137 } | 1323 } |
| 1138 }); | 1324 }); |
| 1139 | 1325 |
| 1140 // Clean up the expectation. | 1326 // Clean up the expectation. |
| 1141 if (result != null) { | 1327 if (result != null) { |
| 1142 var newResult = {}; | 1328 var newResult = {}; |
| 1143 result.forEach((description, version) { | 1329 result.forEach((description, version) { |
| 1144 var id = parseSpec(description, version); | 1330 var id = parseSpec(description, version); |
| 1145 newResult[id.name] = id; | 1331 newResult[id.name] = id; |
| 1146 }); | 1332 }); |
| 1147 result = newResult; | 1333 result = newResult; |
| 1148 } | 1334 } |
| 1149 | 1335 |
| 1150 // Parse the lockfile. | 1336 // Parse the lockfile. |
| 1151 var realLockFile = new LockFile.empty(); | 1337 var realLockFile = new LockFile.empty(); |
| 1152 if (lockfile != null) { | 1338 if (lockfile != null) { |
| 1153 lockfile.forEach((name, version) { | 1339 lockfile.forEach((name, version) { |
| 1154 version = new Version.parse(version); | 1340 version = new Version.parse(version); |
| 1155 realLockFile.packages[name] = | 1341 realLockFile.packages[name] = |
| 1156 new PackageId(name, source1.name, version, name); | 1342 new PackageId(name, source1.name, version, name); |
| 1157 }); | 1343 }); |
| 1158 } | 1344 } |
| 1159 | 1345 |
| 1160 // Resolve the versions. | 1346 // Resolve the versions. |
| 1161 var future = resolveVersions( | 1347 var future = resolveVersions( |
| 1162 downgrade ? SolveType.DOWNGRADE : SolveType.GET, | 1348 downgrade ? SolveType.DOWNGRADE : SolveType.GET, |
| 1163 cache.sources, root, lockFile: realLockFile); | 1349 cache.sources, |
| 1350 root, |
| 1351 lockFile: realLockFile); |
| 1164 | 1352 |
| 1165 var matcher; | 1353 var matcher; |
| 1166 if (result != null) { | 1354 if (result != null) { |
| 1167 matcher = new SolveSuccessMatcher(result, maxTries); | 1355 matcher = new SolveSuccessMatcher(result, maxTries); |
| 1168 } else if (error != null) { | 1356 } else if (error != null) { |
| 1169 matcher = error(maxTries); | 1357 matcher = error(maxTries); |
| 1170 } | 1358 } |
| 1171 | 1359 |
| 1172 expect(future, completion(matcher)); | 1360 expect(future, completion(matcher)); |
| 1173 }); | 1361 }); |
| 1174 } | 1362 } |
| 1175 | 1363 |
| 1176 typedef SolveFailMatcher FailMatcherBuilder(int maxTries); | 1364 typedef SolveFailMatcher FailMatcherBuilder(int maxTries); |
| 1177 | 1365 |
| 1178 FailMatcherBuilder noVersion(List<String> packages) { | 1366 FailMatcherBuilder noVersion(List<String> packages) { |
| 1179 return (maxTries) => new SolveFailMatcher(packages, maxTries, | 1367 return (maxTries) => |
| 1180 NoVersionException); | 1368 new SolveFailMatcher(packages, maxTries, NoVersionException); |
| 1181 } | 1369 } |
| 1182 | 1370 |
| 1183 FailMatcherBuilder disjointConstraint(List<String> packages) { | 1371 FailMatcherBuilder disjointConstraint(List<String> packages) { |
| 1184 return (maxTries) => new SolveFailMatcher(packages, maxTries, | 1372 return (maxTries) => |
| 1185 DisjointConstraintException); | 1373 new SolveFailMatcher(packages, maxTries, DisjointConstraintException); |
| 1186 } | 1374 } |
| 1187 | 1375 |
| 1188 FailMatcherBuilder descriptionMismatch( | 1376 FailMatcherBuilder descriptionMismatch(String package, String depender1, |
| 1189 String package, String depender1, String depender2) { | 1377 String depender2) { |
| 1190 return (maxTries) => new SolveFailMatcher([package, depender1, depender2], | 1378 return (maxTries) => |
| 1191 maxTries, DescriptionMismatchException); | 1379 new SolveFailMatcher( |
| 1380 [package, depender1, depender2], |
| 1381 maxTries, |
| 1382 DescriptionMismatchException); |
| 1192 } | 1383 } |
| 1193 | 1384 |
| 1194 // If no solution can be found, the solver just reports the last failure that | 1385 // If no solution can be found, the solver just reports the last failure that |
| 1195 // happened during propagation. Since we don't specify the order that solutions | 1386 // happened during propagation. Since we don't specify the order that solutions |
| 1196 // are tried, this just validates that *some* failure occurred, but not which. | 1387 // are tried, this just validates that *some* failure occurred, but not which. |
| 1197 SolveFailMatcher couldNotSolve(maxTries) => | 1388 SolveFailMatcher couldNotSolve(maxTries) => |
| 1198 new SolveFailMatcher([], maxTries, null); | 1389 new SolveFailMatcher([], maxTries, null); |
| 1199 | 1390 |
| 1200 FailMatcherBuilder sourceMismatch( | 1391 FailMatcherBuilder sourceMismatch(String package, String depender1, |
| 1201 String package, String depender1, String depender2) { | 1392 String depender2) { |
| 1202 return (maxTries) => new SolveFailMatcher([package, depender1, depender2], | 1393 return (maxTries) => |
| 1203 maxTries, SourceMismatchException); | 1394 new SolveFailMatcher( |
| 1395 [package, depender1, depender2], |
| 1396 maxTries, |
| 1397 SourceMismatchException); |
| 1204 } | 1398 } |
| 1205 | 1399 |
| 1206 unknownSource(String depender, String dependency, String source) { | 1400 unknownSource(String depender, String dependency, String source) { |
| 1207 return (maxTries) => new SolveFailMatcher([depender, dependency, source], | 1401 return (maxTries) => |
| 1208 maxTries, UnknownSourceException); | 1402 new SolveFailMatcher( |
| 1403 [depender, dependency, source], |
| 1404 maxTries, |
| 1405 UnknownSourceException); |
| 1209 } | 1406 } |
| 1210 | 1407 |
| 1211 class SolveSuccessMatcher implements Matcher { | 1408 class SolveSuccessMatcher implements Matcher { |
| 1212 /// The expected concrete package selections. | 1409 /// The expected concrete package selections. |
| 1213 final Map<String, PackageId> _expected; | 1410 final Map<String, PackageId> _expected; |
| 1214 | 1411 |
| 1215 /// The maximum number of attempts that should have been tried before finding | 1412 /// The maximum number of attempts that should have been tried before finding |
| 1216 /// the solution. | 1413 /// the solution. |
| 1217 final int _maxTries; | 1414 final int _maxTries; |
| 1218 | 1415 |
| 1219 SolveSuccessMatcher(this._expected, this._maxTries); | 1416 SolveSuccessMatcher(this._expected, this._maxTries); |
| 1220 | 1417 |
| 1221 Description describe(Description description) { | 1418 Description describe(Description description) { |
| 1222 return description.add( | 1419 return description.add( |
| 1223 'Solver to use at most $_maxTries attempts to find:\n' | 1420 'Solver to use at most $_maxTries attempts to find:\n' |
| 1224 '${_listPackages(_expected.values)}'); | 1421 '${_listPackages(_expected.values)}'); |
| 1225 } | 1422 } |
| 1226 | 1423 |
| 1227 Description describeMismatch(SolveResult result, | 1424 Description describeMismatch(SolveResult result, Description description, |
| 1228 Description description, | 1425 Map state, bool verbose) { |
| 1229 Map state, bool verbose) { | |
| 1230 if (!result.succeeded) { | 1426 if (!result.succeeded) { |
| 1231 description.add('Solver failed with:\n${result.error}'); | 1427 description.add('Solver failed with:\n${result.error}'); |
| 1232 return null; | 1428 return null; |
| 1233 } | 1429 } |
| 1234 | 1430 |
| 1235 description.add('Resolved:\n${_listPackages(result.packages)}\n'); | 1431 description.add('Resolved:\n${_listPackages(result.packages)}\n'); |
| 1236 description.add(state['failures']); | 1432 description.add(state['failures']); |
| 1237 return description; | 1433 return description; |
| 1238 } | 1434 } |
| 1239 | 1435 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1293 | 1489 |
| 1294 Description describe(Description description) { | 1490 Description describe(Description description) { |
| 1295 description.add('Solver should fail after at most $_maxTries attempts.'); | 1491 description.add('Solver should fail after at most $_maxTries attempts.'); |
| 1296 if (!_expected.isEmpty) { | 1492 if (!_expected.isEmpty) { |
| 1297 var textList = _expected.map((s) => '"$s"').join(", "); | 1493 var textList = _expected.map((s) => '"$s"').join(", "); |
| 1298 description.add(' The error should contain $textList.'); | 1494 description.add(' The error should contain $textList.'); |
| 1299 } | 1495 } |
| 1300 return description; | 1496 return description; |
| 1301 } | 1497 } |
| 1302 | 1498 |
| 1303 Description describeMismatch(SolveResult result, | 1499 Description describeMismatch(SolveResult result, Description description, |
| 1304 Description description, | 1500 Map state, bool verbose) { |
| 1305 Map state, bool verbose) { | |
| 1306 description.add(state['failures']); | 1501 description.add(state['failures']); |
| 1307 return description; | 1502 return description; |
| 1308 } | 1503 } |
| 1309 | 1504 |
| 1310 bool matches(SolveResult result, Map state) { | 1505 bool matches(SolveResult result, Map state) { |
| 1311 var failures = new StringBuffer(); | 1506 var failures = new StringBuffer(); |
| 1312 | 1507 |
| 1313 if (result.succeeded) { | 1508 if (result.succeeded) { |
| 1314 failures.writeln('Solver succeeded'); | 1509 failures.writeln('Solver succeeded'); |
| 1315 } else { | 1510 } else { |
| 1316 if (_expectedType != null && result.error.runtimeType != _expectedType) { | 1511 if (_expectedType != null && result.error.runtimeType != _expectedType) { |
| 1317 failures.writeln('Should have error type $_expectedType, got ' | 1512 failures.writeln( |
| 1318 '${result.error.runtimeType}'); | 1513 'Should have error type $_expectedType, got ' '${result.error.runtim
eType}'); |
| 1319 } | 1514 } |
| 1320 | 1515 |
| 1321 var message = result.error.toString(); | 1516 var message = result.error.toString(); |
| 1322 for (var expected in _expected) { | 1517 for (var expected in _expected) { |
| 1323 if (!message.contains(expected)) { | 1518 if (!message.contains(expected)) { |
| 1324 failures.writeln( | 1519 failures.writeln( |
| 1325 'Expected error to contain "$expected", got:\n$message'); | 1520 'Expected error to contain "$expected", got:\n$message'); |
| 1326 } | 1521 } |
| 1327 } | 1522 } |
| 1328 | 1523 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 /// source is only hit once for a given package and that pub internally | 1556 /// source is only hit once for a given package and that pub internally |
| 1362 /// caches the results. | 1557 /// caches the results. |
| 1363 final _requestedPubspecs = new Map<String, Set<Version>>(); | 1558 final _requestedPubspecs = new Map<String, Set<Version>>(); |
| 1364 | 1559 |
| 1365 final String name; | 1560 final String name; |
| 1366 final hasMultipleVersions = true; | 1561 final hasMultipleVersions = true; |
| 1367 | 1562 |
| 1368 MockSource(this.name); | 1563 MockSource(this.name); |
| 1369 | 1564 |
| 1370 dynamic parseDescription(String containingPath, description, | 1565 dynamic parseDescription(String containingPath, description, |
| 1371 {bool fromLockFile: false}) => description; | 1566 {bool fromLockFile: false}) => |
| 1567 description; |
| 1372 | 1568 |
| 1373 bool descriptionsEqual(description1, description2) => | 1569 bool descriptionsEqual(description1, description2) => |
| 1374 description1 == description2; | 1570 description1 == description2; |
| 1375 | 1571 |
| 1376 Future<String> getDirectory(PackageId id) { | 1572 Future<String> getDirectory(PackageId id) { |
| 1377 return new Future.value('${id.name}-${id.version}'); | 1573 return new Future.value('${id.name}-${id.version}'); |
| 1378 } | 1574 } |
| 1379 | 1575 |
| 1380 Future<List<Version>> getVersions(String name, String description) { | 1576 Future<List<Version>> getVersions(String name, String description) { |
| 1381 return new Future.sync(() { | 1577 return new Future.sync(() { |
| 1382 // Make sure the solver doesn't request the same thing twice. | 1578 // Make sure the solver doesn't request the same thing twice. |
| 1383 if (_requestedVersions.contains(description)) { | 1579 if (_requestedVersions.contains(description)) { |
| 1384 throw new Exception('Version list for $description was already ' | 1580 throw new Exception( |
| 1385 'requested.'); | 1581 'Version list for $description was already ' 'requested.'); |
| 1386 } | 1582 } |
| 1387 | 1583 |
| 1388 _requestedVersions.add(description); | 1584 _requestedVersions.add(description); |
| 1389 | 1585 |
| 1390 if (!_packages.containsKey(description)){ | 1586 if (!_packages.containsKey(description)) { |
| 1391 throw new Exception('MockSource does not have a package matching ' | 1587 throw new Exception( |
| 1392 '"$description".'); | 1588 'MockSource does not have a package matching ' '"$description".'); |
| 1393 } | 1589 } |
| 1394 | 1590 |
| 1395 return _packages[description].keys.toList(); | 1591 return _packages[description].keys.toList(); |
| 1396 }); | 1592 }); |
| 1397 } | 1593 } |
| 1398 | 1594 |
| 1399 Future<Pubspec> describeUncached(PackageId id) { | 1595 Future<Pubspec> describeUncached(PackageId id) { |
| 1400 return new Future.sync(() { | 1596 return new Future.sync(() { |
| 1401 // Make sure the solver doesn't request the same thing twice. | 1597 // Make sure the solver doesn't request the same thing twice. |
| 1402 if (_requestedPubspecs.containsKey(id.description) && | 1598 if (_requestedPubspecs.containsKey(id.description) && |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1432 // Build the pubspec dependencies. | 1628 // Build the pubspec dependencies. |
| 1433 var dependencies = <PackageDep>[]; | 1629 var dependencies = <PackageDep>[]; |
| 1434 var devDependencies = <PackageDep>[]; | 1630 var devDependencies = <PackageDep>[]; |
| 1435 | 1631 |
| 1436 dependencyStrings.forEach((spec, constraint) { | 1632 dependencyStrings.forEach((spec, constraint) { |
| 1437 var isDev = spec.startsWith("(dev) "); | 1633 var isDev = spec.startsWith("(dev) "); |
| 1438 if (isDev) { | 1634 if (isDev) { |
| 1439 spec = spec.substring("(dev) ".length); | 1635 spec = spec.substring("(dev) ".length); |
| 1440 } | 1636 } |
| 1441 | 1637 |
| 1442 var dep = parseSpec(spec).withConstraint( | 1638 var dep = |
| 1443 new VersionConstraint.parse(constraint)); | 1639 parseSpec(spec).withConstraint(new VersionConstraint.parse(constraint)); |
| 1444 | 1640 |
| 1445 if (dep.name == 'sdk') { | 1641 if (dep.name == 'sdk') { |
| 1446 sdkConstraint = dep.constraint; | 1642 sdkConstraint = dep.constraint; |
| 1447 return; | 1643 return; |
| 1448 } | 1644 } |
| 1449 | 1645 |
| 1450 if (isDev) { | 1646 if (isDev) { |
| 1451 devDependencies.add(dep); | 1647 devDependencies.add(dep); |
| 1452 } else { | 1648 } else { |
| 1453 dependencies.add(dep); | 1649 dependencies.add(dep); |
| 1454 } | 1650 } |
| 1455 }); | 1651 }); |
| 1456 | 1652 |
| 1457 var dependencyOverrides = <PackageDep>[]; | 1653 var dependencyOverrides = <PackageDep>[]; |
| 1458 if (overrides != null) { | 1654 if (overrides != null) { |
| 1459 overrides.forEach((spec, constraint) { | 1655 overrides.forEach((spec, constraint) { |
| 1460 dependencyOverrides.add(parseSpec(spec).withConstraint( | 1656 dependencyOverrides.add( |
| 1461 new VersionConstraint.parse(constraint))); | 1657 parseSpec(spec).withConstraint(new VersionConstraint.parse(constraint)
)); |
| 1462 }); | 1658 }); |
| 1463 } | 1659 } |
| 1464 | 1660 |
| 1465 return new Package.inMemory(new Pubspec(id.name, | 1661 return new Package.inMemory( |
| 1466 version: id.version, | 1662 new Pubspec( |
| 1467 dependencies: dependencies, | 1663 id.name, |
| 1468 devDependencies: devDependencies, | 1664 version: id.version, |
| 1469 dependencyOverrides: dependencyOverrides, | 1665 dependencies: dependencies, |
| 1470 sdkConstraint: sdkConstraint)); | 1666 devDependencies: devDependencies, |
| 1667 dependencyOverrides: dependencyOverrides, |
| 1668 sdkConstraint: sdkConstraint)); |
| 1471 } | 1669 } |
| 1472 | 1670 |
| 1473 /// Creates a new [PackageId] parsed from [text], which looks something like | 1671 /// Creates a new [PackageId] parsed from [text], which looks something like |
| 1474 /// this: | 1672 /// this: |
| 1475 /// | 1673 /// |
| 1476 /// foo-xyz 1.0.0 from mock | 1674 /// foo-xyz 1.0.0 from mock |
| 1477 /// | 1675 /// |
| 1478 /// The package name is "foo". A hyphenated suffix like "-xyz" here is part | 1676 /// The package name is "foo". A hyphenated suffix like "-xyz" here is part |
| 1479 /// of the package description, but not its name, so the description here is | 1677 /// of the package description, but not its name, so the description here is |
| 1480 /// "foo-xyz". | 1678 /// "foo-xyz". |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1492 throw new FormatException("Could not parse spec '$text'."); | 1690 throw new FormatException("Could not parse spec '$text'."); |
| 1493 } | 1691 } |
| 1494 | 1692 |
| 1495 var description = match[1]; | 1693 var description = match[1]; |
| 1496 var name = match[2]; | 1694 var name = match[2]; |
| 1497 | 1695 |
| 1498 var parsedVersion; | 1696 var parsedVersion; |
| 1499 if (version != null) { | 1697 if (version != null) { |
| 1500 // Spec string shouldn't also contain a version. | 1698 // Spec string shouldn't also contain a version. |
| 1501 if (match[5] != null) { | 1699 if (match[5] != null) { |
| 1502 throw new ArgumentError("Spec '$text' should not contain a version " | 1700 throw new ArgumentError( |
| 1503 "since '$version' was passed in explicitly."); | 1701 "Spec '$text' should not contain a version " |
| 1702 "since '$version' was passed in explicitly."); |
| 1504 } | 1703 } |
| 1505 parsedVersion = new Version.parse(version); | 1704 parsedVersion = new Version.parse(version); |
| 1506 } else { | 1705 } else { |
| 1507 if (match[5] != null) { | 1706 if (match[5] != null) { |
| 1508 parsedVersion = new Version.parse(match[5]); | 1707 parsedVersion = new Version.parse(match[5]); |
| 1509 } else { | 1708 } else { |
| 1510 parsedVersion = Version.none; | 1709 parsedVersion = Version.none; |
| 1511 } | 1710 } |
| 1512 } | 1711 } |
| 1513 | 1712 |
| 1514 var source = "mock1"; | 1713 var source = "mock1"; |
| 1515 if (match[7] != null) { | 1714 if (match[7] != null) { |
| 1516 source = match[7]; | 1715 source = match[7]; |
| 1517 if (source == "root") source = null; | 1716 if (source == "root") source = null; |
| 1518 } | 1717 } |
| 1519 | 1718 |
| 1520 return new PackageId(name, source, parsedVersion, description); | 1719 return new PackageId(name, source, parsedVersion, description); |
| 1521 } | 1720 } |
| OLD | NEW |