package livednstest_test import ( "context" "sync" "testing" "time" "github.com/stretchr/testify/assert" "sneak.berlin/go/dnswatcher/internal/livednstest" ) // Tests for the retry and the concurrency limit themselves. They // perform no DNS resolution of any kind. func TestRetryRecoversFromTransientFailure(t *testing.T) { t.Parallel() const wantAttempts = 2 attempts := 0 livednstest.Retry(t, "transient", func(_ context.Context) error { attempts++ if attempts < wantAttempts { return livednstest.ErrNoAnswer } return nil }) assert.Equal(t, wantAttempts, attempts) } func TestRetryGivesEachAttemptADeadline(t *testing.T) { t.Parallel() livednstest.Retry(t, "deadline", func(ctx context.Context) error { deadline, ok := ctx.Deadline() assert.True(t, ok, "attempt should carry a deadline") remaining := time.Until(deadline) assert.LessOrEqual(t, remaining, livednstest.AttemptTimeout) // Lower bound too: without one this passes for a // deadline far shorter than intended, which would // silently turn every live attempt into an instant // timeout. assert.Greater(t, remaining, livednstest.AttemptTimeout/2) return nil }) } func TestRunBoundsConcurrency(t *testing.T) { t.Parallel() const workers = 24 var ( mu sync.Mutex wg sync.WaitGroup inFlight int maxSeen int ) wg.Add(workers) for range workers { go func() { defer wg.Done() _ = livednstest.Run(func(_ context.Context) error { mu.Lock() inFlight++ if inFlight > maxSeen { maxSeen = inFlight } mu.Unlock() time.Sleep(time.Millisecond) mu.Lock() inFlight-- mu.Unlock() return nil }) }() } wg.Wait() assert.Positive(t, maxSeen) assert.LessOrEqual( t, maxSeen, livednstest.Concurrency, "live queries must stay under the package-wide gate", ) }