github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/modfetch/coderepo_test.go (about) 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 5 package modfetch 6 7 import ( 8 "archive/zip" 9 "crypto/sha256" 10 "encoding/hex" 11 "hash" 12 "github.com/gagliardetto/golang-go/not-internal/testenv" 13 "io" 14 "io/ioutil" 15 "log" 16 "os" 17 "reflect" 18 "strings" 19 "testing" 20 "time" 21 22 "github.com/gagliardetto/golang-go/cmd/go/not-internal/cfg" 23 "github.com/gagliardetto/golang-go/cmd/go/not-internal/modfetch/codehost" 24 25 "golang.org/x/mod/sumdb/dirhash" 26 ) 27 28 func TestMain(m *testing.M) { 29 os.Exit(testMain(m)) 30 } 31 32 func testMain(m *testing.M) int { 33 cfg.GOPROXY = "direct" 34 35 // The sum database is populated using a released version of the go command, 36 // but this test may include fixes for additional modules that previously 37 // could not be fetched. Since this test isn't executing any of the resolved 38 // code, bypass the sum database. 39 cfg.GOSUMDB = "off" 40 41 dir, err := ioutil.TempDir("", "gitrepo-test-") 42 if err != nil { 43 log.Fatal(err) 44 } 45 defer os.RemoveAll(dir) 46 47 codehost.WorkRoot = dir 48 return m.Run() 49 } 50 51 const ( 52 vgotest1git = "github.com/rsc/vgotest1" 53 vgotest1hg = "vcs-test.golang.org/hg/vgotest1.hg" 54 ) 55 56 var altVgotests = map[string]string{ 57 "hg": vgotest1hg, 58 } 59 60 type codeRepoTest struct { 61 vcs string 62 path string 63 lookErr string 64 mpath string 65 rev string 66 err string 67 version string 68 name string 69 short string 70 time time.Time 71 gomod string 72 gomodErr string 73 zip []string 74 zipErr string 75 zipSum string 76 zipFileHash string 77 } 78 79 var codeRepoTests = []codeRepoTest{ 80 { 81 vcs: "git", 82 path: "github.com/rsc/vgotest1", 83 rev: "v0.0.0", 84 version: "v0.0.0", 85 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", 86 short: "80d85c5d4d17", 87 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), 88 zip: []string{ 89 "LICENSE", 90 "README.md", 91 "pkg/p.go", 92 }, 93 zipSum: "h1:zVEjciLdlk/TPWCOyZo7k24T+tOKRQC+u8MKq/xS80I=", 94 zipFileHash: "738a00ddbfe8c329dce6b48e1f23c8e22a92db50f3cfb2653caa0d62676bc09c", 95 }, 96 { 97 vcs: "git", 98 path: "github.com/rsc/vgotest1", 99 rev: "v0.0.0-20180219231006-80d85c5d4d17", 100 version: "v0.0.0-20180219231006-80d85c5d4d17", 101 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", 102 short: "80d85c5d4d17", 103 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), 104 zip: []string{ 105 "LICENSE", 106 "README.md", 107 "pkg/p.go", 108 }, 109 zipSum: "h1:nOznk2xKsLGkTnXe0q9t1Ewt9jxK+oadtafSUqHM3Ec=", 110 zipFileHash: "bacb08f391e29d2eaaef8281b5c129ee6d890e608ee65877e0003c0181a766c8", 111 }, 112 { 113 vcs: "git", 114 path: "github.com/rsc/vgotest1", 115 rev: "v0.0.1-0.20180219231006-80d85c5d4d17", 116 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`, 117 }, 118 { 119 vcs: "git", 120 path: "github.com/rsc/vgotest1", 121 rev: "v1.0.0", 122 version: "v1.0.0", 123 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", 124 short: "80d85c5d4d17", 125 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), 126 zip: []string{ 127 "LICENSE", 128 "README.md", 129 "pkg/p.go", 130 }, 131 zipSum: "h1:e040hOoWGeuJLawDjK9DW6med+cz9FxMFYDMOVG8ctQ=", 132 zipFileHash: "74caab65cfbea427c341fa815f3bb0378681d8f0e3cf62a7f207014263ec7be3", 133 }, 134 { 135 vcs: "git", 136 path: "github.com/rsc/vgotest1/v2", 137 rev: "v2.0.0", 138 version: "v2.0.0", 139 name: "45f53230a74ad275c7127e117ac46914c8126160", 140 short: "45f53230a74a", 141 time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC), 142 err: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0", 143 }, 144 { 145 vcs: "git", 146 path: "github.com/rsc/vgotest1", 147 rev: "80d85c5", 148 version: "v1.0.0", 149 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", 150 short: "80d85c5d4d17", 151 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), 152 zip: []string{ 153 "LICENSE", 154 "README.md", 155 "pkg/p.go", 156 }, 157 zipSum: "h1:e040hOoWGeuJLawDjK9DW6med+cz9FxMFYDMOVG8ctQ=", 158 zipFileHash: "74caab65cfbea427c341fa815f3bb0378681d8f0e3cf62a7f207014263ec7be3", 159 }, 160 { 161 vcs: "git", 162 path: "github.com/rsc/vgotest1", 163 rev: "mytag", 164 version: "v1.0.0", 165 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", 166 short: "80d85c5d4d17", 167 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), 168 zip: []string{ 169 "LICENSE", 170 "README.md", 171 "pkg/p.go", 172 }, 173 }, 174 { 175 vcs: "git", 176 path: "github.com/rsc/vgotest1/v2", 177 rev: "45f53230a", 178 version: "v2.0.0", 179 name: "45f53230a74ad275c7127e117ac46914c8126160", 180 short: "45f53230a74a", 181 time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC), 182 err: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0", 183 }, 184 { 185 vcs: "git", 186 path: "github.com/rsc/vgotest1/v54321", 187 rev: "80d85c5", 188 version: "v54321.0.0-20180219231006-80d85c5d4d17", 189 name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", 190 short: "80d85c5d4d17", 191 time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), 192 err: "missing github.com/rsc/vgotest1/go.mod and .../v54321/go.mod at revision 80d85c5d4d17", 193 }, 194 { 195 vcs: "git", 196 path: "github.com/rsc/vgotest1/submod", 197 rev: "v1.0.0", 198 err: "unknown revision submod/v1.0.0", 199 }, 200 { 201 vcs: "git", 202 path: "github.com/rsc/vgotest1/submod", 203 rev: "v1.0.3", 204 err: "unknown revision submod/v1.0.3", 205 }, 206 { 207 vcs: "git", 208 path: "github.com/rsc/vgotest1/submod", 209 rev: "v1.0.4", 210 version: "v1.0.4", 211 name: "8afe2b2efed96e0880ecd2a69b98a53b8c2738b6", 212 short: "8afe2b2efed9", 213 time: time.Date(2018, 2, 19, 23, 12, 7, 0, time.UTC), 214 gomod: "module \"github.com/vgotest1/submod\" // submod/go.mod\n", 215 zip: []string{ 216 "go.mod", 217 "pkg/p.go", 218 "LICENSE", 219 }, 220 zipSum: "h1:iMsJ/9uQsk6MnZNnJK311f11QiSlmN92Q2aSjCywuJY=", 221 zipFileHash: "95801bfa69c5197ae809af512946d22f22850068527cd78100ae3f176bc8043b", 222 }, 223 { 224 vcs: "git", 225 path: "github.com/rsc/vgotest1", 226 rev: "v1.1.0", 227 version: "v1.1.0", 228 name: "b769f2de407a4db81af9c5de0a06016d60d2ea09", 229 short: "b769f2de407a", 230 time: time.Date(2018, 2, 19, 23, 13, 36, 0, time.UTC), 231 gomod: "module \"github.com/rsc/vgotest1\" // root go.mod\nrequire \"github.com/rsc/vgotest1/submod\" v1.0.5\n", 232 zip: []string{ 233 "LICENSE", 234 "README.md", 235 "go.mod", 236 "pkg/p.go", 237 }, 238 zipSum: "h1:M69k7q+8bQ+QUpHov45Z/NoR8rj3DsQJUnXLWvf01+Q=", 239 zipFileHash: "58af45fb248d320ea471f568e006379e2b8d71d6d1663f9b19b2e00fd9ac9265", 240 }, 241 { 242 vcs: "git", 243 path: "github.com/rsc/vgotest1/v2", 244 rev: "v2.0.1", 245 version: "v2.0.1", 246 name: "ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9", 247 short: "ea65f87c8f52", 248 time: time.Date(2018, 2, 19, 23, 14, 23, 0, time.UTC), 249 gomod: "module \"github.com/rsc/vgotest1/v2\" // root go.mod\n", 250 zipSum: "h1:QmgYy/zt+uoWhDpcsgrSVzYFvKtBEjl5zT/FRz9GTzA=", 251 zipFileHash: "1aedf1546d322a0121879ddfd6d0e8bfbd916d2cafbeb538ddb440e04b04b9ef", 252 }, 253 { 254 vcs: "git", 255 path: "github.com/rsc/vgotest1/v2", 256 rev: "v2.0.3", 257 version: "v2.0.3", 258 name: "f18795870fb14388a21ef3ebc1d75911c8694f31", 259 short: "f18795870fb1", 260 time: time.Date(2018, 2, 19, 23, 16, 4, 0, time.UTC), 261 err: "github.com/rsc/vgotest1/v2/go.mod has non-.../v2 module path \"github.com/rsc/vgotest\" at revision v2.0.3", 262 }, 263 { 264 vcs: "git", 265 path: "github.com/rsc/vgotest1/v2", 266 rev: "v2.0.4", 267 version: "v2.0.4", 268 name: "1f863feb76bc7029b78b21c5375644838962f88d", 269 short: "1f863feb76bc", 270 time: time.Date(2018, 2, 20, 0, 3, 38, 0, time.UTC), 271 err: "github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision v2.0.4", 272 }, 273 { 274 vcs: "git", 275 path: "github.com/rsc/vgotest1/v2", 276 rev: "v2.0.5", 277 version: "v2.0.5", 278 name: "2f615117ce481c8efef46e0cc0b4b4dccfac8fea", 279 short: "2f615117ce48", 280 time: time.Date(2018, 2, 20, 0, 3, 59, 0, time.UTC), 281 gomod: "module \"github.com/rsc/vgotest1/v2\" // v2/go.mod\n", 282 zipSum: "h1:RIEb9q1SUSEQOzMn0zfl/LQxGFWlhWEAdeEguf1MLGU=", 283 zipFileHash: "7d92c2c328c5e9b0694101353705d5843746ec1d93a1e986d0da54c8a14dfe6d", 284 }, 285 { 286 // redirect to github 287 vcs: "git", 288 path: "rsc.io/quote", 289 rev: "v1.0.0", 290 version: "v1.0.0", 291 name: "f488df80bcdbd3e5bafdc24ad7d1e79e83edd7e6", 292 short: "f488df80bcdb", 293 time: time.Date(2018, 2, 14, 0, 45, 20, 0, time.UTC), 294 gomod: "module \"rsc.io/quote\"\n", 295 zipSum: "h1:haUSojyo3j2M9g7CEUFG8Na09dtn7QKxvPGaPVQdGwM=", 296 zipFileHash: "5c08ba2c09a364f93704aaa780e7504346102c6ef4fe1333a11f09904a732078", 297 }, 298 { 299 // redirect to static hosting proxy 300 vcs: "mod", 301 path: "swtch.com/testmod", 302 rev: "v1.0.0", 303 version: "v1.0.0", 304 // NO name or short - we intentionally ignore those in the proxy protocol 305 time: time.Date(1972, 7, 18, 12, 34, 56, 0, time.UTC), 306 gomod: "module \"swtch.com/testmod\"\n", 307 }, 308 { 309 // redirect to googlesource 310 vcs: "git", 311 path: "golang.org/x/text", 312 rev: "4e4a3210bb", 313 version: "v0.3.1-0.20180208041248-4e4a3210bb54", 314 name: "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1", 315 short: "4e4a3210bb54", 316 time: time.Date(2018, 2, 8, 4, 12, 48, 0, time.UTC), 317 zipSum: "h1:Yxu6pHX9X2RECiuw/Q5/4uvajuaowck8zOFKXgbfNBk=", 318 zipFileHash: "ac2c165a5c10aa5a7545dea60a08e019270b982fa6c8bdcb5943931de64922fe", 319 }, 320 { 321 vcs: "git", 322 path: "github.com/pkg/errors", 323 rev: "v0.8.0", 324 version: "v0.8.0", 325 name: "645ef00459ed84a119197bfb8d8205042c6df63d", 326 short: "645ef00459ed", 327 time: time.Date(2016, 9, 29, 1, 48, 1, 0, time.UTC), 328 zipSum: "h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=", 329 zipFileHash: "e4fa69ba057356614edbc1da881a7d3ebb688505be49f65965686bcb859e2fae", 330 }, 331 { 332 // package in subdirectory - custom domain 333 // In general we can't reject these definitively in Lookup, 334 // but gopkg.in is special. 335 vcs: "git", 336 path: "gopkg.in/yaml.v2/abc", 337 lookErr: "invalid module path \"gopkg.in/yaml.v2/abc\"", 338 }, 339 { 340 // package in subdirectory - github 341 // Because it's a package, Stat should fail entirely. 342 vcs: "git", 343 path: "github.com/rsc/quote/buggy", 344 rev: "c4d4236f", 345 err: "missing github.com/rsc/quote/buggy/go.mod at revision c4d4236f9242", 346 }, 347 { 348 vcs: "git", 349 path: "gopkg.in/yaml.v2", 350 rev: "d670f940", 351 version: "v2.0.0", 352 name: "d670f9405373e636a5a2765eea47fac0c9bc91a4", 353 short: "d670f9405373", 354 time: time.Date(2018, 1, 9, 11, 43, 31, 0, time.UTC), 355 gomod: "module gopkg.in/yaml.v2\n", 356 zipSum: "h1:uUkhRGrsEyx/laRdeS6YIQKIys8pg+lRSRdVMTYjivs=", 357 zipFileHash: "7b0a141b1b0b49772ab4eecfd11dfd6609a94a5e868cab04a3abb1861ffaa877", 358 }, 359 { 360 vcs: "git", 361 path: "gopkg.in/check.v1", 362 rev: "20d25e280405", 363 version: "v1.0.0-20161208181325-20d25e280405", 364 name: "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec", 365 short: "20d25e280405", 366 time: time.Date(2016, 12, 8, 18, 13, 25, 0, time.UTC), 367 gomod: "module gopkg.in/check.v1\n", 368 zipSum: "h1:829vOVxxusYHC+IqBtkX5mbKtsY9fheQiQn0MZRVLfQ=", 369 zipFileHash: "9e7cb3f4f1e66d722306442b0dbe1f6f43d74d1736d54c510537bdfb1d6f432f", 370 }, 371 { 372 vcs: "git", 373 path: "vcs-test.golang.org/go/mod/gitrepo1", 374 rev: "master", 375 version: "v1.2.4-annotated", 376 name: "ede458df7cd0fdca520df19a33158086a8a68e81", 377 short: "ede458df7cd0", 378 time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC), 379 gomod: "module vcs-test.golang.org/go/mod/gitrepo1\n", 380 zipSum: "h1:YJYZRsM9BHFTlVr8YADjT0cJH8uFIDtoc5NLiVqZEx8=", 381 zipFileHash: "c15e49d58b7a4c37966cbe5bc01a0330cd5f2927e990e1839bda1d407766d9c5", 382 }, 383 { 384 vcs: "git", 385 path: "gopkg.in/natefinch/lumberjack.v2", 386 rev: "latest", 387 version: "v2.0.0-20170531160350-a96e63847dc3", 388 name: "a96e63847dc3c67d17befa69c303767e2f84e54f", 389 short: "a96e63847dc3", 390 time: time.Date(2017, 5, 31, 16, 3, 50, 0, time.UTC), 391 gomod: "module gopkg.in/natefinch/lumberjack.v2\n", 392 zipSum: "h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI=", 393 zipFileHash: "b5de0da7bbbec76709eef1ac71b6c9ff423b9fbf3bb97b56743450d4937b06d5", 394 }, 395 { 396 vcs: "git", 397 path: "gopkg.in/natefinch/lumberjack.v2", 398 // This repo has a v2.1 tag. 399 // We only allow semver references to tags that are fully qualified, as in v2.1.0. 400 // Because we can't record v2.1.0 (the actual tag is v2.1), we record a pseudo-version 401 // instead, same as if the tag were any other non-version-looking string. 402 // We use a v2 pseudo-version here because of the .v2 in the path, not because 403 // of the v2 in the rev. 404 rev: "v2.1", // non-canonical semantic version turns into pseudo-version 405 version: "v2.0.0-20170531160350-a96e63847dc3", 406 name: "a96e63847dc3c67d17befa69c303767e2f84e54f", 407 short: "a96e63847dc3", 408 time: time.Date(2017, 5, 31, 16, 3, 50, 0, time.UTC), 409 gomod: "module gopkg.in/natefinch/lumberjack.v2\n", 410 }, 411 { 412 vcs: "git", 413 path: "vcs-test.golang.org/go/v2module/v2", 414 rev: "v2.0.0", 415 version: "v2.0.0", 416 name: "203b91c896acd173aa719e4cdcb7d463c4b090fa", 417 short: "203b91c896ac", 418 time: time.Date(2019, 4, 3, 15, 52, 15, 0, time.UTC), 419 gomod: "module vcs-test.golang.org/go/v2module/v2\n\ngo 1.12\n", 420 zipSum: "h1:JItBZ+gwA5WvtZEGEbuDL4lUttGtLrs53lmdurq3bOg=", 421 zipFileHash: "9ea9ae1673cffcc44b7fdd3cc89953d68c102449b46c982dbf085e4f2e394da5", 422 }, 423 } 424 425 func TestCodeRepo(t *testing.T) { 426 testenv.MustHaveExternalNetwork(t) 427 428 tmpdir, err := ioutil.TempDir("", "modfetch-test-") 429 if err != nil { 430 t.Fatal(err) 431 } 432 defer os.RemoveAll(tmpdir) 433 434 t.Run("parallel", func(t *testing.T) { 435 for _, tt := range codeRepoTests { 436 f := func(tt codeRepoTest) func(t *testing.T) { 437 return func(t *testing.T) { 438 t.Parallel() 439 if tt.vcs != "mod" { 440 testenv.MustHaveExecPath(t, tt.vcs) 441 } 442 443 repo, err := Lookup("direct", tt.path) 444 if tt.lookErr != "" { 445 if err != nil && err.Error() == tt.lookErr { 446 return 447 } 448 t.Errorf("Lookup(%q): %v, want error %q", tt.path, err, tt.lookErr) 449 } 450 if err != nil { 451 t.Fatalf("Lookup(%q): %v", tt.path, err) 452 } 453 454 if tt.mpath == "" { 455 tt.mpath = tt.path 456 } 457 if mpath := repo.ModulePath(); mpath != tt.mpath { 458 t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath) 459 } 460 461 info, err := repo.Stat(tt.rev) 462 if err != nil { 463 if tt.err != "" { 464 if !strings.Contains(err.Error(), tt.err) { 465 t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err) 466 } 467 return 468 } 469 t.Fatalf("repo.Stat(%q): %v", tt.rev, err) 470 } 471 if tt.err != "" { 472 t.Errorf("repo.Stat(%q): success, wanted error", tt.rev) 473 } 474 if info.Version != tt.version { 475 t.Errorf("info.Version = %q, want %q", info.Version, tt.version) 476 } 477 if info.Name != tt.name { 478 t.Errorf("info.Name = %q, want %q", info.Name, tt.name) 479 } 480 if info.Short != tt.short { 481 t.Errorf("info.Short = %q, want %q", info.Short, tt.short) 482 } 483 if !info.Time.Equal(tt.time) { 484 t.Errorf("info.Time = %v, want %v", info.Time, tt.time) 485 } 486 487 if tt.gomod != "" || tt.gomodErr != "" { 488 data, err := repo.GoMod(tt.version) 489 if err != nil && tt.gomodErr == "" { 490 t.Errorf("repo.GoMod(%q): %v", tt.version, err) 491 } else if err != nil && tt.gomodErr != "" { 492 if err.Error() != tt.gomodErr { 493 t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr) 494 } 495 } else if tt.gomodErr != "" { 496 t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr) 497 } else if string(data) != tt.gomod { 498 t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod) 499 } 500 } 501 502 needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "") 503 if tt.zip != nil || tt.zipErr != "" || needHash { 504 f, err := ioutil.TempFile(tmpdir, tt.version+".zip.") 505 if err != nil { 506 t.Fatalf("ioutil.TempFile: %v", err) 507 } 508 zipfile := f.Name() 509 defer func() { 510 f.Close() 511 os.Remove(zipfile) 512 }() 513 514 var w io.Writer 515 var h hash.Hash 516 if needHash { 517 h = sha256.New() 518 w = io.MultiWriter(f, h) 519 } else { 520 w = f 521 } 522 err = repo.Zip(w, tt.version) 523 f.Close() 524 if err != nil { 525 if tt.zipErr != "" { 526 if err.Error() == tt.zipErr { 527 return 528 } 529 t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr) 530 } 531 t.Fatalf("repo.Zip(%q): %v", tt.version, err) 532 } 533 if tt.zipErr != "" { 534 t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr) 535 } 536 537 if tt.zip != nil { 538 prefix := tt.path + "@" + tt.version + "/" 539 z, err := zip.OpenReader(zipfile) 540 if err != nil { 541 t.Fatalf("open zip %s: %v", zipfile, err) 542 } 543 var names []string 544 for _, file := range z.File { 545 if !strings.HasPrefix(file.Name, prefix) { 546 t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix) 547 continue 548 } 549 names = append(names, file.Name[len(prefix):]) 550 } 551 z.Close() 552 if !reflect.DeepEqual(names, tt.zip) { 553 t.Fatalf("zip = %v\nwant %v\n", names, tt.zip) 554 } 555 } 556 557 if needHash { 558 sum, err := dirhash.HashZip(zipfile, dirhash.Hash1) 559 if err != nil { 560 t.Errorf("repo.Zip(%q): %v", tt.version, err) 561 } else if sum != tt.zipSum { 562 t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum) 563 } else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash { 564 t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash) 565 } 566 } 567 } 568 } 569 } 570 t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt)) 571 if strings.HasPrefix(tt.path, vgotest1git) { 572 for vcs, alt := range altVgotests { 573 altTest := tt 574 altTest.vcs = vcs 575 altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git) 576 if strings.HasPrefix(altTest.mpath, vgotest1git) { 577 altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git) 578 } 579 var m map[string]string 580 if alt == vgotest1hg { 581 m = hgmap 582 } 583 altTest.version = remap(altTest.version, m) 584 altTest.name = remap(altTest.name, m) 585 altTest.short = remap(altTest.short, m) 586 altTest.rev = remap(altTest.rev, m) 587 altTest.err = remap(altTest.err, m) 588 altTest.gomodErr = remap(altTest.gomodErr, m) 589 altTest.zipErr = remap(altTest.zipErr, m) 590 altTest.zipSum = "" 591 altTest.zipFileHash = "" 592 t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest)) 593 } 594 } 595 } 596 }) 597 } 598 599 var hgmap = map[string]string{ 600 "github.com/rsc/vgotest1": "vcs-test.golang.org/hg/vgotest1.hg", 601 "f18795870fb14388a21ef3ebc1d75911c8694f31": "a9ad6d1d14eb544f459f446210c7eb3b009807c6", 602 "ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9": "f1fc0f22021b638d073d31c752847e7bf385def7", 603 "b769f2de407a4db81af9c5de0a06016d60d2ea09": "92c7eb888b4fac17f1c6bd2e1060a1b881a3b832", 604 "8afe2b2efed96e0880ecd2a69b98a53b8c2738b6": "4e58084d459ae7e79c8c2264d0e8e9a92eb5cd44", 605 "2f615117ce481c8efef46e0cc0b4b4dccfac8fea": "879ea98f7743c8eff54f59a918f3a24123d1cf46", 606 "80d85c5d4d17598a0e9055e7c175a32b415d6128": "e125018e286a4b09061079a81e7b537070b7ff71", 607 "1f863feb76bc7029b78b21c5375644838962f88d": "bf63880162304a9337477f3858f5b7e255c75459", 608 "45f53230a74ad275c7127e117ac46914c8126160": "814fce58e83abd5bf2a13892e0b0e1198abefcd4", 609 } 610 611 func remap(name string, m map[string]string) string { 612 if m[name] != "" { 613 return m[name] 614 } 615 if codehost.AllHex(name) { 616 for k, v := range m { 617 if strings.HasPrefix(k, name) { 618 return v[:len(name)] 619 } 620 } 621 } 622 for k, v := range m { 623 name = strings.ReplaceAll(name, k, v) 624 if codehost.AllHex(k) { 625 name = strings.ReplaceAll(name, k[:12], v[:12]) 626 } 627 } 628 return name 629 } 630 631 var codeRepoVersionsTests = []struct { 632 vcs string 633 path string 634 prefix string 635 versions []string 636 }{ 637 { 638 vcs: "git", 639 path: "github.com/rsc/vgotest1", 640 versions: []string{"v0.0.0", "v0.0.1", "v1.0.0", "v1.0.1", "v1.0.2", "v1.0.3", "v1.1.0"}, 641 }, 642 { 643 vcs: "git", 644 path: "github.com/rsc/vgotest1", 645 prefix: "v1.0", 646 versions: []string{"v1.0.0", "v1.0.1", "v1.0.2", "v1.0.3"}, 647 }, 648 { 649 vcs: "git", 650 path: "github.com/rsc/vgotest1/v2", 651 versions: []string{"v2.0.0", "v2.0.1", "v2.0.2", "v2.0.3", "v2.0.4", "v2.0.5", "v2.0.6"}, 652 }, 653 { 654 vcs: "mod", 655 path: "swtch.com/testmod", 656 versions: []string{"v1.0.0", "v1.1.1"}, 657 }, 658 { 659 vcs: "git", 660 path: "gopkg.in/russross/blackfriday.v2", 661 versions: []string{"v2.0.0", "v2.0.1"}, 662 }, 663 { 664 vcs: "git", 665 path: "gopkg.in/natefinch/lumberjack.v2", 666 versions: []string{"v2.0.0"}, 667 }, 668 } 669 670 func TestCodeRepoVersions(t *testing.T) { 671 testenv.MustHaveExternalNetwork(t) 672 673 tmpdir, err := ioutil.TempDir("", "vgo-modfetch-test-") 674 if err != nil { 675 t.Fatal(err) 676 } 677 defer os.RemoveAll(tmpdir) 678 679 t.Run("parallel", func(t *testing.T) { 680 for _, tt := range codeRepoVersionsTests { 681 t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) { 682 tt := tt 683 t.Parallel() 684 if tt.vcs != "mod" { 685 testenv.MustHaveExecPath(t, tt.vcs) 686 } 687 688 repo, err := Lookup("direct", tt.path) 689 if err != nil { 690 t.Fatalf("Lookup(%q): %v", tt.path, err) 691 } 692 list, err := repo.Versions(tt.prefix) 693 if err != nil { 694 t.Fatalf("Versions(%q): %v", tt.prefix, err) 695 } 696 if !reflect.DeepEqual(list, tt.versions) { 697 t.Fatalf("Versions(%q):\nhave %v\nwant %v", tt.prefix, list, tt.versions) 698 } 699 }) 700 } 701 }) 702 } 703 704 var latestTests = []struct { 705 vcs string 706 path string 707 version string 708 err string 709 }{ 710 { 711 vcs: "git", 712 path: "github.com/rsc/empty", 713 err: "no commits", 714 }, 715 { 716 vcs: "git", 717 path: "github.com/rsc/vgotest1", 718 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`, 719 }, 720 { 721 vcs: "git", 722 path: "github.com/rsc/vgotest1/v2", 723 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`, 724 }, 725 { 726 vcs: "git", 727 path: "github.com/rsc/vgotest1/subdir", 728 err: "github.com/rsc/vgotest1/subdir@v0.0.0-20180219223237-a08abb797a67: invalid version: missing github.com/rsc/vgotest1/subdir/go.mod at revision a08abb797a67", 729 }, 730 { 731 vcs: "git", 732 path: "vcs-test.golang.org/git/commit-after-tag.git", 733 version: "v1.0.1-0.20190715211727-b325d8217783", 734 }, 735 { 736 vcs: "git", 737 path: "vcs-test.golang.org/git/no-tags.git", 738 version: "v0.0.0-20190715212047-e706ba1d9f6d", 739 }, 740 { 741 vcs: "mod", 742 path: "swtch.com/testmod", 743 version: "v1.1.1", 744 }, 745 } 746 747 func TestLatest(t *testing.T) { 748 testenv.MustHaveExternalNetwork(t) 749 750 tmpdir, err := ioutil.TempDir("", "vgo-modfetch-test-") 751 if err != nil { 752 t.Fatal(err) 753 } 754 defer os.RemoveAll(tmpdir) 755 756 t.Run("parallel", func(t *testing.T) { 757 for _, tt := range latestTests { 758 name := strings.ReplaceAll(tt.path, "/", "_") 759 t.Run(name, func(t *testing.T) { 760 tt := tt 761 t.Parallel() 762 if tt.vcs != "mod" { 763 testenv.MustHaveExecPath(t, tt.vcs) 764 } 765 766 repo, err := Lookup("direct", tt.path) 767 if err != nil { 768 t.Fatalf("Lookup(%q): %v", tt.path, err) 769 } 770 info, err := repo.Latest() 771 if err != nil { 772 if tt.err != "" { 773 if err.Error() == tt.err { 774 return 775 } 776 t.Fatalf("Latest(): %v, want %q", err, tt.err) 777 } 778 t.Fatalf("Latest(): %v", err) 779 } 780 if tt.err != "" { 781 t.Fatalf("Latest() = %v, want error %q", info.Version, tt.err) 782 } 783 if info.Version != tt.version { 784 t.Fatalf("Latest() = %v, want %v", info.Version, tt.version) 785 } 786 }) 787 } 788 }) 789 } 790 791 // fixedTagsRepo is a fake codehost.Repo that returns a fixed list of tags 792 type fixedTagsRepo struct { 793 tags []string 794 codehost.Repo 795 } 796 797 func (ch *fixedTagsRepo) Tags(string) ([]string, error) { return ch.tags, nil } 798 799 func TestNonCanonicalSemver(t *testing.T) { 800 root := "golang.org/x/issue24476" 801 ch := &fixedTagsRepo{ 802 tags: []string{ 803 "", "huh?", "1.0.1", 804 // what about "version 1 dot dogcow"? 805 "v1.🐕.🐄", 806 "v1", "v0.1", 807 // and one normal one that should pass through 808 "v1.0.1", 809 }, 810 } 811 812 cr, err := newCodeRepo(ch, root, root) 813 if err != nil { 814 t.Fatal(err) 815 } 816 817 v, err := cr.Versions("") 818 if err != nil { 819 t.Fatal(err) 820 } 821 if len(v) != 1 || v[0] != "v1.0.1" { 822 t.Fatal("unexpected versions returned:", v) 823 } 824 }