github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/version/version_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package version_test 5 6 import ( 7 "encoding/json" 8 "io/ioutil" 9 "path/filepath" 10 "runtime" 11 "strings" 12 stdtesting "testing" 13 14 "labix.org/v2/mgo/bson" 15 gc "launchpad.net/gocheck" 16 "launchpad.net/goyaml" 17 18 "github.com/juju/juju/testing" 19 "github.com/juju/juju/version" 20 ) 21 22 type suite struct { 23 testing.BaseSuite 24 } 25 26 var _ = gc.Suite(&suite{}) 27 28 func Test(t *stdtesting.T) { 29 gc.TestingT(t) 30 } 31 32 // N.B. The FORCE-VERSION logic is tested in the environs package. 33 34 func (*suite) TestCompare(c *gc.C) { 35 cmpTests := []struct { 36 v1, v2 string 37 compare int 38 }{ 39 {"1.0.0", "1.0.0", 0}, 40 {"01.0.0", "1.0.0", 0}, 41 {"10.0.0", "9.0.0", 1}, 42 {"1.0.0", "1.0.1", -1}, 43 {"1.0.1", "1.0.0", 1}, 44 {"1.0.0", "1.1.0", -1}, 45 {"1.1.0", "1.0.0", 1}, 46 {"1.0.0", "2.0.0", -1}, 47 {"1.2-alpha1", "1.2.0", -1}, 48 {"1.2-alpha2", "1.2-alpha1", 1}, 49 {"1.2-alpha2.1", "1.2-alpha2", 1}, 50 {"1.2-alpha2.2", "1.2-alpha2.1", 1}, 51 {"1.2-beta1", "1.2-alpha1", 1}, 52 {"1.2-beta1", "1.2-alpha2.1", 1}, 53 {"1.2-beta1", "1.2.0", -1}, 54 {"1.2.1", "1.2.0", 1}, 55 {"2.0.0", "1.0.0", 1}, 56 {"2.0.0.0", "2.0.0", 0}, 57 {"2.0.0.0", "2.0.0.0", 0}, 58 {"2.0.0.1", "2.0.0.0", 1}, 59 {"2.0.1.10", "2.0.0.0", 1}, 60 } 61 62 for i, test := range cmpTests { 63 c.Logf("test %d", i) 64 v1, err := version.Parse(test.v1) 65 c.Assert(err, gc.IsNil) 66 v2, err := version.Parse(test.v2) 67 c.Assert(err, gc.IsNil) 68 compare := v1.Compare(v2) 69 c.Check(compare, gc.Equals, test.compare) 70 // Check that reversing the operands has 71 // the expected result. 72 compare = v2.Compare(v1) 73 c.Check(compare, gc.Equals, -test.compare) 74 } 75 } 76 77 var parseTests = []struct { 78 v string 79 err string 80 expect version.Number 81 dev bool 82 }{{ 83 v: "0.0.0", 84 }, { 85 v: "0.0.1", 86 expect: version.Number{Major: 0, Minor: 0, Patch: 1}, 87 }, { 88 v: "0.0.2", 89 expect: version.Number{Major: 0, Minor: 0, Patch: 2}, 90 }, { 91 v: "0.1.0", 92 expect: version.Number{Major: 0, Minor: 1, Patch: 0}, 93 dev: true, 94 }, { 95 v: "0.2.3", 96 expect: version.Number{Major: 0, Minor: 2, Patch: 3}, 97 }, { 98 v: "1.0.0", 99 expect: version.Number{Major: 1, Minor: 0, Patch: 0}, 100 }, { 101 v: "10.234.3456", 102 expect: version.Number{Major: 10, Minor: 234, Patch: 3456}, 103 }, { 104 v: "10.234.3456.1", 105 expect: version.Number{Major: 10, Minor: 234, Patch: 3456, Build: 1}, 106 dev: true, 107 }, { 108 v: "10.234.3456.64", 109 expect: version.Number{Major: 10, Minor: 234, Patch: 3456, Build: 64}, 110 dev: true, 111 }, { 112 v: "10.235.3456", 113 expect: version.Number{Major: 10, Minor: 235, Patch: 3456}, 114 }, { 115 v: "1.21-alpha1", 116 expect: version.Number{Major: 1, Minor: 21, Patch: 1, Tag: "alpha"}, 117 dev: true, 118 }, { 119 v: "1.21-alpha1.1", 120 expect: version.Number{Major: 1, Minor: 21, Patch: 1, Tag: "alpha", Build: 1}, 121 dev: true, 122 }, { 123 v: "1.21.0", 124 expect: version.Number{Major: 1, Minor: 21}, 125 }, { 126 v: "1234567890.2.1", 127 err: "invalid version.*", 128 }, { 129 v: "0.2..1", 130 err: "invalid version.*", 131 }, { 132 v: "1.21.alpha1", 133 err: "invalid version.*", 134 }, { 135 v: "1.21-alpha", 136 err: "invalid version.*", 137 }, { 138 v: "1.21-alpha1beta", 139 err: "invalid version.*", 140 }, { 141 v: "1.21-alpha-dev", 142 err: "invalid version.*", 143 }} 144 145 func (*suite) TestParse(c *gc.C) { 146 for i, test := range parseTests { 147 c.Logf("test %d", i) 148 got, err := version.Parse(test.v) 149 if test.err != "" { 150 c.Assert(err, gc.ErrorMatches, test.err) 151 } else { 152 c.Assert(err, gc.IsNil) 153 c.Assert(got, gc.Equals, test.expect) 154 c.Check(got.IsDev(), gc.Equals, test.dev) 155 c.Check(got.String(), gc.Equals, test.v) 156 } 157 } 158 } 159 160 func binaryVersion(major, minor, patch, build int, tag, series, arch string) version.Binary { 161 return version.Binary{ 162 Number: version.Number{ 163 Major: major, 164 Minor: minor, 165 Patch: patch, 166 Build: build, 167 Tag: tag, 168 }, 169 Series: series, 170 Arch: arch, 171 } 172 } 173 174 func (*suite) TestParseBinary(c *gc.C) { 175 parseBinaryTests := []struct { 176 v string 177 err string 178 expect version.Binary 179 }{{ 180 v: "1.2.3-a-b", 181 expect: binaryVersion(1, 2, 3, 0, "", "a", "b"), 182 }, { 183 v: "1.2.3.4-a-b", 184 expect: binaryVersion(1, 2, 3, 4, "", "a", "b"), 185 }, { 186 v: "1.2-alpha3-a-b", 187 expect: binaryVersion(1, 2, 3, 0, "alpha", "a", "b"), 188 }, { 189 v: "1.2-alpha3.4-a-b", 190 expect: binaryVersion(1, 2, 3, 4, "alpha", "a", "b"), 191 }, { 192 v: "1.2.3", 193 err: "invalid binary version.*", 194 }, { 195 v: "1.2-beta1", 196 err: "invalid binary version.*", 197 }, { 198 v: "1.2.3--b", 199 err: "invalid binary version.*", 200 }, { 201 v: "1.2.3-a-", 202 err: "invalid binary version.*", 203 }} 204 205 for i, test := range parseBinaryTests { 206 c.Logf("test 1: %d", i) 207 got, err := version.ParseBinary(test.v) 208 if test.err != "" { 209 c.Assert(err, gc.ErrorMatches, test.err) 210 } else { 211 c.Assert(err, gc.IsNil) 212 c.Assert(got, gc.Equals, test.expect) 213 } 214 } 215 216 for i, test := range parseTests { 217 c.Logf("test 2: %d", i) 218 v := test.v + "-a-b" 219 got, err := version.ParseBinary(v) 220 expect := version.Binary{ 221 Number: test.expect, 222 Series: "a", 223 Arch: "b", 224 } 225 if test.err != "" { 226 c.Assert(err, gc.ErrorMatches, strings.Replace(test.err, "version", "binary version", 1)) 227 } else { 228 c.Assert(err, gc.IsNil) 229 c.Assert(got, gc.Equals, expect) 230 c.Check(got.IsDev(), gc.Equals, test.dev) 231 } 232 } 233 } 234 235 var marshallers = []struct { 236 name string 237 marshal func(interface{}) ([]byte, error) 238 unmarshal func([]byte, interface{}) error 239 }{{ 240 "json", 241 json.Marshal, 242 json.Unmarshal, 243 }, { 244 "bson", 245 bson.Marshal, 246 bson.Unmarshal, 247 }, { 248 "yaml", 249 goyaml.Marshal, 250 goyaml.Unmarshal, 251 }} 252 253 func (*suite) TestBinaryMarshalUnmarshal(c *gc.C) { 254 for _, m := range marshallers { 255 c.Logf("encoding %v", m.name) 256 type doc struct { 257 Version *version.Binary 258 } 259 // Work around goyaml bug #1096149 260 // SetYAML is not called for non-pointer fields. 261 bp := version.MustParseBinary("1.2.3-foo-bar") 262 v := doc{&bp} 263 data, err := m.marshal(&v) 264 c.Assert(err, gc.IsNil) 265 var bv doc 266 err = m.unmarshal(data, &bv) 267 c.Assert(err, gc.IsNil) 268 c.Assert(bv, gc.DeepEquals, v) 269 } 270 } 271 272 func (*suite) TestNumberMarshalUnmarshal(c *gc.C) { 273 for _, m := range marshallers { 274 c.Logf("encoding %v", m.name) 275 type doc struct { 276 Version *version.Number 277 } 278 // Work around goyaml bug #1096149 279 // SetYAML is not called for non-pointer fields. 280 np := version.MustParse("1.2.3") 281 v := doc{&np} 282 data, err := m.marshal(&v) 283 c.Assert(err, gc.IsNil) 284 var nv doc 285 err = m.unmarshal(data, &nv) 286 c.Assert(err, gc.IsNil) 287 c.Assert(nv, gc.DeepEquals, v) 288 } 289 } 290 291 func (*suite) TestParseMajorMinor(c *gc.C) { 292 parseMajorMinorTests := []struct { 293 v string 294 err string 295 expectMajor int 296 expectMinor int 297 }{{ 298 v: "1.2", 299 expectMajor: 1, 300 expectMinor: 2, 301 }, { 302 v: "1", 303 expectMajor: 1, 304 expectMinor: -1, 305 }, { 306 v: "1.2.3", 307 err: "invalid major.minor version number 1.2.3", 308 }, { 309 v: "blah", 310 err: `invalid major version number blah: strconv.ParseInt: parsing "blah": invalid syntax`, 311 }} 312 313 for i, test := range parseMajorMinorTests { 314 c.Logf("test %d", i) 315 major, minor, err := version.ParseMajorMinor(test.v) 316 if test.err != "" { 317 c.Check(err, gc.ErrorMatches, test.err) 318 } else { 319 c.Check(err, gc.IsNil) 320 c.Check(major, gc.Equals, test.expectMajor) 321 c.Check(minor, gc.Equals, test.expectMinor) 322 } 323 } 324 } 325 326 func (s *suite) TestUseFastLXC(c *gc.C) { 327 for i, test := range []struct { 328 message string 329 releaseContent string 330 expected string 331 }{{ 332 message: "missing release file", 333 }, { 334 message: "missing prefix in file", 335 releaseContent: "some junk\nand more junk", 336 }, { 337 message: "precise release", 338 releaseContent: ` 339 DISTRIB_ID=Ubuntu 340 DISTRIB_RELEASE=12.04 341 DISTRIB_CODENAME=precise 342 DISTRIB_DESCRIPTION="Ubuntu 12.04.3 LTS" 343 `, 344 expected: "12.04", 345 }, { 346 message: "trusty release", 347 releaseContent: ` 348 DISTRIB_ID=Ubuntu 349 DISTRIB_RELEASE=14.04 350 DISTRIB_CODENAME=trusty 351 DISTRIB_DESCRIPTION="Ubuntu Trusty Tahr (development branch)" 352 `, 353 expected: "14.04", 354 }, { 355 message: "minimal trusty release", 356 releaseContent: `DISTRIB_RELEASE=14.04`, 357 expected: "14.04", 358 }, { 359 message: "minimal unstable unicorn", 360 releaseContent: `DISTRIB_RELEASE=14.10`, 361 expected: "14.10", 362 }, { 363 message: "minimal jaunty", 364 releaseContent: `DISTRIB_RELEASE=9.10`, 365 expected: "9.10", 366 }} { 367 c.Logf("%v: %v", i, test.message) 368 filename := filepath.Join(c.MkDir(), "lsbRelease") 369 s.PatchValue(version.LSBReleaseFileVar, filename) 370 if test.releaseContent != "" { 371 err := ioutil.WriteFile(filename, []byte(test.releaseContent+"\n"), 0644) 372 c.Assert(err, gc.IsNil) 373 } 374 value := version.ReleaseVersion() 375 c.Assert(value, gc.Equals, test.expected) 376 } 377 } 378 379 func (s *suite) TestCompiler(c *gc.C) { 380 c.Assert(version.Compiler, gc.Equals, runtime.Compiler) 381 }