github.com/snyk/vervet/v6@v6.2.4/version_test.go (about) 1 package vervet_test 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 qt "github.com/frankban/quicktest" 9 10 . "github.com/snyk/vervet/v6" 11 ) 12 13 func TestParseVersion(t *testing.T) { 14 c := qt.New(t) 15 tests := []struct { 16 vs string 17 d string 18 stab Stability 19 err string 20 }{{ 21 vs: "2021-01-01", 22 d: "2021-01-01", 23 stab: StabilityGA, 24 }, { 25 vs: "2021-02-02~beta", 26 d: "2021-02-02", 27 stab: StabilityBeta, 28 }, { 29 vs: "2021-03-03~experimental", 30 d: "2021-03-03", 31 stab: StabilityExperimental, 32 }, { 33 vs: "unknown", 34 err: `invalid version "unknown"`, 35 }} 36 for i := range tests { 37 c.Logf("parse version %q", tests[i].vs) 38 v, err := ParseVersion(tests[i].vs) 39 if tests[i].err != "" { 40 c.Assert(err, qt.ErrorMatches, tests[i].err) 41 c.Assert(func() { MustParseVersion(tests[i].vs) }, qt.PanicMatches, tests[i].err) 42 } else { 43 c.Assert(v.Date.Format("2006-01-02"), qt.Equals, tests[i].d) 44 c.Assert(v.Stability, qt.Equals, tests[i].stab) 45 } 46 } 47 } 48 49 func TestVersionStringPanics(t *testing.T) { 50 c := qt.New(t) 51 var v Version 52 c.Assert(func() { 53 c.Log(v.String()) 54 }, qt.PanicMatches, "invalid stability.*") 55 var s Stability 56 c.Assert(func() { 57 c.Log(s.String()) 58 }, qt.PanicMatches, "invalid stability.*") 59 } 60 61 func TestVersionOrder(t *testing.T) { 62 c := qt.New(t) 63 tests := []struct { 64 l, r string 65 cmp int 66 }{{ 67 // Compare some date versions 68 l: "2020-12-31", r: "2021-01-01", cmp: -1, 69 }, { 70 l: "2021-01-01", r: "2020-12-31", cmp: 1, 71 }, { 72 l: "2021-01-01", r: "2021-01-01", cmp: 0, 73 }, { 74 l: "9999-12-31", r: "9999-12-31~beta", cmp: 1, 75 }, { 76 // Compare date versions and special tags 77 l: "9999-12-31~beta", r: "9999-12-31", cmp: -1, 78 }, { 79 l: "9999-12-31", r: "9999-12-31~experimental", cmp: 1, 80 }, { 81 l: "9999-12-31~experimental", r: "9999-12-31", cmp: -1, 82 // Compare special tags 83 }, { 84 l: "2021-08-01~beta", r: "2021-08-01~experimental", cmp: 1, 85 }, { 86 l: "2021-08-01~experimental", r: "2021-08-01~beta", cmp: -1, 87 }, { 88 l: "2021-08-01~beta", r: "2021-08-01~beta", cmp: 0, 89 }, { 90 l: "2021-08-01~experimental", r: "2021-08-01~experimental", cmp: 0, 91 }, { 92 l: "2021-08-01~wip", r: "2021-08-01~experimental", cmp: -1, 93 }} 94 for i := range tests { 95 c.Logf("test %d %#v", i, tests[i]) 96 lv, err := ParseVersion(tests[i].l) 97 c.Assert(err, qt.IsNil) 98 rv, err := ParseVersion(tests[i].r) 99 c.Assert(err, qt.IsNil) 100 c.Assert(lv.Compare(rv), qt.Equals, tests[i].cmp) 101 } 102 } 103 104 func TestVersionDateStrings(t *testing.T) { 105 c := qt.New(t) 106 c.Assert(VersionDateStrings([]Version{ 107 MustParseVersion("2021-06-01~wip"), 108 MustParseVersion("2021-06-01~beta"), 109 MustParseVersion("2021-06-10~beta"), 110 MustParseVersion("2021-06-10"), 111 MustParseVersion("2021-07-12~wip"), 112 MustParseVersion("2021-07-12~experimental"), 113 MustParseVersion("2021-07-12~beta"), 114 }), qt.ContentEquals, []string{"2021-06-01", "2021-06-10", "2021-07-12"}) 115 } 116 117 func TestVersionIndex(t *testing.T) { 118 type matchTest struct { 119 match string 120 atStability string 121 mostStable string 122 err string 123 } 124 tests := []struct { 125 versions VersionSlice 126 first string 127 last string 128 matchTests []matchTest 129 }{{ 130 versions: VersionSlice{ 131 MustParseVersion("2021-07-12~experimental"), 132 MustParseVersion("2021-06-01~beta"), 133 MustParseVersion("2021-07-12~beta"), 134 MustParseVersion("2021-06-10"), 135 MustParseVersion("2021-06-01~wip"), 136 MustParseVersion("2021-07-12~wip"), 137 MustParseVersion("2021-06-10~beta"), 138 }, 139 first: "2021-06-01~wip", 140 last: "2021-07-12~beta", 141 matchTests: []matchTest{{ 142 match: "2021-06-10", 143 atStability: "2021-06-10", 144 mostStable: "2021-06-10", 145 }, { 146 match: "2021-06-10~beta", 147 atStability: "2021-06-10~beta", 148 mostStable: "2021-06-10", 149 }, { 150 match: "2021-06-11~beta", 151 atStability: "2021-06-10~beta", 152 mostStable: "2021-06-10", 153 }, { 154 match: "2021-06-11", 155 atStability: "2021-06-10", 156 mostStable: "2021-06-10", 157 }, { 158 match: "2021-06-10~experimental", 159 atStability: "2021-06-10~beta", 160 mostStable: "2021-06-10", 161 }, { 162 match: "2021-06-11~experimental", 163 atStability: "2021-06-10~beta", 164 mostStable: "2021-06-10", 165 }, { 166 match: "2021-01-01", 167 err: "no matching version", 168 }, { 169 match: "2022-01-01", 170 atStability: "2021-06-10", 171 mostStable: "2021-06-10", 172 }, { 173 match: "2022-01-01~experimental", 174 atStability: "2021-07-12~experimental", 175 mostStable: "2021-07-12~beta", 176 }, { 177 match: "2022-01-01~beta", 178 atStability: "2021-07-12~beta", 179 mostStable: "2021-07-12~beta", 180 }}, 181 }, { 182 versions: VersionSlice{ 183 MustParseVersion("2021-06-10~beta"), 184 }, 185 first: "2021-06-10~beta", 186 last: "2021-06-10~beta", 187 matchTests: []matchTest{{ 188 match: "2021-06-10", 189 err: "no matching version", 190 }, { 191 match: "2021-06-10~beta", 192 atStability: "2021-06-10~beta", 193 mostStable: "2021-06-10~beta", 194 }, { 195 match: "2021-06-10~experimental", 196 atStability: "2021-06-10~beta", 197 mostStable: "2021-06-10~beta", 198 }, { 199 match: "2021-06-11~wip", 200 atStability: "2021-06-10~beta", 201 mostStable: "2021-06-10~beta", 202 }, { 203 match: "2021-01-01", 204 err: "no matching version", 205 }, { 206 match: "2022-01-01~wip", 207 atStability: "2021-06-10~beta", 208 mostStable: "2021-06-10~beta", 209 }}, 210 }, { 211 versions: VersionSlice{ 212 MustParseVersion("2021-06-10~beta"), 213 MustParseVersion("2022-01-10~experimental"), 214 }, 215 first: "2021-06-10~beta", 216 last: "2022-01-10~experimental", 217 matchTests: []matchTest{{ 218 match: "2021-04-10", 219 err: "no matching version", 220 }, { 221 match: "2021-08-10~beta", 222 atStability: "2021-06-10~beta", 223 mostStable: "2021-06-10~beta", 224 }, { 225 match: "2022-02-10~wip", 226 atStability: "2022-01-10~experimental", 227 mostStable: "2022-01-10~experimental", 228 }, { 229 match: "2021-01-30", 230 err: "no matching version", 231 }}, 232 }, { 233 versions: VersionSlice{ 234 MustParseVersion("2021-09-06"), 235 MustParseVersion("2021-10-06"), 236 }, 237 first: "2021-09-06", 238 last: "2021-10-06", 239 matchTests: []matchTest{{ 240 match: "2021-10-12~wip", 241 atStability: "2021-10-06", 242 mostStable: "2021-10-06", 243 }}, 244 }, { 245 versions: VersionSlice{ 246 MustParseVersion("2021-09-06~beta"), 247 MustParseVersion("2021-09-07"), 248 MustParseVersion("2021-09-08~beta"), 249 MustParseVersion("2021-09-09~experimental"), 250 }, 251 first: "2021-09-06~beta", 252 last: "2021-09-09~experimental", 253 matchTests: []matchTest{{ 254 match: "2021-09-10", 255 atStability: "2021-09-07", 256 mostStable: "2021-09-07", 257 }}, 258 }} 259 c := qt.New(t) 260 for _, t := range tests { 261 index := NewVersionIndex(t.versions) 262 c.Log(t.versions) 263 c.Assert(t.versions[0].String(), qt.Equals, t.first) 264 c.Assert(t.versions[len(t.versions)-1].String(), qt.Equals, t.last) 265 for _, mt := range t.matchTests { 266 c.Log(mt) 267 match := MustParseVersion(mt.match) 268 atStability, err := index.Resolve(match) 269 if err != nil { 270 c.Assert(err, qt.ErrorMatches, mt.err) 271 } else { 272 c.Assert(atStability.String(), qt.Equals, mt.atStability) 273 } 274 mostStable, err := index.ResolveForBuild(match) 275 if err != nil { 276 c.Assert(err, qt.ErrorMatches, mt.err) 277 } else { 278 c.Assert(mostStable.String(), qt.Equals, mt.mostStable) 279 } 280 } 281 } 282 } 283 284 func TestVersionIndexResolveEmpty(t *testing.T) { 285 c := qt.New(t) 286 vi := NewVersionIndex(VersionSlice{}) 287 _, err := vi.Resolve(MustParseVersion("2021-10-31")) 288 c.Assert(err, qt.ErrorMatches, "no matching version") 289 _, err = vi.ResolveForBuild(MustParseVersion("2021-10-31")) 290 c.Assert(err, qt.ErrorMatches, "no matching version") 291 } 292 293 func TestDeprecatedBy(t *testing.T) { 294 c := qt.New(t) 295 tests := []struct { 296 base, deprecatedBy string 297 result bool 298 }{{ 299 "2021-06-01", "2021-02-01", false, 300 }, { 301 "2021-06-01", "2021-02-01~experimental", false, 302 }, { 303 "2021-06-01", "2021-02-01~beta", false, 304 }, { 305 "2021-06-01", "2022-02-01~beta", false, 306 }, { 307 "2021-06-01", "2022-02-01~experimental", false, 308 }, { 309 "2021-06-01", "2021-06-01", false, 310 }, { 311 "2021-06-01", "2021-06-02", true, 312 }, { 313 "2021-06-01~experimental", "2021-06-02~beta", true, 314 }, { 315 "2021-06-01~beta", "2021-06-02", true, 316 }, { 317 "2021-06-01", "2021-06-01", false, 318 }} 319 for i, test := range tests { 320 c.Logf("test#%d: %#v", i, test) 321 base, deprecatedBy := MustParseVersion(test.base), MustParseVersion(test.deprecatedBy) 322 c.Assert(base.DeprecatedBy(deprecatedBy), qt.Equals, test.result) 323 } 324 } 325 326 func TestDeprecates(t *testing.T) { 327 c := qt.New(t) 328 versions := NewVersionIndex(VersionSlice{ 329 MustParseVersion("2021-06-01~experimental"), 330 MustParseVersion("2021-06-07~beta"), 331 MustParseVersion("2021-07-01"), 332 MustParseVersion("2021-08-12~experimental"), 333 MustParseVersion("2021-09-16~beta"), 334 MustParseVersion("2021-10-31"), 335 }) 336 tests := []struct { 337 name string 338 target Version 339 deprecatedBy Version 340 isDeprecated bool 341 sunset time.Time 342 }{{ 343 name: "beta deprecates experimental", 344 target: MustParseVersion("2021-06-01~experimental"), 345 deprecatedBy: MustParseVersion("2021-06-07~beta"), 346 isDeprecated: true, 347 sunset: time.Date(2021, time.June, 8, 0, 0, 0, 0, time.UTC), 348 }, { 349 name: "ga deprecates beta", 350 target: MustParseVersion("2021-06-07~beta"), 351 deprecatedBy: MustParseVersion("2021-07-01"), 352 isDeprecated: true, 353 sunset: time.Date(2021, time.September, 30, 0, 0, 0, 0, time.UTC), 354 }, { 355 name: "ga deprecates ga", 356 target: MustParseVersion("2021-07-01"), 357 deprecatedBy: MustParseVersion("2021-10-31"), 358 isDeprecated: true, 359 sunset: time.Date(2022, time.April, 30, 0, 0, 0, 0, time.UTC), 360 }} 361 for i, test := range tests { 362 c.Logf("test#%d: %s", i, test.name) 363 deprecates, ok := versions.Deprecates(test.target) 364 c.Assert(ok, qt.Equals, test.isDeprecated) 365 if test.isDeprecated { 366 c.Assert(test.deprecatedBy, qt.DeepEquals, deprecates) 367 sunset, ok := test.target.Sunset(deprecates) 368 c.Assert(ok, qt.IsTrue) 369 c.Assert(test.sunset, qt.Equals, sunset) 370 } 371 } 372 } 373 374 func TestLifecycleAtEnv(t *testing.T) { 375 c := qt.New(t) 376 tests := []struct { 377 version Version 378 lifecycle string 379 at string 380 }{{ 381 version: MustParseVersion("2022-08-16~wip"), 382 lifecycle: "sunset", 383 at: "2022-08-16", 384 }, { 385 version: MustParseVersion("2022-08-16~experimental"), 386 lifecycle: "deprecated", 387 at: "2022-08-16", 388 }, { 389 version: MustParseVersion("2022-08-16~experimental"), 390 lifecycle: "sunset", 391 at: "2022-11-16", 392 }, { 393 version: MustParseVersion("2022-08-16~beta"), 394 lifecycle: "released", 395 at: "2022-08-16", 396 }, { 397 version: MustParseVersion("2022-08-16~beta"), 398 lifecycle: "released", 399 at: "2022-11-16", 400 }} 401 for _, test := range tests { 402 c.Run(fmt.Sprintf("test %v", test.version), func(c *qt.C) { 403 c.Setenv("VERVET_LIFECYCLE_AT", test.at) 404 lifecycle := test.version.LifecycleAt(time.Time{}) 405 c.Assert(lifecycle.String(), qt.Equals, test.lifecycle) 406 }) 407 } 408 } 409 410 func TestLifecycleAtDefaultDate(t *testing.T) { 411 c := qt.New(t) 412 tests := []struct { 413 version Version 414 lifecycle string 415 at string 416 }{{ 417 version: MustParseVersion("2022-08-16~wip"), 418 lifecycle: "sunset", 419 }, { 420 version: MustParseVersion("2022-08-16~experimental"), 421 lifecycle: "deprecated", 422 }, { 423 version: MustParseVersion("2022-05-16~experimental"), 424 lifecycle: "sunset", 425 }, { 426 version: MustParseVersion("2022-08-16~beta"), 427 lifecycle: "released", 428 }, { 429 version: MustParseVersion("2022-08-16~beta"), 430 lifecycle: "released", 431 }} 432 for _, test := range tests { 433 c.Run(fmt.Sprintf("test %v", test.version), func(c *qt.C) { 434 c.Patch(TimeNow, func() time.Time { return time.Date(2022, time.September, 6, 14, 49, 50, 0, time.UTC) }) 435 lifecycle := test.version.LifecycleAt(time.Time{}) 436 c.Assert(lifecycle.String(), qt.Equals, test.lifecycle) 437 }) 438 } 439 } 440 441 func TestLifecycleAtUnreleasedVersionStringPanics(t *testing.T) { 442 c := qt.New(t) 443 c.Patch(TimeNow, func() time.Time { return time.Date(2022, time.June, 6, 14, 49, 50, 0, time.UTC) }) 444 version := MustParseVersion("2022-10-16~wip") 445 lifecycle := version.LifecycleAt(time.Time{}) 446 c.Assert(func() { 447 c.Log(lifecycle.String()) 448 }, qt.PanicMatches, "invalid lifecycle.*") 449 }