package runtimeinfo import ( "runtime/debug" "sync" "sync/atomic" "testing" ) func TestVersion(t *testing.T) { tests := []struct { name string injected string info *debug.BuildInfo ok bool want string }{ { name: "injected version takes precedence", injected: "v1.2.3", info: &debug.BuildInfo{Main: debug.Module{Version: "v4.5.6"}}, ok: true, want: "v1.2.3", }, { name: "main module version", info: &debug.BuildInfo{Main: debug.Module{Version: "v4.5.6"}}, ok: true, want: "v4.5.6", }, { name: "missing build information", want: "dev", }, { name: "development main module", info: &debug.BuildInfo{Main: debug.Module{Version: "(devel)"}}, ok: true, want: "dev", }, { name: "empty main module version", info: &debug.BuildInfo{Main: debug.Module{}}, ok: true, want: "dev", }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { got := version(test.injected, func() (*debug.BuildInfo, bool) { return test.info, test.ok }) if got != test.want { t.Fatalf("version() = %q, want %q", got, test.want) } }) } } func TestFallbackVersionReadsMetadataOnceConcurrently(t *testing.T) { var reads atomic.Int32 fallback := newFallbackVersion(func() (*debug.BuildInfo, bool) { reads.Add(1) return &debug.BuildInfo{Main: debug.Module{Version: "v4.5.6"}}, true }) const callers = 32 results := make(chan string, callers) var workers sync.WaitGroup workers.Add(callers) for i := 0; i < callers; i++ { go func() { defer workers.Done() results <- fallback() }() } workers.Wait() close(results) for result := range results { if result != "v4.5.6" { t.Errorf("fallback() = %q, want stable version", result) } } if got := reads.Load(); got != 1 { t.Fatalf("metadata reader called %d times, want once", got) } } func TestFallbackVersionCachesUnavailableAndDevelopmentMetadata(t *testing.T) { for _, test := range []struct { name string read func() (*debug.BuildInfo, bool) }{ {name: "unavailable", read: func() (*debug.BuildInfo, bool) { return nil, false }}, {name: "development", read: func() (*debug.BuildInfo, bool) { return &debug.BuildInfo{Main: debug.Module{Version: "(devel)"}}, true }}, } { t.Run(test.name, func(t *testing.T) { fallback := newFallbackVersion(test.read) if got := fallback(); got != "dev" { t.Fatalf("fallback() = %q, want dev", got) } if got := fallback(); got != "dev" { t.Fatalf("repeated fallback() = %q, want dev", got) } }) } }