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