func TestRoundRobin(t *testing.T) { var ( counts = []int{0, 0, 0} endpoints = []endpoint.Endpoint{ func(context.Context, interface{}) (interface{}, error) { counts[0]++; return struct{}{}, nil }, func(context.Context, interface{}) (interface{}, error) { counts[1]++; return struct{}{}, nil }, func(context.Context, interface{}) (interface{}, error) { counts[2]++; return struct{}{}, nil }, } ) subscriber := sd.FixedSubscriber(endpoints) balancer := NewRoundRobin(subscriber) for i, want := range [][]int{ {1, 0, 0}, {1, 1, 0}, {1, 1, 1}, {2, 1, 1}, {2, 2, 1}, {2, 2, 2}, {3, 2, 2}, } { endpoint, err := balancer.Endpoint() if err != nil { t.Fatal(err) } endpoint(context.Background(), struct{}{}) if have := counts; !reflect.DeepEqual(want, have) { t.Fatalf("%d: want %v, have %v", i, want, have) } } }
func TestRandom(t *testing.T) { var ( n = 7 endpoints = make([]endpoint.Endpoint, n) counts = make([]int, n) seed = int64(12345) iterations = 1000000 want = iterations / n tolerance = want / 100 // 1% ) for i := 0; i < n; i++ { i0 := i endpoints[i] = func(context.Context, interface{}) (interface{}, error) { counts[i0]++; return struct{}{}, nil } } subscriber := sd.FixedSubscriber(endpoints) balancer := NewRandom(subscriber, seed) for i := 0; i < iterations; i++ { endpoint, _ := balancer.Endpoint() endpoint(context.Background(), struct{}{}) } for i, have := range counts { delta := int(math.Abs(float64(want - have))) if delta > tolerance { t.Errorf("%d: want %d, have %d, delta %d > %d tolerance", i, want, have, delta, tolerance) } } }
func TestRoundRobinNoRace(t *testing.T) { balancer := NewRoundRobin(sd.FixedSubscriber([]endpoint.Endpoint{ endpoint.Nop, endpoint.Nop, endpoint.Nop, endpoint.Nop, endpoint.Nop, })) var ( n = 100 done = make(chan struct{}) wg sync.WaitGroup count uint64 ) wg.Add(n) for i := 0; i < n; i++ { go func() { defer wg.Done() for { select { case <-done: return default: _, _ = balancer.Endpoint() atomic.AddUint64(&count, 1) } } }() } time.Sleep(time.Second) close(done) wg.Wait() t.Logf("made %d calls", atomic.LoadUint64(&count)) }