OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library version_test; | |
6 | |
7 import 'package:unittest/unittest.dart'; | |
8 import 'test_pub.dart'; | |
9 import '../../pub/utils.dart'; | |
10 import '../../pub/version.dart'; | |
11 | |
12 main() { | |
13 initConfig(); | |
14 | |
15 final v123 = new Version.parse('1.2.3'); | |
16 final v114 = new Version.parse('1.1.4'); | |
17 final v124 = new Version.parse('1.2.4'); | |
18 final v200 = new Version.parse('2.0.0'); | |
19 final v234 = new Version.parse('2.3.4'); | |
20 final v250 = new Version.parse('2.5.0'); | |
21 final v300 = new Version.parse('3.0.0'); | |
22 | |
23 group('Version', () { | |
24 test('none', () { | |
25 expect(Version.none.toString(), equals('0.0.0')); | |
26 }); | |
27 | |
28 group('constructor', () { | |
29 test('throws on negative numbers', () { | |
30 throwsIllegalArg(() => new Version(-1, 1, 1)); | |
31 throwsIllegalArg(() => new Version(1, -1, 1)); | |
32 throwsIllegalArg(() => new Version(1, 1, -1)); | |
33 }); | |
34 }); | |
35 | |
36 group('comparison', () { | |
37 // A correctly sorted list of versions. | |
38 var versions = [ | |
39 '1.0.0-alpha', | |
40 '1.0.0-alpha.1', | |
41 '1.0.0-beta.2', | |
42 '1.0.0-beta.11', | |
43 '1.0.0-rc.1', | |
44 '1.0.0-rc.1+build.1', | |
45 '1.0.0', | |
46 '1.0.0+0.3.7', | |
47 '1.3.7+build', | |
48 '1.3.7+build.2.b8f12d7', | |
49 '1.3.7+build.11.e0f985a', | |
50 '2.0.0', | |
51 '2.1.0', | |
52 '2.2.0', | |
53 '2.11.0', | |
54 '2.11.1' | |
55 ]; | |
56 | |
57 test('compareTo()', () { | |
58 // Ensure that every pair of versions compares in the order that it | |
59 // appears in the list. | |
60 for (var i = 0; i < versions.length; i++) { | |
61 for (var j = 0; j < versions.length; j++) { | |
62 var a = new Version.parse(versions[i]); | |
63 var b = new Version.parse(versions[j]); | |
64 var expectation = i.compareTo(j); | |
65 expect(a.compareTo(b), equals(expectation)); | |
66 } | |
67 } | |
68 }); | |
69 | |
70 test('operators', () { | |
71 for (var i = 0; i < versions.length; i++) { | |
72 for (var j = 0; j < versions.length; j++) { | |
73 var a = new Version.parse(versions[i]); | |
74 var b = new Version.parse(versions[j]); | |
75 expect(a < b, equals(i < j)); | |
76 expect(a > b, equals(i > j)); | |
77 expect(a <= b, equals(i <= j)); | |
78 expect(a >= b, equals(i >= j)); | |
79 expect(a == b, equals(i == j)); | |
80 expect(a != b, equals(i != j)); | |
81 } | |
82 } | |
83 }); | |
84 }); | |
85 | |
86 test('allows()', () { | |
87 expect(v123.allows(v123), isTrue); | |
88 expect(v123.allows(v114), isFalse); | |
89 expect(v123.allows(v124), isFalse); | |
90 }); | |
91 | |
92 test('intersect()', () { | |
93 // Intersecting the same version returns the version. | |
94 expect(v123.intersect(v123), equals(v123)); | |
95 | |
96 // Intersecting a different version allows no versions. | |
97 expect(v123.intersect(v114).isEmpty, isTrue); | |
98 | |
99 // Intersecting a range returns the version if the range allows it. | |
100 expect(v123.intersect(new VersionRange(min: v114, max: v124)), | |
101 equals(v123)); | |
102 | |
103 // Intersecting a range allows no versions if the range doesn't allow it. | |
104 expect(v114.intersect(new VersionRange(min: v123, max: v124)).isEmpty, | |
105 isTrue); | |
106 }); | |
107 | |
108 test('isEmpty', () { | |
109 expect(v123.isEmpty, isFalse); | |
110 }); | |
111 | |
112 test('parse()', () { | |
113 expect(new Version.parse('0.0.0'), equals(new Version(0, 0, 0))); | |
114 expect(new Version.parse('12.34.56'), equals(new Version(12, 34, 56))); | |
115 | |
116 expect(new Version.parse('1.2.3-alpha.1'), equals( | |
117 new Version(1, 2, 3, pre: 'alpha.1'))); | |
118 expect(new Version.parse('1.2.3-x.7.z-92'), equals( | |
119 new Version(1, 2, 3, pre: 'x.7.z-92'))); | |
120 | |
121 expect(new Version.parse('1.2.3+build.1'), equals( | |
122 new Version(1, 2, 3, build: 'build.1'))); | |
123 expect(new Version.parse('1.2.3+x.7.z-92'), equals( | |
124 new Version(1, 2, 3, build: 'x.7.z-92'))); | |
125 | |
126 expect(new Version.parse('1.0.0-rc-1+build-1'), equals( | |
127 new Version(1, 0, 0, pre: 'rc-1', build: 'build-1'))); | |
128 | |
129 expect(() => new Version.parse('1.0'), throwsFormatException); | |
130 expect(() => new Version.parse('1.2.3.4'), throwsFormatException); | |
131 expect(() => new Version.parse('1234'), throwsFormatException); | |
132 expect(() => new Version.parse('-2.3.4'), throwsFormatException); | |
133 expect(() => new Version.parse('1.3-pre'), throwsFormatException); | |
134 expect(() => new Version.parse('1.3+build'), throwsFormatException); | |
135 expect(() => new Version.parse('1.3+bu?!3ild'), throwsFormatException); | |
136 }); | |
137 | |
138 test('toString()', () { | |
139 expect(new Version(0, 0, 0).toString(), equals('0.0.0')); | |
140 expect(new Version(12, 34, 56).toString(), equals('12.34.56')); | |
141 | |
142 expect(new Version(1, 2, 3, pre: 'alpha.1').toString(), equals( | |
143 '1.2.3-alpha.1')); | |
144 expect(new Version(1, 2, 3, pre: 'x.7.z-92').toString(), equals( | |
145 '1.2.3-x.7.z-92')); | |
146 | |
147 expect(new Version(1, 2, 3, build: 'build.1').toString(), equals( | |
148 '1.2.3+build.1')); | |
149 expect(new Version(1, 2, 3, pre: 'pre', build: 'bui').toString(), equals( | |
150 '1.2.3-pre+bui')); | |
151 }); | |
152 }); | |
153 | |
154 group('VersionRange', () { | |
155 group('constructor', () { | |
156 test('takes a min and max', () { | |
157 var range = new VersionRange(min: v123, max: v124); | |
158 expect(range.min, equals(v123)); | |
159 expect(range.max, equals(v124)); | |
160 }); | |
161 | |
162 test('allows omitting max', () { | |
163 var range = new VersionRange(min: v123); | |
164 expect(range.min, equals(v123)); | |
165 expect(range.max, isNull); | |
166 }); | |
167 | |
168 test('allows omitting min and max', () { | |
169 var range = new VersionRange(); | |
170 expect(range.min, isNull); | |
171 expect(range.max, isNull); | |
172 }); | |
173 | |
174 test('takes includeMin', () { | |
175 var range = new VersionRange(min: v123, includeMin: true); | |
176 expect(range.includeMin, isTrue); | |
177 }); | |
178 | |
179 test('includeMin defaults to false if omitted', () { | |
180 var range = new VersionRange(min: v123); | |
181 expect(range.includeMin, isFalse); | |
182 }); | |
183 | |
184 test('takes includeMax', () { | |
185 var range = new VersionRange(max: v123, includeMax: true); | |
186 expect(range.includeMax, isTrue); | |
187 }); | |
188 | |
189 test('includeMax defaults to false if omitted', () { | |
190 var range = new VersionRange(max: v123); | |
191 expect(range.includeMax, isFalse); | |
192 }); | |
193 | |
194 test('throws if min > max', () { | |
195 throwsIllegalArg(() => new VersionRange(min: v124, max: v123)); | |
196 }); | |
197 }); | |
198 | |
199 group('allows()', () { | |
200 test('version must be greater than min', () { | |
201 var range = new VersionRange(min: v123, max: v234); | |
202 | |
203 expect(range.allows(new Version.parse('1.2.2')), isFalse); | |
204 expect(range.allows(new Version.parse('1.2.3')), isFalse); | |
205 expect(range.allows(new Version.parse('1.3.3')), isTrue); | |
206 expect(range.allows(new Version.parse('2.3.3')), isTrue); | |
207 }); | |
208 | |
209 test('version must be min or greater if includeMin', () { | |
210 var range = new VersionRange(min: v123, max: v234, includeMin: true); | |
211 | |
212 expect(range.allows(new Version.parse('1.2.2')), isFalse); | |
213 expect(range.allows(new Version.parse('1.2.3')), isTrue); | |
214 expect(range.allows(new Version.parse('1.3.3')), isTrue); | |
215 expect(range.allows(new Version.parse('2.3.3')), isTrue); | |
216 }); | |
217 | |
218 test('version must be less than max', () { | |
219 var range = new VersionRange(min: v123, max: v234); | |
220 | |
221 expect(range.allows(new Version.parse('2.3.3')), isTrue); | |
222 expect(range.allows(new Version.parse('2.3.4')), isFalse); | |
223 expect(range.allows(new Version.parse('2.4.3')), isFalse); | |
224 }); | |
225 | |
226 test('version must be max or less if includeMax', () { | |
227 var range = new VersionRange(min: v123, max: v234, includeMax: true); | |
228 | |
229 expect(range.allows(new Version.parse('2.3.3')), isTrue); | |
230 expect(range.allows(new Version.parse('2.3.4')), isTrue); | |
231 expect(range.allows(new Version.parse('2.4.3')), isFalse); | |
232 }); | |
233 | |
234 test('has no min if one was not set', () { | |
235 var range = new VersionRange(max: v123); | |
236 | |
237 expect(range.allows(new Version.parse('0.0.0')), isTrue); | |
238 expect(range.allows(new Version.parse('1.2.3')), isFalse); | |
239 }); | |
240 | |
241 test('has no max if one was not set', () { | |
242 var range = new VersionRange(min: v123); | |
243 | |
244 expect(range.allows(new Version.parse('1.2.3')), isFalse); | |
245 expect(range.allows(new Version.parse('1.3.3')), isTrue); | |
246 expect(range.allows(new Version.parse('999.3.3')), isTrue); | |
247 }); | |
248 | |
249 test('allows any version if there is no min or max', () { | |
250 var range = new VersionRange(); | |
251 | |
252 expect(range.allows(new Version.parse('0.0.0')), isTrue); | |
253 expect(range.allows(new Version.parse('999.99.9')), isTrue); | |
254 }); | |
255 }); | |
256 | |
257 group('intersect()', () { | |
258 test('two overlapping ranges', () { | |
259 var a = new VersionRange(min: v123, max: v250); | |
260 var b = new VersionRange(min: v200, max: v300); | |
261 var intersect = a.intersect(b); | |
262 expect(intersect.min, equals(v200)); | |
263 expect(intersect.max, equals(v250)); | |
264 expect(intersect.includeMin, isFalse); | |
265 expect(intersect.includeMax, isFalse); | |
266 }); | |
267 | |
268 test('a non-overlapping range allows no versions', () { | |
269 var a = new VersionRange(min: v114, max: v124); | |
270 var b = new VersionRange(min: v200, max: v250); | |
271 expect(a.intersect(b).isEmpty, isTrue); | |
272 }); | |
273 | |
274 test('adjacent ranges allow no versions if exclusive', () { | |
275 var a = new VersionRange(min: v114, max: v124, includeMax: false); | |
276 var b = new VersionRange(min: v124, max: v200, includeMin: true); | |
277 expect(a.intersect(b).isEmpty, isTrue); | |
278 }); | |
279 | |
280 test('adjacent ranges allow version if inclusive', () { | |
281 var a = new VersionRange(min: v114, max: v124, includeMax: true); | |
282 var b = new VersionRange(min: v124, max: v200, includeMin: true); | |
283 expect(a.intersect(b), equals(v124)); | |
284 }); | |
285 | |
286 test('with an open range', () { | |
287 var open = new VersionRange(); | |
288 var a = new VersionRange(min: v114, max: v124); | |
289 expect(open.intersect(open), equals(open)); | |
290 expect(a.intersect(open), equals(a)); | |
291 }); | |
292 | |
293 test('returns the version if the range allows it', () { | |
294 expect(new VersionRange(min: v114, max: v124).intersect(v123), | |
295 equals(v123)); | |
296 expect(new VersionRange(min: v123, max: v124).intersect(v114).isEmpty, | |
297 isTrue); | |
298 }); | |
299 }); | |
300 | |
301 test('isEmpty', () { | |
302 expect(new VersionRange().isEmpty, isFalse); | |
303 expect(new VersionRange(min: v123, max: v124).isEmpty, isFalse); | |
304 }); | |
305 }); | |
306 | |
307 group('VersionConstraint', () { | |
308 test('any', () { | |
309 expect(VersionConstraint.any.isAny, isTrue); | |
310 expect(VersionConstraint.any, allows([ | |
311 new Version.parse('0.0.0-blah'), | |
312 new Version.parse('1.2.3'), | |
313 new Version.parse('12345.678.90')])); | |
314 }); | |
315 | |
316 test('empty', () { | |
317 expect(VersionConstraint.empty.isEmpty, isTrue); | |
318 expect(VersionConstraint.empty, doesNotAllow([ | |
319 new Version.parse('0.0.0-blah'), | |
320 new Version.parse('1.2.3'), | |
321 new Version.parse('12345.678.90')])); | |
322 }); | |
323 | |
324 group('parse()', () { | |
325 test('parses an exact version', () { | |
326 var constraint = new VersionConstraint.parse('1.2.3-alpha'); | |
327 expect(constraint is Version, isTrue); | |
328 expect(constraint, equals(new Version(1, 2, 3, pre: 'alpha'))); | |
329 }); | |
330 | |
331 test('parses "any"', () { | |
332 var constraint = new VersionConstraint.parse('any'); | |
333 expect(constraint is VersionConstraint, isTrue); | |
334 expect(constraint, allows([ | |
335 new Version.parse('0.0.0'), | |
336 new Version.parse('1.2.3'), | |
337 new Version.parse('12345.678.90')])); | |
338 }); | |
339 | |
340 test('parses a ">" minimum version', () { | |
341 expect(new VersionConstraint.parse('>1.2.3'), allows([ | |
342 new Version.parse('1.2.3+foo'), | |
343 new Version.parse('1.2.4')])); | |
344 expect(new VersionConstraint.parse('>1.2.3'), doesNotAllow([ | |
345 new Version.parse('1.2.1'), | |
346 new Version.parse('1.2.3-build'), | |
347 new Version.parse('1.2.3')])); | |
348 }); | |
349 | |
350 test('parses a ">=" minimum version', () { | |
351 expect(new VersionConstraint.parse('>=1.2.3'), allows([ | |
352 new Version.parse('1.2.3'), | |
353 new Version.parse('1.2.3+foo'), | |
354 new Version.parse('1.2.4')])); | |
355 expect(new VersionConstraint.parse('>=1.2.3'), doesNotAllow([ | |
356 new Version.parse('1.2.1'), | |
357 new Version.parse('1.2.3-build')])); | |
358 }); | |
359 | |
360 test('parses a "<" maximum version', () { | |
361 expect(new VersionConstraint.parse('<1.2.3'), allows([ | |
362 new Version.parse('1.2.1'), | |
363 new Version.parse('1.2.3-build')])); | |
364 expect(new VersionConstraint.parse('<1.2.3'), doesNotAllow([ | |
365 new Version.parse('1.2.3'), | |
366 new Version.parse('1.2.3+foo'), | |
367 new Version.parse('1.2.4')])); | |
368 }); | |
369 | |
370 test('parses a "<=" maximum version', () { | |
371 expect(new VersionConstraint.parse('<=1.2.3'), allows([ | |
372 new Version.parse('1.2.1'), | |
373 new Version.parse('1.2.3-build'), | |
374 new Version.parse('1.2.3')])); | |
375 expect(new VersionConstraint.parse('<=1.2.3'), doesNotAllow([ | |
376 new Version.parse('1.2.3+foo'), | |
377 new Version.parse('1.2.4')])); | |
378 }); | |
379 | |
380 test('parses a series of space-separated constraints', () { | |
381 var constraint = new VersionConstraint.parse('>1.0.0 >=1.2.3 <1.3.0'); | |
382 expect(constraint, allows([ | |
383 new Version.parse('1.2.3'), | |
384 new Version.parse('1.2.5')])); | |
385 expect(constraint, doesNotAllow([ | |
386 new Version.parse('1.2.3-pre'), | |
387 new Version.parse('1.3.0'), | |
388 new Version.parse('3.4.5')])); | |
389 }); | |
390 | |
391 test('ignores whitespace around operators', () { | |
392 var constraint = new VersionConstraint.parse(' >1.0.0>=1.2.3 < 1.3.0'); | |
393 expect(constraint, allows([ | |
394 new Version.parse('1.2.3'), | |
395 new Version.parse('1.2.5')])); | |
396 expect(constraint, doesNotAllow([ | |
397 new Version.parse('1.2.3-pre'), | |
398 new Version.parse('1.3.0'), | |
399 new Version.parse('3.4.5')])); | |
400 }); | |
401 | |
402 test('does not allow "any" to be mixed with other constraints', () { | |
403 expect(() => new VersionConstraint.parse('any 1.0.0'), | |
404 throwsFormatException); | |
405 }); | |
406 | |
407 test('throws FormatException on a bad string', () { | |
408 var bad = [ | |
409 "", " ", // Empty string. | |
410 "foo", // Bad text. | |
411 ">foo", // Bad text after operator. | |
412 "1.0.0 foo", "1.0.0foo", // Bad text after version. | |
413 "anything", // Bad text after "any". | |
414 "<>1.0.0", // Multiple operators. | |
415 "1.0.0<" // Trailing operator. | |
416 ]; | |
417 | |
418 for (var text in bad) { | |
419 expect(() => new VersionConstraint.parse(text), | |
420 throwsFormatException); | |
421 } | |
422 }); | |
423 }); | |
424 }); | |
425 } | |
426 | |
427 class VersionConstraintMatcher implements Matcher { | |
428 final List<Version> _expected; | |
429 final bool _allow; | |
430 | |
431 VersionConstraintMatcher(this._expected, this._allow); | |
432 | |
433 bool matches(item, MatchState matchState) => (item is VersionConstraint) && | |
434 _expected.every((version) => item.allows(version) == _allow); | |
435 | |
436 Description describe(Description description) => | |
437 description.add(' ${_allow ? "allows" : "does not allow"} versions'); | |
438 | |
439 Description describeMismatch(item, Description mismatchDescription, | |
440 MatchState matchState, bool verbose) { | |
441 if (item is! VersionConstraint) { | |
442 mismatchDescription.add('was not a VersionConstraint'); | |
443 return mismatchDescription; | |
444 } | |
445 | |
446 bool first = true; | |
447 for (var version in _expected) { | |
448 if (item.allows(version) != _allow) { | |
449 if (first) { | |
450 if (_allow) { | |
451 mismatchDescription.addDescriptionOf(item).add('did not allow '); | |
452 } else { | |
453 mismatchDescription.addDescriptionOf(item).add('allowed '); | |
454 } | |
455 } else { | |
456 mismatchDescription.add(' and '); | |
457 } | |
458 first = false; | |
459 | |
460 mismatchDescription.add(version.toString()); | |
461 } | |
462 } | |
463 | |
464 return mismatchDescription; | |
465 } | |
466 } | |
467 | |
468 Matcher allows(List<Version> versions) => | |
469 new VersionConstraintMatcher(versions, true); | |
470 | |
471 Matcher doesNotAllow(List<Version> versions) => | |
472 new VersionConstraintMatcher(versions, false); | |
473 | |
474 throwsIllegalArg(function) { | |
475 expect(function, throwsA((e) => e is ArgumentError)); | |
476 } | |
OLD | NEW |