init commit
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
// pkg/redisclient/redis.go
|
||||
|
||||
package redisclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
var RDB *redis.Client
|
||||
|
||||
func Init() {
|
||||
redisHost := os.Getenv("REDIS_HOST")
|
||||
if redisHost == "" {
|
||||
redisHost = "localhost"
|
||||
}
|
||||
|
||||
redisPort := os.Getenv("REDIS_PORT")
|
||||
if redisPort == "" {
|
||||
redisPort = "6379"
|
||||
}
|
||||
|
||||
redisPassword := os.Getenv("REDIS_PASSWORD")
|
||||
if redisPassword == "" {
|
||||
redisPassword = ""
|
||||
}
|
||||
|
||||
// Configure Redis client with security settings
|
||||
opts := &redis.Options{
|
||||
Addr: fmt.Sprintf("%s:%s", redisHost, redisPort),
|
||||
Password: redisPassword,
|
||||
DB: 0,
|
||||
DisableIndentity: true, // Disable client-side caching to prevent protocol confusion
|
||||
IdentitySuffix: "", // Disable identity suffix
|
||||
}
|
||||
|
||||
RDB = redis.NewClient(opts)
|
||||
|
||||
// Test connection with authentication
|
||||
ctx := context.Background()
|
||||
if _, err := RDB.Ping(ctx).Result(); err != nil {
|
||||
panic(fmt.Sprintf("Could not connect to Redis: %v", err))
|
||||
}
|
||||
|
||||
// Log connection security status
|
||||
if redisPassword != "" {
|
||||
fmt.Println("✓ Redis connection secured with password authentication")
|
||||
} else {
|
||||
fmt.Println("⚠ WARNING: Redis connection without password - security risk!")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package redisclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alicebob/miniredis/v2"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
func TestRedisConnection(t *testing.T) {
|
||||
// Create a miniredis server
|
||||
mr, err := miniredis.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to start miniredis: %v", err)
|
||||
}
|
||||
defer mr.Close()
|
||||
|
||||
// Create a test Redis client
|
||||
testClient := redis.NewClient(&redis.Options{
|
||||
Addr: mr.Addr(),
|
||||
})
|
||||
defer testClient.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Test SET
|
||||
err = testClient.Set(ctx, "test_key", "test_value", time.Minute).Err()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to set key: %v", err)
|
||||
}
|
||||
|
||||
// Test GET
|
||||
val, err := testClient.Get(ctx, "test_key").Result()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to get key: %v", err)
|
||||
}
|
||||
|
||||
if val != "test_value" {
|
||||
t.Errorf("Expected 'test_value', got '%s'", val)
|
||||
}
|
||||
|
||||
// Test DEL
|
||||
err = testClient.Del(ctx, "test_key").Err()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to delete key: %v", err)
|
||||
}
|
||||
|
||||
// Verify key was deleted
|
||||
_, err = testClient.Get(ctx, "test_key").Result()
|
||||
if err != redis.Nil {
|
||||
t.Errorf("Expected redis.Nil error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisExpiry(t *testing.T) {
|
||||
mr, err := miniredis.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to start miniredis: %v", err)
|
||||
}
|
||||
defer mr.Close()
|
||||
|
||||
testClient := redis.NewClient(&redis.Options{
|
||||
Addr: mr.Addr(),
|
||||
})
|
||||
defer testClient.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Set key with TTL
|
||||
err = testClient.Set(ctx, "expiring_key", "value", time.Second).Err()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to set key with TTL: %v", err)
|
||||
}
|
||||
|
||||
// Check TTL
|
||||
ttl := mr.TTL("expiring_key")
|
||||
if ttl <= 0 {
|
||||
t.Error("Expected TTL to be set")
|
||||
}
|
||||
|
||||
// Fast forward time in miniredis
|
||||
mr.FastForward(2 * time.Second)
|
||||
|
||||
// Key should be expired
|
||||
_, err = testClient.Get(ctx, "expiring_key").Result()
|
||||
if err != redis.Nil {
|
||||
t.Errorf("Expected key to be expired, got error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisIncrement(t *testing.T) {
|
||||
mr, err := miniredis.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to start miniredis: %v", err)
|
||||
}
|
||||
defer mr.Close()
|
||||
|
||||
testClient := redis.NewClient(&redis.Options{
|
||||
Addr: mr.Addr(),
|
||||
})
|
||||
defer testClient.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Test INCR
|
||||
val, err := testClient.Incr(ctx, "counter").Result()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to increment: %v", err)
|
||||
}
|
||||
|
||||
if val != 1 {
|
||||
t.Errorf("Expected 1, got %d", val)
|
||||
}
|
||||
|
||||
// Increment again
|
||||
val, err = testClient.Incr(ctx, "counter").Result()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to increment: %v", err)
|
||||
}
|
||||
|
||||
if val != 2 {
|
||||
t.Errorf("Expected 2, got %d", val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisExists(t *testing.T) {
|
||||
mr, err := miniredis.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to start miniredis: %v", err)
|
||||
}
|
||||
defer mr.Close()
|
||||
|
||||
testClient := redis.NewClient(&redis.Options{
|
||||
Addr: mr.Addr(),
|
||||
})
|
||||
defer testClient.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Key shouldn't exist initially
|
||||
exists, err := testClient.Exists(ctx, "nonexistent").Result()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to check existence: %v", err)
|
||||
}
|
||||
|
||||
if exists != 0 {
|
||||
t.Errorf("Expected 0, got %d", exists)
|
||||
}
|
||||
|
||||
// Set key
|
||||
err = testClient.Set(ctx, "existing_key", "value", 0).Err()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to set key: %v", err)
|
||||
}
|
||||
|
||||
// Key should exist now
|
||||
exists, err = testClient.Exists(ctx, "existing_key").Result()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to check existence: %v", err)
|
||||
}
|
||||
|
||||
if exists != 1 {
|
||||
t.Errorf("Expected 1, got %d", exists)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisPing(t *testing.T) {
|
||||
mr, err := miniredis.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to start miniredis: %v", err)
|
||||
}
|
||||
defer mr.Close()
|
||||
|
||||
testClient := redis.NewClient(&redis.Options{
|
||||
Addr: mr.Addr(),
|
||||
})
|
||||
defer testClient.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Test PING
|
||||
pong, err := testClient.Ping(ctx).Result()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to ping: %v", err)
|
||||
}
|
||||
|
||||
if pong != "PONG" {
|
||||
t.Errorf("Expected 'PONG', got '%s'", pong)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisMultipleKeys(t *testing.T) {
|
||||
mr, err := miniredis.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to start miniredis: %v", err)
|
||||
}
|
||||
defer mr.Close()
|
||||
|
||||
testClient := redis.NewClient(&redis.Options{
|
||||
Addr: mr.Addr(),
|
||||
})
|
||||
defer testClient.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Set multiple keys
|
||||
keys := map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
"key3": "value3",
|
||||
}
|
||||
|
||||
for k, v := range keys {
|
||||
err := testClient.Set(ctx, k, v, 0).Err()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to set %s: %v", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Get all keys
|
||||
for k, expectedV := range keys {
|
||||
val, err := testClient.Get(ctx, k).Result()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to get %s: %v", k, err)
|
||||
}
|
||||
|
||||
if val != expectedV {
|
||||
t.Errorf("Expected '%s', got '%s' for key %s", expectedV, val, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user