1// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package module
6
7import (
8 "testing"
9
10 "cuelang.org/go/cue/ast"
11 "cuelang.org/go/internal/cuetest"
12 "github.com/go-quicktest/qt"
13)
14
15var checkTests = []struct {
16 path string
17 version string
18 ok bool
19}{
20 {"rsc.io/quote@v0", "0.1.0", false},
21 {"rsc io/quote", "v1.0.0", false},
22
23 {"github.com/go-yaml/yaml@v0", "v0.8.0", true},
24 {"github.com/go-yaml/yaml@v1", "v1.0.0", true},
25 {"github.com/go-yaml/yaml", "v2.0.0", false},
26 {"github.com/go-yaml/yaml@v1", "v2.1.5", false},
27 {"github.com/go-yaml/yaml@v3.0", "v3.0.0", false},
28
29 {"github.com/go-yaml/yaml@v2", "v1.0.0", false},
30 {"github.com/go-yaml/yaml@v2", "v2.0.0", true},
31 {"github.com/go-yaml/yaml@v2", "v2.1.5", true},
32 {"github.com/go-yaml/yaml@v2", "v3.0.0", false},
33
34 {"rsc.io/quote", "v17.0.0", false},
35}
36
37func TestCheck(t *testing.T) {
38 for _, tt := range checkTests {
39 err := Check(tt.path, tt.version)
40 if tt.ok && err != nil {
41 t.Errorf("Check(%q, %q) = %v, wanted nil error", tt.path, tt.version, err)
42 } else if !tt.ok && err == nil {
43 t.Errorf("Check(%q, %q) succeeded, wanted error", tt.path, tt.version)
44 }
45 }
46}
47
48type checkPathTest struct {
49 path string
50 modErr string
51 importErr string
52 fileErr string
53}
54
55var checkPathTests = []checkPathTest{{
56 path: `x.y/z`,
57}, {
58 path: `x.y`,
59}, {
60 path: ``,
61 modErr: `empty string`,
62 importErr: `malformed import path "": empty string`,
63 fileErr: `malformed file path "": empty string`,
64}, {
65 path: "x.y/\xffz",
66 modErr: `invalid UTF-8`,
67 importErr: `malformed import path "x.y/\xffz": invalid UTF-8`,
68 fileErr: `malformed file path "x.y/\xffz": invalid UTF-8`,
69}, {
70 path: `/x.y/z`,
71 modErr: `empty path element`,
72 importErr: `malformed import path "/x.y/z": empty path element`,
73 fileErr: `malformed file path "/x.y/z": empty path element`,
74}, {
75 path: `x./z`,
76 modErr: `trailing '.' in path element`,
77 importErr: `malformed import path "x./z": trailing dot in path element`,
78 fileErr: `malformed file path "x./z": trailing dot in path element`,
79}, {
80 path: `.x/z`,
81 modErr: `leading '.' in path element`,
82}, {
83 path: `-x/z`,
84 modErr: `leading dash`,
85 importErr: `malformed import path "-x/z": leading dash`,
86}, {
87 path: `x..y/z`,
88 modErr: `path does not conform to OCI repository name restrictions; see https://github.com/opencontainers/distribution-spec/blob/HEAD/spec.md#pulling-manifests`,
89}, {
90 path: `x.y/z/../../w`,
91 modErr: `invalid path element ".."`,
92 importErr: `malformed import path "x.y/z/../../w": invalid path element ".."`,
93 fileErr: `malformed file path "x.y/z/../../w": invalid path element ".."`,
94}, {
95 path: `x.y//z`,
96 modErr: `double slash`,
97 importErr: `malformed import path "x.y//z": double slash`,
98 fileErr: `malformed file path "x.y//z": double slash`,
99}, {
100 path: `x.y/z//w`,
101 modErr: `double slash`,
102 importErr: `malformed import path "x.y/z//w": double slash`,
103 fileErr: `malformed file path "x.y/z//w": double slash`,
104}, {
105 path: `x.y/z/`,
106 modErr: `trailing slash`,
107 importErr: `malformed import path "x.y/z/": trailing slash`,
108 fileErr: `malformed file path "x.y/z/": trailing slash`,
109}, {
110 path: `x.y/z/v0`,
111}, {
112 path: `x.y/z/v1`,
113}, {
114 path: `x.y/z/v2`,
115}, {
116 path: `x.y/z/v2.0`,
117}, {
118 path: `X.y/z`,
119 modErr: `invalid char 'X'`,
120}, {
121 path: `!x.y/z`,
122 modErr: `invalid char '!'`,
123 importErr: `malformed import path "!x.y/z": invalid char '!'`,
124}, {
125 path: `_x.y/z`,
126 modErr: `leading '_' in path element`,
127}, {
128 path: `x.y!/z`,
129 modErr: `invalid char '!'`,
130 importErr: `malformed import path "x.y!/z": invalid char '!'`,
131}, {
132 path: `x.y"/z`,
133 modErr: `invalid char '"'`,
134 importErr: `malformed import path "x.y\"/z": invalid char '"'`,
135 fileErr: `malformed file path "x.y\"/z": invalid char '"'`,
136}, {
137 path: `x.y#/z`,
138 modErr: `invalid char '#'`,
139 importErr: `malformed import path "x.y#/z": invalid char '#'`,
140}, {
141 path: `x.y$/z`,
142 modErr: `invalid char '$'`,
143 importErr: `malformed import path "x.y$/z": invalid char '$'`,
144}, {
145 path: `x.y%/z`,
146 modErr: `invalid char '%'`,
147 importErr: `malformed import path "x.y%/z": invalid char '%'`,
148}, {
149 path: `x.y&/z`,
150 modErr: `invalid char '&'`,
151 importErr: `malformed import path "x.y&/z": invalid char '&'`,
152}, {
153 path: `x.y'/z`,
154 modErr: `invalid char '\''`,
155 importErr: `malformed import path "x.y'/z": invalid char '\''`,
156 fileErr: `malformed file path "x.y'/z": invalid char '\''`,
157}, {
158 path: `x.y(/z`,
159 modErr: `invalid char '('`,
160 importErr: `malformed import path "x.y(/z": invalid char '('`,
161}, {
162 path: `x.y)/z`,
163 modErr: `invalid char ')'`,
164 importErr: `malformed import path "x.y)/z": invalid char ')'`,
165}, {
166 path: `x.y*/z`,
167 modErr: `invalid char '*'`,
168 importErr: `malformed import path "x.y*/z": invalid char '*'`,
169 fileErr: `malformed file path "x.y*/z": invalid char '*'`,
170}, {
171 path: `x.y+/z`,
172 modErr: `invalid char '+'`,
173}, {
174 path: `x.y,/z`,
175 modErr: `invalid char ','`,
176 importErr: `malformed import path "x.y,/z": invalid char ','`,
177}, {
178 path: `x.y-/z`,
179 modErr: `trailing '-' in path element`,
180}, {
181 path: `x.y./zt`,
182 modErr: `trailing '.' in path element`,
183 importErr: `malformed import path "x.y./zt": trailing dot in path element`,
184 fileErr: `malformed file path "x.y./zt": trailing dot in path element`,
185}, {
186 path: `x.y:/z`,
187 modErr: `invalid char ':'`,
188 importErr: `malformed import path "x.y:/z": invalid char ':'`,
189 fileErr: `malformed file path "x.y:/z": invalid char ':'`,
190}, {
191 path: `x.y;/z`,
192 modErr: `invalid char ';'`,
193 importErr: `malformed import path "x.y;/z": invalid char ';'`,
194 fileErr: `malformed file path "x.y;/z": invalid char ';'`,
195}, {
196 path: `x.y</z`,
197 modErr: `invalid char '<'`,
198 importErr: `malformed import path "x.y</z": invalid char '<'`,
199 fileErr: `malformed file path "x.y</z": invalid char '<'`,
200}, {
201 path: `x.y=/z`,
202 modErr: `invalid char '='`,
203 importErr: `malformed import path "x.y=/z": invalid char '='`,
204}, {
205 path: `x.y>/z`,
206 modErr: `invalid char '>'`,
207 importErr: `malformed import path "x.y>/z": invalid char '>'`,
208 fileErr: `malformed file path "x.y>/z": invalid char '>'`,
209}, {
210 path: `x.y?/z`,
211 modErr: `invalid char '?'`,
212 importErr: `malformed import path "x.y?/z": invalid char '?'`,
213 fileErr: `malformed file path "x.y?/z": invalid char '?'`,
214}, {
215 path: `x.y@/z`,
216 modErr: `module path inappropriately contains version`,
217 importErr: `malformed import path "x.y@/z": import paths can only contain a major version specifier`,
218}, {
219 path: `x.y[/z`,
220 modErr: `invalid char '['`,
221 importErr: `malformed import path "x.y[/z": invalid char '['`,
222}, {
223 path: `x.y\/z`,
224 modErr: `invalid char '\\'`,
225 importErr: `malformed import path "x.y\\/z": invalid char '\\'`,
226 fileErr: `malformed file path "x.y\\/z": invalid char '\\'`,
227}, {
228 path: `x.y]/z`,
229 modErr: `invalid char ']'`,
230 importErr: `malformed import path "x.y]/z": invalid char ']'`,
231}, {
232 path: `x.y^/z`,
233 modErr: `invalid char '^'`,
234 importErr: `malformed import path "x.y^/z": invalid char '^'`,
235}, {
236 path: `x.y_/z`,
237 modErr: `trailing '_' in path element`,
238}, {
239 path: "x.y`/z",
240 modErr: "invalid char '`'",
241 importErr: "malformed import path \"x.y`/z\": invalid char '`'",
242 fileErr: "malformed file path \"x.y`/z\": invalid char '`'",
243}, {
244 path: `x.y{/z`,
245 modErr: `invalid char '{'`,
246 importErr: `malformed import path "x.y{/z": invalid char '{'`,
247}, {
248 path: `x.y}/z`,
249 modErr: `invalid char '}'`,
250 importErr: `malformed import path "x.y}/z": invalid char '}'`,
251}, {
252 path: `x.y~/z`,
253 modErr: `invalid char '~'`,
254}, {
255 path: `x.y/z!`,
256 modErr: `invalid char '!'`,
257 importErr: `malformed import path "x.y/z!": invalid char '!'`,
258}, {
259 path: `x.y/z"`,
260 modErr: `invalid char '"'`,
261 importErr: `malformed import path "x.y/z\"": invalid char '"'`,
262 fileErr: `malformed file path "x.y/z\"": invalid char '"'`,
263}, {
264 path: `x.y/z#`,
265 modErr: `invalid char '#'`,
266 importErr: `malformed import path "x.y/z#": invalid char '#'`,
267}, {
268 path: `x.y/z$`,
269 modErr: `invalid char '$'`,
270 importErr: `malformed import path "x.y/z$": invalid char '$'`,
271}, {
272 path: `x.y/z%`,
273 modErr: `invalid char '%'`,
274 importErr: `malformed import path "x.y/z%": invalid char '%'`,
275}, {
276 path: `x.y/z&`,
277 modErr: `invalid char '&'`,
278 importErr: `malformed import path "x.y/z&": invalid char '&'`,
279}, {
280 path: `x.y/z'`,
281 modErr: `invalid char '\''`,
282 importErr: `malformed import path "x.y/z'": invalid char '\''`,
283 fileErr: `malformed file path "x.y/z'": invalid char '\''`,
284}, {
285 path: `x.y/z(`,
286 modErr: `invalid char '('`,
287 importErr: `malformed import path "x.y/z(": invalid char '('`,
288}, {
289 path: `x.y/z)`,
290 modErr: `invalid char ')'`,
291 importErr: `malformed import path "x.y/z)": invalid char ')'`,
292}, {
293 path: `x.y/z*`,
294 modErr: `invalid char '*'`,
295 importErr: `malformed import path "x.y/z*": invalid char '*'`,
296 fileErr: `malformed file path "x.y/z*": invalid char '*'`,
297}, {
298 path: `x.y/z++`,
299 modErr: `invalid char '+'`,
300}, {
301 path: `x.y/z,`,
302 modErr: `invalid char ','`,
303 importErr: `malformed import path "x.y/z,": invalid char ','`,
304}, {
305 path: `x.y/z-`,
306 modErr: `trailing '-' in path element`,
307}, {
308 path: `x.y/z.t`,
309}, {
310 path: `x.y/z/t`,
311}, {
312 path: `x.y/z:`,
313 modErr: `invalid char ':'`,
314 fileErr: `malformed file path "x.y/z:": invalid char ':'`,
315}, {
316 path: `x.y/z;`,
317 modErr: `invalid char ';'`,
318 importErr: `malformed import path "x.y/z;": invalid char ';'`,
319 fileErr: `malformed file path "x.y/z;": invalid char ';'`,
320}, {
321 path: `x.y/z<`,
322 modErr: `invalid char '<'`,
323 importErr: `malformed import path "x.y/z<": invalid char '<'`,
324 fileErr: `malformed file path "x.y/z<": invalid char '<'`,
325}, {
326 path: `x.y/z=`,
327 modErr: `invalid char '='`,
328 importErr: `malformed import path "x.y/z=": invalid char '='`,
329}, {
330 path: `x.y/z>`,
331 modErr: `invalid char '>'`,
332 importErr: `malformed import path "x.y/z>": invalid char '>'`,
333 fileErr: `malformed file path "x.y/z>": invalid char '>'`,
334}, {
335 path: `x.y/z?`,
336 modErr: `invalid char '?'`,
337 importErr: `malformed import path "x.y/z?": invalid char '?'`,
338 fileErr: `malformed file path "x.y/z?": invalid char '?'`,
339}, {
340 path: `x.y/z@`,
341 modErr: `invalid char '@'`,
342 importErr: `malformed import path "x.y/z@": invalid char '@'`,
343}, {
344 path: `x.y/z[`,
345 modErr: `invalid char '['`,
346 importErr: `malformed import path "x.y/z[": invalid char '['`,
347}, {
348 path: `x.y/z\`,
349 modErr: `invalid char '\\'`,
350 importErr: `malformed import path "x.y/z\\": invalid char '\\'`,
351 fileErr: `malformed file path "x.y/z\\": invalid char '\\'`,
352}, {
353 path: `x.y/z]`,
354 modErr: `invalid char ']'`,
355 importErr: `malformed import path "x.y/z]": invalid char ']'`,
356}, {
357 path: `x.y/z^`,
358 modErr: `invalid char '^'`,
359 importErr: `malformed import path "x.y/z^": invalid char '^'`,
360}, {
361 path: `x.y/z_`,
362 modErr: `trailing '_' in path element`,
363}, {
364 path: "x.y/z`",
365 modErr: "invalid char '`'",
366 importErr: "malformed import path \"x.y/z`\": invalid char '`'",
367 fileErr: "malformed file path \"x.y/z`\": invalid char '`'",
368}, {
369 path: `x.y/z{`,
370 modErr: `invalid char '{'`,
371 importErr: `malformed import path "x.y/z{": invalid char '{'`,
372}, {
373 path: `x.y/z}`,
374 modErr: `invalid char '}'`,
375 importErr: `malformed import path "x.y/z}": invalid char '}'`,
376}, {
377 path: `x.y/z~`,
378 modErr: `invalid char '~'`,
379}, {
380 path: `x.y/x.foo`,
381}, {
382 path: `x.y/aux.foo`,
383 modErr: `"aux" disallowed as path element component on Windows`,
384 importErr: `malformed import path "x.y/aux.foo": "aux" disallowed as path element component on Windows`,
385 fileErr: `malformed file path "x.y/aux.foo": "aux" disallowed as path element component on Windows`,
386}, {
387 path: `x.y/prn`,
388 modErr: `"prn" disallowed as path element component on Windows`,
389 importErr: `malformed import path "x.y/prn": "prn" disallowed as path element component on Windows`,
390 fileErr: `malformed file path "x.y/prn": "prn" disallowed as path element component on Windows`,
391}, {
392 path: `x.y/prn2`,
393}, {
394 path: `x.y/com`,
395}, {
396 path: `x.y/com1`,
397 modErr: `"com1" disallowed as path element component on Windows`,
398 importErr: `malformed import path "x.y/com1": "com1" disallowed as path element component on Windows`,
399 fileErr: `malformed file path "x.y/com1": "com1" disallowed as path element component on Windows`,
400}, {
401 path: `x.y/com1.txt`,
402 modErr: `"com1" disallowed as path element component on Windows`,
403 importErr: `malformed import path "x.y/com1.txt": "com1" disallowed as path element component on Windows`,
404 fileErr: `malformed file path "x.y/com1.txt": "com1" disallowed as path element component on Windows`,
405}, {
406 path: `x.y/calm1`,
407}, {
408 path: `x.y/z~`,
409 modErr: `invalid char '~'`,
410}, {
411 path: `x.y/z~0`,
412 modErr: `invalid char '~'`,
413 importErr: `malformed import path "x.y/z~0": trailing tilde and digits in path element`,
414}, {
415 path: `x.y/z~09`,
416 modErr: `invalid char '~'`,
417 importErr: `malformed import path "x.y/z~09": trailing tilde and digits in path element`,
418}, {
419 path: `x.y/z09`,
420}, {
421 path: `x.y/z09~`,
422 modErr: `invalid char '~'`,
423}, {
424 path: `x.y/z09~09z`,
425 modErr: `invalid char '~'`,
426}, {
427 path: `x.y/z09~09z~09`,
428 modErr: `invalid char '~'`,
429 importErr: `malformed import path "x.y/z09~09z~09": trailing tilde and digits in path element`,
430}, {
431 path: `github.com/!123/logrus`,
432 modErr: `invalid char '!'`,
433 importErr: `malformed import path "github.com/!123/logrus": invalid char '!'`,
434}, {
435 path: `github.com/user/unicode/испытание`,
436 modErr: `invalid char 'и'`,
437 importErr: `malformed import path "github.com/user/unicode/испытание": invalid char 'и'`,
438}, {
439 path: `../x`,
440 modErr: `invalid path element ".."`,
441 importErr: `malformed import path "../x": invalid path element ".."`,
442 fileErr: `malformed file path "../x": invalid path element ".."`,
443}, {
444 path: `./y`,
445 modErr: `invalid path element "."`,
446 importErr: `malformed import path "./y": invalid path element "."`,
447 fileErr: `malformed file path "./y": invalid path element "."`,
448}, {
449 path: `x:y`,
450 modErr: `invalid char ':'`,
451 fileErr: `malformed file path "x:y": invalid char ':'`,
452}, {
453 path: `\temp\foo`,
454 modErr: `invalid char '\\'`,
455 importErr: `malformed import path "\\temp\\foo": invalid char '\\'`,
456 fileErr: `malformed file path "\\temp\\foo": invalid char '\\'`,
457}, {
458 path: `.gitignore`,
459 modErr: `leading '.' in path element`,
460}, {
461 path: `.github/ISSUE_TEMPLATE`,
462 modErr: `leading '.' in path element`,
463}, {
464 path: `x☺y`,
465 modErr: `invalid char '☺'`,
466 importErr: `malformed import path "x☺y": invalid char '☺'`,
467 fileErr: `malformed file path "x☺y": invalid char '☺'`,
468}, {
469 path: `bar.com/foo.`,
470 modErr: `trailing '.' in path element`,
471 importErr: `malformed import path "bar.com/foo.": trailing dot in path element`,
472 fileErr: `malformed file path "bar.com/foo.": trailing dot in path element`,
473}, {
474 path: `bar.com/_foo`,
475 modErr: `leading '_' in path element`,
476}, {
477 path: `bar.com/foo___x`,
478 modErr: `path does not conform to OCI repository name restrictions; see https://github.com/opencontainers/distribution-spec/blob/HEAD/spec.md#pulling-manifests`,
479}, {
480 path: `bar.com/Sushi`,
481 modErr: `invalid char 'S'`,
482}, {
483 path: `rsc io/quote`,
484 modErr: `invalid char ' '`,
485 importErr: `malformed import path "rsc io/quote": invalid char ' '`,
486}, {
487 path: `foo.com@v0`,
488 modErr: `module path inappropriately contains version`,
489}, {
490 path: `foo.com/bar/baz`,
491}}
492
493func TestCheckPathWithoutVersion(t *testing.T) {
494 cuetest.Run(t, checkPathTests, func(t *cuetest.T, test *checkPathTest) {
495 t.Logf("path: `%s`", test.path)
496 t.Equal(errStr(CheckPathWithoutVersion(test.path)), test.modErr)
497 })
498}
499
500func TestCheckImportPath(t *testing.T) {
501 cuetest.Run(t, checkPathTests, func(t *cuetest.T, test *checkPathTest) {
502 t.Logf("path: `%s`", test.path)
503 t.Equal(errStr(CheckImportPath(test.path)), test.importErr)
504 })
505}
506
507func TestCheckFilePath(t *testing.T) {
508 cuetest.Run(t, checkPathTests, func(t *cuetest.T, test *checkPathTest) {
509 t.Logf("path: `%s`", test.path)
510 t.Equal(errStr(CheckFilePath(test.path)), test.fileErr)
511 })
512}
513
514var newVersionTests = []struct {
515 path, vers string
516 wantError string
517 wantPath string
518 wantBasePath string
519}{{
520 path: "github.com/foo/bar@v0",
521 vers: "v0.1.2",
522 wantPath: "github.com/foo/bar@v0",
523 wantBasePath: "github.com/foo/bar",
524}, {
525 path: "github.com/foo/bar",
526 vers: "v3.1.2",
527 wantPath: "github.com/foo/bar@v3",
528 wantBasePath: "github.com/foo/bar",
529}, {
530 path: "github.com/foo/bar@v1",
531 vers: "",
532 wantPath: "github.com/foo/bar@v1",
533 wantBasePath: "github.com/foo/bar",
534}, {
535 path: "github.com/foo/bar@v1",
536 vers: "v3.1.2",
537 wantError: `mismatched major version suffix in "github.com/foo/bar@v1" \(version v3\.1\.2\)`,
538}, {
539 path: "github.com/foo/bar@v1",
540 vers: "v3.1",
541 wantError: `version "v3.1" \(of module "github.com/foo/bar@v1"\) is not canonical`,
542}, {
543 path: "github.com/foo/bar@v1",
544 vers: "v3.10.4+build",
545 wantError: `version "v3.10.4\+build" \(of module "github.com/foo/bar@v1"\) is not canonical`,
546}, {
547 path: "something/bad@v1",
548 vers: "v1.2.3",
549 wantError: `malformed module path "something/bad@v1": missing dot in first path element`,
550}, {
551 path: "foo.com/bar",
552 vers: "",
553 wantError: `path "foo.com/bar" has no major version`,
554}, {
555 path: "x.com",
556 vers: "bad",
557 wantError: `version "bad" \(of module "x.com"\) is not well formed`,
558}, {
559 path: "local",
560 vers: "",
561 wantPath: "local",
562 wantBasePath: "local",
563}, {
564 path: "local",
565 vers: "v0.1.2",
566 wantError: `module 'local' cannot have version`,
567}, {
568 path: "local@v1",
569 vers: "",
570 wantError: `module 'local' cannot have version`,
571}}
572
573func TestNewVersion(t *testing.T) {
574 for _, test := range newVersionTests {
575 t.Run(test.path+"@"+test.vers, func(t *testing.T) {
576 v, err := NewVersion(test.path, test.vers)
577 if test.wantError != "" {
578 qt.Assert(t, qt.ErrorMatches(err, test.wantError))
579 return
580 }
581 qt.Assert(t, qt.IsNil(err))
582 qt.Assert(t, qt.Equals(v.Path(), test.wantPath))
583 qt.Assert(t, qt.Equals(v.BasePath(), test.wantBasePath))
584 qt.Assert(t, qt.Equals(v.Version(), test.vers))
585 })
586 }
587}
588
589var parseVersionTests = []struct {
590 s string
591 wantError string
592}{{
593 s: "github.com/foo/bar@v0.1.2",
594}}
595
596func TestParseVersion(t *testing.T) {
597 for _, test := range parseVersionTests {
598 t.Run(test.s, func(t *testing.T) {
599 v, err := ParseVersion(test.s)
600 if test.wantError != "" {
601 qt.Assert(t, qt.ErrorMatches(err, test.wantError))
602 return
603 }
604 qt.Assert(t, qt.IsNil(err))
605 qt.Assert(t, qt.Equals(v.String(), test.s))
606 })
607 }
608}
609
610var escapeVersionTests = []struct {
611 v string
612 esc string // empty means same as path
613}{
614 {v: "v1.2.3-alpha"},
615 {v: "v3"},
616 {v: "v2.3.1-ABcD", esc: "v2.3.1-!a!bc!d"},
617}
618
619func TestEscapeVersion(t *testing.T) {
620 for _, tt := range escapeVersionTests {
621 esc, err := EscapeVersion(tt.v)
622 if err != nil {
623 t.Errorf("EscapeVersion(%q): unexpected error: %v", tt.v, err)
624 continue
625 }
626 want := tt.esc
627 if want == "" {
628 want = tt.v
629 }
630 if esc != want {
631 t.Errorf("EscapeVersion(%q) = %q, want %q", tt.v, esc, want)
632 }
633 }
634}
635
636func TestEscapePath(t *testing.T) {
637 // Check invalid paths.
638 for _, tt := range checkPathTests {
639 if tt.modErr != "" {
640 _, err := EscapePath(tt.path)
641 if err == nil {
642 t.Errorf("EscapePath(%q): succeeded, want error (invalid path)", tt.path)
643 }
644 }
645 }
646 path := "foo.com/bar"
647 esc, err := EscapePath(path)
648 if err != nil {
649 t.Fatal(err)
650 }
651 if esc != path {
652 t.Fatalf("EscapePath(%q) = %q, want %q", path, esc, path)
653 }
654}
655
656func TestParseImportPath(t *testing.T) {
657 // Just a smoke test to make sure that the (deprecated)
658 // ParseImportPath function is still wired up and the
659 // ImportPath type is still defined.
660 ip := ast.ParseImportPath("foo.com/bar@v0:baz")
661 qt.Assert(t, qt.DeepEquals(ip, ast.ImportPath{
662 Path: "foo.com/bar",
663 Version: "v0",
664 Qualifier: "baz",
665 ExplicitQualifier: true,
666 }))
667}
668
669func errStr(err error) string {
670 if err == nil {
671 return ""
672 }
673 if e := err.Error(); e != "" {
674 return e
675 }
676 panic("non-nil error with empty string")
677}