1
16
17 package resource
18
19 import (
20 "bytes"
21 "errors"
22 "fmt"
23 "io"
24 "io/fs"
25 "os"
26 "path/filepath"
27 "strings"
28 "testing"
29 "time"
30
31 "github.com/stretchr/testify/assert"
32 "k8s.io/apimachinery/pkg/util/dump"
33 )
34
35 func TestVisitorHttpGet(t *testing.T) {
36 type httpArgs struct {
37 duration time.Duration
38 u string
39 attempts int
40 }
41
42 i := 0
43 tests := []struct {
44 name string
45 httpRetries httpget
46 args httpArgs
47 expectedErr error
48 actualBytes io.ReadCloser
49 actualErr error
50 count int
51 isNotNil bool
52 }{
53 {
54 name: "Test retries on errors",
55 httpRetries: func(url string) (int, string, io.ReadCloser, error) {
56 assert.Equal(t, "hello", url)
57 i++
58 if i > 2 {
59 return 0, "", nil, fmt.Errorf("Failed to get http")
60 }
61 return 0, "", nil, fmt.Errorf("Unexpected error")
62
63 },
64 expectedErr: fmt.Errorf("Failed to get http"),
65 args: httpArgs{
66 duration: 0,
67 u: "hello",
68 attempts: 3,
69 },
70 count: 3,
71 },
72 {
73 name: "Test that 500s are retried",
74 httpRetries: func(url string) (int, string, io.ReadCloser, error) {
75 assert.Equal(t, "hello", url)
76 i++
77 return 501, "Status", io.NopCloser(new(bytes.Buffer)), nil
78 },
79 args: httpArgs{
80 duration: 0,
81 u: "hello",
82 attempts: 3,
83 },
84 count: 3,
85 },
86 {
87 name: "Test that 300s are not retried",
88 httpRetries: func(url string) (int, string, io.ReadCloser, error) {
89 assert.Equal(t, "hello", url)
90 i++
91 return 300, "Status", io.NopCloser(new(bytes.Buffer)), nil
92
93 },
94 args: httpArgs{
95 duration: 0,
96 u: "hello",
97 attempts: 3,
98 },
99 count: 1,
100 },
101 {
102 name: "Test attempt count is respected",
103 httpRetries: func(url string) (int, string, io.ReadCloser, error) {
104 assert.Equal(t, "hello", url)
105 i++
106 return 501, "Status", io.NopCloser(new(bytes.Buffer)), nil
107
108 },
109 args: httpArgs{
110 duration: 0,
111 u: "hello",
112 attempts: 1,
113 },
114 count: 1,
115 },
116 {
117 name: "Test attempts less than 1 results in an error",
118 httpRetries: func(url string) (int, string, io.ReadCloser, error) {
119 return 200, "Status", io.NopCloser(new(bytes.Buffer)), nil
120
121 },
122 args: httpArgs{
123 duration: 0,
124 u: "hello",
125 attempts: 0,
126 },
127 count: 0,
128 },
129 {
130 name: "Test Success",
131 httpRetries: func(url string) (int, string, io.ReadCloser, error) {
132 assert.Equal(t, "hello", url)
133 i++
134 if i > 1 {
135 return 200, "Status", io.NopCloser(new(bytes.Buffer)), nil
136 }
137 return 501, "Status", io.NopCloser(new(bytes.Buffer)), nil
138
139 },
140 args: httpArgs{
141 duration: 0,
142 u: "hello",
143 attempts: 3,
144 },
145 count: 2,
146 isNotNil: true,
147 },
148 }
149
150 for _, tt := range tests {
151 t.Run(tt.name, func(t *testing.T) {
152 i = 0
153 actualBytes, actualErr := readHttpWithRetries(tt.httpRetries, tt.args.duration, tt.args.u, tt.args.attempts)
154
155 if tt.isNotNil {
156 assert.Nil(t, actualErr)
157 assert.NotNil(t, actualBytes)
158 } else {
159 if tt.expectedErr != nil {
160 assert.Equal(t, tt.expectedErr, actualErr)
161 } else {
162 assert.Error(t, actualErr)
163 }
164 assert.Nil(t, actualBytes)
165 }
166
167 assert.Equal(t, tt.count, i)
168 })
169 }
170 }
171
172 func TestFlattenListVisitor(t *testing.T) {
173 b := newDefaultBuilder().
174 FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../artifacts/deeply-nested.yaml"}}).
175 Flatten()
176
177 test := &testVisitor{}
178
179 err := b.Do().Visit(test.Handle)
180 if err != nil {
181 t.Fatal(err)
182 }
183 if len(test.Infos) != 6 {
184 t.Fatal(dump.Pretty(test.Infos))
185 }
186 }
187
188 func TestFlattenListVisitorWithVisitorError(t *testing.T) {
189 b := newDefaultBuilder().
190 FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../artifacts/deeply-nested.yaml"}}).
191 Flatten()
192
193 test := &testVisitor{InjectErr: errors.New("visitor error")}
194 err := b.Do().Visit(test.Handle)
195 if err == nil || !strings.Contains(err.Error(), "visitor error") {
196 t.Fatal(err)
197 }
198 if len(test.Infos) != 6 {
199 t.Fatal(dump.Pretty(test.Infos))
200 }
201 }
202
203 func TestExpandPathsToFileVisitors(t *testing.T) {
204
205 testDir := t.TempDir()
206 filePaths := []string{
207 filepath.Join(testDir, "0", "10.yaml"),
208 filepath.Join(testDir, "0", "a", "10.yaml"),
209 filepath.Join(testDir, "02.yaml"),
210 filepath.Join(testDir, "10.yaml"),
211 filepath.Join(testDir, "2.yaml"),
212 filepath.Join(testDir, "AB.yaml"),
213 filepath.Join(testDir, "a", "a.yaml"),
214 filepath.Join(testDir, "a", "b.json"),
215 filepath.Join(testDir, "a.yaml"),
216 filepath.Join(testDir, "aa.yaml"),
217 filepath.Join(testDir, "b.yml"),
218 }
219 for _, fp := range filePaths {
220 if err := os.MkdirAll(filepath.Dir(fp), 0700); err != nil {
221 t.Fatal(err)
222 }
223 func() {
224 f, err := os.Create(fp)
225 if err != nil {
226 t.Fatal(err)
227 }
228 defer f.Close()
229 }()
230 }
231
232
233 tests := []struct {
234 name string
235 path string
236 recursive bool
237 fileExtensions []string
238 expectedPaths []string
239 expectPathError bool
240 }{
241 {
242 name: "Recursive with default file extensions",
243 path: testDir,
244 recursive: true,
245 fileExtensions: FileExtensions,
246 expectedPaths: []string{
247 filepath.Join(testDir, "0", "10.yaml"),
248 filepath.Join(testDir, "0", "a", "10.yaml"),
249 filepath.Join(testDir, "02.yaml"),
250 filepath.Join(testDir, "10.yaml"),
251 filepath.Join(testDir, "2.yaml"),
252 filepath.Join(testDir, "AB.yaml"),
253 filepath.Join(testDir, "a", "a.yaml"),
254 filepath.Join(testDir, "a", "b.json"),
255 filepath.Join(testDir, "a.yaml"),
256 filepath.Join(testDir, "aa.yaml"),
257 filepath.Join(testDir, "b.yml"),
258 },
259 },
260 {
261 name: "Non-recursive with default file extensions",
262 path: testDir,
263 fileExtensions: FileExtensions,
264 expectedPaths: []string{
265 filepath.Join(testDir, "02.yaml"),
266 filepath.Join(testDir, "10.yaml"),
267 filepath.Join(testDir, "2.yaml"),
268 filepath.Join(testDir, "AB.yaml"),
269 filepath.Join(testDir, "a.yaml"),
270 filepath.Join(testDir, "aa.yaml"),
271 filepath.Join(testDir, "b.yml"),
272 },
273 },
274 {
275 name: "Recursive with yaml file extension",
276 path: testDir,
277 recursive: true,
278 fileExtensions: []string{".yaml"},
279 expectedPaths: []string{
280 filepath.Join(testDir, "0", "10.yaml"),
281 filepath.Join(testDir, "0", "a", "10.yaml"),
282 filepath.Join(testDir, "02.yaml"),
283 filepath.Join(testDir, "10.yaml"),
284 filepath.Join(testDir, "2.yaml"),
285 filepath.Join(testDir, "AB.yaml"),
286 filepath.Join(testDir, "a", "a.yaml"),
287 filepath.Join(testDir, "a.yaml"),
288 filepath.Join(testDir, "aa.yaml"),
289 },
290 },
291 {
292 name: "Recursive with json and yml file extensions",
293 path: testDir,
294 recursive: true,
295 fileExtensions: []string{".json", ".yml"},
296 expectedPaths: []string{
297 filepath.Join(testDir, "a", "b.json"),
298 filepath.Join(testDir, "b.yml"),
299 },
300 },
301 {
302 name: "Non-recursive with json and yml file extensions",
303 path: testDir,
304 fileExtensions: []string{".json", ".yml"},
305 expectedPaths: []string{
306 filepath.Join(testDir, "b.yml"),
307 },
308 },
309 {
310 name: "Non-existent file extensions should return nothing",
311 path: testDir,
312 recursive: true,
313 fileExtensions: []string{".foo"},
314 expectedPaths: []string{},
315 },
316 {
317 name: "Non-existent path should return file not found error",
318 path: filepath.Join(testDir, "does", "not", "exist"),
319 recursive: true,
320 fileExtensions: []string{".foo"},
321 expectedPaths: []string{},
322 expectPathError: true,
323 },
324 {
325 name: "Visitor for single file is returned even if extension does not match",
326 path: filepath.Join(testDir, "a.yaml"),
327 recursive: true,
328 fileExtensions: []string{"foo"},
329 expectedPaths: []string{
330 filepath.Join(testDir, "a.yaml"),
331 },
332 },
333 }
334
335 for _, tt := range tests {
336 t.Run(tt.name, func(t *testing.T) {
337 visitors, err := ExpandPathsToFileVisitors(nil, tt.path, tt.recursive, tt.fileExtensions, nil)
338 if err != nil {
339 switch e := err.(type) {
340 case *fs.PathError:
341 if tt.expectPathError {
342
343 assert.Equal(t, tt.path, e.Path)
344 return
345 }
346 }
347 t.Fatal(err)
348 }
349
350 actualPaths := []string{}
351 for _, v := range visitors {
352 actualPaths = append(actualPaths, v.(*FileVisitor).Path)
353 }
354 assert.Equal(t, tt.expectedPaths, actualPaths)
355 })
356 }
357 }
358
View as plain text