feat: use postgres
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
package redisconn_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"galaxy/redisconn"
|
||||
|
||||
"github.com/alicebob/miniredis/v2"
|
||||
"go.opentelemetry.io/otel/metric/noop"
|
||||
tracenoop "go.opentelemetry.io/otel/trace/noop"
|
||||
)
|
||||
|
||||
func TestDefaultConfigReturnsExpectedTuning(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := redisconn.DefaultConfig()
|
||||
if cfg.OperationTimeout != redisconn.DefaultOperationTimeout {
|
||||
t.Fatalf("operation timeout = %v, want %v", cfg.OperationTimeout, redisconn.DefaultOperationTimeout)
|
||||
}
|
||||
if cfg.DB != redisconn.DefaultDB {
|
||||
t.Fatalf("db = %d, want %d", cfg.DB, redisconn.DefaultDB)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigValidateRejectsInvalidValues(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*redisconn.Config)
|
||||
wantSub string
|
||||
}{
|
||||
{
|
||||
name: "missing master",
|
||||
mutate: func(c *redisconn.Config) {
|
||||
c.MasterAddr = ""
|
||||
},
|
||||
wantSub: "master addr",
|
||||
},
|
||||
{
|
||||
name: "missing password",
|
||||
mutate: func(c *redisconn.Config) {
|
||||
c.Password = ""
|
||||
},
|
||||
wantSub: "password",
|
||||
},
|
||||
{
|
||||
name: "blank replica entry",
|
||||
mutate: func(c *redisconn.Config) {
|
||||
c.ReplicaAddrs = []string{" "}
|
||||
},
|
||||
wantSub: "replica addr",
|
||||
},
|
||||
{
|
||||
name: "negative db",
|
||||
mutate: func(c *redisconn.Config) {
|
||||
c.DB = -1
|
||||
},
|
||||
wantSub: "db must not be negative",
|
||||
},
|
||||
{
|
||||
name: "non-positive timeout",
|
||||
mutate: func(c *redisconn.Config) {
|
||||
c.OperationTimeout = 0
|
||||
},
|
||||
wantSub: "operation timeout",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := redisconn.DefaultConfig()
|
||||
cfg.MasterAddr = "127.0.0.1:6379"
|
||||
cfg.Password = "secret"
|
||||
tt.mutate(&cfg)
|
||||
|
||||
err := cfg.Validate()
|
||||
if err == nil {
|
||||
t.Fatalf("expected validate error, got nil")
|
||||
}
|
||||
if !strings.Contains(err.Error(), tt.wantSub) {
|
||||
t.Fatalf("error %q does not contain %q", err, tt.wantSub)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFromEnvHappyPath(t *testing.T) {
|
||||
const prefix = "TESTSVC"
|
||||
t.Setenv(prefix+"_REDIS_MASTER_ADDR", "127.0.0.1:6379")
|
||||
t.Setenv(prefix+"_REDIS_REPLICA_ADDRS", "127.0.0.1:6380, 127.0.0.1:6381 ,")
|
||||
t.Setenv(prefix+"_REDIS_PASSWORD", "secret")
|
||||
t.Setenv(prefix+"_REDIS_DB", "3")
|
||||
t.Setenv(prefix+"_REDIS_OPERATION_TIMEOUT", "500ms")
|
||||
|
||||
cfg, err := redisconn.LoadFromEnv(prefix)
|
||||
if err != nil {
|
||||
t.Fatalf("load from env: %v", err)
|
||||
}
|
||||
if cfg.MasterAddr != "127.0.0.1:6379" {
|
||||
t.Fatalf("master addr = %q", cfg.MasterAddr)
|
||||
}
|
||||
if cfg.Password != "secret" {
|
||||
t.Fatalf("password = %q", cfg.Password)
|
||||
}
|
||||
if got, want := cfg.DB, 3; got != want {
|
||||
t.Fatalf("db = %d, want %d", got, want)
|
||||
}
|
||||
if got, want := cfg.OperationTimeout, 500*time.Millisecond; got != want {
|
||||
t.Fatalf("operation timeout = %v, want %v", got, want)
|
||||
}
|
||||
if got, want := len(cfg.ReplicaAddrs), 2; got != want {
|
||||
t.Fatalf("replica count = %d, want %d", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFromEnvRejectsDeprecatedTLSEnabled(t *testing.T) {
|
||||
const prefix = "TESTSVC"
|
||||
t.Setenv(prefix+"_REDIS_MASTER_ADDR", "127.0.0.1:6379")
|
||||
t.Setenv(prefix+"_REDIS_PASSWORD", "secret")
|
||||
t.Setenv(prefix+"_REDIS_TLS_ENABLED", "true")
|
||||
|
||||
_, err := redisconn.LoadFromEnv(prefix)
|
||||
if err == nil {
|
||||
t.Fatal("expected error when TLS_ENABLED is set")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "TLS_ENABLED") {
|
||||
t.Fatalf("error %q should name TLS_ENABLED", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "ARCHITECTURE.md") {
|
||||
t.Fatalf("error %q should reference ARCHITECTURE.md", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFromEnvRejectsDeprecatedUsername(t *testing.T) {
|
||||
const prefix = "TESTSVC"
|
||||
t.Setenv(prefix+"_REDIS_MASTER_ADDR", "127.0.0.1:6379")
|
||||
t.Setenv(prefix+"_REDIS_PASSWORD", "secret")
|
||||
t.Setenv(prefix+"_REDIS_USERNAME", "anything")
|
||||
|
||||
_, err := redisconn.LoadFromEnv(prefix)
|
||||
if err == nil {
|
||||
t.Fatal("expected error when USERNAME is set")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "USERNAME") {
|
||||
t.Fatalf("error %q should name USERNAME", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFromEnvRequiresPassword(t *testing.T) {
|
||||
const prefix = "TESTSVC"
|
||||
t.Setenv(prefix+"_REDIS_MASTER_ADDR", "127.0.0.1:6379")
|
||||
t.Setenv(prefix+"_REDIS_PASSWORD", "")
|
||||
|
||||
if _, err := redisconn.LoadFromEnv(prefix); err == nil {
|
||||
t.Fatal("expected error when password is empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewMasterClientPingsMiniredis(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := miniredis.RunT(t)
|
||||
server.RequireAuth("secret")
|
||||
|
||||
cfg := redisconn.DefaultConfig()
|
||||
cfg.MasterAddr = server.Addr()
|
||||
cfg.Password = "secret"
|
||||
if err := cfg.Validate(); err != nil {
|
||||
t.Fatalf("validate: %v", err)
|
||||
}
|
||||
|
||||
client := redisconn.NewMasterClient(cfg)
|
||||
t.Cleanup(func() {
|
||||
_ = client.Close()
|
||||
})
|
||||
|
||||
if err := redisconn.Ping(context.Background(), client, cfg.OperationTimeout); err != nil {
|
||||
t.Fatalf("ping miniredis: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewReplicaClientsReturnsExpectedLength(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server1 := miniredis.RunT(t)
|
||||
server2 := miniredis.RunT(t)
|
||||
|
||||
cfg := redisconn.DefaultConfig()
|
||||
cfg.MasterAddr = "ignored:6379"
|
||||
cfg.Password = "secret"
|
||||
cfg.ReplicaAddrs = []string{server1.Addr(), server2.Addr()}
|
||||
|
||||
clients := redisconn.NewReplicaClients(cfg)
|
||||
t.Cleanup(func() {
|
||||
for _, client := range clients {
|
||||
_ = client.Close()
|
||||
}
|
||||
})
|
||||
|
||||
if got, want := len(clients), 2; got != want {
|
||||
t.Fatalf("client count = %d, want %d", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewReplicaClientsReturnsNilWhenUnconfigured(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := redisconn.DefaultConfig()
|
||||
cfg.MasterAddr = "ignored:6379"
|
||||
cfg.Password = "secret"
|
||||
|
||||
if clients := redisconn.NewReplicaClients(cfg); clients != nil {
|
||||
t.Fatalf("clients = %v, want nil", clients)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstrumentAcceptsNoopProviders(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := miniredis.RunT(t)
|
||||
server.RequireAuth("secret")
|
||||
|
||||
cfg := redisconn.DefaultConfig()
|
||||
cfg.MasterAddr = server.Addr()
|
||||
cfg.Password = "secret"
|
||||
|
||||
client := redisconn.NewMasterClient(cfg)
|
||||
t.Cleanup(func() {
|
||||
_ = client.Close()
|
||||
})
|
||||
|
||||
err := redisconn.Instrument(
|
||||
client,
|
||||
redisconn.WithTracerProvider(tracenoop.NewTracerProvider()),
|
||||
redisconn.WithMeterProvider(noop.NewMeterProvider()),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("instrument: %v", err)
|
||||
}
|
||||
|
||||
if err := redisconn.Ping(context.Background(), client, cfg.OperationTimeout); err != nil {
|
||||
t.Fatalf("ping after instrument: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstrumentRejectsNilClient(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if err := redisconn.Instrument(nil); err == nil {
|
||||
t.Fatal("expected error for nil client")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user