mirror of
https://github.com/makayabou/asg-server.git
synced 2026-05-02 17:43:36 +02:00
492 lines
10 KiB
Go
492 lines
10 KiB
Go
package cache_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/android-sms-gateway/server/pkg/cache"
|
|
)
|
|
|
|
func TestMemoryCache_SetAndGet(t *testing.T) {
|
|
cache := cache.NewMemory(0) // No TTL for basic tests
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value := "test-value"
|
|
|
|
// Test setting a value
|
|
err := cache.Set(ctx, key, value)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Test getting the value
|
|
retrieved, err := cache.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value {
|
|
t.Errorf("Expected %s, got %s", value, retrieved)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_SetAndGetWithTTL(t *testing.T) {
|
|
c := cache.NewMemory(0) // No default TTL
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value := "test-value"
|
|
ttl := 2 * time.Hour
|
|
|
|
// Test setting a value with TTL
|
|
err := c.Set(ctx, key, value, cache.WithTTL(ttl))
|
|
if err != nil {
|
|
t.Fatalf("Set with TTL failed: %v", err)
|
|
}
|
|
|
|
// Test getting the value
|
|
retrieved, err := c.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value {
|
|
t.Errorf("Expected %s, got %s", value, retrieved)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_SetAndGetWithValidUntil(t *testing.T) {
|
|
c := cache.NewMemory(0) // No default TTL
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value := "test-value"
|
|
validUntil := time.Now().Add(2 * time.Hour)
|
|
|
|
// Test setting a value with validUntil
|
|
err := c.Set(ctx, key, value, cache.WithValidUntil(validUntil))
|
|
if err != nil {
|
|
t.Fatalf("Set with validUntil failed: %v", err)
|
|
}
|
|
|
|
// Test getting the value
|
|
retrieved, err := c.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value {
|
|
t.Errorf("Expected %s, got %s", value, retrieved)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_SetAndGetWithDefaultTTL(t *testing.T) {
|
|
defaultTTL := 1 * time.Hour
|
|
cache := cache.NewMemory(defaultTTL) // With default TTL
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value := "test-value"
|
|
|
|
// Test setting a value without explicit TTL (should use default)
|
|
err := cache.Set(ctx, key, value)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Test getting the value
|
|
retrieved, err := cache.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value {
|
|
t.Errorf("Expected %s, got %s", value, retrieved)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_GetNotFound(t *testing.T) {
|
|
c := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "non-existent-key"
|
|
|
|
_, err := c.Get(ctx, key)
|
|
if err != cache.ErrKeyNotFound {
|
|
t.Errorf("Expected ErrKeyNotFound, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_SetOrFailNewKey(t *testing.T) {
|
|
cache := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value := "test-value"
|
|
|
|
// Test SetOrFail with new key
|
|
err := cache.SetOrFail(ctx, key, value)
|
|
if err != nil {
|
|
t.Fatalf("SetOrFail failed: %v", err)
|
|
}
|
|
|
|
// Verify the value was set
|
|
retrieved, err := cache.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value {
|
|
t.Errorf("Expected %s, got %s", value, retrieved)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_SetOrFailExistingKey(t *testing.T) {
|
|
c := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value1 := "value1"
|
|
value2 := "value2"
|
|
|
|
// Set initial value
|
|
err := c.Set(ctx, key, value1)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Try SetOrFail with existing key
|
|
err = c.SetOrFail(ctx, key, value2)
|
|
if err != cache.ErrKeyExists {
|
|
t.Errorf("Expected ErrKeyExists, got %v", err)
|
|
}
|
|
|
|
// Verify original value is still there
|
|
retrieved, err := c.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value1 {
|
|
t.Errorf("Expected %s, got %s", value1, retrieved)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_Delete(t *testing.T) {
|
|
c := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value := "test-value"
|
|
|
|
// Set a value
|
|
err := c.Set(ctx, key, value)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Delete the key
|
|
err = c.Delete(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Delete failed: %v", err)
|
|
}
|
|
|
|
// Verify the key is gone
|
|
_, err = c.Get(ctx, key)
|
|
if err != cache.ErrKeyNotFound {
|
|
t.Errorf("Expected ErrKeyNotFound after delete, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_DeleteNonExistent(t *testing.T) {
|
|
cache := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "non-existent-key"
|
|
|
|
// Delete non-existent key should not fail
|
|
err := cache.Delete(ctx, key)
|
|
if err != nil {
|
|
t.Errorf("Delete of non-existent key failed: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_GetAndDelete(t *testing.T) {
|
|
c := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value := "test-value"
|
|
|
|
// Set a value
|
|
err := c.Set(ctx, key, value)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Get and delete the key
|
|
retrieved, err := c.GetAndDelete(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("GetAndDelete failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value {
|
|
t.Errorf("Expected %s, got %s", value, retrieved)
|
|
}
|
|
|
|
// Verify the key is gone
|
|
_, err = c.Get(ctx, key)
|
|
if err != cache.ErrKeyNotFound {
|
|
t.Errorf("Expected ErrKeyNotFound after GetAndDelete, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_GetAndDeleteNonExistent(t *testing.T) {
|
|
c := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "non-existent-key"
|
|
|
|
// GetAndDelete non-existent key should return ErrKeyNotFound
|
|
_, err := c.GetAndDelete(ctx, key)
|
|
if err != cache.ErrKeyNotFound {
|
|
t.Errorf("Expected ErrKeyNotFound, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_Drain(t *testing.T) {
|
|
c := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
items := map[string]string{
|
|
"key1": "value1",
|
|
"key2": "value2",
|
|
"key3": "value3",
|
|
}
|
|
|
|
// Set multiple values
|
|
for key, value := range items {
|
|
err := c.Set(ctx, key, value)
|
|
if err != nil {
|
|
t.Fatalf("Set failed for %s: %v", key, err)
|
|
}
|
|
}
|
|
|
|
// Drain the cache
|
|
drained, err := c.Drain(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Drain failed: %v", err)
|
|
}
|
|
|
|
// Verify all items are drained
|
|
if len(drained) != len(items) {
|
|
t.Errorf("Expected %d items, got %d", len(items), len(drained))
|
|
}
|
|
|
|
for key, expectedValue := range items {
|
|
actualValue, ok := drained[key]
|
|
if !ok {
|
|
t.Errorf("Expected key %s in drained items", key)
|
|
continue
|
|
}
|
|
if actualValue != expectedValue {
|
|
t.Errorf("Expected %s, got %s for key %s", expectedValue, actualValue, key)
|
|
}
|
|
}
|
|
|
|
// Verify cache is now empty
|
|
for key := range items {
|
|
_, err := c.Get(ctx, key)
|
|
if err != cache.ErrKeyNotFound {
|
|
t.Errorf("Expected ErrKeyNotFound for key %s after drain, got %v", key, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_DrainEmpty(t *testing.T) {
|
|
cache := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
|
|
// Drain empty cache
|
|
drained, err := cache.Drain(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Drain failed: %v", err)
|
|
}
|
|
|
|
if len(drained) != 0 {
|
|
t.Errorf("Expected 0 items from empty cache, got %d", len(drained))
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_Cleanup(t *testing.T) {
|
|
c := cache.NewMemory(0) // No default TTL
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value := "test-value"
|
|
shortTTL := 100 * time.Millisecond
|
|
|
|
// Set a value with short TTL
|
|
err := c.Set(ctx, key, value, cache.WithTTL(shortTTL))
|
|
if err != nil {
|
|
t.Fatalf("Set with TTL failed: %v", err)
|
|
}
|
|
|
|
// Verify the value is there initially
|
|
_, err = c.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
// Wait for the item to expire
|
|
time.Sleep(2 * shortTTL)
|
|
|
|
// Run cleanup
|
|
err = c.Cleanup(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Cleanup failed: %v", err)
|
|
}
|
|
|
|
// Verify the expired item is gone
|
|
_, err = c.Get(ctx, key)
|
|
if err != cache.ErrKeyNotFound {
|
|
t.Errorf("Expected ErrKeyNotFound after cleanup, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_CleanupNoExpired(t *testing.T) {
|
|
cache := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value := "test-value"
|
|
|
|
// Set a value without TTL
|
|
err := cache.Set(ctx, key, value)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Run cleanup on cache with no expired items
|
|
err = cache.Cleanup(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Cleanup failed: %v", err)
|
|
}
|
|
|
|
// Verify the value is still there
|
|
retrieved, err := cache.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value {
|
|
t.Errorf("Expected %s, got %s", value, retrieved)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_Overwrite(t *testing.T) {
|
|
cache := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value1 := "value1"
|
|
value2 := "value2"
|
|
|
|
// Set initial value
|
|
err := cache.Set(ctx, key, value1)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Overwrite with new value
|
|
err = cache.Set(ctx, key, value2)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Verify the new value is there
|
|
retrieved, err := cache.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value2 {
|
|
t.Errorf("Expected %s, got %s", value2, retrieved)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_EmptyValue(t *testing.T) {
|
|
cache := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "test-key"
|
|
value := ""
|
|
|
|
// Set empty value
|
|
err := cache.Set(ctx, key, value)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Get the empty value
|
|
retrieved, err := cache.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value {
|
|
t.Errorf("Expected empty string, got %s", retrieved)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_SpecialCharacters(t *testing.T) {
|
|
cache := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "test:key/with@special#chars"
|
|
value := "value with special chars: !@#$%^&*()"
|
|
|
|
// Set value with special characters
|
|
err := cache.Set(ctx, key, value)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Get the value
|
|
retrieved, err := cache.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value {
|
|
t.Errorf("Expected %s, got %s", value, retrieved)
|
|
}
|
|
}
|
|
|
|
func TestMemoryCache_LargeValue(t *testing.T) {
|
|
cache := cache.NewMemory(0)
|
|
|
|
ctx := context.Background()
|
|
key := "large-key"
|
|
value := string(make([]byte, 1024*1024)) // 1MB value
|
|
|
|
// Set large value
|
|
err := cache.Set(ctx, key, value)
|
|
if err != nil {
|
|
t.Fatalf("Set failed: %v", err)
|
|
}
|
|
|
|
// Get the large value
|
|
retrieved, err := cache.Get(ctx, key)
|
|
if err != nil {
|
|
t.Fatalf("Get failed: %v", err)
|
|
}
|
|
|
|
if retrieved != value {
|
|
t.Errorf("Large value mismatch")
|
|
}
|
|
}
|