spark-server/internal/bootstrap/health_test.go
zhr ae9a71034d feat: implement Spark IM V3 modular monolith
Add HTTP /v1 MVC, TCP send path, groups with server-side member-avatar collage, object-storage upload, and friends/favorites around the architecture-v3 layout.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 19:52:11 +08:00

86 lines
2.1 KiB
Go

package bootstrap
import (
"sync/atomic"
"testing"
)
func TestParseEnvAndProductionValidate(t *testing.T) {
t.Setenv("SPARK_ENV", "")
t.Setenv("SPARK_JWT_SECRET", "")
if parseEnv("") != EnvDev || parseEnv("production") != EnvProd || parseEnv("PROD") != EnvProd {
t.Fatal("parseEnv")
}
dev := &Config{Env: "dev", JWT: JWTConfig{Secret: DefaultJWTSecret}}
if err := dev.normalize(); err != nil {
t.Fatal(err)
}
if dev.Production() {
t.Fatal("dev")
}
prod := &Config{Env: "prod"}
if err := prod.normalize(); err == nil {
t.Fatal("prod missing stores")
}
prod = &Config{
Env: "prod",
MySQL: MySQLConfig{DSN: "user:pass@tcp(127.0.0.1:3306)/im"},
Redis: RedisConfig{Addr: "127.0.0.1:6379"},
JWT: JWTConfig{Secret: DefaultJWTSecret},
}
if err := prod.normalize(); err == nil {
t.Fatal("prod default jwt")
}
prod.JWT.Secret = "long-enough-production-secret"
if err := prod.normalize(); err != nil {
t.Fatal(err)
}
if !prod.Production() {
t.Fatal("prod flag")
}
}
func TestRedisPasswordFromEnv(t *testing.T) {
t.Setenv("SPARK_REDIS_PASSWORD", "from-env")
cfg := &Config{Redis: RedisConfig{Addr: "127.0.0.1:6379", Password: "from-yaml"}}
if err := cfg.normalize(); err != nil {
t.Fatal(err)
}
if cfg.Redis.Password != "from-env" {
t.Fatalf("password %q", cfg.Redis.Password)
}
}
func TestProbeReadyDevSkipsStores(t *testing.T) {
p := &Probe{requireDeps: false}
ok, data := p.Ready(t.Context())
if ok {
t.Fatal("not accepting")
}
rep := data.(ProbeReport)
if rep.MySQL != depSkipped || rep.Redis != depSkipped || rep.Status != "not_ready" {
t.Fatalf("%+v", rep)
}
var accepting atomic.Bool
accepting.Store(true)
p.accepting = &accepting
ok, data = p.Ready(t.Context())
if !ok {
t.Fatalf("%+v", data)
}
}
func TestProbeReadyProdRequiresStores(t *testing.T) {
var accepting atomic.Bool
accepting.Store(true)
p := &Probe{requireDeps: true, accepting: &accepting}
ok, data := p.Ready(t.Context())
if ok {
t.Fatal("want down")
}
rep := data.(ProbeReport)
if rep.MySQL != depDown || rep.Redis != depDown {
t.Fatalf("%+v", rep)
}
}