1
2
3
4
5 package module
6
7 import "testing"
8
9 var checkTests = []struct {
10 path string
11 version string
12 ok bool
13 }{
14 {"rsc.io/quote", "0.1.0", false},
15 {"rsc io/quote", "v1.0.0", false},
16
17 {"github.com/go-yaml/yaml", "v0.8.0", true},
18 {"github.com/go-yaml/yaml", "v1.0.0", true},
19 {"github.com/go-yaml/yaml", "v2.0.0", false},
20 {"github.com/go-yaml/yaml", "v2.1.5", false},
21 {"github.com/go-yaml/yaml", "v3.0.0", false},
22
23 {"github.com/go-yaml/yaml/v2", "v1.0.0", false},
24 {"github.com/go-yaml/yaml/v2", "v2.0.0", true},
25 {"github.com/go-yaml/yaml/v2", "v2.1.5", true},
26 {"github.com/go-yaml/yaml/v2", "v3.0.0", false},
27
28 {"gopkg.in/yaml.v0", "v0.8.0", true},
29 {"gopkg.in/yaml.v0", "v1.0.0", false},
30 {"gopkg.in/yaml.v0", "v2.0.0", false},
31 {"gopkg.in/yaml.v0", "v2.1.5", false},
32 {"gopkg.in/yaml.v0", "v3.0.0", false},
33
34 {"gopkg.in/yaml.v1", "v0.8.0", false},
35 {"gopkg.in/yaml.v1", "v1.0.0", true},
36 {"gopkg.in/yaml.v1", "v2.0.0", false},
37 {"gopkg.in/yaml.v1", "v2.1.5", false},
38 {"gopkg.in/yaml.v1", "v3.0.0", false},
39
40
41
42
43
44
45 {"gopkg.in/check.v1", "v0.0.0", false},
46 {"gopkg.in/check.v1", "v0.0.0-20160102150405-abcdef123456", true},
47
48 {"gopkg.in/yaml.v2", "v1.0.0", false},
49 {"gopkg.in/yaml.v2", "v2.0.0", true},
50 {"gopkg.in/yaml.v2", "v2.1.5", true},
51 {"gopkg.in/yaml.v2", "v3.0.0", false},
52
53 {"rsc.io/quote", "v17.0.0", false},
54 {"rsc.io/quote", "v17.0.0+incompatible", true},
55 }
56
57 func TestCheck(t *testing.T) {
58 for _, tt := range checkTests {
59 err := Check(tt.path, tt.version)
60 if tt.ok && err != nil {
61 t.Errorf("Check(%q, %q) = %v, wanted nil error", tt.path, tt.version, err)
62 } else if !tt.ok && err == nil {
63 t.Errorf("Check(%q, %q) succeeded, wanted error", tt.path, tt.version)
64 }
65 }
66 }
67
68 var checkPathTests = []struct {
69 path string
70 ok bool
71 importOK bool
72 fileOK bool
73 }{
74 {"x.y/z", true, true, true},
75 {"x.y", true, true, true},
76
77 {"", false, false, false},
78 {"x.y/\xFFz", false, false, false},
79 {"/x.y/z", false, false, false},
80 {"x./z", false, false, false},
81 {".x/z", false, true, true},
82 {"-x/z", false, false, true},
83 {"x..y/z", true, true, true},
84 {"x.y/z/../../w", false, false, false},
85 {"x.y//z", false, false, false},
86 {"x.y/z//w", false, false, false},
87 {"x.y/z/", false, false, false},
88
89 {"x.y/z/v0", false, true, true},
90 {"x.y/z/v1", false, true, true},
91 {"x.y/z/v2", true, true, true},
92 {"x.y/z/v2.0", false, true, true},
93 {"X.y/z", false, true, true},
94
95 {"!x.y/z", false, false, true},
96 {"_x.y/z", false, true, true},
97 {"x.y!/z", false, false, true},
98 {"x.y\"/z", false, false, false},
99 {"x.y#/z", false, false, true},
100 {"x.y$/z", false, false, true},
101 {"x.y%/z", false, false, true},
102 {"x.y&/z", false, false, true},
103 {"x.y'/z", false, false, false},
104 {"x.y(/z", false, false, true},
105 {"x.y)/z", false, false, true},
106 {"x.y*/z", false, false, false},
107 {"x.y+/z", false, true, true},
108 {"x.y,/z", false, false, true},
109 {"x.y-/z", true, true, true},
110 {"x.y./zt", false, false, false},
111 {"x.y:/z", false, false, false},
112 {"x.y;/z", false, false, false},
113 {"x.y</z", false, false, false},
114 {"x.y=/z", false, false, true},
115 {"x.y>/z", false, false, false},
116 {"x.y?/z", false, false, false},
117 {"x.y@/z", false, false, true},
118 {"x.y[/z", false, false, true},
119 {"x.y\\/z", false, false, false},
120 {"x.y]/z", false, false, true},
121 {"x.y^/z", false, false, true},
122 {"x.y_/z", false, true, true},
123 {"x.y`/z", false, false, false},
124 {"x.y{/z", false, false, true},
125 {"x.y}/z", false, false, true},
126 {"x.y~/z", false, true, true},
127 {"x.y/z!", false, false, true},
128 {"x.y/z\"", false, false, false},
129 {"x.y/z#", false, false, true},
130 {"x.y/z$", false, false, true},
131 {"x.y/z%", false, false, true},
132 {"x.y/z&", false, false, true},
133 {"x.y/z'", false, false, false},
134 {"x.y/z(", false, false, true},
135 {"x.y/z)", false, false, true},
136 {"x.y/z*", false, false, false},
137 {"x.y/z++", false, true, true},
138 {"x.y/z,", false, false, true},
139 {"x.y/z-", true, true, true},
140 {"x.y/z.t", true, true, true},
141 {"x.y/z/t", true, true, true},
142 {"x.y/z:", false, false, false},
143 {"x.y/z;", false, false, false},
144 {"x.y/z<", false, false, false},
145 {"x.y/z=", false, false, true},
146 {"x.y/z>", false, false, false},
147 {"x.y/z?", false, false, false},
148 {"x.y/z@", false, false, true},
149 {"x.y/z[", false, false, true},
150 {"x.y/z\\", false, false, false},
151 {"x.y/z]", false, false, true},
152 {"x.y/z^", false, false, true},
153 {"x.y/z_", true, true, true},
154 {"x.y/z`", false, false, false},
155 {"x.y/z{", false, false, true},
156 {"x.y/z}", false, false, true},
157 {"x.y/z~", true, true, true},
158 {"x.y/x.foo", true, true, true},
159 {"x.y/aux.foo", false, false, false},
160 {"x.y/prn", false, false, false},
161 {"x.y/prn2", true, true, true},
162 {"x.y/com", true, true, true},
163 {"x.y/com1", false, false, false},
164 {"x.y/com1.txt", false, false, false},
165 {"x.y/calm1", true, true, true},
166 {"x.y/z~", true, true, true},
167 {"x.y/z~0", false, false, true},
168 {"x.y/z~09", false, false, true},
169 {"x.y/z09", true, true, true},
170 {"x.y/z09~", true, true, true},
171 {"x.y/z09~09z", true, true, true},
172 {"x.y/z09~09z~09", false, false, true},
173 {"github.com/!123/logrus", false, false, true},
174
175
176
177
178
179
180
181 {"github.com/user/unicode/испытание", false, false, true},
182
183 {"../x", false, false, false},
184 {"./y", false, false, false},
185 {"x:y", false, false, false},
186 {`\temp\foo`, false, false, false},
187 {".gitignore", false, true, true},
188 {".github/ISSUE_TEMPLATE", false, true, true},
189 {"x☺y", false, false, false},
190 }
191
192 func TestCheckPath(t *testing.T) {
193 for _, tt := range checkPathTests {
194 err := CheckPath(tt.path)
195 if tt.ok && err != nil {
196 t.Errorf("CheckPath(%q) = %v, wanted nil error", tt.path, err)
197 } else if !tt.ok && err == nil {
198 t.Errorf("CheckPath(%q) succeeded, wanted error", tt.path)
199 }
200
201 err = CheckImportPath(tt.path)
202 if tt.importOK && err != nil {
203 t.Errorf("CheckImportPath(%q) = %v, wanted nil error", tt.path, err)
204 } else if !tt.importOK && err == nil {
205 t.Errorf("CheckImportPath(%q) succeeded, wanted error", tt.path)
206 }
207
208 err = CheckFilePath(tt.path)
209 if tt.fileOK && err != nil {
210 t.Errorf("CheckFilePath(%q) = %v, wanted nil error", tt.path, err)
211 } else if !tt.fileOK && err == nil {
212 t.Errorf("CheckFilePath(%q) succeeded, wanted error", tt.path)
213 }
214 }
215 }
216
217 var splitPathVersionTests = []struct {
218 pathPrefix string
219 version string
220 }{
221 {"x.y/z", ""},
222 {"x.y/z", "/v2"},
223 {"x.y/z", "/v3"},
224 {"x.y/v", ""},
225 {"gopkg.in/yaml", ".v0"},
226 {"gopkg.in/yaml", ".v1"},
227 {"gopkg.in/yaml", ".v2"},
228 {"gopkg.in/yaml", ".v3"},
229 }
230
231 func TestSplitPathVersion(t *testing.T) {
232 for _, tt := range splitPathVersionTests {
233 pathPrefix, version, ok := SplitPathVersion(tt.pathPrefix + tt.version)
234 if pathPrefix != tt.pathPrefix || version != tt.version || !ok {
235 t.Errorf("SplitPathVersion(%q) = %q, %q, %v, want %q, %q, true", tt.pathPrefix+tt.version, pathPrefix, version, ok, tt.pathPrefix, tt.version)
236 }
237 }
238
239 for _, tt := range checkPathTests {
240 pathPrefix, version, ok := SplitPathVersion(tt.path)
241 if pathPrefix+version != tt.path {
242 t.Errorf("SplitPathVersion(%q) = %q, %q, %v, doesn't add to input", tt.path, pathPrefix, version, ok)
243 }
244 }
245 }
246
247 var escapeTests = []struct {
248 path string
249 esc string
250 }{
251 {path: "ascii.com/abcdefghijklmnopqrstuvwxyz.-/~_0123456789"},
252 {path: "github.com/GoogleCloudPlatform/omega", esc: "github.com/!google!cloud!platform/omega"},
253 }
254
255 func TestEscapePath(t *testing.T) {
256
257 for _, tt := range checkPathTests {
258 if !tt.ok {
259 _, err := EscapePath(tt.path)
260 if err == nil {
261 t.Errorf("EscapePath(%q): succeeded, want error (invalid path)", tt.path)
262 }
263 }
264 }
265
266
267 for _, tt := range escapeTests {
268 esc, err := EscapePath(tt.path)
269 if err != nil {
270 t.Errorf("EscapePath(%q): unexpected error: %v", tt.path, err)
271 continue
272 }
273 want := tt.esc
274 if want == "" {
275 want = tt.path
276 }
277 if esc != want {
278 t.Errorf("EscapePath(%q) = %q, want %q", tt.path, esc, want)
279 }
280 }
281 }
282
283 var badUnescape = []string{
284 "github.com/GoogleCloudPlatform/omega",
285 "github.com/!google!cloud!platform!/omega",
286 "github.com/!0google!cloud!platform/omega",
287 "github.com/!_google!cloud!platform/omega",
288 "github.com/!!google!cloud!platform/omega",
289 "",
290 }
291
292 func TestUnescapePath(t *testing.T) {
293
294 for _, bad := range badUnescape {
295 _, err := UnescapePath(bad)
296 if err == nil {
297 t.Errorf("UnescapePath(%q): succeeded, want error (invalid decoding)", bad)
298 }
299 }
300
301
302 for _, tt := range checkPathTests {
303 if !tt.ok {
304 path, err := UnescapePath(tt.path)
305 if err == nil {
306 t.Errorf("UnescapePath(%q) = %q, want error (invalid path)", tt.path, path)
307 }
308 }
309 }
310
311
312 for _, tt := range escapeTests {
313 esc := tt.esc
314 if esc == "" {
315 esc = tt.path
316 }
317 path, err := UnescapePath(esc)
318 if err != nil {
319 t.Errorf("UnescapePath(%q): unexpected error: %v", esc, err)
320 continue
321 }
322 if path != tt.path {
323 t.Errorf("UnescapePath(%q) = %q, want %q", esc, path, tt.path)
324 }
325 }
326 }
327
328 func TestMatchPathMajor(t *testing.T) {
329 for _, test := range []struct {
330 v, pathMajor string
331 want bool
332 }{
333 {"v0.0.0", "", true},
334 {"v0.0.0", "/v2", false},
335 {"v0.0.0", ".v0", true},
336 {"v0.0.0-20190510104115-cbcb75029529", ".v1", true},
337 {"v1.0.0", "/v2", false},
338 {"v1.0.0", ".v1", true},
339 {"v1.0.0", ".v1-unstable", true},
340 {"v2.0.0+incompatible", "", true},
341 {"v2.0.0", "", false},
342 {"v2.0.0", "/v2", true},
343 {"v2.0.0", ".v2", true},
344 } {
345 if got := MatchPathMajor(test.v, test.pathMajor); got != test.want {
346 t.Errorf("MatchPathMajor(%q, %q) = %v, want %v", test.v, test.pathMajor, got, test.want)
347 }
348 }
349 }
350
351 func TestMatchPrefixPatterns(t *testing.T) {
352 for _, test := range []struct {
353 globs, target string
354 want bool
355 }{
356 {"", "rsc.io/quote", false},
357 {"/", "rsc.io/quote", false},
358 {"*/quote", "rsc.io/quote", true},
359 {"*/quo", "rsc.io/quote", false},
360 {"*/quo??", "rsc.io/quote", true},
361 {"*/quo*", "rsc.io/quote", true},
362 {"*quo*", "rsc.io/quote", false},
363 {"rsc.io", "rsc.io/quote", true},
364 {"*.io", "rsc.io/quote", true},
365 {"rsc.io/", "rsc.io/quote", true},
366 {"rsc", "rsc.io/quote", false},
367 {"rsc*", "rsc.io/quote", true},
368
369 {"rsc.io", "rsc.io/quote/v3", true},
370 {"*/quote", "rsc.io/quote/v3", true},
371 {"*/quote/", "rsc.io/quote/v3", true},
372 {"*/quote/*", "rsc.io/quote/v3", true},
373 {"*/quote/*/", "rsc.io/quote/v3", true},
374 {"*/v3", "rsc.io/quote/v3", false},
375 {"*/*/v3", "rsc.io/quote/v3", true},
376 {"*/*/*", "rsc.io/quote/v3", true},
377 {"*/*/*/", "rsc.io/quote/v3", true},
378 {"*/*/*", "rsc.io/quote", false},
379 {"*/*/*/", "rsc.io/quote", false},
380
381 {"*/*/*,,", "rsc.io/quote", false},
382 {"*/*/*,,*/quote", "rsc.io/quote", true},
383 {",,*/quote", "rsc.io/quote", true},
384 } {
385 if got := MatchPrefixPatterns(test.globs, test.target); got != test.want {
386 t.Errorf("MatchPrefixPatterns(%q, %q) = %t, want %t", test.globs, test.target, got, test.want)
387 }
388 }
389 }
390
View as plain text