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 } 167 168 for _, tc := range tests { 169 v1, err := NewVersion(tc.v1) 170 if err != nil { 171 t.Errorf("Error parsing version: %s", err) 172 } 173 174 v2, err := NewVersion(tc.v2) 175 if err != nil { 176 t.Errorf("Error parsing version: %s", err) 177 } 178 179 a := v1.Compare(v2) 180 e := tc.expected 181 if a != e { 182 t.Errorf( 183 "Comparison of '%s' and '%s' failed. Expected '%d', got '%d'", 184 tc.v1, tc.v2, e, a, 185 ) 186 } 187 } 188} 189 190func TestLessThan(t *testing.T) { 191 tests := []struct { 192 v1 string 193 v2 string 194 expected bool 195 }{ 196 {"1.2.3", "1.5.1", true}, 197 {"2.2.3", "1.5.1", false}, 198 {"3.2-beta", "3.2-beta", false}, 199 } 200 201 for _, tc := range tests { 202 v1, err := NewVersion(tc.v1) 203 if err != nil { 204 t.Errorf("Error parsing version: %s", err) 205 } 206 207 v2, err := NewVersion(tc.v2) 208 if err != nil { 209 t.Errorf("Error parsing version: %s", err) 210 } 211 212 a := v1.LessThan(v2) 213 e := tc.expected 214 if a != e { 215 t.Errorf( 216 "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", 217 tc.v1, tc.v2, e, a, 218 ) 219 } 220 } 221} 222 223func TestGreaterThan(t *testing.T) { 224 tests := []struct { 225 v1 string 226 v2 string 227 expected bool 228 }{ 229 {"1.2.3", "1.5.1", false}, 230 {"2.2.3", "1.5.1", true}, 231 {"3.2-beta", "3.2-beta", false}, 232 {"3.2.0-beta.1", "3.2.0-beta.5", false}, 233 {"3.2-beta.4", "3.2-beta.2", true}, 234 {"7.43.0-SNAPSHOT.99", "7.43.0-SNAPSHOT.103", false}, 235 {"7.43.0-SNAPSHOT.FOO", "7.43.0-SNAPSHOT.103", true}, 236 {"7.43.0-SNAPSHOT.99", "7.43.0-SNAPSHOT.BAR", false}, 237 } 238 239 for _, tc := range tests { 240 v1, err := NewVersion(tc.v1) 241 if err != nil { 242 t.Errorf("Error parsing version: %s", err) 243 } 244 245 v2, err := NewVersion(tc.v2) 246 if err != nil { 247 t.Errorf("Error parsing version: %s", err) 248 } 249 250 a := v1.GreaterThan(v2) 251 e := tc.expected 252 if a != e { 253 t.Errorf( 254 "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", 255 tc.v1, tc.v2, e, a, 256 ) 257 } 258 } 259} 260 261func TestEqual(t *testing.T) { 262 tests := []struct { 263 v1 string 264 v2 string 265 expected bool 266 }{ 267 {"1.2.3", "1.5.1", false}, 268 {"2.2.3", "1.5.1", false}, 269 {"3.2-beta", "3.2-beta", true}, 270 {"3.2-beta+foo", "3.2-beta+bar", true}, 271 } 272 273 for _, tc := range tests { 274 v1, err := NewVersion(tc.v1) 275 if err != nil { 276 t.Errorf("Error parsing version: %s", err) 277 } 278 279 v2, err := NewVersion(tc.v2) 280 if err != nil { 281 t.Errorf("Error parsing version: %s", err) 282 } 283 284 a := v1.Equal(v2) 285 e := tc.expected 286 if a != e { 287 t.Errorf( 288 "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", 289 tc.v1, tc.v2, e, a, 290 ) 291 } 292 } 293} 294 295func TestInc(t *testing.T) { 296 tests := []struct { 297 v1 string 298 expected string 299 how string 300 expectedOriginal string 301 }{ 302 {"1.2.3", "1.2.4", "patch", "1.2.4"}, 303 {"v1.2.4", "1.2.5", "patch", "v1.2.5"}, 304 {"1.2.3", "1.3.0", "minor", "1.3.0"}, 305 {"v1.2.4", "1.3.0", "minor", "v1.3.0"}, 306 {"1.2.3", "2.0.0", "major", "2.0.0"}, 307 {"v1.2.4", "2.0.0", "major", "v2.0.0"}, 308 {"1.2.3+meta", "1.2.4", "patch", "1.2.4"}, 309 {"1.2.3-beta+meta", "1.2.3", "patch", "1.2.3"}, 310 {"v1.2.4-beta+meta", "1.2.4", "patch", "v1.2.4"}, 311 {"1.2.3-beta+meta", "1.3.0", "minor", "1.3.0"}, 312 {"v1.2.4-beta+meta", "1.3.0", "minor", "v1.3.0"}, 313 {"1.2.3-beta+meta", "2.0.0", "major", "2.0.0"}, 314 {"v1.2.4-beta+meta", "2.0.0", "major", "v2.0.0"}, 315 } 316 317 for _, tc := range tests { 318 v1, err := NewVersion(tc.v1) 319 if err != nil { 320 t.Errorf("Error parsing version: %s", err) 321 } 322 var v2 Version 323 switch tc.how { 324 case "patch": 325 v2 = v1.IncPatch() 326 case "minor": 327 v2 = v1.IncMinor() 328 case "major": 329 v2 = v1.IncMajor() 330 } 331 332 a := v2.String() 333 e := tc.expected 334 if a != e { 335 t.Errorf( 336 "Inc %q failed. Expected %q got %q", 337 tc.how, e, a, 338 ) 339 } 340 341 a = v2.Original() 342 e = tc.expectedOriginal 343 if a != e { 344 t.Errorf( 345 "Inc %q failed. Expected original %q got %q", 346 tc.how, e, a, 347 ) 348 } 349 } 350} 351 352func TestSetPrerelease(t *testing.T) { 353 tests := []struct { 354 v1 string 355 prerelease string 356 expectedVersion string 357 expectedPrerelease string 358 expectedOriginal string 359 expectedErr error 360 }{ 361 {"1.2.3", "**", "1.2.3", "", "1.2.3", ErrInvalidPrerelease}, 362 {"1.2.3", "beta", "1.2.3-beta", "beta", "1.2.3-beta", nil}, 363 {"v1.2.4", "beta", "1.2.4-beta", "beta", "v1.2.4-beta", nil}, 364 } 365 366 for _, tc := range tests { 367 v1, err := NewVersion(tc.v1) 368 if err != nil { 369 t.Errorf("Error parsing version: %s", err) 370 } 371 372 v2, err := v1.SetPrerelease(tc.prerelease) 373 if err != tc.expectedErr { 374 t.Errorf("Expected to get err=%s, but got err=%s", tc.expectedErr, err) 375 } 376 377 a := v2.Prerelease() 378 e := tc.expectedPrerelease 379 if a != e { 380 t.Errorf("Expected prerelease value=%q, but got %q", e, a) 381 } 382 383 a = v2.String() 384 e = tc.expectedVersion 385 if a != e { 386 t.Errorf("Expected version string=%q, but got %q", e, a) 387 } 388 389 a = v2.Original() 390 e = tc.expectedOriginal 391 if a != e { 392 t.Errorf("Expected version original=%q, but got %q", e, a) 393 } 394 } 395} 396 397func TestSetMetadata(t *testing.T) { 398 tests := []struct { 399 v1 string 400 metadata string 401 expectedVersion string 402 expectedMetadata string 403 expectedOriginal string 404 expectedErr error 405 }{ 406 {"1.2.3", "**", "1.2.3", "", "1.2.3", ErrInvalidMetadata}, 407 {"1.2.3", "meta", "1.2.3+meta", "meta", "1.2.3+meta", nil}, 408 {"v1.2.4", "meta", "1.2.4+meta", "meta", "v1.2.4+meta", nil}, 409 } 410 411 for _, tc := range tests { 412 v1, err := NewVersion(tc.v1) 413 if err != nil { 414 t.Errorf("Error parsing version: %s", err) 415 } 416 417 v2, err := v1.SetMetadata(tc.metadata) 418 if err != tc.expectedErr { 419 t.Errorf("Expected to get err=%s, but got err=%s", tc.expectedErr, err) 420 } 421 422 a := v2.Metadata() 423 e := tc.expectedMetadata 424 if a != e { 425 t.Errorf("Expected metadata value=%q, but got %q", e, a) 426 } 427 428 a = v2.String() 429 e = tc.expectedVersion 430 if e != a { 431 t.Errorf("Expected version string=%q, but got %q", e, a) 432 } 433 434 a = v2.Original() 435 e = tc.expectedOriginal 436 if a != e { 437 t.Errorf("Expected version original=%q, but got %q", e, a) 438 } 439 } 440} 441 442func TestOriginalVPrefix(t *testing.T) { 443 tests := []struct { 444 version string 445 vprefix string 446 }{ 447 {"1.2.3", ""}, 448 {"v1.2.4", "v"}, 449 } 450 451 for _, tc := range tests { 452 v1, _ := NewVersion(tc.version) 453 a := v1.originalVPrefix() 454 e := tc.vprefix 455 if a != e { 456 t.Errorf("Expected vprefix=%q, but got %q", e, a) 457 } 458 } 459} 460 461func TestJsonMarshal(t *testing.T) { 462 sVer := "1.1.1" 463 x, err := NewVersion(sVer) 464 if err != nil { 465 t.Errorf("Error creating version: %s", err) 466 } 467 out, err2 := json.Marshal(x) 468 if err2 != nil { 469 t.Errorf("Error marshaling version: %s", err2) 470 } 471 got := string(out) 472 want := fmt.Sprintf("%q", sVer) 473 if got != want { 474 t.Errorf("Error marshaling unexpected marshaled content: got=%q want=%q", got, want) 475 } 476} 477 478func TestJsonUnmarshal(t *testing.T) { 479 sVer := "1.1.1" 480 ver := &Version{} 481 err := json.Unmarshal([]byte(fmt.Sprintf("%q", sVer)), ver) 482 if err != nil { 483 t.Errorf("Error unmarshaling version: %s", err) 484 } 485 got := ver.String() 486 want := sVer 487 if got != want { 488 t.Errorf("Error unmarshaling unexpected object content: got=%q want=%q", got, want) 489 } 490} 491