You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
4.2 KiB
Go

package redis
// Tests for Redis config and client behavior.
import (
"context"
"errors"
"net"
"strconv"
"testing"
"time"
"github.com/alicebob/miniredis/v2"
redisv9 "github.com/redis/go-redis/v9"
"github.com/stretchr/testify/require"
)
// TestDefaultConfig verifies default configuration values for the client.
func TestDefaultConfig(t *testing.T) {
cfg := DefaultConfig()
require.Equal(t, "localhost", cfg.Host)
require.Equal(t, 6379, cfg.Port)
}
// TestAddr verifies Redis address formatting from config.
func TestAddr(t *testing.T) {
cfg := DefaultConfig()
require.Equal(t, "localhost:6379", cfg.Addr())
}
func newClientForMiniRedis(t *testing.T) (*Client, *miniredis.Miniredis) {
t.Helper()
mr := miniredis.RunT(t)
cfg := DefaultConfig()
host, portStr, err := net.SplitHostPort(mr.Addr())
require.NoError(t, err)
port, err := strconv.Atoi(portStr)
require.NoError(t, err)
cfg.Host = host
cfg.Port = port
client, err := NewClient(cfg)
require.NoError(t, err)
t.Cleanup(func() {
_ = client.Close()
})
return client, mr
}
// TestHealthCheck verifies health checks use the real ping.
func TestHealthCheck(t *testing.T) {
client, _ := newClientForMiniRedis(t)
require.NoError(t, client.HealthCheck(context.Background()))
}
// TestSetGet verifies values can be stored and retrieved.
func TestSetGet(t *testing.T) {
client, _ := newClientForMiniRedis(t)
ctx := context.Background()
require.NoError(t, client.Set(ctx, "k", "v", 0))
got, err := client.Get(ctx, "k")
require.NoError(t, err)
require.Equal(t, "v", got)
}
// TestDeleteExists verifies deletion and existence checks.
func TestDeleteExists(t *testing.T) {
client, _ := newClientForMiniRedis(t)
ctx := context.Background()
require.NoError(t, client.Set(ctx, "k", "v", 0))
exists, err := client.Exists(ctx, "k")
require.NoError(t, err)
require.True(t, exists)
require.NoError(t, client.Delete(ctx, "k"))
exists, err = client.Exists(ctx, "k")
require.NoError(t, err)
require.False(t, exists)
}
// TestIncr verifies atomic increments.
func TestIncr(t *testing.T) {
client, _ := newClientForMiniRedis(t)
ctx := context.Background()
n, err := client.Incr(ctx, "counter")
require.NoError(t, err)
require.Equal(t, int64(1), n)
n, err = client.Incr(ctx, "counter")
require.NoError(t, err)
require.Equal(t, int64(2), n)
}
// TestExpire verifies key expiration behavior.
func TestExpire(t *testing.T) {
client, mr := newClientForMiniRedis(t)
ctx := context.Background()
require.NoError(t, client.Set(ctx, "temp", "value", 0))
require.NoError(t, client.Expire(ctx, "temp", time.Second))
mr.FastForward(2 * time.Second)
_, err := client.Get(ctx, "temp")
require.Error(t, err)
require.True(t, errors.Is(err, redisv9.Nil))
}
// TestGetNotFound verifies missing keys return redis.Nil.
func TestGetNotFound(t *testing.T) {
client, _ := newClientForMiniRedis(t)
_, err := client.Get(context.Background(), "missing")
require.Error(t, err)
require.True(t, errors.Is(err, redisv9.Nil))
}
// TestConfigFromEnvDefaults verifies default env behavior.
func TestConfigFromEnvDefaults(t *testing.T) {
t.Setenv("REDIS_HOST", "")
t.Setenv("REDIS_PORT", "")
cfg := ConfigFromEnv()
def := DefaultConfig()
require.Equal(t, def.Host, cfg.Host)
require.Equal(t, def.Port, cfg.Port)
}
// TestConfigFromEnvOverrides verifies valid env overrides.
func TestConfigFromEnvOverrides(t *testing.T) {
t.Setenv("REDIS_HOST", "cache")
t.Setenv("REDIS_PORT", "6380")
t.Setenv("REDIS_PASSWORD", "secret")
t.Setenv("REDIS_DB", "2")
t.Setenv("REDIS_POOL_SIZE", "25")
t.Setenv("REDIS_MIN_IDLE_CONNS", "3")
t.Setenv("REDIS_DIAL_TIMEOUT", "2s")
t.Setenv("REDIS_READ_TIMEOUT", "4s")
t.Setenv("REDIS_WRITE_TIMEOUT", "5s")
cfg := ConfigFromEnv()
require.Equal(t, "cache", cfg.Host)
require.Equal(t, 6380, cfg.Port)
require.Equal(t, "secret", cfg.Password)
require.Equal(t, 2, cfg.DB)
require.Equal(t, 25, cfg.PoolSize)
require.Equal(t, 3, cfg.MinIdleConns)
require.Equal(t, 2*time.Second, cfg.DialTimeout)
require.Equal(t, 4*time.Second, cfg.ReadTimeout)
require.Equal(t, 5*time.Second, cfg.WriteTimeout)
}
// TestNewClientInvalidConfig verifies early validation errors.
func TestNewClientInvalidConfig(t *testing.T) {
cfg := DefaultConfig()
cfg.Port = 0
_, err := NewClient(cfg)
require.Error(t, err)
}