1
2
3
4
5 package modfetch
6
7 import (
8 "archive/zip"
9 "context"
10 "crypto/sha256"
11 "encoding/hex"
12 "flag"
13 "hash"
14 "internal/testenv"
15 "io"
16 "log"
17 "os"
18 "path/filepath"
19 "reflect"
20 "strings"
21 "testing"
22 "time"
23
24 "cmd/go/internal/cfg"
25 "cmd/go/internal/modfetch/codehost"
26 "cmd/go/internal/vcweb/vcstest"
27
28 "golang.org/x/mod/sumdb/dirhash"
29 )
30
31 func TestMain(m *testing.M) {
32 flag.Parse()
33 if err := testMain(m); err != nil {
34 log.Fatal(err)
35 }
36 }
37
38 func testMain(m *testing.M) (err error) {
39
40 cfg.GOPROXY = "direct"
41
42
43
44
45
46 cfg.GOSUMDB = "off"
47
48 dir, err := os.MkdirTemp("", "gitrepo-test-")
49 if err != nil {
50 return err
51 }
52 defer func() {
53 if rmErr := os.RemoveAll(dir); err == nil {
54 err = rmErr
55 }
56 }()
57
58 cfg.GOMODCACHE = filepath.Join(dir, "modcache")
59 if err := os.Mkdir(cfg.GOMODCACHE, 0755); err != nil {
60 return err
61 }
62
63 srv, err := vcstest.NewServer()
64 if err != nil {
65 return err
66 }
67 defer func() {
68 if closeErr := srv.Close(); err == nil {
69 err = closeErr
70 }
71 }()
72
73 m.Run()
74 return nil
75 }
76
77 const (
78 vgotest1git = "github.com/rsc/vgotest1"
79 vgotest1hg = "vcs-test.golang.org/hg/vgotest1.hg"
80 )
81
82 var altVgotests = map[string]string{
83 "hg": vgotest1hg,
84 }
85
86 type codeRepoTest struct {
87 vcs string
88 path string
89 mpath string
90 rev string
91 err string
92 version string
93 name string
94 short string
95 time time.Time
96 gomod string
97 gomodErr string
98 zip []string
99 zipErr string
100 zipSum string
101 zipFileHash string
102 }
103
104 var codeRepoTests = []codeRepoTest{
105 {
106 vcs: "git",
107 path: "github.com/rsc/vgotest1",
108 rev: "v0.0.0",
109 version: "v0.0.0",
110 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
111 short: "80d85c5d4d17",
112 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
113 zip: []string{
114 "LICENSE",
115 "README.md",
116 "pkg/p.go",
117 },
118 zipSum: "h1:zVEjciLdlk/TPWCOyZo7k24T+tOKRQC+u8MKq/xS80I=",
119 zipFileHash: "738a00ddbfe8c329dce6b48e1f23c8e22a92db50f3cfb2653caa0d62676bc09c",
120 },
121 {
122 vcs: "git",
123 path: "github.com/rsc/vgotest1",
124 rev: "v0.0.0-20180219231006-80d85c5d4d17",
125 version: "v0.0.0-20180219231006-80d85c5d4d17",
126 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
127 short: "80d85c5d4d17",
128 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
129 zip: []string{
130 "LICENSE",
131 "README.md",
132 "pkg/p.go",
133 },
134 zipSum: "h1:nOznk2xKsLGkTnXe0q9t1Ewt9jxK+oadtafSUqHM3Ec=",
135 zipFileHash: "bacb08f391e29d2eaaef8281b5c129ee6d890e608ee65877e0003c0181a766c8",
136 },
137 {
138 vcs: "git",
139 path: "github.com/rsc/vgotest1",
140 rev: "v0.0.1-0.20180219231006-80d85c5d4d17",
141 err: `github.com/rsc/vgotest1@v0.0.1-0.20180219231006-80d85c5d4d17: invalid pseudo-version: tag (v0.0.0) found on revision 80d85c5d4d17 is already canonical, so should not be replaced with a pseudo-version derived from that tag`,
142 },
143 {
144 vcs: "git",
145 path: "github.com/rsc/vgotest1",
146 rev: "v1.0.0",
147 version: "v1.0.0",
148 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
149 short: "80d85c5d4d17",
150 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
151 zip: []string{
152 "LICENSE",
153 "README.md",
154 "pkg/p.go",
155 },
156 zipSum: "h1:e040hOoWGeuJLawDjK9DW6med+cz9FxMFYDMOVG8ctQ=",
157 zipFileHash: "74caab65cfbea427c341fa815f3bb0378681d8f0e3cf62a7f207014263ec7be3",
158 },
159 {
160 vcs: "git",
161 path: "github.com/rsc/vgotest1/v2",
162 rev: "v2.0.0",
163 version: "v2.0.0",
164 name: "45f53230a74ad275c7127e117ac46914c8126160",
165 short: "45f53230a74a",
166 time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC),
167 err: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0",
168 },
169 {
170 vcs: "git",
171 path: "github.com/rsc/vgotest1",
172 rev: "80d85c5",
173 version: "v1.0.0",
174 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
175 short: "80d85c5d4d17",
176 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
177 zip: []string{
178 "LICENSE",
179 "README.md",
180 "pkg/p.go",
181 },
182 zipSum: "h1:e040hOoWGeuJLawDjK9DW6med+cz9FxMFYDMOVG8ctQ=",
183 zipFileHash: "74caab65cfbea427c341fa815f3bb0378681d8f0e3cf62a7f207014263ec7be3",
184 },
185 {
186 vcs: "git",
187 path: "github.com/rsc/vgotest1",
188 rev: "mytag",
189 version: "v1.0.0",
190 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
191 short: "80d85c5d4d17",
192 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
193 zip: []string{
194 "LICENSE",
195 "README.md",
196 "pkg/p.go",
197 },
198 },
199 {
200 vcs: "git",
201 path: "github.com/rsc/vgotest1/v2",
202 rev: "45f53230a",
203 version: "v2.0.0",
204 name: "45f53230a74ad275c7127e117ac46914c8126160",
205 short: "45f53230a74a",
206 time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC),
207 err: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0",
208 },
209 {
210 vcs: "git",
211 path: "github.com/rsc/vgotest1/v54321",
212 rev: "80d85c5",
213 version: "v54321.0.0-20180219231006-80d85c5d4d17",
214 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
215 short: "80d85c5d4d17",
216 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
217 err: "missing github.com/rsc/vgotest1/go.mod and .../v54321/go.mod at revision 80d85c5d4d17",
218 },
219 {
220 vcs: "git",
221 path: "github.com/rsc/vgotest1/submod",
222 rev: "v1.0.0",
223 err: "unknown revision submod/v1.0.0",
224 },
225 {
226 vcs: "git",
227 path: "github.com/rsc/vgotest1/submod",
228 rev: "v1.0.3",
229 err: "unknown revision submod/v1.0.3",
230 },
231 {
232 vcs: "git",
233 path: "github.com/rsc/vgotest1/submod",
234 rev: "v1.0.4",
235 version: "v1.0.4",
236 name: "8afe2b2efed96e0880ecd2a69b98a53b8c2738b6",
237 short: "8afe2b2efed9",
238 time: time.Date(2018, 2, 19, 23, 12, 7, 0, time.UTC),
239 gomod: "module \"github.com/vgotest1/submod\" // submod/go.mod\n",
240 zip: []string{
241 "go.mod",
242 "pkg/p.go",
243 "LICENSE",
244 },
245 zipSum: "h1:iMsJ/9uQsk6MnZNnJK311f11QiSlmN92Q2aSjCywuJY=",
246 zipFileHash: "95801bfa69c5197ae809af512946d22f22850068527cd78100ae3f176bc8043b",
247 },
248 {
249 vcs: "git",
250 path: "github.com/rsc/vgotest1",
251 rev: "v1.1.0",
252 version: "v1.1.0",
253 name: "b769f2de407a4db81af9c5de0a06016d60d2ea09",
254 short: "b769f2de407a",
255 time: time.Date(2018, 2, 19, 23, 13, 36, 0, time.UTC),
256 gomod: "module \"github.com/rsc/vgotest1\" // root go.mod\nrequire \"github.com/rsc/vgotest1/submod\" v1.0.5\n",
257 zip: []string{
258 "LICENSE",
259 "README.md",
260 "go.mod",
261 "pkg/p.go",
262 },
263 zipSum: "h1:M69k7q+8bQ+QUpHov45Z/NoR8rj3DsQJUnXLWvf01+Q=",
264 zipFileHash: "58af45fb248d320ea471f568e006379e2b8d71d6d1663f9b19b2e00fd9ac9265",
265 },
266 {
267 vcs: "git",
268 path: "github.com/rsc/vgotest1/v2",
269 rev: "v2.0.1",
270 version: "v2.0.1",
271 name: "ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9",
272 short: "ea65f87c8f52",
273 time: time.Date(2018, 2, 19, 23, 14, 23, 0, time.UTC),
274 gomod: "module \"github.com/rsc/vgotest1/v2\" // root go.mod\n",
275 zipSum: "h1:QmgYy/zt+uoWhDpcsgrSVzYFvKtBEjl5zT/FRz9GTzA=",
276 zipFileHash: "1aedf1546d322a0121879ddfd6d0e8bfbd916d2cafbeb538ddb440e04b04b9ef",
277 },
278 {
279 vcs: "git",
280 path: "github.com/rsc/vgotest1/v2",
281 rev: "v2.0.3",
282 version: "v2.0.3",
283 name: "f18795870fb14388a21ef3ebc1d75911c8694f31",
284 short: "f18795870fb1",
285 time: time.Date(2018, 2, 19, 23, 16, 4, 0, time.UTC),
286 err: "github.com/rsc/vgotest1/v2/go.mod has non-.../v2 module path \"github.com/rsc/vgotest\" at revision v2.0.3",
287 },
288 {
289 vcs: "git",
290 path: "github.com/rsc/vgotest1/v2",
291 rev: "v2.0.4",
292 version: "v2.0.4",
293 name: "1f863feb76bc7029b78b21c5375644838962f88d",
294 short: "1f863feb76bc",
295 time: time.Date(2018, 2, 20, 0, 3, 38, 0, time.UTC),
296 err: "github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision v2.0.4",
297 },
298 {
299 vcs: "git",
300 path: "github.com/rsc/vgotest1/v2",
301 rev: "v2.0.5",
302 version: "v2.0.5",
303 name: "2f615117ce481c8efef46e0cc0b4b4dccfac8fea",
304 short: "2f615117ce48",
305 time: time.Date(2018, 2, 20, 0, 3, 59, 0, time.UTC),
306 gomod: "module \"github.com/rsc/vgotest1/v2\" // v2/go.mod\n",
307 zipSum: "h1:RIEb9q1SUSEQOzMn0zfl/LQxGFWlhWEAdeEguf1MLGU=",
308 zipFileHash: "7d92c2c328c5e9b0694101353705d5843746ec1d93a1e986d0da54c8a14dfe6d",
309 },
310 {
311
312 vcs: "git",
313 path: "rsc.io/quote",
314 rev: "v1.0.0",
315 version: "v1.0.0",
316 name: "f488df80bcdbd3e5bafdc24ad7d1e79e83edd7e6",
317 short: "f488df80bcdb",
318 time: time.Date(2018, 2, 14, 0, 45, 20, 0, time.UTC),
319 gomod: "module \"rsc.io/quote\"\n",
320 zipSum: "h1:haUSojyo3j2M9g7CEUFG8Na09dtn7QKxvPGaPVQdGwM=",
321 zipFileHash: "5c08ba2c09a364f93704aaa780e7504346102c6ef4fe1333a11f09904a732078",
322 },
323 {
324
325 vcs: "mod",
326 path: "swtch.com/testmod",
327 rev: "v1.0.0",
328 version: "v1.0.0",
329
330 time: time.Date(1972, 7, 18, 12, 34, 56, 0, time.UTC),
331 gomod: "module \"swtch.com/testmod\"\n",
332 },
333 {
334
335 vcs: "git",
336 path: "golang.org/x/text",
337 rev: "4e4a3210bb",
338 version: "v0.3.1-0.20180208041248-4e4a3210bb54",
339 name: "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1",
340 short: "4e4a3210bb54",
341 time: time.Date(2018, 2, 8, 4, 12, 48, 0, time.UTC),
342 zipSum: "h1:Yxu6pHX9X2RECiuw/Q5/4uvajuaowck8zOFKXgbfNBk=",
343 zipFileHash: "ac2c165a5c10aa5a7545dea60a08e019270b982fa6c8bdcb5943931de64922fe",
344 },
345 {
346 vcs: "git",
347 path: "github.com/pkg/errors",
348 rev: "v0.8.0",
349 version: "v0.8.0",
350 name: "645ef00459ed84a119197bfb8d8205042c6df63d",
351 short: "645ef00459ed",
352 time: time.Date(2016, 9, 29, 1, 48, 1, 0, time.UTC),
353 zipSum: "h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=",
354 zipFileHash: "e4fa69ba057356614edbc1da881a7d3ebb688505be49f65965686bcb859e2fae",
355 },
356 {
357
358
359
360 vcs: "git",
361 path: "gopkg.in/yaml.v2/abc",
362 err: "invalid module path \"gopkg.in/yaml.v2/abc\"",
363 },
364 {
365
366
367 vcs: "git",
368 path: "github.com/rsc/quote/buggy",
369 rev: "c4d4236f",
370 err: "missing github.com/rsc/quote/buggy/go.mod at revision c4d4236f9242",
371 },
372 {
373 vcs: "git",
374 path: "gopkg.in/yaml.v2",
375 rev: "d670f940",
376 version: "v2.0.0",
377 name: "d670f9405373e636a5a2765eea47fac0c9bc91a4",
378 short: "d670f9405373",
379 time: time.Date(2018, 1, 9, 11, 43, 31, 0, time.UTC),
380 gomod: "module gopkg.in/yaml.v2\n",
381 zipSum: "h1:uUkhRGrsEyx/laRdeS6YIQKIys8pg+lRSRdVMTYjivs=",
382 zipFileHash: "7b0a141b1b0b49772ab4eecfd11dfd6609a94a5e868cab04a3abb1861ffaa877",
383 },
384 {
385 vcs: "git",
386 path: "gopkg.in/check.v1",
387 rev: "20d25e280405",
388 version: "v1.0.0-20161208181325-20d25e280405",
389 name: "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec",
390 short: "20d25e280405",
391 time: time.Date(2016, 12, 8, 18, 13, 25, 0, time.UTC),
392 gomod: "module gopkg.in/check.v1\n",
393 zipSum: "h1:829vOVxxusYHC+IqBtkX5mbKtsY9fheQiQn0MZRVLfQ=",
394 zipFileHash: "9e7cb3f4f1e66d722306442b0dbe1f6f43d74d1736d54c510537bdfb1d6f432f",
395 },
396 {
397 vcs: "git",
398 path: "vcs-test.golang.org/go/mod/gitrepo1",
399 rev: "master",
400 version: "v1.2.4-annotated",
401 name: "ede458df7cd0fdca520df19a33158086a8a68e81",
402 short: "ede458df7cd0",
403 time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
404 gomod: "module vcs-test.golang.org/go/mod/gitrepo1\n",
405 zipSum: "h1:YJYZRsM9BHFTlVr8YADjT0cJH8uFIDtoc5NLiVqZEx8=",
406 zipFileHash: "c15e49d58b7a4c37966cbe5bc01a0330cd5f2927e990e1839bda1d407766d9c5",
407 },
408 {
409 vcs: "git",
410 path: "gopkg.in/natefinch/lumberjack.v2",
411
412
413
414
415
416
417 rev: "v2.1",
418 version: "v2.0.0-20170531160350-a96e63847dc3",
419 name: "a96e63847dc3c67d17befa69c303767e2f84e54f",
420 short: "a96e63847dc3",
421 time: time.Date(2017, 5, 31, 16, 3, 50, 0, time.UTC),
422 gomod: "module gopkg.in/natefinch/lumberjack.v2\n",
423 },
424 {
425 vcs: "git",
426 path: "vcs-test.golang.org/go/v2module/v2",
427 rev: "v2.0.0",
428 version: "v2.0.0",
429 name: "203b91c896acd173aa719e4cdcb7d463c4b090fa",
430 short: "203b91c896ac",
431 time: time.Date(2019, 4, 3, 15, 52, 15, 0, time.UTC),
432 gomod: "module vcs-test.golang.org/go/v2module/v2\n\ngo 1.12\n",
433 zipSum: "h1:JItBZ+gwA5WvtZEGEbuDL4lUttGtLrs53lmdurq3bOg=",
434 zipFileHash: "9ea9ae1673cffcc44b7fdd3cc89953d68c102449b46c982dbf085e4f2e394da5",
435 },
436 {
437
438 vcs: "git",
439 path: "vcs-test.golang.org/go/mod/gitrepo1",
440 rev: "v2.3.4+incompatible",
441 err: `resolves to version v2.0.1+incompatible (v2.3.4 is not a tag)`,
442 },
443 {
444
445 vcs: "git",
446 path: "vcs-test.golang.org/git/semver-branch.git",
447 rev: "v1.0.0",
448 err: `resolves to version v0.1.1-0.20220202191944-09c4d8f6938c (v1.0.0 is not a tag)`,
449 },
450 {
451
452
453 vcs: "git",
454 path: "vcs-test.golang.org/git/semver-branch.git",
455 rev: "v2.0.0+incompatible",
456 err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`,
457 },
458 {
459
460
461 vcs: "git",
462 path: "vcs-test.golang.org/git/semver-branch.git",
463 rev: "v2.0.0",
464 err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`,
465 },
466 {
467
468
469
470
471 vcs: "git",
472 path: "vcs-test.golang.org/git/semver-branch.git",
473 rev: "v3.0.0-devel",
474 err: `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`,
475 },
476
477
478
479
480
481
482
483
484
485 {
486 vcs: "git",
487 path: "vcs-test.golang.org/git/v2sub.git",
488 rev: "80beb17a1603",
489 version: "v0.0.0-20220222205507-80beb17a1603",
490 name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
491 short: "80beb17a1603",
492 time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
493 },
494 {
495 vcs: "git",
496 path: "vcs-test.golang.org/git/v2sub.git",
497 rev: "v2.0.0",
498 err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
499 },
500 {
501 vcs: "git",
502 path: "vcs-test.golang.org/git/v2sub.git",
503 rev: "v2.0.1-0.20220222205507-80beb17a1603",
504 err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
505 },
506 {
507 vcs: "git",
508 path: "vcs-test.golang.org/git/v2sub.git",
509 rev: "v2.0.0+incompatible",
510 version: "v2.0.0+incompatible",
511 name: "5fcd3eaeeb391d399f562fd45a50dac9fc34ae8b",
512 short: "5fcd3eaeeb39",
513 time: time.Date(2022, 2, 22, 20, 53, 33, 0, time.UTC),
514 },
515 {
516 vcs: "git",
517 path: "vcs-test.golang.org/git/v2sub.git",
518 rev: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
519 version: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
520 name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
521 short: "80beb17a1603",
522 time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
523 },
524
525
526
527 {
528 vcs: "git",
529 path: "vcs-test.golang.org/git/odd-tags.git",
530 rev: "v0.1.0+build-metadata",
531 version: "v0.1.1-0.20220223184835-9d863d525bbf",
532 name: "9d863d525bbfcc8eda09364738c4032393711a56",
533 short: "9d863d525bbf",
534 time: time.Date(2022, 2, 23, 18, 48, 35, 0, time.UTC),
535 },
536 {
537 vcs: "git",
538 path: "vcs-test.golang.org/git/odd-tags.git",
539 rev: "9d863d525bbf",
540 version: "v0.1.1-0.20220223184835-9d863d525bbf",
541 name: "9d863d525bbfcc8eda09364738c4032393711a56",
542 short: "9d863d525bbf",
543 time: time.Date(2022, 2, 23, 18, 48, 35, 0, time.UTC),
544 },
545 {
546 vcs: "git",
547 path: "vcs-test.golang.org/git/odd-tags.git",
548 rev: "latest",
549 version: "v0.1.1-0.20220223184835-9d863d525bbf",
550 name: "9d863d525bbfcc8eda09364738c4032393711a56",
551 short: "9d863d525bbf",
552 time: time.Date(2022, 2, 23, 18, 48, 35, 0, time.UTC),
553 },
554
555
556
557
558
559
560 {
561 vcs: "git",
562 path: "vcs-test.golang.org/git/odd-tags.git",
563 rev: "v2.0.0+incompatible",
564 err: `unknown revision v2.0.0`,
565 },
566 {
567 vcs: "git",
568 path: "vcs-test.golang.org/git/odd-tags.git",
569 rev: "12d19af20458",
570 version: "v2.0.1-0.20220223184802-12d19af20458+incompatible",
571 name: "12d19af204585b0db3d2a876ceddf5b9323f5a4a",
572 short: "12d19af20458",
573 time: time.Date(2022, 2, 23, 18, 48, 2, 0, time.UTC),
574 },
575
576
577
578 {
579 vcs: "git",
580 path: "vcs-test.golang.org/git/odd-tags.git",
581 rev: "v3.0.0-20220223184802-12d19af20458",
582 version: "v3.0.0-20220223184802-12d19af20458+incompatible",
583 name: "12d19af204585b0db3d2a876ceddf5b9323f5a4a",
584 short: "12d19af20458",
585 time: time.Date(2022, 2, 23, 18, 48, 2, 0, time.UTC),
586 },
587 }
588
589 func TestCodeRepo(t *testing.T) {
590 testenv.MustHaveExternalNetwork(t)
591 tmpdir := t.TempDir()
592
593 for _, tt := range codeRepoTests {
594 f := func(tt codeRepoTest) func(t *testing.T) {
595 return func(t *testing.T) {
596 if strings.Contains(tt.path, "gopkg.in") {
597 testenv.SkipFlaky(t, 54503)
598 }
599
600 t.Parallel()
601 if tt.vcs != "mod" {
602 testenv.MustHaveExecPath(t, tt.vcs)
603 }
604 ctx := context.Background()
605
606 repo := Lookup(ctx, "direct", tt.path)
607
608 if tt.mpath == "" {
609 tt.mpath = tt.path
610 }
611 if mpath := repo.ModulePath(); mpath != tt.mpath {
612 t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath)
613 }
614
615 info, err := repo.Stat(ctx, tt.rev)
616 if err != nil {
617 if tt.err != "" {
618 if !strings.Contains(err.Error(), tt.err) {
619 t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err)
620 }
621 return
622 }
623 t.Fatalf("repo.Stat(%q): %v", tt.rev, err)
624 }
625 if tt.err != "" {
626 t.Errorf("repo.Stat(%q): success, wanted error", tt.rev)
627 }
628 if info.Version != tt.version {
629 t.Errorf("info.Version = %q, want %q", info.Version, tt.version)
630 }
631 if info.Name != tt.name {
632 t.Errorf("info.Name = %q, want %q", info.Name, tt.name)
633 }
634 if info.Short != tt.short {
635 t.Errorf("info.Short = %q, want %q", info.Short, tt.short)
636 }
637 if !info.Time.Equal(tt.time) {
638 t.Errorf("info.Time = %v, want %v", info.Time, tt.time)
639 }
640
641 if tt.gomod != "" || tt.gomodErr != "" {
642 data, err := repo.GoMod(ctx, tt.version)
643 if err != nil && tt.gomodErr == "" {
644 t.Errorf("repo.GoMod(%q): %v", tt.version, err)
645 } else if err != nil && tt.gomodErr != "" {
646 if err.Error() != tt.gomodErr {
647 t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr)
648 }
649 } else if tt.gomodErr != "" {
650 t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr)
651 } else if string(data) != tt.gomod {
652 t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod)
653 }
654 }
655
656 needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "")
657 if tt.zip != nil || tt.zipErr != "" || needHash {
658 f, err := os.CreateTemp(tmpdir, tt.version+".zip.")
659 if err != nil {
660 t.Fatalf("os.CreateTemp: %v", err)
661 }
662 zipfile := f.Name()
663 defer func() {
664 f.Close()
665 os.Remove(zipfile)
666 }()
667
668 var w io.Writer
669 var h hash.Hash
670 if needHash {
671 h = sha256.New()
672 w = io.MultiWriter(f, h)
673 } else {
674 w = f
675 }
676 err = repo.Zip(ctx, w, tt.version)
677 f.Close()
678 if err != nil {
679 if tt.zipErr != "" {
680 if err.Error() == tt.zipErr {
681 return
682 }
683 t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr)
684 }
685 t.Fatalf("repo.Zip(%q): %v", tt.version, err)
686 }
687 if tt.zipErr != "" {
688 t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr)
689 }
690
691 if tt.zip != nil {
692 prefix := tt.path + "@" + tt.version + "/"
693 z, err := zip.OpenReader(zipfile)
694 if err != nil {
695 t.Fatalf("open zip %s: %v", zipfile, err)
696 }
697 var names []string
698 for _, file := range z.File {
699 if !strings.HasPrefix(file.Name, prefix) {
700 t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix)
701 continue
702 }
703 names = append(names, file.Name[len(prefix):])
704 }
705 z.Close()
706 if !reflect.DeepEqual(names, tt.zip) {
707 t.Fatalf("zip = %v\nwant %v\n", names, tt.zip)
708 }
709 }
710
711 if needHash {
712 sum, err := dirhash.HashZip(zipfile, dirhash.Hash1)
713 if err != nil {
714 t.Errorf("repo.Zip(%q): %v", tt.version, err)
715 } else if sum != tt.zipSum {
716 t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum)
717 } else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash {
718 t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash)
719 }
720 }
721 }
722 }
723 }
724 t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt))
725 if strings.HasPrefix(tt.path, vgotest1git) {
726 for vcs, alt := range altVgotests {
727 altTest := tt
728 altTest.vcs = vcs
729 altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git)
730 if strings.HasPrefix(altTest.mpath, vgotest1git) {
731 altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git)
732 }
733 var m map[string]string
734 if alt == vgotest1hg {
735 m = hgmap
736 }
737 altTest.version = remap(altTest.version, m)
738 altTest.name = remap(altTest.name, m)
739 altTest.short = remap(altTest.short, m)
740 altTest.rev = remap(altTest.rev, m)
741 altTest.err = remap(altTest.err, m)
742 altTest.gomodErr = remap(altTest.gomodErr, m)
743 altTest.zipErr = remap(altTest.zipErr, m)
744 altTest.zipSum = ""
745 altTest.zipFileHash = ""
746 t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest))
747 }
748 }
749 }
750 }
751
752 var hgmap = map[string]string{
753 "github.com/rsc/vgotest1": "vcs-test.golang.org/hg/vgotest1.hg",
754 "f18795870fb14388a21ef3ebc1d75911c8694f31": "a9ad6d1d14eb544f459f446210c7eb3b009807c6",
755 "ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9": "f1fc0f22021b638d073d31c752847e7bf385def7",
756 "b769f2de407a4db81af9c5de0a06016d60d2ea09": "92c7eb888b4fac17f1c6bd2e1060a1b881a3b832",
757 "8afe2b2efed96e0880ecd2a69b98a53b8c2738b6": "4e58084d459ae7e79c8c2264d0e8e9a92eb5cd44",
758 "2f615117ce481c8efef46e0cc0b4b4dccfac8fea": "879ea98f7743c8eff54f59a918f3a24123d1cf46",
759 "80d85c5d4d17598a0e9055e7c175a32b415d6128": "e125018e286a4b09061079a81e7b537070b7ff71",
760 "1f863feb76bc7029b78b21c5375644838962f88d": "bf63880162304a9337477f3858f5b7e255c75459",
761 "45f53230a74ad275c7127e117ac46914c8126160": "814fce58e83abd5bf2a13892e0b0e1198abefcd4",
762 }
763
764 func remap(name string, m map[string]string) string {
765 if m[name] != "" {
766 return m[name]
767 }
768 if codehost.AllHex(name) {
769 for k, v := range m {
770 if strings.HasPrefix(k, name) {
771 return v[:len(name)]
772 }
773 }
774 }
775 for k, v := range m {
776 name = strings.ReplaceAll(name, k, v)
777 if codehost.AllHex(k) {
778 name = strings.ReplaceAll(name, k[:12], v[:12])
779 }
780 }
781 return name
782 }
783
784 var codeRepoVersionsTests = []struct {
785 vcs string
786 path string
787 prefix string
788 versions []string
789 }{
790 {
791 vcs: "git",
792 path: "github.com/rsc/vgotest1",
793 versions: []string{"v0.0.0", "v0.0.1", "v1.0.0", "v1.0.1", "v1.0.2", "v1.0.3", "v1.1.0"},
794 },
795 {
796 vcs: "git",
797 path: "github.com/rsc/vgotest1",
798 prefix: "v1.0",
799 versions: []string{"v1.0.0", "v1.0.1", "v1.0.2", "v1.0.3"},
800 },
801 {
802 vcs: "git",
803 path: "github.com/rsc/vgotest1/v2",
804 versions: []string{"v2.0.0", "v2.0.1", "v2.0.2", "v2.0.3", "v2.0.4", "v2.0.5", "v2.0.6"},
805 },
806 {
807 vcs: "mod",
808 path: "swtch.com/testmod",
809 versions: []string{"v1.0.0", "v1.1.1"},
810 },
811 {
812 vcs: "git",
813 path: "vcs-test.golang.org/git/odd-tags.git",
814 versions: nil,
815 },
816 }
817
818 func TestCodeRepoVersions(t *testing.T) {
819 testenv.MustHaveExternalNetwork(t)
820
821 for _, tt := range codeRepoVersionsTests {
822 tt := tt
823 t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) {
824 if strings.Contains(tt.path, "gopkg.in") {
825 testenv.SkipFlaky(t, 54503)
826 }
827
828 t.Parallel()
829 if tt.vcs != "mod" {
830 testenv.MustHaveExecPath(t, tt.vcs)
831 }
832 ctx := context.Background()
833
834 repo := Lookup(ctx, "direct", tt.path)
835 list, err := repo.Versions(ctx, tt.prefix)
836 if err != nil {
837 t.Fatalf("Versions(%q): %v", tt.prefix, err)
838 }
839 if !reflect.DeepEqual(list.List, tt.versions) {
840 t.Fatalf("Versions(%q):\nhave %v\nwant %v", tt.prefix, list, tt.versions)
841 }
842 })
843 }
844 }
845
846 var latestTests = []struct {
847 vcs string
848 path string
849 version string
850 err string
851 }{
852 {
853 vcs: "git",
854 path: "github.com/rsc/empty",
855 err: "no commits",
856 },
857 {
858 vcs: "git",
859 path: "github.com/rsc/vgotest1",
860 err: `github.com/rsc/vgotest1@v0.0.0-20180219223237-a08abb797a67: invalid version: go.mod has post-v0 module path "github.com/vgotest1/v2" at revision a08abb797a67`,
861 },
862 {
863 vcs: "git",
864 path: "github.com/rsc/vgotest1/v2",
865 err: `github.com/rsc/vgotest1/v2@v2.0.0-20180219223237-a08abb797a67: invalid version: github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision a08abb797a67`,
866 },
867 {
868 vcs: "git",
869 path: "github.com/rsc/vgotest1/subdir",
870 err: "github.com/rsc/vgotest1/subdir@v0.0.0-20180219223237-a08abb797a67: invalid version: missing github.com/rsc/vgotest1/subdir/go.mod at revision a08abb797a67",
871 },
872 {
873 vcs: "git",
874 path: "vcs-test.golang.org/git/commit-after-tag.git",
875 version: "v1.0.1-0.20190715211727-b325d8217783",
876 },
877 {
878 vcs: "git",
879 path: "vcs-test.golang.org/git/no-tags.git",
880 version: "v0.0.0-20190715212047-e706ba1d9f6d",
881 },
882 {
883 vcs: "mod",
884 path: "swtch.com/testmod",
885 version: "v1.1.1",
886 },
887 }
888
889 func TestLatest(t *testing.T) {
890 testenv.MustHaveExternalNetwork(t)
891
892 for _, tt := range latestTests {
893 name := strings.ReplaceAll(tt.path, "/", "_")
894 t.Run(name, func(t *testing.T) {
895 tt := tt
896 t.Parallel()
897 if tt.vcs != "mod" {
898 testenv.MustHaveExecPath(t, tt.vcs)
899 }
900 ctx := context.Background()
901
902 repo := Lookup(ctx, "direct", tt.path)
903 info, err := repo.Latest(ctx)
904 if err != nil {
905 if tt.err != "" {
906 if err.Error() == tt.err {
907 return
908 }
909 t.Fatalf("Latest(): %v, want %q", err, tt.err)
910 }
911 t.Fatalf("Latest(): %v", err)
912 }
913 if tt.err != "" {
914 t.Fatalf("Latest() = %v, want error %q", info.Version, tt.err)
915 }
916 if info.Version != tt.version {
917 t.Fatalf("Latest() = %v, want %v", info.Version, tt.version)
918 }
919 })
920 }
921 }
922
923
924 type fixedTagsRepo struct {
925 tags []string
926 codehost.Repo
927 }
928
929 func (ch *fixedTagsRepo) Tags(ctx context.Context, prefix string) (*codehost.Tags, error) {
930 tags := &codehost.Tags{}
931 for _, t := range ch.tags {
932 tags.List = append(tags.List, codehost.Tag{Name: t})
933 }
934 return tags, nil
935 }
936
937 func TestNonCanonicalSemver(t *testing.T) {
938 t.Parallel()
939 ctx := context.Background()
940
941 root := "golang.org/x/issue24476"
942 ch := &fixedTagsRepo{
943 tags: []string{
944 "", "huh?", "1.0.1",
945
946 "v1.🐕.🐄",
947 "v1", "v0.1",
948
949 "v1.0.1",
950 },
951 }
952
953 cr, err := newCodeRepo(ch, root, root)
954 if err != nil {
955 t.Fatal(err)
956 }
957
958 v, err := cr.Versions(ctx, "")
959 if err != nil {
960 t.Fatal(err)
961 }
962 if len(v.List) != 1 || v.List[0] != "v1.0.1" {
963 t.Fatal("unexpected versions returned:", v)
964 }
965 }
966
View as plain text