Skip to content

Commit

Permalink
predicates/traffic: fix flaky TrafficSegment tests (#2423)
Browse files Browse the repository at this point in the history
Test failure could be reproduced via:
```
go test ./predicates/traffic/ -count=100 -run=TestTrafficSegmentSplit
```

* use delta of expected value instead of total number of test requests
* use predefined number of test requests for all tests

Based on the biggest difference seen for 1000 test requests:
```
Max difference between 500 and 462 allowed is 25, but difference was 38
```
the delta should be 38/500=0.076

To reduce flakiness:

* increase total number of samples to 10'000
* then increase delta to 6% based on the failed test case output

Signed-off-by: Alexander Yastrebov <alexander.yastrebov@zalando.de>
  • Loading branch information
AlexanderYastrebov authored Jun 23, 2023
1 parent 46c84af commit 399b08b
Showing 1 changed file with 31 additions and 38 deletions.
69 changes: 31 additions & 38 deletions predicates/traffic/segment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,30 @@ func requestWithR(r float64) *http.Request {
return req
}

func doN(t *testing.T, n int, client *proxytest.TestClient, request func() *http.Request) map[int]int {
codes := make(map[int]int)
// doN performs a number of requests and returns the number of responses for each status code and
// a total number of requests performed.
// Results use float64 type to simplify fractional comparisons.
func doN(t *testing.T, client *proxytest.TestClient, request func() *http.Request) (map[int]float64, float64) {
const n = 10_000
codes := make(map[int]float64)
for i := 0; i < n; i++ {
rsp, err := client.Do(request())
require.NoError(t, err)
rsp.Body.Close()

codes[rsp.StatusCode]++
}
return codes
return codes, n
}

func getN(t *testing.T, n int, client *proxytest.TestClient, url string) map[int]int {
return doN(t, n, client, func() *http.Request {
// assertEqualWithTolerance verifies that actual value is within predefined delta of the expected value.
func assertEqualWithTolerance(t *testing.T, expected, actual float64) {
t.Helper()
assert.InDelta(t, expected, actual, 0.06*expected)
}

func getN(t *testing.T, client *proxytest.TestClient, url string) (map[int]float64, float64) {
return doN(t, client, func() *http.Request {
req, err := http.NewRequest("GET", url, nil)
require.NoError(t, err)
return req
Expand Down Expand Up @@ -129,18 +139,13 @@ func TestTrafficSegmentSplit(t *testing.T) {
}.Create()
defer p.Close()

const (
N = 1_000
delta = 0.05 * N
)

codes := getN(t, N, p.Client(), p.URL+"/test")
codes, n := getN(t, p.Client(), p.URL+"/test")

t.Logf("Response codes: %v", codes)

assert.InDelta(t, N*0.5, codes[200], delta)
assert.InDelta(t, N*0.3, codes[201], delta)
assert.InDelta(t, N*0.2, codes[202], delta)
assertEqualWithTolerance(t, n*0.5, codes[200])
assertEqualWithTolerance(t, n*0.3, codes[201])
assertEqualWithTolerance(t, n*0.2, codes[202])
}

func TestTrafficSegmentRouteWeight(t *testing.T) {
Expand All @@ -159,17 +164,15 @@ func TestTrafficSegmentRouteWeight(t *testing.T) {
}.Create()
defer p.Close()

const N = 1_000
codes, n := getN(t, p.Client(), p.URL+"/test")
assert.Equal(t, n, codes[200])

codes := getN(t, N, p.Client(), p.URL+"/test")
assert.Equal(t, N, codes[200])

codes = doN(t, N, p.Client(), func() *http.Request {
codes, n = doN(t, p.Client(), func() *http.Request {
req, _ := http.NewRequest("GET", p.URL+"/test", nil)
req.Header.Set("X-Foo", "bar")
return req
})
assert.Equal(t, N, codes[201])
assert.Equal(t, n, codes[201])
}

func TestTrafficSegmentTeeLoopback(t *testing.T) {
Expand All @@ -196,22 +199,17 @@ func TestTrafficSegmentTeeLoopback(t *testing.T) {
}.Create()
defer p.Close()

const (
N = 1_000
delta = 0.05 * N
)

codes := getN(t, N, p.Client(), p.URL+"/test")
codes, n := getN(t, p.Client(), p.URL+"/test")

// wait for loopback requests to complete
time.Sleep(100 * time.Millisecond)

loopRequests := int(atomic.LoadInt32(loopRequestsPtr))
loopRequests := float64(atomic.LoadInt32(loopRequestsPtr))

t.Logf("Response codes: %v, loopRequests: %d", codes, loopRequests)
t.Logf("Response codes: %v, loopRequests: %f", codes, loopRequests)

assert.InDelta(t, N*0.5, codes[200], delta)
assert.InDelta(t, N*0.5, codes[201], delta)
assertEqualWithTolerance(t, n*0.5, codes[200])
assertEqualWithTolerance(t, n*0.5, codes[201])
assert.Equal(t, codes[201], loopRequests)
}

Expand All @@ -233,15 +231,10 @@ func TestTrafficSegmentLoopbackBackend(t *testing.T) {
}.Create()
defer p.Close()

const (
N = 1_000
delta = 0.05 * N
)

codes := getN(t, N, p.Client(), p.URL+"/test")
codes, n := getN(t, p.Client(), p.URL+"/test")

t.Logf("Response codes: %v", codes)

assert.InDelta(t, N*0.5, codes[200], delta)
assert.InDelta(t, N*0.5, codes[201], delta)
assertEqualWithTolerance(t, n*0.5, codes[200])
assertEqualWithTolerance(t, n*0.5, codes[201])
}

0 comments on commit 399b08b

Please sign in to comment.