Skip to content

Commit

Permalink
predicates/traffic: deflake TestTrafficSegmentSplit
Browse files Browse the repository at this point in the history
Use fixed random sequence to deflake TestTrafficSegmentSplit.

Fixes #2665

Signed-off-by: Alexander Yastrebov <alexander.yastrebov@zalando.de>
  • Loading branch information
AlexanderYastrebov committed Dec 5, 2024
1 parent e2973de commit 309fe1f
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 7 deletions.
11 changes: 11 additions & 0 deletions predicates/traffic/export_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
package traffic

import "github.com/zalando/skipper/routing"

var ExportRandomValue = randomValue

func WithRandFloat64(ps routing.PredicateSpec, randFloat64 func() float64) routing.PredicateSpec {
if s, ok := ps.(*segmentSpec); ok {
s.randFloat64 = randFloat64
} else {
panic("invalid predicate spec, expected *segmentSpec")
}
return ps
}
18 changes: 18 additions & 0 deletions predicates/traffic/rand_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package traffic_test

import (
"math/rand/v2"
"sync"
)

var (
testRandMu sync.Mutex
testRand = rand.New(rand.NewPCG(0x5EED_1, 0x5EED_2))
)

// testRandFloat64 is a helper function to generate fixed sequence of random float64 values for testing.
func testRandFloat64() float64 {
testRandMu.Lock()
defer testRandMu.Unlock()
return testRand.Float64()
}
17 changes: 11 additions & 6 deletions predicates/traffic/segment.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ import (
)

type (
segmentSpec struct{}
segmentPredicate struct{ min, max float64 }
segmentSpec struct {
randFloat64 func() float64
}
segmentPredicate struct {
randFloat64 func() float64
min, max float64
}
)

type contextKey struct{}
Expand All @@ -19,7 +24,7 @@ var randomValue contextKey

// NewSegment creates a new traffic segment predicate specification
func NewSegment() routing.WeightedPredicateSpec {
return &segmentSpec{}
return &segmentSpec{rand.Float64}
}

func (*segmentSpec) Name() string {
Expand All @@ -42,12 +47,12 @@ func (*segmentSpec) Name() string {
// r50: Path("/test") && TrafficSegment(0.0, 0.5) -> <shunt>;
// r30: Path("/test") && TrafficSegment(0.5, 0.8) -> <shunt>;
// r20: Path("/test") && TrafficSegment(0.8, 1.0) -> <shunt>;
func (*segmentSpec) Create(args []any) (routing.Predicate, error) {
func (s *segmentSpec) Create(args []any) (routing.Predicate, error) {
if len(args) != 2 {
return nil, predicates.ErrInvalidPredicateParameters
}

p, ok := &segmentPredicate{}, false
p, ok := &segmentPredicate{randFloat64: s.randFloat64}, false

if p.min, ok = args[0].(float64); !ok || p.min < 0 || p.min > 1 {
return nil, predicates.ErrInvalidPredicateParameters
Expand All @@ -72,7 +77,7 @@ func (*segmentSpec) Weight() int {
}

func (p *segmentPredicate) Match(req *http.Request) bool {
r := routing.FromContext(req.Context(), randomValue, rand.Float64)
r := routing.FromContext(req.Context(), randomValue, p.randFloat64)
// min == max defines a never-matching interval and always yields false
return p.min <= r && r < p.max
}
4 changes: 3 additions & 1 deletion predicates/traffic/segment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ func TestTrafficSegmentSplit(t *testing.T) {
RoutingOptions: routing.Options{
FilterRegistry: builtin.MakeRegistry(),
Predicates: []routing.PredicateSpec{
traffic.NewSegment(),
// Use fixed random sequence to deflake the test,
// see https://github.com/zalando/skipper/issues/2665
traffic.WithRandFloat64(traffic.NewSegment(), testRandFloat64),
},
},
Routes: eskip.MustParse(`
Expand Down

0 comments on commit 309fe1f

Please sign in to comment.