kittenipc/kitcom/internal/tsgo/semver/version_test.go
2025-10-15 10:12:44 +03:00

148 lines
5.3 KiB
Go

package semver
import (
"testing"
"gotest.tools/v3/assert"
)
func TestTryParseSemver(t *testing.T) {
t.Parallel()
tests := []struct {
in string
out Version
}{
{"1.2.3-pre.4+build.5", Version{major: 1, minor: 2, patch: 3, prerelease: []string{"pre", "4"}, build: []string{"build", "5"}}},
{"1.2.3-pre.4", Version{major: 1, minor: 2, patch: 3, prerelease: []string{"pre", "4"}}},
{"1.2.3+build.4", Version{major: 1, minor: 2, patch: 3, build: []string{"build", "4"}}},
{"1.2.3", Version{major: 1, minor: 2, patch: 3}},
}
for _, test := range tests {
t.Run(test.in, func(t *testing.T) {
t.Parallel()
v, err := TryParseVersion(test.in)
assert.NilError(t, err)
assertVersion(t, v, test.out)
})
}
}
func TestVersionString(t *testing.T) {
t.Parallel()
tests := []struct {
in Version
out string
}{
{Version{major: 1, minor: 2, patch: 3, prerelease: []string{"pre", "4"}, build: []string{"build", "5"}}, "1.2.3-pre.4+build.5"},
{Version{major: 1, minor: 2, patch: 3, prerelease: []string{"pre", "4"}, build: []string{"build"}}, "1.2.3-pre.4+build"},
{Version{major: 1, minor: 2, patch: 3, build: []string{"build"}}, "1.2.3+build"},
{Version{major: 1, minor: 2, patch: 3, prerelease: []string{"pre", "4"}}, "1.2.3-pre.4"},
{Version{major: 1, minor: 2, patch: 3, build: []string{"build", "4"}}, "1.2.3+build.4"},
{Version{major: 1, minor: 2, patch: 3}, "1.2.3"},
}
for _, test := range tests {
t.Run(test.out, func(t *testing.T) {
t.Parallel()
assert.Equal(t, test.in.String(), test.out)
})
}
}
func TestVersionCompare(t *testing.T) {
t.Parallel()
tests := []struct {
v1, v2 string
want int
}{
// https://semver.org/#spec-item-11
// > Precedence is determined by the first difference when comparing each of these
// > identifiers from left to right as follows: Major, minor, and patch versions are
// > always compared numerically.
{"1.0.0", "2.0.0", comparisonLessThan},
{"1.0.0", "1.1.0", comparisonLessThan},
{"1.0.0", "1.0.1", comparisonLessThan},
{"2.0.0", "1.0.0", comparisonGreaterThan},
{"1.1.0", "1.0.0", comparisonGreaterThan},
{"1.0.1", "1.0.0", comparisonGreaterThan},
{"1.0.0", "1.0.0", comparisonEqualTo},
// https://semver.org/#spec-item-11
// > When major, minor, and patch are equal, a pre-release version has lower
// > precedence than a normal version.
{"1.0.0", "1.0.0-pre", comparisonGreaterThan},
{"1.0.1-pre", "1.0.0", comparisonGreaterThan},
{"1.0.0-pre", "1.0.0", comparisonLessThan},
// https://semver.org/#spec-item-11
// > identifiers consisting of only digits are compared numerically
{"1.0.0-0", "1.0.0-1", comparisonLessThan},
{"1.0.0-1", "1.0.0-0", comparisonGreaterThan},
{"1.0.0-2", "1.0.0-10", comparisonLessThan},
{"1.0.0-10", "1.0.0-2", comparisonGreaterThan},
{"1.0.0-0", "1.0.0-0", comparisonEqualTo},
// https://semver.org/#spec-item-11
// > identifiers with letters or hyphens are compared lexically in ASCII sort order.
{"1.0.0-a", "1.0.0-b", comparisonLessThan},
{"1.0.0-a-2", "1.0.0-a-10", comparisonGreaterThan},
{"1.0.0-b", "1.0.0-a", comparisonGreaterThan},
{"1.0.0-a", "1.0.0-a", comparisonEqualTo},
{"1.0.0-A", "1.0.0-a", comparisonLessThan},
// https://semver.org/#spec-item-11
// > Numeric identifiers always have lower precedence than non-numeric identifiers.
{"1.0.0-0", "1.0.0-alpha", comparisonLessThan},
{"1.0.0-alpha", "1.0.0-0", comparisonGreaterThan},
{"1.0.0-0", "1.0.0-0", comparisonEqualTo},
{"1.0.0-alpha", "1.0.0-alpha", comparisonEqualTo},
// https://semver.org/#spec-item-11
// > A larger set of pre-release fields has a higher precedence than a smaller set, if all
// > of the preceding identifiers are equal.
{"1.0.0-alpha", "1.0.0-alpha.0", comparisonLessThan},
{"1.0.0-alpha.0", "1.0.0-alpha", comparisonGreaterThan},
// https://semver.org/#spec-item-11
// > Precedence for two pre-release versions with the same major, minor, and patch version
// > MUST be determined by comparing each dot separated identifier from left to right until
// > a difference is found [...]
{"1.0.0-a.0.b.1", "1.0.0-a.0.b.2", comparisonLessThan},
{"1.0.0-a.0.b.1", "1.0.0-b.0.a.1", comparisonLessThan},
{"1.0.0-a.0.b.2", "1.0.0-a.0.b.1", comparisonGreaterThan},
{"1.0.0-b.0.a.1", "1.0.0-a.0.b.1", comparisonGreaterThan},
// https://semver.org/#spec-item-11
// > Build metadata does not figure into precedence
{"1.0.0+build", "1.0.0", comparisonEqualTo},
{"1.0.0+build.stuff", "1.0.0", comparisonEqualTo},
{"1.0.0", "1.0.0+build", comparisonEqualTo},
{"1.0.0+build", "1.0.0+stuff", comparisonEqualTo},
// https://semver.org/#spec-item-11
// Edge cases for numeric and lexical comparison of prerelease identifiers.
{"1.0.0-alpha.99999", "1.0.0-alpha.100000", comparisonLessThan},
{"1.0.0-alpha.beta", "1.0.0-alpha.alpha", comparisonGreaterThan},
}
for _, test := range tests {
t.Run(test.v1+" <=> "+test.v2, func(t *testing.T) {
t.Parallel()
v1, err1 := TryParseVersion(test.v1)
assert.NilError(t, err1, test.v1)
v2, err2 := TryParseVersion(test.v2)
assert.NilError(t, err2, test.v2)
assert.Equal(t, v1.Compare(&v2), test.want)
})
}
}
func assertVersion(t *testing.T, a, b Version) {
assert.Equal(t, a.major, b.major)
assert.Equal(t, a.minor, b.minor)
assert.Equal(t, a.patch, b.patch)
assert.DeepEqual(t, a.prerelease, b.prerelease)
assert.DeepEqual(t, a.build, b.build)
}