sigs.k8s.io/cluster-api@v1.7.1/util/version/version_test.go (about) 1 /* 2 Copyright 2021 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package version 18 19 import ( 20 "testing" 21 22 "github.com/blang/semver/v4" 23 . "github.com/onsi/gomega" 24 ) 25 26 func TestParseMajorMinorPatch(t *testing.T) { 27 g := NewWithT(t) 28 29 var testcases = []struct { 30 name string 31 input string 32 output semver.Version 33 expectError bool 34 }{ 35 { 36 name: "should parse an OCI compliant string", 37 input: "v1.2.16_foo-1", 38 output: semver.Version{ 39 Major: 1, 40 Minor: 2, 41 Patch: 16, 42 }, 43 }, 44 { 45 name: "should parse a valid semver", 46 input: "v1.16.6+foobar-0", 47 output: semver.Version{ 48 Major: 1, 49 Minor: 16, 50 Patch: 6, 51 }, 52 }, 53 { 54 name: "should error if there is no patch version", 55 input: "v1.16+foobar-0", 56 expectError: true, 57 }, 58 { 59 name: "should error if there is no minor and patch", 60 input: "v1+foobar-0", 61 expectError: true, 62 }, 63 { 64 name: "should error if there is no v prefix", 65 input: "1.4.7", 66 expectError: true, 67 }, 68 } 69 70 for _, tc := range testcases { 71 t.Run(tc.name, func(*testing.T) { 72 out, err := ParseMajorMinorPatch(tc.input) 73 g.Expect(err != nil).To(Equal(tc.expectError)) 74 g.Expect(out).To(BeComparableTo(tc.output)) 75 }) 76 } 77 } 78 79 func TestParseMajorMinorPatchTolerant(t *testing.T) { 80 g := NewWithT(t) 81 82 var testcases = []struct { 83 name string 84 input string 85 output semver.Version 86 expectError bool 87 }{ 88 { 89 name: "should parse an OCI compliant string", 90 input: "v1.2.16_foo-1", 91 output: semver.Version{ 92 Major: 1, 93 Minor: 2, 94 Patch: 16, 95 }, 96 }, 97 { 98 name: "should parse a valid semver with no v prefix", 99 input: "1.16.6+foobar-0", 100 output: semver.Version{ 101 Major: 1, 102 Minor: 16, 103 Patch: 6, 104 }, 105 }, 106 { 107 name: "should error if there is no patch version", 108 input: "1.16+foobar-0", 109 expectError: true, 110 }, 111 { 112 name: "should error if there is no minor and patch", 113 input: "1+foobar-0", 114 expectError: true, 115 }, 116 } 117 118 for _, tc := range testcases { 119 t.Run(tc.name, func(*testing.T) { 120 out, err := ParseMajorMinorPatchTolerant(tc.input) 121 g.Expect(err != nil).To(Equal(tc.expectError)) 122 g.Expect(out).To(BeComparableTo(tc.output)) 123 }) 124 } 125 } 126 127 func TestCompare(t *testing.T) { 128 tests := []struct { 129 name string 130 aVersion semver.Version 131 bVersion semver.Version 132 options []CompareOption 133 want int 134 }{ 135 { 136 name: "comparing with no options should perform standard compare", 137 aVersion: semver.MustParse("1.2.3"), 138 bVersion: semver.MustParse("1.3.1"), 139 want: -1, 140 }, 141 { 142 name: "comparing with no options should perform standard compare - equal versions", 143 aVersion: semver.MustParse("1.2.3+xyz.1"), 144 bVersion: semver.MustParse("1.2.3+xyz.2"), 145 want: 0, 146 }, 147 { 148 name: "compare with build tags using the WithBuildTags option", 149 aVersion: semver.MustParse("1.2.3+xyz.1"), 150 bVersion: semver.MustParse("1.2.3+xyz.2"), 151 options: []CompareOption{WithBuildTags()}, 152 want: -1, 153 }, 154 { 155 name: "compare with no build identifiers", 156 aVersion: mustParseTolerant("v1.20.1"), 157 bVersion: mustParseTolerant("v1.20.2"), 158 options: []CompareOption{WithBuildTags()}, 159 want: -1, 160 }, 161 { 162 name: "compare with pre release versions and no build identifiers", 163 aVersion: mustParseTolerant("v1.20.1-alpha.1"), 164 bVersion: mustParseTolerant("v1.20.1-alpha.2"), 165 options: []CompareOption{WithBuildTags()}, 166 want: -1, 167 }, 168 { 169 name: "compare with pre release versions and build identifiers", 170 aVersion: mustParseTolerant("v1.20.1-alpha.1+xyz.1"), 171 bVersion: mustParseTolerant("v1.20.1-alpha.1+xyz.2"), 172 options: []CompareOption{WithBuildTags()}, 173 want: -1, 174 }, 175 { 176 name: "compare with build identifiers - smaller", 177 aVersion: mustParseTolerant("v1.20.1+xyz.1"), 178 bVersion: mustParseTolerant("v1.20.1+xyz.2"), 179 options: []CompareOption{WithBuildTags()}, 180 want: -1, 181 }, 182 { 183 name: "compare with build identifiers - equal", 184 aVersion: mustParseTolerant("v1.20.1+xyz.1"), 185 bVersion: mustParseTolerant("v1.20.1+xyz.1"), 186 options: []CompareOption{WithBuildTags()}, 187 want: 0, 188 }, 189 { 190 name: "compare with build identifiers - greater", 191 aVersion: mustParseTolerant("v1.20.1+xyz.3"), 192 bVersion: mustParseTolerant("v1.20.1+xyz.2"), 193 options: []CompareOption{WithBuildTags()}, 194 want: 1, 195 }, 196 { 197 name: "compare with build identifiers - smaller by sub version", 198 aVersion: mustParseTolerant("v1.20.1+xyz.1.0"), 199 bVersion: mustParseTolerant("v1.20.1+xyz.1.1"), 200 options: []CompareOption{WithBuildTags()}, 201 want: -1, 202 }, 203 { 204 name: "compare with build identifiers - smaller - different version lengths", 205 aVersion: mustParseTolerant("v1.20.1+xyz.1.1"), 206 bVersion: mustParseTolerant("v1.20.1+xyz.2"), 207 options: []CompareOption{WithBuildTags()}, 208 want: -1, 209 }, 210 { 211 name: "compare with build identifiers - greater by length", 212 aVersion: mustParseTolerant("v1.20.1+xyz.1.1"), 213 bVersion: mustParseTolerant("v1.20.1+xyz.1"), 214 options: []CompareOption{WithBuildTags()}, 215 want: 1, 216 }, 217 { 218 name: "compare with build identifiers - different non numeric", 219 aVersion: mustParseTolerant("v1.20.1+xyz.a"), 220 bVersion: mustParseTolerant("v1.20.1+xyz.b"), 221 options: []CompareOption{WithBuildTags()}, 222 want: 2, 223 }, 224 { 225 name: "compare with build identifiers - equal non numeric", 226 aVersion: mustParseTolerant("v1.20.1+xyz.a"), 227 bVersion: mustParseTolerant("v1.20.1+xyz.a"), 228 options: []CompareOption{WithBuildTags()}, 229 want: 0, 230 }, 231 { 232 name: "compare with build identifiers - smaller - a is numeric b is not", 233 aVersion: mustParseTolerant("v1.20.1+xyz.1"), 234 bVersion: mustParseTolerant("v1.20.1+xyz.abc"), 235 options: []CompareOption{WithBuildTags()}, 236 want: -1, 237 }, 238 } 239 240 for _, tt := range tests { 241 t.Run(tt.name, func(t *testing.T) { 242 g := NewWithT(t) 243 g.Expect(Compare(tt.aVersion, tt.bVersion, tt.options...)).To(Equal(tt.want)) 244 }) 245 } 246 } 247 248 func mustParseTolerant(s string) semver.Version { 249 v, err := semver.ParseTolerant(s) 250 if err != nil { 251 panic(`semver: ParseTolerant(` + s + `): ` + err.Error()) 252 } 253 return v 254 }