package infra import ( "encoding/json" "fmt" "os" "sync" "testing" "time" ) func tempDB(t *testing.T) string { t.Helper() f, err := os.CreateTemp(t.TempDir(), "cache_*.db") if err != nil { t.Fatal(err) } f.Close() return f.Name() } func TestCacheToSQLite_SetGet(t *testing.T) { t.Run("Set/Get basico", func(t *testing.T) { c, err := CacheToSQLite(tempDB(t), "default") if err != nil { t.Fatal(err) } defer c.Close() payload, _ := json.Marshal(map[string]int{"x": 1}) if err := c.Set("foo", payload, 0); err != nil { t.Fatal(err) } got, ok := c.Get("foo") if !ok { t.Fatal("expected cache hit") } var result map[string]int json.Unmarshal(got, &result) if result["x"] != 1 { t.Errorf("got %v, want x=1", result) } }) } func TestCacheToSQLite_TTLExpirado(t *testing.T) { t.Run("TTL expirado", func(t *testing.T) { c, err := CacheToSQLite(tempDB(t), "default") if err != nil { t.Fatal(err) } defer c.Close() payload, _ := json.Marshal("hello") c.Set("temp", payload, 50*time.Millisecond) time.Sleep(100 * time.Millisecond) _, ok := c.Get("temp") if ok { t.Error("expected cache miss after TTL expiry") } }) } func TestCacheToSQLite_GetOrSet(t *testing.T) { t.Run("GetOrSet con factory", func(t *testing.T) { c, err := CacheToSQLite(tempDB(t), "default") if err != nil { t.Fatal(err) } defer c.Close() calls := 0 factory := func() ([]byte, error) { calls++ return json.Marshal("computed") } v1, err := c.GetOrSet("k", factory, time.Minute) if err != nil { t.Fatal(err) } v2, err := c.GetOrSet("k", factory, time.Minute) if err != nil { t.Fatal(err) } if string(v1) != string(v2) { t.Errorf("v1=%s v2=%s, want equal", v1, v2) } if calls != 1 { t.Errorf("factory called %d times, want 1", calls) } }) } func TestCacheToSQLite_Concurrencia(t *testing.T) { t.Run("Concurrencia (goroutines)", func(t *testing.T) { c, err := CacheToSQLite(tempDB(t), "parallel") if err != nil { t.Fatal(err) } defer c.Close() var wg sync.WaitGroup errs := make(chan error, 40) for i := 0; i < 20; i++ { wg.Add(1) go func(n int) { defer wg.Done() key := fmt.Sprintf("key_%d", n) payload, _ := json.Marshal(n) if err := c.Set(key, payload, 0); err != nil { errs <- err return } got, ok := c.Get(key) if !ok { errs <- fmt.Errorf("miss for key %s", key) return } var val int json.Unmarshal(got, &val) if val != n { errs <- fmt.Errorf("key %s: got %d want %d", key, val, n) } }(i) } wg.Wait() close(errs) for err := range errs { t.Error(err) } }) }