Source file
src/k8s.io/client-go/tools/cache/reflector_data_consistency_detector_test.go
1
16
17 package cache
18
19 import (
20 "fmt"
21 "testing"
22
23 "github.com/stretchr/testify/require"
24
25 v1 "k8s.io/api/core/v1"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/apimachinery/pkg/watch"
29 )
30
31 func TestWatchListConsistency(t *testing.T) {
32 scenarios := []struct {
33 name string
34
35 podList *v1.PodList
36 storeContent []*v1.Pod
37
38 expectedRequestOptions []metav1.ListOptions
39 expectedListRequests int
40 expectPanic bool
41 }{
42 {
43 name: "watchlist consistency check won't panic when data is consistent",
44 podList: &v1.PodList{
45 ListMeta: metav1.ListMeta{ResourceVersion: "2"},
46 Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2")},
47 },
48 storeContent: []*v1.Pod{makePod("p1", "1"), makePod("p2", "2")},
49 expectedListRequests: 1,
50 expectedRequestOptions: []metav1.ListOptions{
51 {
52 ResourceVersion: "2",
53 ResourceVersionMatch: metav1.ResourceVersionMatchExact,
54 },
55 },
56 },
57
58 {
59 name: "watchlist consistency check won't panic when there is no data",
60 podList: &v1.PodList{
61 ListMeta: metav1.ListMeta{ResourceVersion: "2"},
62 },
63 expectedListRequests: 1,
64 expectedRequestOptions: []metav1.ListOptions{
65 {
66 ResourceVersion: "2",
67 ResourceVersionMatch: metav1.ResourceVersionMatchExact,
68 },
69 },
70 },
71
72 {
73 name: "watchlist consistency panics when data is inconsistent",
74 podList: &v1.PodList{
75 ListMeta: metav1.ListMeta{ResourceVersion: "2"},
76 Items: []v1.Pod{*makePod("p1", "1"), *makePod("p2", "2"), *makePod("p3", "3")},
77 },
78 storeContent: []*v1.Pod{makePod("p1", "1"), makePod("p2", "2")},
79 expectedListRequests: 1,
80 expectedRequestOptions: []metav1.ListOptions{
81 {
82 ResourceVersion: "2",
83 ResourceVersionMatch: metav1.ResourceVersionMatchExact,
84 },
85 },
86 expectPanic: true,
87 },
88 }
89
90 for _, scenario := range scenarios {
91 t.Run(scenario.name, func(t *testing.T) {
92 listWatcher, store, _, stopCh := testData()
93 for _, obj := range scenario.storeContent {
94 require.NoError(t, store.Add(obj))
95 }
96 listWatcher.customListResponse = scenario.podList
97
98 if scenario.expectPanic {
99 require.Panics(t, func() { checkWatchListConsistency(stopCh, "", scenario.podList.ResourceVersion, listWatcher, store) })
100 } else {
101 checkWatchListConsistency(stopCh, "", scenario.podList.ResourceVersion, listWatcher, store)
102 }
103
104 verifyListCounter(t, listWatcher, scenario.expectedListRequests)
105 verifyRequestOptions(t, listWatcher, scenario.expectedRequestOptions)
106 })
107 }
108 }
109
110 func TestDriveWatchLisConsistencyIfRequired(t *testing.T) {
111 stopCh := make(chan struct{})
112 defer close(stopCh)
113 checkWatchListConsistencyIfRequested(stopCh, "", "", nil, nil)
114 }
115
116 func TestWatchListConsistencyRetry(t *testing.T) {
117 store := NewStore(MetaNamespaceKeyFunc)
118 stopCh := make(chan struct{})
119 defer close(stopCh)
120
121 stopListErrorAfter := 5
122 errLister := &errorLister{stopErrorAfter: stopListErrorAfter}
123
124 checkWatchListConsistency(stopCh, "", "", errLister, store)
125 require.Equal(t, errLister.listCounter, errLister.stopErrorAfter)
126 }
127
128 type errorLister struct {
129 listCounter int
130 stopErrorAfter int
131 }
132
133 func (lw *errorLister) List(_ metav1.ListOptions) (runtime.Object, error) {
134 lw.listCounter++
135 if lw.listCounter == lw.stopErrorAfter {
136 return &v1.PodList{}, nil
137 }
138 return nil, fmt.Errorf("nasty error")
139 }
140
141 func (lw *errorLister) Watch(_ metav1.ListOptions) (watch.Interface, error) {
142 panic("not implemented")
143 }
144
View as plain text