// Copyright (c) 2021 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package version import "testing" // TestSemVerParsing ensures parsing a semantic version string works as // expected. func TestSemVerParsing(t *testing.T) { tests := []struct { ver string // semantic version string to parse major uint32 // expected major version minor uint32 // expected minor version patch uint32 // expected patch version pre string // expected pre-release string build string // expected build metadata string invalid bool // expected error }{{ ver: "0.0.4", major: 0, minor: 0, patch: 4, }, { ver: "1.2.3", major: 1, minor: 2, patch: 3, }, { ver: "10.20.30", major: 10, minor: 20, patch: 30, }, { ver: "1.1.2-prerelease+meta", major: 1, minor: 1, patch: 2, pre: "prerelease", build: "meta", }, { ver: "1.1.2+meta", major: 1, minor: 1, patch: 2, build: "meta", }, { ver: "1.1.2+meta-valid", major: 1, minor: 1, patch: 2, build: "meta-valid", }, { ver: "1.0.0-alpha", major: 1, minor: 0, patch: 0, pre: "alpha", }, { ver: "1.0.0-beta", major: 1, minor: 0, patch: 0, pre: "beta", }, { ver: "1.0.0-alpha.beta", major: 1, minor: 0, patch: 0, pre: "alpha.beta", }, { ver: "1.0.0-alpha.beta.1", major: 1, minor: 0, patch: 0, pre: "alpha.beta.1", }, { ver: "1.0.0-alpha.1", major: 1, minor: 0, patch: 0, pre: "alpha.1", }, { ver: "1.0.0-alpha0.valid", major: 1, minor: 0, patch: 0, pre: "alpha0.valid", }, { ver: "1.0.0-alpha.0valid", major: 1, minor: 0, patch: 0, pre: "alpha.0valid", }, { ver: "1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay", major: 1, minor: 0, patch: 0, pre: "alpha-a.b-c-somethinglong", build: "build.1-aef.1-its-okay", }, { ver: "1.0.0-rc.1+build.1", major: 1, minor: 0, patch: 0, pre: "rc.1", build: "build.1", }, { ver: "2.0.0-rc.1+build.123", major: 2, minor: 0, patch: 0, pre: "rc.1", build: "build.123", }, { ver: "1.2.3-beta", major: 1, minor: 2, patch: 3, pre: "beta", }, { ver: "10.2.3-DEV-SNAPSHOT", major: 10, minor: 2, patch: 3, pre: "DEV-SNAPSHOT", }, { ver: "1.2.3-SNAPSHOT-123", major: 1, minor: 2, patch: 3, pre: "SNAPSHOT-123", }, { ver: "1.0.0", major: 1, minor: 0, patch: 0, }, { ver: "2.0.0", major: 2, minor: 0, patch: 0, }, { ver: "1.1.7", major: 1, minor: 1, patch: 7, }, { ver: "2.0.0+build.1848", major: 2, minor: 0, patch: 0, build: "build.1848", }, { ver: "2.0.1-alpha.1227", major: 2, minor: 0, patch: 1, pre: "alpha.1227", }, { ver: "1.0.0-alpha+beta", major: 1, minor: 0, patch: 0, pre: "alpha", build: "beta", }, { ver: "1.2.3----RC-SNAPSHOT.12.9.1--.12+788", major: 1, minor: 2, patch: 3, pre: "---RC-SNAPSHOT.12.9.1--.12", build: "788", }, { ver: "1.2.3----R-S.12.9.1--.12+meta", major: 1, minor: 2, patch: 3, pre: "---R-S.12.9.1--.12", build: "meta", }, { ver: "1.2.3----RC-SNAPSHOT.12.9.1--.12", major: 1, minor: 2, patch: 3, pre: "---RC-SNAPSHOT.12.9.1--.12", }, { ver: "1.0.0+0.build.1-rc.10000aaa-kk-0.1", major: 1, minor: 0, patch: 0, build: "0.build.1-rc.10000aaa-kk-0.1", }, { ver: "1.0.0-0A.is.legal", major: 1, minor: 0, patch: 0, pre: "0A.is.legal", }, { ver: "1", invalid: true, }, { ver: "1.2", invalid: true, }, { ver: "1.2.3-0123", invalid: true, }, { ver: "1.2.3-0123.0123", invalid: true, }, { ver: "1.1.2+.123", invalid: true, }, { ver: "+invalid", invalid: true, }, { ver: "-invalid", invalid: true, }, { ver: "-invalid+invalid", invalid: true, }, { ver: "-invalid.01", invalid: true, }, { ver: "alpha", invalid: true, }, { ver: "alpha.beta", invalid: true, }, { ver: "alpha.beta.1", invalid: true, }, { ver: "alpha.1", invalid: true, }, { ver: "alpha+beta", invalid: true, }, { ver: "alpha_beta", invalid: true, }, { ver: "alpha.", invalid: true, }, { ver: "alpha..", invalid: true, }, { ver: "beta", invalid: true, }, { ver: "1.0.0-alpha_beta", invalid: true, }, { ver: "-alpha.", invalid: true, }, { ver: "1.0.0-alpha..", invalid: true, }, { ver: "1.0.0-alpha..1", invalid: true, }, { ver: "1.0.0-alpha...1", invalid: true, }, { ver: "1.0.0-alpha....1", invalid: true, }, { ver: "1.0.0-alpha.....1", invalid: true, }, { ver: "1.0.0-alpha......1", invalid: true, }, { ver: "1.0.0-alpha.......1", invalid: true, }, { ver: "01.1.1", invalid: true, }, { ver: "1.01.1", invalid: true, }, { ver: "1.1.01", invalid: true, }, { ver: "1.2", invalid: true, }, { ver: "1.2.3.DEV", invalid: true, }, { ver: "1.2-SNAPSHOT", invalid: true, }, { ver: "1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788", invalid: true, }, { ver: "1.2-RC-SNAPSHOT", invalid: true, }, { ver: "-1.0.3-gamma+b7718", invalid: true, }, { ver: "+justmeta", invalid: true, }, { ver: "9.8.7+meta+meta", invalid: true, }, { ver: "9.8.7-whatever+meta+meta", invalid: true, }, { // Would be valid except major is > max uint64. ver: "99999999999999999999999.999999999999999999.99999999999999999", invalid: true, }, { ver: "999999999.999999999.999999999----RC-SNAPSHOT.12.09.1-----------" + "---------------------..12", invalid: true, }} for _, test := range tests { major, minor, patch, pre, build, err := parseSemVer(test.ver) if test.invalid && err == nil { t.Errorf("%q: did not receive expected error", test.ver) continue } if !test.invalid && err != nil { t.Errorf("%q: unexpected err: %v", test.ver, err) continue } if major != test.major { t.Errorf("%q: mismatched major -- got %d, want %d", test.ver, major, test.major) continue } if minor != test.minor { t.Errorf("%q: mismatched minor -- got %d, want %d", test.ver, minor, test.minor) continue } if patch != test.patch { t.Errorf("%q: mismatched patch -- got %d, want %d", test.ver, patch, test.patch) continue } if pre != test.pre { t.Errorf("%q: mismatched pre-release -- got %s, want %s", test.ver, pre, test.pre) continue } if build != test.build { t.Errorf("%q: mismatched buildmetadata -- got %s, want %s", test.ver, build, test.build) continue } } }