package syncx import ( "context" "math" "sync" "testing" "time" "forge.cadoles.com/cadoles/bouncer/internal/cache/memory" "forge.cadoles.com/cadoles/bouncer/internal/cache/ttl" "github.com/pkg/errors" ) func TestCachedResource(t *testing.T) { refreshCalls := 0 cacheTTL := 1*time.Second + 500*time.Millisecond duration := 2 * time.Second expectedCalls := math.Ceil(float64(duration) / float64(cacheTTL)) resource := NewCachedResource( ttl.NewCache( memory.NewCache[string, string](), memory.NewCache[string, time.Time](), cacheTTL, ), func(ctx context.Context, key string) (string, error) { refreshCalls++ return "bar", nil }, ) concurrents := 50 key := "foo" var wg sync.WaitGroup wg.Add(concurrents) for i := range concurrents { go func(i int) { done := time.After(duration) defer wg.Done() for { select { case <-done: return default: value, fresh, err := resource.Get(context.Background(), key) if err != nil { t.Errorf("%+v", errors.WithStack(err)) } t.Logf("resource retrieved for goroutine #%d: (%s, %s, %v)", i, key, value, fresh) } } }(i) } wg.Wait() if e, g := int(expectedCalls), refreshCalls; e != g { t.Errorf("refreshCalls: expected '%d', got '%d'", e, g) } }