package cache import ( "fmt" "reflect" "sync" "testing" "time" ) func TestCacheBasicOperations(t *testing.T) { cache := New[string, int]() // Test Set and Get cache.Set("key1", 42, 10*time.Second) value, exists := cache.Get("key1") if !exists { t.Errorf("expected key to exist") } if value != 42 { t.Errorf("expected value 42, got %v", value) } // Test non-existent key value, exists = cache.Get("nonexistent") if exists { t.Errorf("expected key to not exist") } if value != 0 { t.Errorf("expected zero value, got %v", value) } } func TestCacheExpiration(t *testing.T) { cache := New[string, int]() // Set value with very short TTL cache.Set("short-lived", 42, 100*time.Millisecond) // Verify initial existence value, exists := cache.Get("short-lived") if !exists { t.Errorf("expected key to exist initially") } if value != 42 { t.Errorf("expected value 42, got %v", value) } // Wait for expiration time.Sleep(150 * time.Millisecond) // Verify expiration value, exists = cache.Get("short-lived") if exists { t.Errorf("expected key to have expired") } if value != 0 { t.Errorf("expected zero value, got %v", value) } } func TestCacheConcurrentAccess(t *testing.T) { cache := New[string, int]() // Start multiple writers var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func(i int) { defer wg.Done() cache.Set(fmt.Sprintf("key%d", i), i*2, 10*time.Second) }(i) } // Start multiple readers for i := 0; i < 10; i++ { wg.Add(1) go func(i int) { defer wg.Done() cache.Get(fmt.Sprintf("key%d", i)) }(i) } wg.Wait() // Verify all values were written correctly for i := 0; i < 10; i++ { value, exists := cache.Get(fmt.Sprintf("key%d", i)) if !exists { t.Errorf("expected key%d to exist", i) } if value != (i * 2) { t.Errorf("expected value %d for key%d, got %d", i*2, i, value) } } } func TestCacheGenericTypes(t *testing.T) { // Test with string values strCache := New[int, string]() strCache.Set(1, "hello", 10*time.Second) value, exists := strCache.Get(1) if !exists { t.Errorf("expected key to exist") } if value != "hello" { t.Errorf("expected value hello, got %v", value) } // Test with struct values type Person struct { Name string Age int } personCache := New[string, Person]() personCache.Set("john", Person{"John", 30}, 10*time.Second) person, exists := personCache.Get("john") if !exists { t.Errorf("expected key to exist") } expected := Person{"John", 30} if !reflect.DeepEqual(person, expected) { t.Errorf("expected %+v, got %+v", expected, person) } } func TestCacheDelete(t *testing.T) { cache := New[string, int]() // Set and verify cache.Set("key1", 42, 10*time.Second) _, exists := cache.Get("key1") if !exists { t.Errorf("expected key to exist") } // Delete cache.Delete("key1") // Verify deletion _, exists = cache.Get("key1") if exists { t.Errorf("expected key to not exist after deletion") } }