Files
multica/server/cmd/server/main_test.go
Marcelo Cecin 7985699df9 feat(help): surface the running server version in the Help popover (#4959)
Surface the running server build version in the Help popover so self-hosted
operators can confirm what's deployed and include it in bug reports.

- Backend exposes it via /api/config's server_version (from main.version),
  omitempty so older/unstamped builds omit the field.
- Unstamped "dev" builds are normalized to empty and the row stays hidden.
- The row is suppressed on the managed cloud (frontend host multica.ai) and
  shown only on self-hosted deployments.
- Frontend renders a muted footer row in the Help popover only when the value
  is non-empty; i18n added for en/ja/ko/zh-Hans.
2026-07-14 20:11:52 +08:00

136 lines
4.2 KiB
Go

package main
import (
"os"
"testing"
"github.com/redis/go-redis/v9"
)
func TestRedisClientName(t *testing.T) {
tests := []struct {
name string
existing string
suffix string
want string
}{
{"empty_suffix_returns_existing", "multica-api:store", "", "multica-api:store"},
{"empty_existing_uses_default_prefix", "", "store", "multica-api:store"},
{"both_set_joins_with_colon", "custom", "store", "custom:store"},
{"empty_both_returns_empty", "", "", ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := redisClientName(tt.existing, tt.suffix)
if got != tt.want {
t.Errorf("redisClientName(%q, %q) = %q, want %q", tt.existing, tt.suffix, got, tt.want)
}
})
}
}
func TestNewNamedRedisClient_SetsClientName(t *testing.T) {
t.Setenv("REDIS_DISABLE_CLIENT_NAME", "")
base := &redis.Options{Addr: "localhost:6379"}
client := newNamedRedisClient(base, "store")
defer client.Close()
opts := client.Options()
if opts.ClientName != "multica-api:store" {
t.Errorf("ClientName = %q, want %q", opts.ClientName, "multica-api:store")
}
}
func TestNewNamedRedisClient_DisableClientName(t *testing.T) {
t.Setenv("REDIS_DISABLE_CLIENT_NAME", "true")
base := &redis.Options{Addr: "localhost:6379"}
client := newNamedRedisClient(base, "store")
defer client.Close()
opts := client.Options()
if opts.ClientName != "" {
t.Errorf("ClientName = %q, want empty when REDIS_DISABLE_CLIENT_NAME=true", opts.ClientName)
}
}
func TestNewNamedRedisClient_DisableClientName_ClearsPreExistingName(t *testing.T) {
t.Setenv("REDIS_DISABLE_CLIENT_NAME", "true")
// Simulate REDIS_URL with ?client_name=foo — ParseURL sets ClientName.
base := &redis.Options{Addr: "localhost:6379", ClientName: "foo"}
client := newNamedRedisClient(base, "store")
defer client.Close()
opts := client.Options()
if opts.ClientName != "" {
t.Errorf("ClientName = %q, want empty: REDIS_DISABLE_CLIENT_NAME must clear pre-existing name from URL", opts.ClientName)
}
}
func TestNewNamedRedisClient_DisableClientName_InvalidValue(t *testing.T) {
t.Setenv("REDIS_DISABLE_CLIENT_NAME", "not-a-bool")
base := &redis.Options{Addr: "localhost:6379"}
client := newNamedRedisClient(base, "store")
defer client.Close()
opts := client.Options()
// Invalid value falls back to default (false), so ClientName IS set
if opts.ClientName != "multica-api:store" {
t.Errorf("ClientName = %q, want %q (invalid env should fall back to naming enabled)", opts.ClientName, "multica-api:store")
}
}
// TestNormalizeServerVersion covers the router-config wiring path (not just
// a hand-set handler.Config field): an unstamped "dev" build must not leak
// into /api/config's server_version, or the Help popover would render
// "Server version dev" instead of hiding the row.
func TestNormalizeServerVersion(t *testing.T) {
tests := []struct {
name string
in string
want string
}{
{"unstamped_dev_default_becomes_empty", "dev", ""},
{"already_empty_stays_empty", "", ""},
{"stamped_release_tag_passes_through", "v0.4.0", "v0.4.0"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := normalizeServerVersion(tt.in); got != tt.want {
t.Errorf("normalizeServerVersion(%q) = %q, want %q", tt.in, got, tt.want)
}
})
}
}
func TestEnvBool(t *testing.T) {
tests := []struct {
name string
key string
value string
def bool
want bool
}{
{"empty_returns_default_false", "TEST_ENV_BOOL_1", "", false, false},
{"empty_returns_default_true", "TEST_ENV_BOOL_2", "", true, true},
{"true_string", "TEST_ENV_BOOL_3", "true", false, true},
{"false_string", "TEST_ENV_BOOL_4", "false", true, false},
{"one_is_true", "TEST_ENV_BOOL_5", "1", false, true},
{"zero_is_false", "TEST_ENV_BOOL_6", "0", true, false},
{"invalid_returns_default", "TEST_ENV_BOOL_7", "maybe", false, false},
{"invalid_returns_default_true", "TEST_ENV_BOOL_8", "maybe", true, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.value != "" {
t.Setenv(tt.key, tt.value)
} else {
os.Unsetenv(tt.key)
}
got := envBool(tt.key, tt.def)
if got != tt.want {
t.Errorf("envBool(%q, %v) = %v, want %v", tt.key, tt.def, got, tt.want)
}
})
}
}