Files

85 lines
1.7 KiB
Go
Raw Permalink Normal View History

package jobs
import (
"errors"
"sync/atomic"
"testing"
"time"
"github.com/jackc/pgx/v5"
)
func TestClampSyncWorkers(t *testing.T) {
t.Parallel()
cases := []struct {
in, want int
}{
{0, 1},
{-2, 1},
{1, 1},
{MaxSyncWorkers, MaxSyncWorkers},
{MaxSyncWorkers + 3, MaxSyncWorkers},
}
for _, tc := range cases {
if got := ClampSyncWorkers(tc.in); got != tc.want {
t.Fatalf("ClampSyncWorkers(%d)=%d want %d", tc.in, got, tc.want)
}
}
}
func TestSyncSlotsBoundsConcurrent(t *testing.T) {
t.Parallel()
slots := NewSyncSlots(2)
var inflight atomic.Int32
var maxInflight atomic.Int32
var claimed atomic.Int32
claim := func() error {
if claimed.Add(1) > 4 {
return pgx.ErrNoRows
}
return nil
}
for i := 0; i < 8; i++ {
_, err := slots.TryStart(claim, func() {
n := inflight.Add(1)
for {
cur := maxInflight.Load()
if n <= cur || maxInflight.CompareAndSwap(cur, n) {
break
}
}
time.Sleep(30 * time.Millisecond)
inflight.Add(-1)
})
if err != nil && !errors.Is(err, pgx.ErrNoRows) {
t.Fatalf("claim: %v", err)
}
}
slots.Wait()
if maxInflight.Load() > 2 {
t.Fatalf("max inflight=%d want <=2", maxInflight.Load())
}
}
func TestSyncSlotsRejectsWhenFull(t *testing.T) {
t.Parallel()
slots := NewSyncSlots(1)
block := make(chan struct{})
started, err := slots.TryStart(func() error { return nil }, func() { <-block })
if err != nil || !started {
t.Fatalf("first start: started=%v err=%v", started, err)
}
started, err = slots.TryStart(func() error {
t.Fatal("should not claim when full")
return nil
}, func() {})
if err != nil || started {
t.Fatalf("second start: started=%v err=%v", started, err)
}
close(block)
slots.Wait()
}