1 package semver
2
3 import (
4 "testing"
5 )
6
7 func prstr(s string) PRVersion {
8 return PRVersion{s, 0, false}
9 }
10
11 func prnum(i uint64) PRVersion {
12 return PRVersion{"", i, true}
13 }
14
15 type formatTest struct {
16 v Version
17 result string
18 }
19
20 var formatTests = []formatTest{
21 {Version{1, 2, 3, nil, nil}, "1.2.3"},
22 {Version{0, 0, 1, nil, nil}, "0.0.1"},
23 {Version{0, 0, 1, []PRVersion{prstr("alpha"), prstr("preview")}, []string{"123", "456"}}, "0.0.1-alpha.preview+123.456"},
24 {Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, []string{"123", "456"}}, "1.2.3-alpha.1+123.456"},
25 {Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, nil}, "1.2.3-alpha.1"},
26 {Version{1, 2, 3, nil, []string{"123", "456"}}, "1.2.3+123.456"},
27
28 {Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, []string{"123", "b-uild"}}, "1.2.3-alpha.b-eta+123.b-uild"},
29 {Version{1, 2, 3, nil, []string{"123", "b-uild"}}, "1.2.3+123.b-uild"},
30 {Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, nil}, "1.2.3-alpha.b-eta"},
31 }
32
33 var tolerantFormatTests = []formatTest{
34 {Version{1, 2, 3, nil, nil}, "v1.2.3"},
35 {Version{1, 2, 0, []PRVersion{prstr("alpha")}, nil}, "1.2.0-alpha"},
36 {Version{1, 2, 0, nil, nil}, "1.2.00"},
37 {Version{1, 2, 3, nil, nil}, " 1.2.3 "},
38 {Version{1, 2, 3, nil, nil}, "01.02.03"},
39 {Version{0, 0, 3, nil, nil}, "00.0.03"},
40 {Version{0, 0, 3, nil, nil}, "000.0.03"},
41 {Version{1, 2, 0, nil, nil}, "1.2"},
42 {Version{1, 0, 0, nil, nil}, "1"},
43 }
44
45 func TestStringer(t *testing.T) {
46 for _, test := range formatTests {
47 if res := test.v.String(); res != test.result {
48 t.Errorf("Stringer, expected %q but got %q", test.result, res)
49 }
50 }
51 }
52
53 func TestParse(t *testing.T) {
54 for _, test := range formatTests {
55 if v, err := Parse(test.result); err != nil {
56 t.Errorf("Error parsing %q: %q", test.result, err)
57 } else if comp := v.Compare(test.v); comp != 0 {
58 t.Errorf("Parsing, expected %q but got %q, comp: %d ", test.v, v, comp)
59 } else if err := v.Validate(); err != nil {
60 t.Errorf("Error validating parsed version %q: %q", test.v, err)
61 }
62 }
63 }
64
65 func TestParseTolerant(t *testing.T) {
66 for _, test := range tolerantFormatTests {
67 if v, err := ParseTolerant(test.result); err != nil {
68 t.Errorf("Error parsing %q: %q", test.result, err)
69 } else if comp := v.Compare(test.v); comp != 0 {
70 t.Errorf("Parsing, expected %q but got %q, comp: %d ", test.v, v, comp)
71 } else if err := v.Validate(); err != nil {
72 t.Errorf("Error validating parsed version %q: %q", test.v, err)
73 }
74 }
75 }
76
77 func TestMustParse(t *testing.T) {
78 _ = MustParse("32.2.1-alpha")
79 }
80
81 func TestMustParse_panic(t *testing.T) {
82 defer func() {
83 if recover() == nil {
84 t.Errorf("Should have panicked")
85 }
86 }()
87 _ = MustParse("invalid version")
88 }
89
90 func TestValidate(t *testing.T) {
91 for _, test := range formatTests {
92 if err := test.v.Validate(); err != nil {
93 t.Errorf("Error validating %q: %q", test.v, err)
94 }
95 }
96 }
97
98 var finalizeVersionMethod = []formatTest{
99 {Version{1, 2, 3, nil, nil}, "1.2.3"},
100 {Version{0, 0, 1, nil, nil}, "0.0.1"},
101 {Version{0, 0, 1, []PRVersion{prstr("alpha"), prstr("preview")}, []string{"123", "456"}}, "0.0.1"},
102 {Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, []string{"123", "456"}}, "1.2.3"},
103 {Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, nil}, "1.2.3"},
104 {Version{1, 2, 3, nil, []string{"123", "456"}}, "1.2.3"},
105
106 {Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, []string{"123", "b-uild"}}, "1.2.3"},
107 {Version{1, 2, 3, nil, []string{"123", "b-uild"}}, "1.2.3"},
108 {Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, nil}, "1.2.3"},
109 }
110
111 func TestFinalizeVersionMethod(t *testing.T) {
112 for _, test := range finalizeVersionMethod {
113 out := test.v.FinalizeVersion()
114 if out != test.result {
115 t.Errorf("Finalized version error, expected %q but got %q", test.result, out)
116 }
117 }
118 }
119
120 type compareTest struct {
121 v1 Version
122 v2 Version
123 result int
124 }
125
126 var compareTests = []compareTest{
127 {Version{1, 0, 0, nil, nil}, Version{1, 0, 0, nil, nil}, 0},
128 {Version{2, 0, 0, nil, nil}, Version{1, 0, 0, nil, nil}, 1},
129 {Version{0, 1, 0, nil, nil}, Version{0, 1, 0, nil, nil}, 0},
130 {Version{0, 2, 0, nil, nil}, Version{0, 1, 0, nil, nil}, 1},
131 {Version{0, 0, 1, nil, nil}, Version{0, 0, 1, nil, nil}, 0},
132 {Version{0, 0, 2, nil, nil}, Version{0, 0, 1, nil, nil}, 1},
133 {Version{1, 2, 3, nil, nil}, Version{1, 2, 3, nil, nil}, 0},
134 {Version{2, 2, 4, nil, nil}, Version{1, 2, 4, nil, nil}, 1},
135 {Version{1, 3, 3, nil, nil}, Version{1, 2, 3, nil, nil}, 1},
136 {Version{1, 2, 4, nil, nil}, Version{1, 2, 3, nil, nil}, 1},
137
138
139 {Version{1, 0, 0, nil, nil}, Version{2, 0, 0, nil, nil}, -1},
140 {Version{2, 0, 0, nil, nil}, Version{2, 1, 0, nil, nil}, -1},
141 {Version{2, 1, 0, nil, nil}, Version{2, 1, 1, nil, nil}, -1},
142
143
144 {Version{1, 0, 0, nil, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}, 1},
145 {Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha"), prnum(1)}, nil}, -1},
146 {Version{1, 0, 0, []PRVersion{prstr("alpha"), prnum(1)}, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha"), prstr("beta")}, nil}, -1},
147 {Version{1, 0, 0, []PRVersion{prstr("alpha"), prstr("beta")}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta")}, nil}, -1},
148 {Version{1, 0, 0, []PRVersion{prstr("beta")}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(2)}, nil}, -1},
149 {Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(2)}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(11)}, nil}, -1},
150 {Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(11)}, nil}, Version{1, 0, 0, []PRVersion{prstr("rc"), prnum(1)}, nil}, -1},
151 {Version{1, 0, 0, []PRVersion{prstr("rc"), prnum(1)}, nil}, Version{1, 0, 0, nil, nil}, -1},
152
153
154 {Version{1, 0, 0, nil, []string{"1", "2", "3"}}, Version{1, 0, 0, nil, nil}, 0},
155 }
156
157 func TestCompare(t *testing.T) {
158 for _, test := range compareTests {
159 if res := test.v1.Compare(test.v2); res != test.result {
160 t.Errorf("Comparing %q : %q, expected %d but got %d", test.v1, test.v2, test.result, res)
161 }
162
163 if res := test.v2.Compare(test.v1); res != -test.result {
164 t.Errorf("Comparing %q : %q, expected %d but got %d", test.v2, test.v1, -test.result, res)
165 }
166 }
167 }
168
169 type wrongformatTest struct {
170 v *Version
171 str string
172 }
173
174 var wrongformatTests = []wrongformatTest{
175 {nil, ""},
176 {nil, "."},
177 {nil, "1."},
178 {nil, ".1"},
179 {nil, "a.b.c"},
180 {nil, "1.a.b"},
181 {nil, "1.1.a"},
182 {nil, "1.a.1"},
183 {nil, "a.1.1"},
184 {nil, ".."},
185 {nil, "1.."},
186 {nil, "1.1."},
187 {nil, "1..1"},
188 {nil, "1.1.+123"},
189 {nil, "1.1.-beta"},
190 {nil, "-1.1.1"},
191 {nil, "1.-1.1"},
192 {nil, "1.1.-1"},
193
194 {nil, "20000000000000000000.1.1"},
195 {nil, "1.20000000000000000000.1"},
196 {nil, "1.1.20000000000000000000"},
197 {nil, "1.1.1-20000000000000000000"},
198
199 {nil, "01.1.1"},
200 {nil, "001.1.1"},
201 {nil, "1.01.1"},
202 {nil, "1.001.1"},
203 {nil, "1.1.01"},
204 {nil, "1.1.001"},
205 {nil, "1.1.1-01"},
206 {nil, "1.1.1-001"},
207 {nil, "1.1.1-beta.01"},
208 {nil, "1.1.1-beta.001"},
209 {&Version{0, 0, 0, []PRVersion{prstr("!")}, nil}, "0.0.0-!"},
210 {&Version{0, 0, 0, nil, []string{"!"}}, "0.0.0+!"},
211
212 {&Version{0, 0, 0, []PRVersion{prstr(""), prstr("alpha")}, nil}, "0.0.0-.alpha"},
213
214 {&Version{0, 0, 0, []PRVersion{prstr("alpha")}, []string{""}}, "0.0.0-alpha+"},
215 {&Version{0, 0, 0, []PRVersion{prstr("alpha")}, []string{"test", ""}}, "0.0.0-alpha+test."},
216 }
217
218 func TestWrongFormat(t *testing.T) {
219 for _, test := range wrongformatTests {
220
221 if res, err := Parse(test.str); err == nil {
222 t.Errorf("Parsing wrong format version %q, expected error but got %q", test.str, res)
223 }
224
225 if test.v != nil {
226 if err := test.v.Validate(); err == nil {
227 t.Errorf("Validating wrong format version %q (%q), expected error", test.v, test.str)
228 }
229 }
230 }
231 }
232
233 var wrongTolerantFormatTests = []wrongformatTest{
234 {nil, "1.0+abc"},
235 {nil, "1.0-rc.1"},
236 }
237
238 func TestWrongTolerantFormat(t *testing.T) {
239 for _, test := range wrongTolerantFormatTests {
240 if res, err := ParseTolerant(test.str); err == nil {
241 t.Errorf("Parsing wrong format version %q, expected error but got %q", test.str, res)
242 }
243 }
244 }
245
246 func TestCompareHelper(t *testing.T) {
247 v := Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}
248 v1 := Version{1, 0, 0, nil, nil}
249 if !v.EQ(v) {
250 t.Errorf("%q should be equal to %q", v, v)
251 }
252 if !v.Equals(v) {
253 t.Errorf("%q should be equal to %q", v, v)
254 }
255 if !v1.NE(v) {
256 t.Errorf("%q should not be equal to %q", v1, v)
257 }
258 if !v.GTE(v) {
259 t.Errorf("%q should be greater than or equal to %q", v, v)
260 }
261 if !v.LTE(v) {
262 t.Errorf("%q should be less than or equal to %q", v, v)
263 }
264 if !v.LT(v1) {
265 t.Errorf("%q should be less than %q", v, v1)
266 }
267 if !v.LTE(v1) {
268 t.Errorf("%q should be less than or equal %q", v, v1)
269 }
270 if !v.LE(v1) {
271 t.Errorf("%q should be less than or equal %q", v, v1)
272 }
273 if !v1.GT(v) {
274 t.Errorf("%q should be greater than %q", v1, v)
275 }
276 if !v1.GTE(v) {
277 t.Errorf("%q should be greater than or equal %q", v1, v)
278 }
279 if !v1.GE(v) {
280 t.Errorf("%q should be greater than or equal %q", v1, v)
281 }
282 }
283
284 const (
285 MAJOR = iota
286 MINOR
287 PATCH
288 )
289
290 type incrementTest struct {
291 version Version
292 incrementType int
293 expectingError bool
294 expectedVersion Version
295 }
296
297 var incrementTests = []incrementTest{
298 {Version{1, 2, 3, nil, nil}, PATCH, false, Version{1, 2, 4, nil, nil}},
299 {Version{1, 2, 3, nil, nil}, MINOR, false, Version{1, 3, 0, nil, nil}},
300 {Version{1, 2, 3, nil, nil}, MAJOR, false, Version{2, 0, 0, nil, nil}},
301 {Version{0, 1, 2, nil, nil}, PATCH, false, Version{0, 1, 3, nil, nil}},
302 {Version{0, 1, 2, nil, nil}, MINOR, false, Version{0, 2, 0, nil, nil}},
303 {Version{0, 1, 2, nil, nil}, MAJOR, false, Version{1, 0, 0, nil, nil}},
304 }
305
306 func TestIncrements(t *testing.T) {
307 for _, test := range incrementTests {
308 var originalVersion = Version{
309 test.version.Major,
310 test.version.Minor,
311 test.version.Patch,
312 test.version.Pre,
313 test.version.Build,
314 }
315 var err error
316 switch test.incrementType {
317 case PATCH:
318 err = test.version.IncrementPatch()
319 case MINOR:
320 err = test.version.IncrementMinor()
321 case MAJOR:
322 err = test.version.IncrementMajor()
323 }
324 if test.expectingError {
325 if err != nil {
326 t.Errorf("Increment version, expecting %q, got error %q", test.expectedVersion, err)
327 }
328 if test.version.EQ(originalVersion) {
329 t.Errorf("Increment version, expecting %q, got %q", test.expectedVersion, test.version)
330 }
331 } else {
332 if (err != nil) && !test.expectingError {
333 t.Errorf("Increment version %q, not expecting error, got %q", test.version, err)
334 }
335 if test.version.NE(test.expectedVersion) {
336 t.Errorf("Increment version, expecting %q, got %q", test.expectedVersion, test.version)
337 }
338 }
339 }
340 }
341
342 func TestPreReleaseVersions(t *testing.T) {
343 p1, err := NewPRVersion("123")
344 if !p1.IsNumeric() {
345 t.Errorf("Expected numeric prversion, got %q", p1)
346 }
347 if p1.VersionNum != 123 {
348 t.Error("Wrong prversion number")
349 }
350 if err != nil {
351 t.Errorf("Not expected error %q", err)
352 }
353 p2, err := NewPRVersion("alpha")
354 if p2.IsNumeric() {
355 t.Errorf("Expected non-numeric prversion, got %q", p2)
356 }
357 if p2.VersionStr != "alpha" {
358 t.Error("Wrong prversion string")
359 }
360 if err != nil {
361 t.Errorf("Not expected error %q", err)
362 }
363 }
364
365 func TestBuildMetaDataVersions(t *testing.T) {
366 _, err := NewBuildVersion("123")
367 if err != nil {
368 t.Errorf("Unexpected error %q", err)
369 }
370
371 _, err = NewBuildVersion("build")
372 if err != nil {
373 t.Errorf("Unexpected error %q", err)
374 }
375
376 _, err = NewBuildVersion("test?")
377 if err == nil {
378 t.Error("Expected error, got none")
379 }
380
381 _, err = NewBuildVersion("")
382 if err == nil {
383 t.Error("Expected error, got none")
384 }
385 }
386
387 func TestNewHelper(t *testing.T) {
388 v, err := New("1.2.3")
389 if err != nil {
390 t.Fatalf("Unexpected error %q", err)
391 }
392
393
394 if v == nil {
395 t.Fatal("Version is nil")
396 }
397 if v.Compare(Version{1, 2, 3, nil, nil}) != 0 {
398 t.Fatal("Unexpected comparison problem")
399 }
400 }
401
402 func TestMakeHelper(t *testing.T) {
403 v, err := Make("1.2.3")
404 if err != nil {
405 t.Fatalf("Unexpected error %q", err)
406 }
407 if v.Compare(Version{1, 2, 3, nil, nil}) != 0 {
408 t.Fatal("Unexpected comparison problem")
409 }
410 }
411
412 type finalizeTest struct {
413 input string
414 output string
415 }
416
417 var finalizeTests = []finalizeTest{
418 {"", ""},
419 {"1.2.3", "1.2.3"},
420 {"0.0.1", "0.0.1"},
421 {"0.0.1-alpha.preview+123.456", "0.0.1"},
422 {"1.2.3-alpha.1+123.456", "1.2.3"},
423 {"1.2.3-alpha.1", "1.2.3"},
424 {"1.2.3+123.456", "1.2.3"},
425 {"1.2.3-alpha.b-eta+123.b-uild", "1.2.3"},
426 {"1.2.3+123.b-uild", "1.2.3"},
427 {"1.2.3-alpha.b-eta", "1.2.3"},
428 {"1.2-alpha", ""},
429 }
430
431 func TestFinalizeVersion(t *testing.T) {
432 for _, test := range finalizeTests {
433 finalVer, err := FinalizeVersion(test.input)
434 if finalVer == "" {
435 if err == nil {
436 t.Errorf("Finalize Version error, expected error but got nil")
437 }
438 } else if finalVer != test.output && err != nil {
439 t.Errorf("Finalize Version error expected %q but got %q", test.output, finalVer)
440 }
441 }
442 }
443
444 func BenchmarkParseSimple(b *testing.B) {
445 const VERSION = "0.0.1"
446 b.ReportAllocs()
447 b.ResetTimer()
448 for n := 0; n < b.N; n++ {
449 _, _ = Parse(VERSION)
450 }
451 }
452
453 func BenchmarkParseComplex(b *testing.B) {
454 const VERSION = "0.0.1-alpha.preview+123.456"
455 b.ReportAllocs()
456 b.ResetTimer()
457 for n := 0; n < b.N; n++ {
458 _, _ = Parse(VERSION)
459 }
460 }
461
462 func BenchmarkParseAverage(b *testing.B) {
463 l := len(formatTests)
464 b.ReportAllocs()
465 b.ResetTimer()
466 for n := 0; n < b.N; n++ {
467 _, _ = Parse(formatTests[n%l].result)
468 }
469 }
470
471 func BenchmarkParseTolerantAverage(b *testing.B) {
472 l := len(tolerantFormatTests)
473 b.ReportAllocs()
474 b.ResetTimer()
475 for n := 0; n < b.N; n++ {
476 _, _ = ParseTolerant(tolerantFormatTests[n%l].result)
477 }
478 }
479
480 func BenchmarkStringSimple(b *testing.B) {
481 const VERSION = "0.0.1"
482 v, _ := Parse(VERSION)
483 b.ReportAllocs()
484 b.ResetTimer()
485 for n := 0; n < b.N; n++ {
486 _ = v.String()
487 }
488 }
489
490 func BenchmarkStringLarger(b *testing.B) {
491 const VERSION = "11.15.2012"
492 v, _ := Parse(VERSION)
493 b.ReportAllocs()
494 b.ResetTimer()
495 for n := 0; n < b.N; n++ {
496 _ = v.String()
497 }
498 }
499
500 func BenchmarkStringComplex(b *testing.B) {
501 const VERSION = "0.0.1-alpha.preview+123.456"
502 v, _ := Parse(VERSION)
503 b.ReportAllocs()
504 b.ResetTimer()
505 for n := 0; n < b.N; n++ {
506 _ = v.String()
507 }
508 }
509
510 func BenchmarkStringAverage(b *testing.B) {
511 l := len(formatTests)
512 b.ReportAllocs()
513 b.ResetTimer()
514 for n := 0; n < b.N; n++ {
515 _ = formatTests[n%l].v.String()
516 }
517 }
518
519 func BenchmarkValidateSimple(b *testing.B) {
520 const VERSION = "0.0.1"
521 v, _ := Parse(VERSION)
522 b.ReportAllocs()
523 b.ResetTimer()
524 for n := 0; n < b.N; n++ {
525 _ = v.Validate()
526 }
527 }
528
529 func BenchmarkValidateComplex(b *testing.B) {
530 const VERSION = "0.0.1-alpha.preview+123.456"
531 v, _ := Parse(VERSION)
532 b.ReportAllocs()
533 b.ResetTimer()
534 for n := 0; n < b.N; n++ {
535 _ = v.Validate()
536 }
537 }
538
539 func BenchmarkValidateAverage(b *testing.B) {
540 l := len(formatTests)
541 b.ReportAllocs()
542 b.ResetTimer()
543 for n := 0; n < b.N; n++ {
544 _ = formatTests[n%l].v.Validate()
545 }
546 }
547
548 func BenchmarkCompareSimple(b *testing.B) {
549 const VERSION = "0.0.1"
550 v, _ := Parse(VERSION)
551 b.ReportAllocs()
552 b.ResetTimer()
553 for n := 0; n < b.N; n++ {
554 v.Compare(v)
555 }
556 }
557
558 func BenchmarkCompareComplex(b *testing.B) {
559 const VERSION = "0.0.1-alpha.preview+123.456"
560 v, _ := Parse(VERSION)
561 b.ReportAllocs()
562 b.ResetTimer()
563 for n := 0; n < b.N; n++ {
564 v.Compare(v)
565 }
566 }
567
568 func BenchmarkCompareAverage(b *testing.B) {
569 l := len(compareTests)
570 b.ReportAllocs()
571 b.ResetTimer()
572 for n := 0; n < b.N; n++ {
573 compareTests[n%l].v1.Compare((compareTests[n%l].v2))
574 }
575 }
576
View as plain text