github.com/snyk/vervet/v4@v4.27.2/version_test.go (about)

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