1
0
Fork 0
discord-tweeter/pkg/cache/cache_test.go
Manuel 21d580d1a6
feat: Major refactor, implement web, caching, better tests and build files
* Update golang version to 1.24
* Update multiarch Dockerfile to be more ISA agnostic
* Refactor existing code and properly structure project into modules
* Get rid of global variables except where necessary (go:embed)
* Add default values to Config
* Add webserver with templates to finally correctly serve videos and gifs
* Add tiny caching library to decrease api load and improve latency
* Improve Webhook data preparation by filtering out redundant links
  from the tweet text and properly attaching videos and gifs in separate
  webhook request by utilising new webserver
* Improve tests for filter function
* Improve bake definition for easier CI integration
2025-03-18 19:22:00 +01:00

145 lines
2.9 KiB
Go

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")
}
}