@@ -67,17 +67,35 @@ func update[T any](oldObj, newObj *T) [2]*T {
67
67
return [2 ]* T {oldObj , newObj }
68
68
}
69
69
70
- func runInputEvents (tCtx * testContext , events []any ) {
71
- for _ , event := range events {
72
- switch event := event .(type ) {
73
- case []any :
74
- for _ , event := range event {
75
- applyEventPair (tCtx , event )
70
+ func runInputEvents (tCtx * testContext , events []any , permutation []int ) {
71
+ for _ , i := range permutation {
72
+ event , name := lookupEvent (events , i )
73
+ stepCtx := tCtx .withLoggerName (fmt .Sprintf ("event #%s" , name ))
74
+ applyEventPair (stepCtx , event )
75
+ }
76
+ }
77
+
78
+ // lookupEvent is the opposite of flatten: it takes an index
79
+ // after flattening and maps it back to the event in the original
80
+ // event hierarchy. To do so, it descends into the second level where necessary.
81
+ func lookupEvent (events []any , index int ) (any , string ) {
82
+ numEvents := 0
83
+ for i := range events {
84
+ if e , ok := events [i ].([]any ); ok {
85
+ for j := range e {
86
+ if numEvents == index {
87
+ return e [j ], fmt .Sprintf ("%d/%d" , i , j )
88
+ }
89
+ numEvents ++
76
90
}
77
- default :
78
- applyEventPair (tCtx , event )
91
+ } else {
92
+ if numEvents == index {
93
+ return events [i ], fmt .Sprintf ("%d" , i )
94
+ }
95
+ numEvents ++
79
96
}
80
97
}
98
+ panic (fmt .Sprintf ("invalid event index #%d" , index ))
81
99
}
82
100
83
101
func applyEventPair (tCtx * testContext , event any ) {
@@ -140,6 +158,18 @@ type testContext struct {
140
158
* fake.Clientset
141
159
}
142
160
161
+ func (t * testContext ) withLoggerName (name string ) * testContext {
162
+ logger := klog .FromContext (t .Context )
163
+ logger = klog .LoggerWithName (logger , name )
164
+ t = & testContext {
165
+ T : t .T ,
166
+ Context : klog .NewContext (t .Context , logger ),
167
+ Tracker : t .Tracker ,
168
+ Clientset : t .Clientset ,
169
+ }
170
+ return t
171
+ }
172
+
143
173
var (
144
174
now , _ = time .Parse (time .RFC3339 , "2006-01-02T15:04:05Z" )
145
175
driver1 = "driver1.example.com"
@@ -335,6 +365,11 @@ func TestListPatchedResourceSlices(t *testing.T) {
335
365
// the order in those nested lists is preserved.
336
366
events []any
337
367
expectedPatchedSlices []* resourceapi.ResourceSlice
368
+ // The exact events that are emitted for a sequence of events is
369
+ // highly dependent on the order in which those events are received.
370
+ // We punt on determining a set of validation criteria for every
371
+ // possible sequence and only check them against the first
372
+ // permutation: the order in which the events are defined.
338
373
expectedHandlerEvents []handlerEvent
339
374
expectEvents func (t * assert.CollectT , events * v1.EventList )
340
375
expectUnhandledErrors func (t * testing.T , errs []error )
@@ -643,7 +678,15 @@ func TestListPatchedResourceSlices(t *testing.T) {
643
678
}
644
679
}
645
680
646
- testHandlers := func (tCtx * testContext , test test , testExpectedEmittedEvents bool ) {
681
+ testHandlers := func (tCtx * testContext , test test , permutation []int ) {
682
+ isPermutated := false
683
+ for i , j := range permutation {
684
+ if i != j {
685
+ isPermutated = true
686
+ break
687
+ }
688
+ }
689
+
647
690
var handlerEvents []handlerEvent
648
691
handler := cache.ResourceEventHandlerFuncs {
649
692
AddFunc : func (obj interface {}) {
@@ -663,9 +706,9 @@ func TestListPatchedResourceSlices(t *testing.T) {
663
706
unhandledErrors = append (unhandledErrors , err )
664
707
}
665
708
666
- runInputEvents (tCtx , test .events )
709
+ runInputEvents (tCtx , test .events , permutation )
667
710
668
- if testExpectedEmittedEvents {
711
+ if ! isPermutated {
669
712
assert .Equal (tCtx , test .expectedHandlerEvents , handlerEvents )
670
713
}
671
714
@@ -709,60 +752,47 @@ func TestListPatchedResourceSlices(t *testing.T) {
709
752
710
753
for name , tc := range tests {
711
754
t .Run (name , func (t * testing.T ) {
712
- // The exact events that are emitted for a sequence of events is
713
- // highly dependent on the order in which those events are received.
714
- // We punt on determining a set of validation criteria for every
715
- // possible sequence and only check them against the first
716
- // permutation: the order in which the events are defined.
717
- testExpectedEmittedEvents := true
718
-
719
- numEvents := len (tc .events )
720
- if numEvents <= 1 {
721
- // No permutations.
722
- tContext := setup (t )
723
- testHandlers (tContext , tc , testExpectedEmittedEvents )
724
- return
725
- }
726
-
727
- // flatten does one level of flattening of events. It also returns
728
- // another slice of pairs of indices representing ranges which were
729
- // flattened.
730
- flatten := func (events []any ) ([]any , [][2 ]int ) {
731
- var ret []any
755
+ // flatten does one level of flattening of events, counting all events.
756
+ // It also returns a slice of pairs of indices representing ranges which were
757
+ // flattened (= came from the second level) and which therefore must
758
+ // remain in that order.
759
+ flatten := func (events []any ) (int , [][2 ]int ) {
760
+ numEvents := 0
732
761
var ranges [][2 ]int
733
762
for _ , e := range events {
734
763
switch e := e .(type ) {
735
764
case []any :
736
- ranges = append (ranges , [2 ]int {len ( ret ), len ( ret ) + len (e )})
737
- ret = append ( ret , e ... )
765
+ ranges = append (ranges , [2 ]int {numEvents , numEvents + len (e )})
766
+ numEvents += len ( e )
738
767
default :
739
- ret = append ( ret , e )
768
+ numEvents ++
740
769
}
741
770
}
742
- return ret , ranges
771
+ return numEvents , ranges
743
772
}
773
+ numEvents , constraints := flatten (tc .events )
744
774
745
- var constraints [][2 ]int
746
- tc .events , constraints = flatten (tc .events )
747
- numEvents = len (tc .events )
775
+ if len (tc .events ) <= 1 {
776
+ // No permutations possible.
777
+ var permutation []int
778
+ for i := 0 ; i < numEvents ; i ++ {
779
+ permutation = append (permutation , i )
780
+ }
781
+ tContext := setup (t )
782
+ testHandlers (tContext , tc , permutation )
783
+ return
784
+ }
748
785
749
786
permutation := make ([]int , numEvents )
750
787
var permutate func (depth int )
751
788
permutate = func (depth int ) {
752
789
if depth >= numEvents {
753
790
// Define a sub-test which runs the current permutation of events.
754
- events := make ([]any , numEvents )
755
- for i := range numEvents {
756
- events [i ] = tc.events [permutation [i ]]
757
- }
758
- tc := tc
759
- tc .events = events
760
791
name := strings .Trim (fmt .Sprintf ("%v" , permutation ), "[]" )
761
792
t .Run (name , func (t * testing.T ) {
762
793
tContext := setup (t )
763
- testHandlers (tContext , tc , testExpectedEmittedEvents )
764
-
765
- testExpectedEmittedEvents = false
794
+ // No need to clone the slice, we don't run in parallel.
795
+ testHandlers (tContext , tc , permutation )
766
796
})
767
797
return
768
798
}
@@ -778,10 +808,13 @@ func TestListPatchedResourceSlices(t *testing.T) {
778
808
}
779
809
for j := i + 1 ; j < constraint [1 ]; j ++ {
780
810
if slices .Contains (permutation [0 :depth ], j ) {
811
+ // Invalid permutation, would change order
812
+ // of sub-events.
781
813
continue nexti
782
814
}
783
815
}
784
816
}
817
+
785
818
// Pick it for the current position in permutation,
786
819
// continue with next position.
787
820
permutation [depth ] = i
0 commit comments