a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
125 lines
3.6 KiB
Go
125 lines
3.6 KiB
Go
package version
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestParse_Valid(t *testing.T) {
|
|
tests := []struct {
|
|
in string
|
|
want Version
|
|
}{
|
|
{"1.2.3", Version{Major: 1, Minor: 2, Patch: 3}},
|
|
{"v1.2.3", Version{Major: 1, Minor: 2, Patch: 3}},
|
|
{"v0.0.1", Version{Patch: 1}},
|
|
{"0.0.0", Version{}},
|
|
{"v1.2.3-rc1", Version{Major: 1, Minor: 2, Patch: 3, Prerelease: "rc1"}},
|
|
{"v1.2.3-rc.1", Version{Major: 1, Minor: 2, Patch: 3, Prerelease: "rc.1"}},
|
|
{"v1.2.3+abc1234", Version{Major: 1, Minor: 2, Patch: 3, Build: "abc1234"}},
|
|
{"v1.2.3-alpha.2+abc1234", Version{Major: 1, Minor: 2, Patch: 3, Prerelease: "alpha.2", Build: "abc1234"}},
|
|
{"v10.20.30+build.456", Version{Major: 10, Minor: 20, Patch: 30, Build: "build.456"}},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.in, func(t *testing.T) {
|
|
got, err := Parse(tt.in)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParse_Invalid(t *testing.T) {
|
|
// A spec-tight parser should reject these — they're the shapes we
|
|
// actually see from tooling (dev builds, shell variable not set,
|
|
// cut-off tags) that must not silently produce 0.0.0.
|
|
bad := []string{
|
|
"",
|
|
"dev",
|
|
"unknown",
|
|
"v",
|
|
"1",
|
|
"1.2",
|
|
"1.2.3.4",
|
|
"v01.2.3", // leading zero
|
|
"v1.2.3-", // empty prerelease
|
|
"v1.2.3+", // empty build
|
|
"v1.2.3-01", // leading-zero numeric prerelease identifier
|
|
"v1.2.3 extra", // trailing garbage
|
|
}
|
|
for _, s := range bad {
|
|
t.Run(s, func(t *testing.T) {
|
|
_, err := Parse(s)
|
|
assert.Error(t, err, "Parse(%q) must fail", s)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestString_Canonical(t *testing.T) {
|
|
// Round-trip: Parse → String → Parse returns an identical value.
|
|
// Catches regressions where String drops or reorders fields.
|
|
samples := []string{
|
|
"v0.0.0",
|
|
"v1.2.3",
|
|
"v1.2.3-rc.1",
|
|
"v1.2.3+abc1234",
|
|
"v1.2.3-alpha+build.456",
|
|
}
|
|
for _, s := range samples {
|
|
v, err := Parse(s)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, s, v.String(), "round-trip failed for %s", s)
|
|
|
|
v2, err := Parse(v.String())
|
|
require.NoError(t, err)
|
|
assert.Equal(t, v, v2, "second parse drifted for %s", s)
|
|
}
|
|
}
|
|
|
|
func TestString_Zero(t *testing.T) {
|
|
var v Version
|
|
assert.Equal(t, "v0.0.0", v.String())
|
|
assert.True(t, v.IsZero())
|
|
}
|
|
|
|
func TestCompose_Semver(t *testing.T) {
|
|
v, err := Compose("v1.2.3", "abc1234")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, Version{Major: 1, Minor: 2, Patch: 3, Build: "abc1234"}, v)
|
|
assert.Equal(t, "v1.2.3+abc1234", v.String())
|
|
}
|
|
|
|
func TestCompose_DevBuild(t *testing.T) {
|
|
// The "dev" / "" / "unknown" sentinels mean "no ldflags injected"
|
|
// (local go build without goreleaser). Compose must not error —
|
|
// callers rely on this to render "(dev build)" cleanly.
|
|
for _, s := range []string{"", "dev", "unknown"} {
|
|
v, err := Compose(s, "abc1234")
|
|
require.NoError(t, err, "Compose(%q, ...) must not error", s)
|
|
assert.True(t, v.IsZero() == (v.Build == ""), "dev-build Version")
|
|
assert.Equal(t, "abc1234", v.Build,
|
|
"dev builds must still surface the commit SHA when one was injected")
|
|
}
|
|
}
|
|
|
|
func TestCompose_BuildSlotOverridesEmbedded(t *testing.T) {
|
|
// If the semver already carries a +build slot but an explicit
|
|
// build arg is provided, the explicit one wins. Lets goreleaser
|
|
// pass ShortCommit unconditionally without worrying about whether
|
|
// the tag author also hand-added one.
|
|
v, err := Compose("v1.2.3+old", "new1234")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "new1234", v.Build)
|
|
}
|
|
|
|
func TestMustParse_PanicsOnInvalid(t *testing.T) {
|
|
defer func() {
|
|
if r := recover(); r == nil {
|
|
t.Fatal("MustParse should panic on invalid input")
|
|
}
|
|
}()
|
|
MustParse("nope")
|
|
}
|