headscale/hscontrol/db/ip_backfill_race_test.go
2026-06-17 16:12:19 +02:00

52 lines
1.1 KiB
Go

package db
import (
"net/netip"
"sync"
"testing"
"github.com/juanfont/headscale/hscontrol/types"
"github.com/stretchr/testify/require"
)
// TestAllocatorConcurrentNextAndBackfillNoRace exercises the registration path
// (Next) concurrently with the backfill allocation path (allocateNext) on
// the same allocator. Backfill used to read prev4/prev6 in the caller's frame
// without the lock, racing Next's writes; both must now take i.mu. Run with
// -race.
func TestAllocatorConcurrentNextAndBackfillNoRace(t *testing.T) {
p4 := netip.MustParsePrefix("100.64.0.0/10")
p6 := netip.MustParsePrefix("fd7a:115c:a1e0::/48")
alloc, err := NewIPAllocator(nil, &p4, &p6, types.IPAllocationStrategySequential)
require.NoError(t, err)
const iterations = 2000
var wg sync.WaitGroup
wg.Go(func() {
for range iterations {
_, _, err := alloc.Next()
if err != nil {
return
}
}
})
wg.Go(func() {
for range iterations {
_, err := alloc.allocateNext(&alloc.prev4, alloc.prefix4)
if err != nil {
return
}
_, err = alloc.allocateNext(&alloc.prev6, alloc.prefix6)
if err != nil {
return
}
}
})
wg.Wait()
}