1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package swag
16
17 import (
18 "net/http"
19 "net/http/httptest"
20 "runtime"
21 "testing"
22
23 "github.com/stretchr/testify/assert"
24 "github.com/stretchr/testify/require"
25 )
26
27 const (
28 validUsername = "fake-user"
29 validPassword = "correct-password"
30 invalidPassword = "incorrect-password"
31 sharedHeaderKey = "X-Myapp"
32 sharedHeaderValue = "MySecretKey"
33 )
34
35 func TestLoadFromHTTP(t *testing.T) {
36 _, err := LoadFromFileOrHTTP("httx://12394:abd")
37 require.Error(t, err)
38
39 serv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
40 rw.WriteHeader(http.StatusNotFound)
41 }))
42 defer serv.Close()
43
44 _, err = LoadFromFileOrHTTP(serv.URL)
45 require.Error(t, err)
46
47 ts2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
48 rw.WriteHeader(http.StatusOK)
49 _, _ = rw.Write([]byte("the content"))
50 }))
51 defer ts2.Close()
52
53 d, err := LoadFromFileOrHTTP(ts2.URL)
54 require.NoError(t, err)
55 assert.Equal(t, []byte("the content"), d)
56
57 ts3 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
58 u, p, ok := r.BasicAuth()
59 if ok && u == validUsername && p == validPassword {
60 rw.WriteHeader(http.StatusOK)
61 } else {
62 rw.WriteHeader(http.StatusForbidden)
63 }
64 }))
65 defer ts3.Close()
66
67
68 _, err = LoadFromFileOrHTTP(ts3.URL)
69 require.Error(t, err)
70
71
72 LoadHTTPBasicAuthUsername = validUsername
73 LoadHTTPBasicAuthPassword = invalidPassword
74
75 _, err = LoadFromFileOrHTTP(ts3.URL)
76 require.Error(t, err)
77
78
79 LoadHTTPBasicAuthUsername = validUsername
80 LoadHTTPBasicAuthPassword = validPassword
81
82 _, err = LoadFromFileOrHTTP(ts3.URL)
83 require.NoError(t, err)
84
85 ts4 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
86 myHeaders := r.Header[sharedHeaderKey]
87 ok := false
88 for _, v := range myHeaders {
89 if v == sharedHeaderValue {
90 ok = true
91 break
92 }
93 }
94 if ok {
95 rw.WriteHeader(http.StatusOK)
96 } else {
97 rw.WriteHeader(http.StatusForbidden)
98 }
99 }))
100 defer ts4.Close()
101
102 _, err = LoadFromFileOrHTTP(ts4.URL)
103 require.Error(t, err)
104
105 LoadHTTPCustomHeaders[sharedHeaderKey] = sharedHeaderValue
106
107 _, err = LoadFromFileOrHTTP(ts4.URL)
108 require.NoError(t, err)
109
110
111 LoadHTTPBasicAuthUsername = ""
112 LoadHTTPBasicAuthPassword = ""
113 LoadHTTPCustomHeaders = map[string]string{}
114 }
115
116 func TestLoadHTTPBytes(t *testing.T) {
117 _, err := LoadFromFileOrHTTP("httx://12394:abd")
118 require.Error(t, err)
119
120 serv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
121 rw.WriteHeader(http.StatusNotFound)
122 }))
123 defer serv.Close()
124
125 _, err = LoadFromFileOrHTTP(serv.URL)
126 require.Error(t, err)
127
128 ts2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
129 rw.WriteHeader(http.StatusOK)
130 _, _ = rw.Write([]byte("the content"))
131 }))
132 defer ts2.Close()
133
134 d, err := LoadFromFileOrHTTP(ts2.URL)
135 require.NoError(t, err)
136 assert.Equal(t, []byte("the content"), d)
137 }
138
139 func TestLoadStrategy(t *testing.T) {
140 loader := func(_ string) ([]byte, error) {
141 return []byte(yamlPetStore), nil
142 }
143 remLoader := func(_ string) ([]byte, error) {
144 return []byte("not it"), nil
145 }
146
147 ld := LoadStrategy("blah", loader, remLoader)
148 b, _ := ld("")
149 assert.Equal(t, []byte(yamlPetStore), b)
150
151 serv := httptest.NewServer(http.HandlerFunc(yamlPestoreServer))
152 defer serv.Close()
153
154 s, err := YAMLDoc(serv.URL)
155 require.NoError(t, err)
156 require.NotNil(t, s)
157
158 ts2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
159 rw.WriteHeader(http.StatusNotFound)
160 _, _ = rw.Write([]byte("\n"))
161 }))
162 defer ts2.Close()
163 _, err = YAMLDoc(ts2.URL)
164 require.Error(t, err)
165 }
166
167 func TestLoadStrategyFile(t *testing.T) {
168 const (
169 thisIsIt = "thisIsIt"
170 thisIsNotIt = "not it"
171 )
172
173 type strategyTest struct {
174 Title string
175 Path string
176 Expected string
177 ExpectedWindows string
178 ExpectError bool
179 }
180
181 t.Run("with local file strategy", func(t *testing.T) {
182 loader := func(called *bool, pth *string) func(string) ([]byte, error) {
183 return func(p string) ([]byte, error) {
184 *called = true
185 *pth = p
186 return []byte(thisIsIt), nil
187 }
188 }
189
190 remLoader := func(_ string) ([]byte, error) {
191 return []byte(thisIsNotIt), nil
192 }
193
194 for _, toPin := range []strategyTest{
195 {
196 Title: "valid fully qualified local URI, with rooted path",
197 Path: "file:///a/c/myfile.yaml",
198 Expected: "/a/c/myfile.yaml",
199 ExpectedWindows: `\a\c\myfile.yaml`,
200 },
201 {
202 Title: "local URI with scheme, with host segment before path",
203 Path: "file://a/c/myfile.yaml",
204 Expected: "a/c/myfile.yaml",
205 ExpectedWindows: `\\a\c\myfile.yaml`,
206 },
207 {
208 Title: "local URI with scheme, with escaped characters",
209 Path: "file://a/c/myfile%20%28x86%29.yaml",
210 Expected: "a/c/myfile (x86).yaml",
211 ExpectedWindows: `\\a\c\myfile (x86).yaml`,
212 },
213 {
214 Title: "local URI with scheme, rooted, with escaped characters",
215 Path: "file:///a/c/myfile%20%28x86%29.yaml",
216 Expected: "/a/c/myfile (x86).yaml",
217 ExpectedWindows: `\a\c\myfile (x86).yaml`,
218 },
219 {
220 Title: "local URI with scheme, unescaped, with host",
221 Path: "file://a/c/myfile (x86).yaml",
222 Expected: "a/c/myfile (x86).yaml",
223 ExpectedWindows: `\\a\c\myfile (x86).yaml`,
224 },
225 {
226 Title: "local URI with scheme, rooted, unescaped",
227 Path: "file:///a/c/myfile (x86).yaml",
228 Expected: "/a/c/myfile (x86).yaml",
229 ExpectedWindows: `\a\c\myfile (x86).yaml`,
230 },
231 {
232 Title: "file URI with drive letter and backslashes, as a relative Windows path",
233 Path: `file://C:\a\c\myfile.yaml`,
234 Expected: `C:\a\c\myfile.yaml`,
235 },
236 {
237 Title: "file URI with drive letter and backslashes, as a rooted Windows path",
238 Path: `file:///C:\a\c\myfile.yaml`,
239 Expected: `/C:\a\c\myfile.yaml`,
240 ExpectedWindows: `C:\a\c\myfile.yaml`,
241 },
242 {
243 Title: "file URI with escaped backslashes",
244 Path: `file://C%3A%5Ca%5Cc%5Cmyfile.yaml`,
245 Expected: `C:\a\c\myfile.yaml`,
246 },
247 {
248 Title: "file URI with escaped backslashes, rooted",
249 Path: `file:///C%3A%5Ca%5Cc%5Cmyfile.yaml`,
250 Expected: `/C:\a\c\myfile.yaml`,
251 ExpectedWindows: `C:\a\c\myfile.yaml`,
252 },
253 {
254 Title: "URI with the file scheme, host omitted: relative path with extra dots",
255 Path: `file://./a/c/d/../myfile.yaml`,
256 Expected: `./a/c/d/../myfile.yaml`,
257 ExpectedWindows: `a\c\myfile.yaml`,
258 },
259 {
260 Title: "relative URI without the file scheme, rooted path",
261 Path: `/a/c/myfile.yaml`,
262 Expected: `/a/c/myfile.yaml`,
263 ExpectedWindows: `\a\c\myfile.yaml`,
264 },
265 {
266 Title: "relative URI without the file scheme, relative path",
267 Path: `a/c/myfile.yaml`,
268 Expected: `a/c/myfile.yaml`,
269 ExpectedWindows: `a\c\myfile.yaml`,
270 },
271 {
272 Title: "relative URI without the file scheme, relative path with dots",
273 Path: `./a/c/myfile.yaml`,
274 Expected: `./a/c/myfile.yaml`,
275 ExpectedWindows: `.\a\c\myfile.yaml`,
276 },
277 {
278 Title: "relative URI without the file scheme, relative path with extra dots",
279 Path: `./a/c/../myfile.yaml`,
280 Expected: `./a/c/../myfile.yaml`,
281 ExpectedWindows: `.\a\c\..\myfile.yaml`,
282 },
283 {
284 Title: "relative URI without the file scheme, windows slashed-path with drive letter",
285 Path: `A:/a/c/myfile.yaml`,
286 Expected: `A:/a/c/myfile.yaml`,
287 ExpectedWindows: `A:\a\c\myfile.yaml`,
288 },
289 {
290 Title: "relative URI without the file scheme, windows backslashed-path with drive letter",
291 Path: `A:\a\c\myfile.yaml`,
292 Expected: `A:\a\c\myfile.yaml`,
293 ExpectedWindows: `A:\a\c\myfile.yaml`,
294 },
295 {
296 Title: "URI with file scheme, host as Windows UNC name",
297 Path: `file://host/share/folder/myfile.yaml`,
298 Expected: `host/share/folder/myfile.yaml`,
299 ExpectedWindows: `\\host\share\folder\myfile.yaml`,
300 },
301
302 } {
303 tc := toPin
304 t.Run(tc.Title, func(t *testing.T) {
305 var (
306 called bool
307 pth string
308 )
309
310 ld := LoadStrategy("local", loader(&called, &pth), remLoader)
311 b, err := ld(tc.Path)
312 if tc.ExpectError {
313 require.Error(t, err)
314 assert.True(t, called)
315
316 return
317 }
318
319 require.NoError(t, err)
320 assert.True(t, called)
321 assert.Equal(t, []byte(thisIsIt), b)
322
323 if tc.ExpectedWindows != "" && runtime.GOOS == "windows" {
324 assert.Equalf(t, tc.ExpectedWindows, pth,
325 "expected local LoadStrategy(%q) to open: %q (windows)",
326 tc.Path, tc.ExpectedWindows,
327 )
328
329 return
330 }
331
332 assert.Equalf(t, tc.Expected, pth,
333 "expected local LoadStrategy(%q) to open: %q (any OS)",
334 tc.Path, tc.Expected,
335 )
336 })
337 }
338 })
339 }
340
View as plain text