1
16
17 package validation
18
19 import (
20 "testing"
21
22 "k8s.io/apimachinery/pkg/apis/meta/internalversion"
23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24 )
25
26 func TestValidateListOptions(t *testing.T) {
27 boolPtrFn := func(b bool) *bool {
28 return &b
29 }
30
31 cases := []struct {
32 name string
33 opts internalversion.ListOptions
34 watchListFeatureEnabled bool
35 expectErrors []string
36 }{{
37 name: "valid-default",
38 opts: internalversion.ListOptions{},
39 }, {
40 name: "valid-resourceversionmatch-exact",
41 opts: internalversion.ListOptions{
42 ResourceVersion: "1",
43 ResourceVersionMatch: metav1.ResourceVersionMatchExact,
44 },
45 }, {
46 name: "invalid-resourceversionmatch-exact",
47 opts: internalversion.ListOptions{
48 ResourceVersion: "0",
49 ResourceVersionMatch: metav1.ResourceVersionMatchExact,
50 },
51 expectErrors: []string{"resourceVersionMatch: Forbidden: resourceVersionMatch \"exact\" is forbidden for resourceVersion \"0\""},
52 }, {
53 name: "valid-resourceversionmatch-notolderthan",
54 opts: internalversion.ListOptions{
55 ResourceVersion: "0",
56 ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
57 },
58 }, {
59 name: "invalid-resourceversionmatch",
60 opts: internalversion.ListOptions{
61 ResourceVersion: "0",
62 ResourceVersionMatch: "foo",
63 },
64 expectErrors: []string{"resourceVersionMatch: Unsupported value: \"foo\": supported values: \"Exact\", \"NotOlderThan\", \"\""},
65 }, {
66 name: "list-sendInitialEvents-forbidden",
67 opts: internalversion.ListOptions{
68 SendInitialEvents: boolPtrFn(true),
69 },
70 expectErrors: []string{"sendInitialEvents: Forbidden: sendInitialEvents is forbidden for list"},
71 }, {
72 name: "valid-watch-default",
73 opts: internalversion.ListOptions{
74 Watch: true,
75 },
76 }, {
77 name: "valid-watch-sendInitialEvents-on",
78 opts: internalversion.ListOptions{
79 Watch: true,
80 SendInitialEvents: boolPtrFn(true),
81 ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
82 AllowWatchBookmarks: true,
83 },
84 watchListFeatureEnabled: true,
85 }, {
86 name: "valid-watch-sendInitialEvents-off",
87 opts: internalversion.ListOptions{
88 Watch: true,
89 SendInitialEvents: boolPtrFn(false),
90 ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
91 AllowWatchBookmarks: true,
92 },
93 watchListFeatureEnabled: true,
94 }, {
95 name: "watch-resourceversionmatch-without-sendInitialEvents-forbidden",
96 opts: internalversion.ListOptions{
97 Watch: true,
98 ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
99 },
100 expectErrors: []string{"resourceVersionMatch: Forbidden: resourceVersionMatch is forbidden for watch unless sendInitialEvents is provided"},
101 }, {
102 name: "watch-sendInitialEvents-without-resourceversionmatch-forbidden",
103 opts: internalversion.ListOptions{
104 Watch: true,
105 SendInitialEvents: boolPtrFn(true),
106 },
107 expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
108 }, {
109 name: "watch-sendInitialEvents-with-exact-resourceversionmatch-forbidden",
110 opts: internalversion.ListOptions{
111 Watch: true,
112 SendInitialEvents: boolPtrFn(true),
113 ResourceVersionMatch: metav1.ResourceVersionMatchExact,
114 AllowWatchBookmarks: true,
115 },
116 watchListFeatureEnabled: true,
117 expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "resourceVersionMatch: Unsupported value: \"Exact\": supported values: \"NotOlderThan\""},
118 }, {
119 name: "watch-sendInitialEvents-on-with-empty-resourceversionmatch-forbidden",
120 opts: internalversion.ListOptions{
121 Watch: true,
122 SendInitialEvents: boolPtrFn(true),
123 ResourceVersionMatch: "",
124 },
125 expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
126 }, {
127 name: "watch-sendInitialEvents-off-with-empty-resourceversionmatch-forbidden",
128 opts: internalversion.ListOptions{
129 Watch: true,
130 SendInitialEvents: boolPtrFn(false),
131 ResourceVersionMatch: "",
132 },
133 expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
134 }, {
135 name: "watch-sendInitialEvents-with-incorrect-resourceversionmatch-forbidden",
136 opts: internalversion.ListOptions{
137 Watch: true,
138 SendInitialEvents: boolPtrFn(true),
139 ResourceVersionMatch: "incorrect",
140 AllowWatchBookmarks: true,
141 },
142 watchListFeatureEnabled: true,
143 expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "resourceVersionMatch: Unsupported value: \"incorrect\": supported values: \"NotOlderThan\""},
144 }, {
145
146
147 name: "watch-sendInitialEvents-no-allowWatchBookmark",
148 opts: internalversion.ListOptions{
149 Watch: true,
150 SendInitialEvents: boolPtrFn(true),
151 ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
152 },
153 watchListFeatureEnabled: true,
154 }, {
155 name: "watch-sendInitialEvents-no-watchlist-fg-disabled",
156 opts: internalversion.ListOptions{
157 Watch: true,
158 SendInitialEvents: boolPtrFn(true),
159 ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
160 AllowWatchBookmarks: true,
161 },
162 expectErrors: []string{"sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
163 }, {
164 name: "watch-sendInitialEvents-no-watchlist-fg-disabled",
165 opts: internalversion.ListOptions{
166 Watch: true,
167 SendInitialEvents: boolPtrFn(true),
168 ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
169 AllowWatchBookmarks: true,
170 Continue: "123",
171 },
172 watchListFeatureEnabled: true,
173 expectErrors: []string{"resourceVersionMatch: Forbidden: resourceVersionMatch is forbidden when continue is provided"},
174 }}
175
176 for _, tc := range cases {
177 t.Run(tc.name, func(t *testing.T) {
178 errs := ValidateListOptions(&tc.opts, tc.watchListFeatureEnabled)
179 if len(tc.expectErrors) > 0 {
180 if len(errs) != len(tc.expectErrors) {
181 t.Errorf("expected %d errors but got %d errors", len(tc.expectErrors), len(errs))
182 return
183 }
184 for i, expectedErr := range tc.expectErrors {
185 if expectedErr != errs[i].Error() {
186 t.Errorf("expected error '%s' but got '%s'", expectedErr, errs[i].Error())
187 }
188 }
189 return
190 }
191 if len(errs) != 0 {
192 t.Errorf("expected no errors, but got: %v", errs)
193 }
194 })
195 }
196 }
197
View as plain text