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 |