package db import ( "errors" "strings" "testing" "time" ) func TestParseRedisAddrs(t *testing.T) { got := parseRedisAddrs("127.0.0.1:26379\n127.0.0.1:26380, 10.0.0.1:26379") if len(got) != 3 { t.Fatalf("want 3 addrs, got %#v", got) } } func TestOpenRedisModeValidation(t *testing.T) { _, err := openRedis(ConnReq{Driver: "redis", RedisMode: "sentinel"}) if err == nil || !strings.Contains(err.Error(), "Sentinel") { t.Fatalf("sentinel without nodes: %v", err) } _, err = openRedis(ConnReq{Driver: "redis", RedisMode: "sentinel", RedisNodes: "127.0.0.1:26379"}) if err == nil || !strings.Contains(err.Error(), "masterName") { t.Fatalf("sentinel without master: %v", err) } _, err = openRedis(ConnReq{Driver: "redis", RedisMode: "cluster"}) if err == nil || !strings.Contains(err.Error(), "Cluster") { t.Fatalf("cluster without nodes: %v", err) } } func TestNormalizeRedisModeInfersClusterFromNodes(t *testing.T) { cases := []struct { name string c ConnReq want string }{ {"空配置回单机", ConnReq{}, "standalone"}, {"显式 sentinel 保留", ConnReq{RedisMode: "Sentinel", RedisNodes: "127.0.0.1:26379"}, "sentinel"}, {"多节点未选模式推断 cluster", ConnReq{RedisNodes: "127.0.0.1:7101,127.0.0.1:7102"}, "cluster"}, {"单节点未选模式保持单机", ConnReq{Host: "127.0.0.1", Port: 6379, RedisNodes: "127.0.0.1:6379"}, "standalone"}, } for _, tc := range cases { if got := normalizeRedisMode(tc.c); got != tc.want { t.Fatalf("%s: want %s, got %s", tc.name, tc.want, got) } } } func TestRedisErrMovedHint(t *testing.T) { res := redisErr(time.Now(), errors.New("MOVED 12503 127.0.0.1:7103")) if !strings.Contains(res.Error, "部署模式切为 Cluster") { t.Fatalf("MOVED 错误应带模式切换提示: %q", res.Error) } res = redisErr(time.Now(), errors.New("WRONGTYPE Operation against")) if strings.Contains(res.Error, "Cluster") { t.Fatalf("普通错误不应带集群提示: %q", res.Error) } }