diff options
author | Martin Polden <mpolden@mpolden.no> | 2021-09-17 15:05:19 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2021-09-20 14:35:29 +0200 |
commit | c561c995b715c73e83c90b66904a2de70c737c71 (patch) | |
tree | 2e608751586a6ab5efc233857f9dca78c0af24d9 /client | |
parent | 0dd24fccd012608867b9ff0c7378044855d99cdb (diff) |
Implement version package
Diffstat (limited to 'client')
-rw-r--r-- | client/go/version/version.go | 61 | ||||
-rw-r--r-- | client/go/version/version_test.go | 59 |
2 files changed, 120 insertions, 0 deletions
diff --git a/client/go/version/version.go b/client/go/version/version.go new file mode 100644 index 00000000000..e0dc8bf39ae --- /dev/null +++ b/client/go/version/version.go @@ -0,0 +1,61 @@ +package version + +import ( + "fmt" + "strconv" + "strings" +) + +// Version represents a semantic version number. +type Version struct { + Major int + Minor int + Patch int +} + +func (v Version) String() string { return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch) } + +// Compare returns a positive integer if v1 is greater than v2, a negative integer if v1 is less than v2 and zero if they +// are equal. +func (v1 Version) Compare(v2 Version) int { + result := v1.Major - v2.Major + if result != 0 { + return result + } + result = v1.Minor - v2.Minor + if result != 0 { + return result + } + result = v1.Patch - v2.Patch + if result != 0 { + return result + } + return 0 +} + +// Less returns true if v1 is lower than v2. +func (v1 Version) Less(v2 Version) bool { return v1.Compare(v2) < 0 } + +// Parse parses a semantic version number from string s. +func Parse(s string) (Version, error) { + if len(s) > 0 && s[0] == 'v' { + s = s[1:] // Trim v prefix + } + parts := strings.Split(s, ".") + if len(parts) != 3 { + return Version{}, fmt.Errorf("invalid version number: %s", s) + } + major, err := strconv.Atoi(parts[0]) + if err != nil { + return Version{}, fmt.Errorf("invalid major version: %s", parts[0]) + } + minor, err := strconv.Atoi(parts[1]) + if err != nil { + return Version{}, fmt.Errorf("invalid minor version: %s", parts[1]) + } + patch, err := strconv.Atoi(parts[2]) + if err != nil { + return Version{}, fmt.Errorf("invalid patch version: %s", parts[2]) + } + return Version{Major: major, Minor: minor, Patch: patch}, nil +} diff --git a/client/go/version/version_test.go b/client/go/version/version_test.go new file mode 100644 index 00000000000..6cfb82ed802 --- /dev/null +++ b/client/go/version/version_test.go @@ -0,0 +1,59 @@ +package version + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParse(t *testing.T) { + _, err := Parse("foo") + assert.NotNil(t, err) + + _, err = Parse("1.2.3-foo") // Labels are unsupported + assert.NotNil(t, err) + + v, err := Parse("1.2.3") + assert.Nil(t, err) + assert.Equal(t, "1.2.3", v.String()) + + v, err = Parse("v4.5.6") + assert.Nil(t, err) + assert.Equal(t, "4.5.6", v.String()) +} + +func TestCompare(t *testing.T) { + assertComparison(t, "1.2.3", '>', "1.0.0") + assertComparison(t, "1.0.0", '<', "1.2.3") + + assertComparison(t, "1.2.3", '=', "1.2.3") + assertComparison(t, "1.2.3", '>', "1.2.0") + assertComparison(t, "1.2.0", '<', "1.2.3") + assertComparison(t, "1.2.3", '>', "1.2.0") + assertComparison(t, "1.0.3", '<', "1.2.3") + + assertComparison(t, "1.2.3", '>', "1.1.4") + assertComparison(t, "1.1.4", '<', "1.2.3") + + assertComparison(t, "2.0.0", '>', "1.2.3") + assertComparison(t, "1.2.3", '<', "2.0.0") +} + +func assertComparison(t *testing.T, s1 string, cmp rune, s2 string) { + v1, err := Parse(s1) + assert.Nil(t, err) + v2, err := Parse(s2) + assert.Nil(t, err) + result := v1.Compare(v2) + switch cmp { + case '<': + assert.True(t, result < 0, fmt.Sprintf("%s is less than %s", v1, v2)) + case '>': + assert.True(t, result > 0, fmt.Sprintf("%s is greater than %s", v1, v2)) + case '=': + assert.True(t, result == 0, fmt.Sprintf("%s is equal to %s", v1, v2)) + default: + t.Fatal("invalid comparator: %r", cmp) + } +} |