1package semver 2 3import ( 4 "database/sql" 5 "encoding/json" 6 "fmt" 7 "testing" 8) 9 10func TestStrictNewVersion(t *testing.T) { 11 tests := []struct { 12 version string 13 err bool 14 }{ 15 {"1.2.3", false}, 16 {"1.2.3-alpha.01", true}, 17 {"1.2.3+test.01", false}, 18 {"1.2.3-alpha.-1", false}, 19 {"v1.2.3", true}, 20 {"1.0", true}, 21 {"v1.0", true}, 22 {"1", true}, 23 {"v1", true}, 24 {"1.2.beta", true}, 25 {"v1.2.beta", true}, 26 {"foo", true}, 27 {"1.2-5", true}, 28 {"v1.2-5", true}, 29 {"1.2-beta.5", true}, 30 {"v1.2-beta.5", true}, 31 {"\n1.2", true}, 32 {"\nv1.2", true}, 33 {"1.2.0-x.Y.0+metadata", false}, 34 {"v1.2.0-x.Y.0+metadata", true}, 35 {"1.2.0-x.Y.0+metadata-width-hypen", false}, 36 {"v1.2.0-x.Y.0+metadata-width-hypen", true}, 37 {"1.2.3-rc1-with-hypen", false}, 38 {"v1.2.3-rc1-with-hypen", true}, 39 {"1.2.3.4", true}, 40 {"v1.2.3.4", true}, 41 {"1.2.2147483648", false}, 42 {"1.2147483648.3", false}, 43 {"2147483648.3.0", false}, 44 } 45 46 for _, tc := range tests { 47 _, err := StrictNewVersion(tc.version) 48 if tc.err && err == nil { 49 t.Fatalf("expected error for version: %s", tc.version) 50 } else if !tc.err && err != nil { 51 t.Fatalf("error for version %s: %s", tc.version, err) 52 } 53 } 54} 55 56func TestNewVersion(t *testing.T) { 57 tests := []struct { 58 version string 59 err bool 60 }{ 61 {"1.2.3", false}, 62 {"1.2.3-alpha.01", true}, 63 {"1.2.3+test.01", false}, 64 {"1.2.3-alpha.-1", false}, 65 {"v1.2.3", false}, 66 {"1.0", false}, 67 {"v1.0", false}, 68 {"1", false}, 69 {"v1", false}, 70 {"1.2.beta", true}, 71 {"v1.2.beta", true}, 72 {"foo", true}, 73 {"1.2-5", false}, 74 {"v1.2-5", false}, 75 {"1.2-beta.5", false}, 76 {"v1.2-beta.5", false}, 77 {"\n1.2", true}, 78 {"\nv1.2", true}, 79 {"1.2.0-x.Y.0+metadata", false}, 80 {"v1.2.0-x.Y.0+metadata", false}, 81 {"1.2.0-x.Y.0+metadata-width-hypen", false}, 82 {"v1.2.0-x.Y.0+metadata-width-hypen", false}, 83 {"1.2.3-rc1-with-hypen", false}, 84 {"v1.2.3-rc1-with-hypen", false}, 85 {"1.2.3.4", true}, 86 {"v1.2.3.4", true}, 87 {"1.2.2147483648", false}, 88 {"1.2147483648.3", false}, 89 {"2147483648.3.0", false}, 90 } 91 92 for _, tc := range tests { 93 _, err := NewVersion(tc.version) 94 if tc.err && err == nil { 95 t.Fatalf("expected error for version: %s", tc.version) 96 } else if !tc.err && err != nil { 97 t.Fatalf("error for version %s: %s", tc.version, err) 98 } 99 } 100} 101 102func TestOriginal(t *testing.T) { 103 tests := []string{ 104 "1.2.3", 105 "v1.2.3", 106 "1.0", 107 "v1.0", 108 "1", 109 "v1", 110 "1.2-5", 111 "v1.2-5", 112 "1.2-beta.5", 113 "v1.2-beta.5", 114 "1.2.0-x.Y.0+metadata", 115 "v1.2.0-x.Y.0+metadata", 116 "1.2.0-x.Y.0+metadata-width-hypen", 117 "v1.2.0-x.Y.0+metadata-width-hypen", 118 "1.2.3-rc1-with-hypen", 119 "v1.2.3-rc1-with-hypen", 120 } 121 122 for _, tc := range tests { 123 v, err := NewVersion(tc) 124 if err != nil { 125 t.Errorf("Error parsing version %s", tc) 126 } 127 128 o := v.Original() 129 if o != tc { 130 t.Errorf("Error retrieving original. Expected '%s' but got '%v'", tc, v) 131 } 132 } 133} 134 135func TestParts(t *testing.T) { 136 v, err := NewVersion("1.2.3-beta.1+build.123") 137 if err != nil { 138 t.Error("Error parsing version 1.2.3-beta.1+build.123") 139 } 140 141 if v.Major() != 1 { 142 t.Error("Major() returning wrong value") 143 } 144 if v.Minor() != 2 { 145 t.Error("Minor() returning wrong value") 146 } 147 if v.Patch() != 3 { 148 t.Error("Patch() returning wrong value") 149 } 150 if v.Prerelease() != "beta.1" { 151 t.Error("Prerelease() returning wrong value") 152 } 153 if v.Metadata() != "build.123" { 154 t.Error("Metadata() returning wrong value") 155 } 156} 157 158func TestCoerceString(t *testing.T) { 159 tests := []struct { 160 version string 161 expected string 162 }{ 163 {"1.2.3", "1.2.3"}, 164 {"v1.2.3", "1.2.3"}, 165 {"1.0", "1.0.0"}, 166 {"v1.0", "1.0.0"}, 167 {"1", "1.0.0"}, 168 {"v1", "1.0.0"}, 169 {"1.2-5", "1.2.0-5"}, 170 {"v1.2-5", "1.2.0-5"}, 171 {"1.2-beta.5", "1.2.0-beta.5"}, 172 {"v1.2-beta.5", "1.2.0-beta.5"}, 173 {"1.2.0-x.Y.0+metadata", "1.2.0-x.Y.0+metadata"}, 174 {"v1.2.0-x.Y.0+metadata", "1.2.0-x.Y.0+metadata"}, 175 {"1.2.0-x.Y.0+metadata-width-hypen", "1.2.0-x.Y.0+metadata-width-hypen"}, 176 {"v1.2.0-x.Y.0+metadata-width-hypen", "1.2.0-x.Y.0+metadata-width-hypen"}, 177 {"1.2.3-rc1-with-hypen", "1.2.3-rc1-with-hypen"}, 178 {"v1.2.3-rc1-with-hypen", "1.2.3-rc1-with-hypen"}, 179 } 180 181 for _, tc := range tests { 182 v, err := NewVersion(tc.version) 183 if err != nil { 184 t.Errorf("Error parsing version %s", tc) 185 } 186 187 s := v.String() 188 if s != tc.expected { 189 t.Errorf("Error generating string. Expected '%s' but got '%s'", tc.expected, s) 190 } 191 } 192} 193 194func TestCompare(t *testing.T) { 195 tests := []struct { 196 v1 string 197 v2 string 198 expected int 199 }{ 200 {"1.2.3", "1.5.1", -1}, 201 {"2.2.3", "1.5.1", 1}, 202 {"2.2.3", "2.2.2", 1}, 203 {"3.2-beta", "3.2-beta", 0}, 204 {"1.3", "1.1.4", 1}, 205 {"4.2", "4.2-beta", 1}, 206 {"4.2-beta", "4.2", -1}, 207 {"4.2-alpha", "4.2-beta", -1}, 208 {"4.2-alpha", "4.2-alpha", 0}, 209 {"4.2-beta.2", "4.2-beta.1", 1}, 210 {"4.2-beta2", "4.2-beta1", 1}, 211 {"4.2-beta", "4.2-beta.2", -1}, 212 {"4.2-beta", "4.2-beta.foo", -1}, 213 {"4.2-beta.2", "4.2-beta", 1}, 214 {"4.2-beta.foo", "4.2-beta", 1}, 215 {"1.2+bar", "1.2+baz", 0}, 216 {"1.0.0-beta.4", "1.0.0-beta.-2", -1}, 217 {"1.0.0-beta.-2", "1.0.0-beta.-3", -1}, 218 {"1.0.0-beta.-3", "1.0.0-beta.5", 1}, 219 } 220 221 for _, tc := range tests { 222 v1, err := NewVersion(tc.v1) 223 if err != nil { 224 t.Errorf("Error parsing version: %s", err) 225 } 226 227 v2, err := NewVersion(tc.v2) 228 if err != nil { 229 t.Errorf("Error parsing version: %s", err) 230 } 231 232 a := v1.Compare(v2) 233 e := tc.expected 234 if a != e { 235 t.Errorf( 236 "Comparison of '%s' and '%s' failed. Expected '%d', got '%d'", 237 tc.v1, tc.v2, e, a, 238 ) 239 } 240 } 241} 242 243func TestLessThan(t *testing.T) { 244 tests := []struct { 245 v1 string 246 v2 string 247 expected bool 248 }{ 249 {"1.2.3", "1.5.1", true}, 250 {"2.2.3", "1.5.1", false}, 251 {"3.2-beta", "3.2-beta", false}, 252 } 253 254 for _, tc := range tests { 255 v1, err := NewVersion(tc.v1) 256 if err != nil { 257 t.Errorf("Error parsing version: %s", err) 258 } 259 260 v2, err := NewVersion(tc.v2) 261 if err != nil { 262 t.Errorf("Error parsing version: %s", err) 263 } 264 265 a := v1.LessThan(v2) 266 e := tc.expected 267 if a != e { 268 t.Errorf( 269 "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", 270 tc.v1, tc.v2, e, a, 271 ) 272 } 273 } 274} 275 276func TestGreaterThan(t *testing.T) { 277 tests := []struct { 278 v1 string 279 v2 string 280 expected bool 281 }{ 282 {"1.2.3", "1.5.1", false}, 283 {"2.2.3", "1.5.1", true}, 284 {"3.2-beta", "3.2-beta", false}, 285 {"3.2.0-beta.1", "3.2.0-beta.5", false}, 286 {"3.2-beta.4", "3.2-beta.2", true}, 287 {"7.43.0-SNAPSHOT.99", "7.43.0-SNAPSHOT.103", false}, 288 {"7.43.0-SNAPSHOT.FOO", "7.43.0-SNAPSHOT.103", true}, 289 {"7.43.0-SNAPSHOT.99", "7.43.0-SNAPSHOT.BAR", false}, 290 } 291 292 for _, tc := range tests { 293 v1, err := NewVersion(tc.v1) 294 if err != nil { 295 t.Errorf("Error parsing version: %s", err) 296 } 297 298 v2, err := NewVersion(tc.v2) 299 if err != nil { 300 t.Errorf("Error parsing version: %s", err) 301 } 302 303 a := v1.GreaterThan(v2) 304 e := tc.expected 305 if a != e { 306 t.Errorf( 307 "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", 308 tc.v1, tc.v2, e, a, 309 ) 310 } 311 } 312} 313 314func TestEqual(t *testing.T) { 315 tests := []struct { 316 v1 string 317 v2 string 318 expected bool 319 }{ 320 {"1.2.3", "1.5.1", false}, 321 {"2.2.3", "1.5.1", false}, 322 {"3.2-beta", "3.2-beta", true}, 323 {"3.2-beta+foo", "3.2-beta+bar", true}, 324 } 325 326 for _, tc := range tests { 327 v1, err := NewVersion(tc.v1) 328 if err != nil { 329 t.Errorf("Error parsing version: %s", err) 330 } 331 332 v2, err := NewVersion(tc.v2) 333 if err != nil { 334 t.Errorf("Error parsing version: %s", err) 335 } 336 337 a := v1.Equal(v2) 338 e := tc.expected 339 if a != e { 340 t.Errorf( 341 "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", 342 tc.v1, tc.v2, e, a, 343 ) 344 } 345 } 346} 347 348func TestInc(t *testing.T) { 349 tests := []struct { 350 v1 string 351 expected string 352 how string 353 expectedOriginal string 354 }{ 355 {"1.2.3", "1.2.4", "patch", "1.2.4"}, 356 {"v1.2.4", "1.2.5", "patch", "v1.2.5"}, 357 {"1.2.3", "1.3.0", "minor", "1.3.0"}, 358 {"v1.2.4", "1.3.0", "minor", "v1.3.0"}, 359 {"1.2.3", "2.0.0", "major", "2.0.0"}, 360 {"v1.2.4", "2.0.0", "major", "v2.0.0"}, 361 {"1.2.3+meta", "1.2.4", "patch", "1.2.4"}, 362 {"1.2.3-beta+meta", "1.2.3", "patch", "1.2.3"}, 363 {"v1.2.4-beta+meta", "1.2.4", "patch", "v1.2.4"}, 364 {"1.2.3-beta+meta", "1.3.0", "minor", "1.3.0"}, 365 {"v1.2.4-beta+meta", "1.3.0", "minor", "v1.3.0"}, 366 {"1.2.3-beta+meta", "2.0.0", "major", "2.0.0"}, 367 {"v1.2.4-beta+meta", "2.0.0", "major", "v2.0.0"}, 368 } 369 370 for _, tc := range tests { 371 v1, err := NewVersion(tc.v1) 372 if err != nil { 373 t.Errorf("Error parsing version: %s", err) 374 } 375 var v2 Version 376 switch tc.how { 377 case "patch": 378 v2 = v1.IncPatch() 379 case "minor": 380 v2 = v1.IncMinor() 381 case "major": 382 v2 = v1.IncMajor() 383 } 384 385 a := v2.String() 386 e := tc.expected 387 if a != e { 388 t.Errorf( 389 "Inc %q failed. Expected %q got %q", 390 tc.how, e, a, 391 ) 392 } 393 394 a = v2.Original() 395 e = tc.expectedOriginal 396 if a != e { 397 t.Errorf( 398 "Inc %q failed. Expected original %q got %q", 399 tc.how, e, a, 400 ) 401 } 402 } 403} 404 405func TestSetPrerelease(t *testing.T) { 406 tests := []struct { 407 v1 string 408 prerelease string 409 expectedVersion string 410 expectedPrerelease string 411 expectedOriginal string 412 expectedErr error 413 }{ 414 {"1.2.3", "**", "1.2.3", "", "1.2.3", ErrInvalidPrerelease}, 415 {"1.2.3", "beta", "1.2.3-beta", "beta", "1.2.3-beta", nil}, 416 {"v1.2.4", "beta", "1.2.4-beta", "beta", "v1.2.4-beta", nil}, 417 } 418 419 for _, tc := range tests { 420 v1, err := NewVersion(tc.v1) 421 if err != nil { 422 t.Errorf("Error parsing version: %s", err) 423 } 424 425 v2, err := v1.SetPrerelease(tc.prerelease) 426 if err != tc.expectedErr { 427 t.Errorf("Expected to get err=%s, but got err=%s", tc.expectedErr, err) 428 } 429 430 a := v2.Prerelease() 431 e := tc.expectedPrerelease 432 if a != e { 433 t.Errorf("Expected prerelease value=%q, but got %q", e, a) 434 } 435 436 a = v2.String() 437 e = tc.expectedVersion 438 if a != e { 439 t.Errorf("Expected version string=%q, but got %q", e, a) 440 } 441 442 a = v2.Original() 443 e = tc.expectedOriginal 444 if a != e { 445 t.Errorf("Expected version original=%q, but got %q", e, a) 446 } 447 } 448} 449 450func TestSetMetadata(t *testing.T) { 451 tests := []struct { 452 v1 string 453 metadata string 454 expectedVersion string 455 expectedMetadata string 456 expectedOriginal string 457 expectedErr error 458 }{ 459 {"1.2.3", "**", "1.2.3", "", "1.2.3", ErrInvalidMetadata}, 460 {"1.2.3", "meta", "1.2.3+meta", "meta", "1.2.3+meta", nil}, 461 {"v1.2.4", "meta", "1.2.4+meta", "meta", "v1.2.4+meta", nil}, 462 } 463 464 for _, tc := range tests { 465 v1, err := NewVersion(tc.v1) 466 if err != nil { 467 t.Errorf("Error parsing version: %s", err) 468 } 469 470 v2, err := v1.SetMetadata(tc.metadata) 471 if err != tc.expectedErr { 472 t.Errorf("Expected to get err=%s, but got err=%s", tc.expectedErr, err) 473 } 474 475 a := v2.Metadata() 476 e := tc.expectedMetadata 477 if a != e { 478 t.Errorf("Expected metadata value=%q, but got %q", e, a) 479 } 480 481 a = v2.String() 482 e = tc.expectedVersion 483 if e != a { 484 t.Errorf("Expected version string=%q, but got %q", e, a) 485 } 486 487 a = v2.Original() 488 e = tc.expectedOriginal 489 if a != e { 490 t.Errorf("Expected version original=%q, but got %q", e, a) 491 } 492 } 493} 494 495func TestOriginalVPrefix(t *testing.T) { 496 tests := []struct { 497 version string 498 vprefix string 499 }{ 500 {"1.2.3", ""}, 501 {"v1.2.4", "v"}, 502 } 503 504 for _, tc := range tests { 505 v1, _ := NewVersion(tc.version) 506 a := v1.originalVPrefix() 507 e := tc.vprefix 508 if a != e { 509 t.Errorf("Expected vprefix=%q, but got %q", e, a) 510 } 511 } 512} 513 514func TestJsonMarshal(t *testing.T) { 515 sVer := "1.1.1" 516 x, err := StrictNewVersion(sVer) 517 if err != nil { 518 t.Errorf("Error creating version: %s", err) 519 } 520 out, err2 := json.Marshal(x) 521 if err2 != nil { 522 t.Errorf("Error marshaling version: %s", err2) 523 } 524 got := string(out) 525 want := fmt.Sprintf("%q", sVer) 526 if got != want { 527 t.Errorf("Error marshaling unexpected marshaled content: got=%q want=%q", got, want) 528 } 529} 530 531func TestJsonUnmarshal(t *testing.T) { 532 sVer := "1.1.1" 533 ver := &Version{} 534 err := json.Unmarshal([]byte(fmt.Sprintf("%q", sVer)), ver) 535 if err != nil { 536 t.Errorf("Error unmarshaling version: %s", err) 537 } 538 got := ver.String() 539 want := sVer 540 if got != want { 541 t.Errorf("Error unmarshaling unexpected object content: got=%q want=%q", got, want) 542 } 543} 544 545func TestSQLScanner(t *testing.T) { 546 sVer := "1.1.1" 547 x, err := StrictNewVersion(sVer) 548 if err != nil { 549 t.Errorf("Error creating version: %s", err) 550 } 551 var s sql.Scanner = x 552 var out *Version 553 var ok bool 554 if out, ok = s.(*Version); !ok { 555 t.Errorf("Error expected Version type, got=%T want=%T", s, Version{}) 556 } 557 got := out.String() 558 want := sVer 559 if got != want { 560 t.Errorf("Error sql scanner unexpected scan content: got=%q want=%q", got, want) 561 } 562} 563 564func TestDriverValuer(t *testing.T) { 565 sVer := "1.1.1" 566 x, err := StrictNewVersion(sVer) 567 if err != nil { 568 t.Errorf("Error creating version: %s", err) 569 } 570 got, err := x.Value() 571 if err != nil { 572 t.Fatalf("Error getting value, got %v", err) 573 } 574 want := sVer 575 if got != want { 576 t.Errorf("Error driver valuer unexpected value content: got=%q want=%q", got, want) 577 } 578} 579 580func TestValidatePrerelease(t *testing.T) { 581 tests := []struct { 582 pre string 583 expected error 584 }{ 585 {"foo", nil}, 586 {"alpha.1", nil}, 587 {"alpha.01", ErrSegmentStartsZero}, 588 {"foo☃︎", ErrInvalidPrerelease}, 589 {"alpha.0-1", nil}, 590 } 591 592 for _, tc := range tests { 593 if err := validatePrerelease(tc.pre); err != tc.expected { 594 t.Errorf("Unexpected error %q for prerelease %q", err, tc.pre) 595 } 596 } 597} 598 599func TestValidateMetadata(t *testing.T) { 600 tests := []struct { 601 meta string 602 expected error 603 }{ 604 {"foo", nil}, 605 {"alpha.1", nil}, 606 {"alpha.01", nil}, 607 {"foo☃︎", ErrInvalidMetadata}, 608 {"alpha.0-1", nil}, 609 {"al-pha.1Phe70CgWe050H9K1mJwRUqTNQXZRERwLOEg37wpXUb4JgzgaD5YkL52ABnoyiE", nil}, 610 } 611 612 for _, tc := range tests { 613 if err := validateMetadata(tc.meta); err != tc.expected { 614 t.Errorf("Unexpected error %q for metadata %q", err, tc.meta) 615 } 616 } 617} 618