github.com/golang/dep@v0.5.4/gps/vcs_source_test.go (about) 1 // Copyright 2017 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 gps 6 7 import ( 8 "context" 9 "io/ioutil" 10 "log" 11 "net/url" 12 "os" 13 "os/exec" 14 "path/filepath" 15 "reflect" 16 "runtime" 17 "strings" 18 "sync" 19 "testing" 20 21 "github.com/golang/dep/internal/test" 22 ) 23 24 // Parent test that executes all the slow vcs interaction tests in parallel. 25 func TestSlowVcs(t *testing.T) { 26 t.Run("write-deptree", testWriteDepTree) 27 t.Run("source-gateway", testSourceGateway) 28 t.Run("bzr-repo", testBzrRepo) 29 t.Run("bzr-source", testBzrSourceInteractions) 30 t.Run("svn-repo", testSvnRepo) 31 // TODO(sdboyer) svn-source 32 t.Run("hg-repo", testHgRepo) 33 t.Run("hg-source", testHgSourceInteractions) 34 t.Run("git-repo", testGitRepo) 35 t.Run("git-source", testGitSourceInteractions) 36 t.Run("gopkgin-source", testGopkginSourceInteractions) 37 } 38 39 func testGitSourceInteractions(t *testing.T) { 40 t.Parallel() 41 42 // This test is slowish, skip it on -short 43 if testing.Short() { 44 t.Skip("Skipping git source version fetching test in short mode") 45 } 46 requiresBins(t, "git") 47 48 cpath, err := ioutil.TempDir("", "smcache") 49 if err != nil { 50 t.Errorf("Failed to create temp dir: %s", err) 51 } 52 defer func() { 53 if err := os.RemoveAll(cpath); err != nil { 54 t.Errorf("removeAll failed: %s", err) 55 } 56 }() 57 os.Mkdir(filepath.Join(cpath, "sources"), 0777) 58 59 n := "github.com/sdboyer/gpkt" 60 un := "https://" + n 61 u, err := url.Parse(un) 62 if err != nil { 63 t.Fatalf("Error parsing URL %s: %s", un, err) 64 } 65 mb := maybeGitSource{ 66 url: u, 67 } 68 69 ctx := context.Background() 70 isrc, err := mb.try(ctx, cpath) 71 if err != nil { 72 t.Fatalf("Unexpected error while setting up gitSource for test repo: %s", err) 73 } 74 75 err = isrc.initLocal(ctx) 76 if err != nil { 77 t.Fatalf("Error on cloning git repo: %s", err) 78 } 79 80 src, ok := isrc.(*gitSource) 81 if !ok { 82 t.Fatalf("Expected a gitSource, got a %T", isrc) 83 } 84 85 if un != src.upstreamURL() { 86 t.Errorf("Expected %s as source URL, got %s", un, src.upstreamURL()) 87 } 88 89 pvlist, err := src.listVersions(ctx) 90 if err != nil { 91 t.Fatalf("Unexpected error getting version pairs from git repo: %s", err) 92 } 93 94 vlist := hidePair(pvlist) 95 // check that an expected rev is present 96 is, err := src.revisionPresentIn(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")) 97 if err != nil { 98 t.Errorf("Unexpected error while checking revision presence: %s", err) 99 } else if !is { 100 t.Errorf("Revision that should exist was not present") 101 } 102 103 if len(vlist) != 7 { 104 t.Errorf("git test repo should've produced seven versions, got %v: vlist was %s", len(vlist), vlist) 105 } else { 106 SortForUpgrade(vlist) 107 evl := []Version{ 108 NewVersion("v2.0.0").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), 109 NewVersion("v1.1.0").Pair(Revision("b2cb48dda625f6640b34d9ffb664533359ac8b91")), 110 NewVersion("v1.0.0").Pair(Revision("bf85021c0405edbc4f3648b0603818d641674f72")), 111 newDefaultBranch("master").Pair(Revision("bf85021c0405edbc4f3648b0603818d641674f72")), 112 NewBranch("v1").Pair(Revision("e3777f683305eafca223aefe56b4e8ecf103f467")), 113 NewBranch("v1.1").Pair(Revision("f1fbc520489a98306eb28c235204e39fa8a89c84")), 114 NewBranch("v3").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), 115 } 116 for k, e := range evl { 117 if !vlist[k].identical(e) { 118 t.Errorf("version list was not what we expected:\n\t(GOT): %#v\n\t(WNT): %#v", vlist, evl) 119 break 120 } 121 } 122 } 123 124 // recheck that rev is present, this time interacting with cache differently 125 is, err = src.revisionPresentIn(Revision("30605f6ac35fcb075ad0bfa9296f90a7d891523e")) 126 if err != nil { 127 t.Errorf("Unexpected error while re-checking revision presence: %s", err) 128 } else if !is { 129 t.Errorf("Revision that should exist was not present on re-check") 130 } 131 } 132 133 func testGopkginSourceInteractions(t *testing.T) { 134 t.Parallel() 135 136 // This test is slowish, skip it on -short 137 if testing.Short() { 138 t.Skip("Skipping gopkg.in source version fetching test in short mode") 139 } 140 requiresBins(t, "git") 141 142 cpath, err := ioutil.TempDir("", "smcache") 143 if err != nil { 144 t.Errorf("Failed to create temp dir: %s", err) 145 } 146 defer func() { 147 if err := os.RemoveAll(cpath); err != nil { 148 t.Errorf("removeAll failed: %s", err) 149 } 150 }() 151 os.Mkdir(filepath.Join(cpath, "sources"), 0777) 152 153 tfunc := func(opath, n string, major uint64, evl []Version) { 154 un := "https://" + opath 155 u, err := url.Parse("https://" + n) 156 if err != nil { 157 t.Errorf("URL was bad, lolwut? errtext: %s", err) 158 return 159 } 160 unstable := strings.HasSuffix(opath, gopkgUnstableSuffix) 161 mb := maybeGopkginSource{ 162 opath: opath, 163 url: u, 164 major: major, 165 unstable: unstable, 166 } 167 168 ctx := context.Background() 169 isrc, err := mb.try(ctx, cpath) 170 if err != nil { 171 t.Errorf("Unexpected error while setting up gopkginSource for test repo: %s", err) 172 return 173 } 174 175 err = isrc.initLocal(ctx) 176 if err != nil { 177 t.Fatalf("Error on cloning git repo: %s", err) 178 } 179 180 src, ok := isrc.(*gopkginSource) 181 if !ok { 182 t.Errorf("Expected a gopkginSource, got a %T", isrc) 183 return 184 } 185 186 if un != src.upstreamURL() { 187 t.Errorf("Expected %s as source URL, got %s", un, src.upstreamURL()) 188 } 189 if src.major != major { 190 t.Errorf("Expected %v as major version filter on gopkginSource, got %v", major, src.major) 191 } 192 193 // check that an expected rev is present 194 rev := evl[0].(PairedVersion).Revision() 195 is, err := src.revisionPresentIn(rev) 196 if err != nil { 197 t.Errorf("Unexpected error while checking revision presence: %s", err) 198 } else if !is { 199 t.Errorf("Revision %s that should exist was not present", rev) 200 } 201 202 pvlist, err := src.listVersions(ctx) 203 if err != nil { 204 t.Errorf("Unexpected error getting version pairs from hg repo: %s", err) 205 } 206 207 vlist := hidePair(pvlist) 208 if len(vlist) != len(evl) { 209 t.Errorf("gopkgin test repo (%s) should've produced %v versions, got %v.\n%v", un, len(evl), len(vlist), vlist) 210 } else { 211 SortForUpgrade(vlist) 212 if !reflect.DeepEqual(vlist, evl) { 213 t.Errorf("Version list for %s was not what we expected:\n\t(GOT): %#v\n\t(WNT): %#v", un, vlist, evl) 214 } 215 } 216 217 // Run again, this time to ensure cache outputs correctly 218 pvlist, err = src.listVersions(ctx) 219 if err != nil { 220 t.Errorf("Unexpected error getting version pairs from hg repo: %s", err) 221 } 222 223 vlist = hidePair(pvlist) 224 if len(vlist) != len(evl) { 225 t.Errorf("gopkgin test repo should've produced %v versions, got %v", len(evl), len(vlist)) 226 } else { 227 SortForUpgrade(vlist) 228 if !reflect.DeepEqual(vlist, evl) { 229 t.Errorf("Version list for %s was not what we expected:\n\t(GOT): %#v\n\t(WNT): %#v", un, vlist, evl) 230 } 231 } 232 233 // recheck that rev is present, this time interacting with cache differently 234 is, err = src.revisionPresentIn(rev) 235 if err != nil { 236 t.Errorf("Unexpected error while re-checking revision presence: %s", err) 237 } else if !is { 238 t.Errorf("Revision that should exist was not present on re-check") 239 } 240 } 241 242 // simultaneously run for v1, v2, and v3 filters of the target repo 243 wg := &sync.WaitGroup{} 244 wg.Add(6) 245 246 go func() { 247 // Treat master as v0 when no other branches/tags exist that match gopkg.in's rules 248 tfunc("gopkg.in/carolynvs/deptest-gopkgin-implicit-v0.v0", "github.com/carolynvs/deptest-gopkgin-implicit-v0", 0, []Version{ 249 newDefaultBranch("notmaster").Pair(Revision("94ee631b9833cd805d15f50a52e0533124ec0292")), 250 }) 251 wg.Done() 252 }() 253 254 go func() { 255 // Use the existing v0 branch for v0, not master 256 tfunc("gopkg.in/carolynvs/deptest-gopkgin-explicit-v0.v0", "github.com/carolynvs/deptest-gopkgin-explicit-v0", 0, []Version{ 257 newDefaultBranch("v0").Pair(Revision("ec73e84554fb28f08dba630e48dbec868e77f734")), 258 }) 259 wg.Done() 260 }() 261 262 go func() { 263 tfunc("gopkg.in/sdboyer/gpkt.v1", "github.com/sdboyer/gpkt", 1, []Version{ 264 NewVersion("v1.1.0").Pair(Revision("b2cb48dda625f6640b34d9ffb664533359ac8b91")), 265 NewVersion("v1.0.0").Pair(Revision("bf85021c0405edbc4f3648b0603818d641674f72")), 266 newDefaultBranch("v1.1").Pair(Revision("f1fbc520489a98306eb28c235204e39fa8a89c84")), 267 NewBranch("v1").Pair(Revision("e3777f683305eafca223aefe56b4e8ecf103f467")), 268 }) 269 wg.Done() 270 }() 271 272 go func() { 273 tfunc("gopkg.in/sdboyer/gpkt.v2", "github.com/sdboyer/gpkt", 2, []Version{ 274 NewVersion("v2.0.0").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), 275 }) 276 wg.Done() 277 }() 278 279 go func() { 280 tfunc("gopkg.in/sdboyer/gpkt.v3", "github.com/sdboyer/gpkt", 3, []Version{ 281 newDefaultBranch("v3").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), 282 }) 283 wg.Done() 284 }() 285 286 go func() { 287 tfunc("github.com/sdboyer/gpkt2.v1-unstable", "github.com/sdboyer/gpkt2", 1, []Version{ 288 newDefaultBranch("v1-unstable").Pair(Revision("24de0be8f4a0b8a44321562117749b257bfcef69")), 289 }) 290 wg.Done() 291 }() 292 293 wg.Wait() 294 } 295 296 func testBzrSourceInteractions(t *testing.T) { 297 t.Parallel() 298 299 // This test is quite slow (ugh bzr), so skip it on -short 300 if testing.Short() { 301 t.Skip("Skipping bzr source version fetching test in short mode") 302 } 303 if runtime.GOOS == "windows" { 304 // TODO bzr on Windows is sometimes weirdly reporting different 305 // "revision-id" (with mention of git), and it's breaking tests. Maybe 306 // this also breaks our model of bzr on Windows; maybe it breaks our 307 // model of bzr in general. But use of bzr is rare and dwindling, so for 308 // now it's least harmful to turn off the test on Windows, as the 309 // alternative is a DEEP dive and possible refactor. 310 t.Skip("TODO: Windows bzr reporting of underlying object ids is confusing") 311 } 312 requiresBins(t, "bzr") 313 314 cpath, err := ioutil.TempDir("", "smcache") 315 if err != nil { 316 t.Errorf("Failed to create temp dir: %s", err) 317 } 318 defer func() { 319 if err := os.RemoveAll(cpath); err != nil { 320 t.Errorf("removeAll failed: %s", err) 321 } 322 }() 323 324 n := "launchpad.net/govcstestbzrrepo" 325 un := "https://" + n 326 u, err := url.Parse(un) 327 if err != nil { 328 t.Fatalf("Error parsing URL %s: %s", un, err) 329 } 330 mb := maybeBzrSource{ 331 url: u, 332 } 333 334 ctx := context.Background() 335 isrc, err := mb.try(ctx, cpath) 336 if err != nil { 337 t.Fatalf("Unexpected error while setting up bzrSource for test repo: %s", err) 338 } 339 340 err = isrc.initLocal(ctx) 341 if err != nil { 342 t.Fatalf("Error on cloning bzr repo: %s", err) 343 } 344 345 src, ok := isrc.(*bzrSource) 346 if !ok { 347 t.Fatalf("Expected a bzrSource, got a %T", isrc) 348 } 349 350 if un != src.upstreamURL() { 351 t.Errorf("Expected %s as source URL, got %s", un, src.upstreamURL()) 352 } 353 evl := []Version{ 354 NewVersion("1.0.0").Pair(Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68")), 355 newDefaultBranch("(default)").Pair(Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68")), 356 } 357 358 // check that an expected rev is present 359 is, err := src.revisionPresentIn(Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68")) 360 if err != nil { 361 t.Errorf("Unexpected error while checking revision presence: %s", err) 362 } else if !is { 363 t.Errorf("Revision that should exist was not present") 364 } 365 366 pvlist, err := src.listVersions(ctx) 367 if err != nil { 368 t.Errorf("Unexpected error getting version pairs from bzr repo: %s", err) 369 } 370 371 vlist := hidePair(pvlist) 372 if len(vlist) != 2 { 373 t.Errorf("bzr test repo should've produced two versions, got %v", len(vlist)) 374 } else { 375 SortForUpgrade(vlist) 376 if !reflect.DeepEqual(vlist, evl) { 377 t.Errorf("bzr version list was not what we expected:\n\t(GOT): %s\n\t(WNT): %s", vlist, evl) 378 } 379 } 380 381 // Run again, this time to ensure cache outputs correctly 382 pvlist, err = src.listVersions(ctx) 383 if err != nil { 384 t.Errorf("Unexpected error getting version pairs from bzr repo: %s", err) 385 } 386 387 vlist = hidePair(pvlist) 388 if len(vlist) != 2 { 389 t.Errorf("bzr test repo should've produced two versions, got %v", len(vlist)) 390 } else { 391 SortForUpgrade(vlist) 392 if !reflect.DeepEqual(vlist, evl) { 393 t.Errorf("bzr version list was not what we expected:\n\t(GOT): %s\n\t(WNT): %s", vlist, evl) 394 } 395 } 396 397 // recheck that rev is present, this time interacting with cache differently 398 is, err = src.revisionPresentIn(Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68")) 399 if err != nil { 400 t.Errorf("Unexpected error while re-checking revision presence: %s", err) 401 } else if !is { 402 t.Errorf("Revision that should exist was not present on re-check") 403 } 404 } 405 406 func testHgSourceInteractions(t *testing.T) { 407 t.Parallel() 408 409 // This test is slow, so skip it on -short 410 if testing.Short() { 411 t.Skip("Skipping hg source version fetching test in short mode") 412 } 413 requiresBins(t, "hg") 414 415 cpath, err := ioutil.TempDir("", "smcache") 416 if err != nil { 417 t.Errorf("Failed to create temp dir: %s", err) 418 } 419 defer func() { 420 if err := os.RemoveAll(cpath); err != nil { 421 t.Errorf("removeAll failed: %s", err) 422 } 423 }() 424 425 tfunc := func(n string, evl []Version) { 426 un := "https://" + n 427 u, err := url.Parse(un) 428 if err != nil { 429 t.Errorf("URL was bad, lolwut? errtext: %s", err) 430 return 431 } 432 mb := maybeHgSource{ 433 url: u, 434 } 435 436 ctx := context.Background() 437 isrc, err := mb.try(ctx, cpath) 438 if err != nil { 439 t.Errorf("Unexpected error while setting up hgSource for test repo: %s", err) 440 return 441 } 442 443 err = isrc.initLocal(ctx) 444 if err != nil { 445 t.Errorf("Error on cloning hg repo: %s", err) 446 return 447 } 448 449 src, ok := isrc.(*hgSource) 450 if !ok { 451 t.Errorf("Expected a hgSource, got a %T", isrc) 452 return 453 } 454 455 if un != src.upstreamURL() { 456 t.Errorf("Expected %s as source URL, got %s", un, src.upstreamURL()) 457 } 458 459 // check that an expected rev is present 460 is, err := src.revisionPresentIn(Revision("103d1bddef2199c80aad7c42041223083d613ef9")) 461 if err != nil { 462 t.Errorf("Unexpected error while checking revision presence: %s", err) 463 } else if !is { 464 t.Errorf("Revision that should exist was not present") 465 } 466 467 pvlist, err := src.listVersions(ctx) 468 if err != nil { 469 t.Errorf("Unexpected error getting version pairs from hg repo: %s", err) 470 } 471 472 vlist := hidePair(pvlist) 473 if len(vlist) != len(evl) { 474 t.Errorf("hg test repo should've produced %v versions, got %v", len(evl), len(vlist)) 475 } else { 476 SortForUpgrade(vlist) 477 478 for k, e := range evl { 479 if !vlist[k].identical(e) { 480 t.Errorf("version list was not what we expected:\n\t(GOT): %#v\n\t(WNT): %#v", vlist, evl) 481 break 482 } 483 } 484 } 485 486 // Run again, this time to ensure cache outputs correctly 487 pvlist, err = src.listVersions(ctx) 488 if err != nil { 489 t.Errorf("Unexpected error getting version pairs from hg repo: %s", err) 490 } 491 492 vlist = hidePair(pvlist) 493 if len(vlist) != len(evl) { 494 t.Errorf("hg test repo should've produced %v versions, got %v", len(evl), len(vlist)) 495 } else { 496 SortForUpgrade(vlist) 497 for k, e := range evl { 498 if !vlist[k].identical(e) { 499 t.Errorf("version list was not what we expected:\n\t(GOT): %#v\n\t(WNT): %#v", vlist, evl) 500 break 501 } 502 } 503 } 504 505 // recheck that rev is present, this time interacting with cache differently 506 is, err = src.revisionPresentIn(Revision("103d1bddef2199c80aad7c42041223083d613ef9")) 507 if err != nil { 508 t.Errorf("Unexpected error while re-checking revision presence: %s", err) 509 } else if !is { 510 t.Errorf("Revision that should exist was not present on re-check") 511 } 512 } 513 514 // simultaneously run for both the repo with and without the magic bookmark 515 donech := make(chan struct{}) 516 go func() { 517 tfunc("bitbucket.org/sdboyer/withbm", []Version{ 518 NewVersion("v1.0.0").Pair(Revision("aa110802a0c64195d0a6c375c9f66668827c90b4")), 519 newDefaultBranch("@").Pair(Revision("b10d05d581e5401f383e48ccfeb84b48fde99d06")), 520 NewBranch("another").Pair(Revision("b10d05d581e5401f383e48ccfeb84b48fde99d06")), 521 NewBranch("default").Pair(Revision("3d466f437f6616da594bbab6446cc1cb4328d1bb")), 522 NewBranch("newbranch").Pair(Revision("5e2a01be9aee942098e44590ae545c7143da9675")), 523 }) 524 close(donech) 525 }() 526 527 tfunc("bitbucket.org/sdboyer/nobm", []Version{ 528 NewVersion("v1.0.0").Pair(Revision("aa110802a0c64195d0a6c375c9f66668827c90b4")), 529 newDefaultBranch("default").Pair(Revision("3d466f437f6616da594bbab6446cc1cb4328d1bb")), 530 NewBranch("another").Pair(Revision("b10d05d581e5401f383e48ccfeb84b48fde99d06")), 531 NewBranch("newbranch").Pair(Revision("5e2a01be9aee942098e44590ae545c7143da9675")), 532 }) 533 534 <-donech 535 } 536 537 func TestGitSourceListVersionsNoHEAD(t *testing.T) { 538 // t.Parallel() 539 540 requiresBins(t, "git") 541 542 h := test.NewHelper(t) 543 defer h.Cleanup() 544 h.TempDir("smcache") 545 cpath := h.Path("smcache") 546 os.Mkdir(filepath.Join(cpath, "sources"), 0777) 547 548 h.TempDir("repo") 549 repoPath := h.Path("repo") 550 551 // Create test repo with a single commit on the master branch 552 h.RunGit(repoPath, "init") 553 h.RunGit(repoPath, "config", "--local", "user.email", "test@example.com") 554 h.RunGit(repoPath, "config", "--local", "user.name", "Test author") 555 h.RunGit(repoPath, "commit", "--allow-empty", `--message="Initial commit"`) 556 557 // Make HEAD point at a nonexistent branch (deleting it is not allowed) 558 // The `git ls-remote` that listVersions() calls will not return a HEAD ref 559 // because it points at a nonexistent branch 560 h.RunGit(repoPath, "symbolic-ref", "HEAD", "refs/heads/nonexistent") 561 562 un := "file://" + filepath.ToSlash(repoPath) 563 u, err := url.Parse(un) 564 if err != nil { 565 t.Fatalf("Error parsing URL %s: %s", un, err) 566 } 567 mb := maybeGitSource{u} 568 569 ctx := context.Background() 570 isrc, err := mb.try(ctx, cpath) 571 if err != nil { 572 t.Fatalf("Unexpected error while setting up gitSource for test repo: %s", err) 573 } 574 575 err = isrc.initLocal(ctx) 576 if err != nil { 577 t.Fatalf("Error on cloning git repo: %s", err) 578 } 579 580 src, ok := isrc.(*gitSource) 581 if !ok { 582 t.Fatalf("Expected a gitSource, got a %T", isrc) 583 } 584 585 pvlist, err := src.listVersions(ctx) 586 if err != nil { 587 t.Fatalf("Unexpected error getting version pairs from git repo: %s", err) 588 } 589 590 if len(pvlist) != 1 { 591 t.Errorf("Unexpected version pair length:\n\t(GOT): %d\n\t(WNT): %d", len(pvlist), 1) 592 } 593 } 594 595 func TestGitSourceListVersionsNoDupes(t *testing.T) { 596 // t.Parallel() 597 598 // This test is slowish, skip it on -short 599 if testing.Short() { 600 t.Skip("Skipping git source version fetching test in short mode") 601 } 602 requiresBins(t, "git") 603 604 cpath, err := ioutil.TempDir("", "smcache") 605 if err != nil { 606 t.Errorf("Failed to create temp dir: %s", err) 607 } 608 defer func() { 609 if err := os.RemoveAll(cpath); err != nil { 610 t.Errorf("removeAll failed: %s", err) 611 } 612 }() 613 os.Mkdir(filepath.Join(cpath, "sources"), 0777) 614 615 n := "github.com/carolynvs/deptest-importers" 616 un := "https://" + n 617 u, err := url.Parse(un) 618 if err != nil { 619 t.Fatalf("Error parsing URL %s: %s", un, err) 620 } 621 mb := maybeGitSource{ 622 url: u, 623 } 624 625 ctx := context.Background() 626 src, err := mb.try(ctx, cpath) 627 if err != nil { 628 t.Fatalf("Unexpected error while setting up gitSource for test repo: %s", err) 629 } 630 631 err = src.initLocal(ctx) 632 if err != nil { 633 t.Fatalf("Error on cloning git repo: %s", err) 634 } 635 636 pvlist, err := src.listVersions(ctx) 637 if err != nil { 638 t.Fatalf("Unexpected error getting version pairs from git repo: %s", err) 639 } 640 641 for i := range pvlist { 642 pv1 := pvlist[i] 643 uv1 := pv1.Unpair() 644 for j := range pvlist { 645 if i == j { 646 continue 647 } 648 pv2 := pvlist[j] 649 uv2 := pv2.Unpair() 650 if uv1 == uv2 { 651 t.Errorf("duplicate version pair mapping from %#v to both %q and %q", uv1, pv1.Revision(), pv2.Revision()) 652 } 653 } 654 } 655 } 656 657 func TestGitSourceAdaptiveCleanup(t *testing.T) { 658 // t.Parallel() 659 660 // This test is slowish, skip it on -short 661 if testing.Short() { 662 t.Skip("Skipping git adaptive failure recovery test in short mode") 663 } 664 requiresBins(t, "git") 665 666 cpath, err := ioutil.TempDir("", "smcache") 667 if err != nil { 668 t.Fatalf("Failed to create temp dir: %s", err) 669 } 670 671 var sm *SourceMgr 672 mkSM := func() { 673 // If sm is already set, make sure it's released, then create a new one. 674 if sm != nil { 675 sm.Release() 676 } 677 678 var err error 679 sm, err = NewSourceManager(SourceManagerConfig{ 680 Cachedir: cpath, 681 Logger: log.New(test.Writer{TB: t}, "", 0), 682 }) 683 if err != nil { 684 t.Fatalf("Unexpected error on SourceManager creation: %s", err) 685 } 686 } 687 688 mkSM() 689 id := mkPI("github.com/sdboyer/gpkt") 690 err = sm.SyncSourceFor(id) 691 if err != nil { 692 t.Fatal(err) 693 } 694 695 repodir := filepath.Join(sm.cachedir, "sources", "https---github.com-sdboyer-gpkt") 696 if _, err := os.Stat(repodir); err != nil { 697 if os.IsNotExist(err) { 698 t.Fatalf("expected location for repodir did not exist: %q", repodir) 699 } else { 700 t.Fatal(err) 701 } 702 } 703 704 // Create a file that git will see as untracked. 705 untrackedPath := filepath.Join(repodir, "untrackedfile") 706 err = ioutil.WriteFile(untrackedPath, []byte("foo"), 0644) 707 if err != nil { 708 t.Fatal(err) 709 } 710 711 mkSM() 712 err = sm.SyncSourceFor(id) 713 if err != nil { 714 t.Fatalf("choked after adding dummy file: %q", err) 715 } 716 717 if _, err := os.Stat(untrackedPath); err == nil { 718 t.Fatal("untracked file still existed after cleanup should've been triggered") 719 } 720 721 // Remove a file that we know exists, which `git status` checks should catch. 722 readmePath := filepath.Join(repodir, "README.md") 723 os.Remove(readmePath) 724 725 mkSM() 726 err = sm.SyncSourceFor(id) 727 if err != nil { 728 t.Fatalf("choked after removing known file: %q", err) 729 } 730 731 if _, err := os.Stat(readmePath); err != nil { 732 t.Fatal("README was still absent after cleanup should've been triggered") 733 } 734 735 // Remove .git/objects directory, which should make git bite it. 736 err = os.RemoveAll(filepath.Join(repodir, ".git", "objects")) 737 if err != nil { 738 t.Fatal(err) 739 } 740 741 mkSM() 742 err = sm.SyncSourceFor(id) 743 if err != nil { 744 t.Fatalf("choked after removing .git/objects directory: %q", err) 745 } 746 747 sm.Release() 748 os.RemoveAll(cpath) 749 } 750 751 func Test_bzrSource_exportRevisionTo_removeVcsFiles(t *testing.T) { 752 t.Parallel() 753 754 // This test is slow, so skip it on -short 755 if testing.Short() { 756 t.Skip("Skipping hg source version fetching test in short mode") 757 } 758 if runtime.GOOS == "windows" { 759 // TODO see todo in TestBzrSourceInteractions 760 t.Skip("TODO: Windows bzr reporting of underlying object ids is confusing") 761 } 762 requiresBins(t, "bzr") 763 764 h := test.NewHelper(t) 765 defer h.Cleanup() 766 h.TempDir("smcache") 767 cpath := h.Path("smcache") 768 repoPath := filepath.Join(h.Path("."), "repo") 769 770 rev := Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68") 771 n := "launchpad.net/govcstestbzrrepo" 772 un := "https://" + n 773 u, err := url.Parse(un) 774 if err != nil { 775 t.Errorf("URL was bad, lolwut? errtext: %s", err) 776 return 777 } 778 mb := maybeBzrSource{u} 779 780 ctx := context.Background() 781 isrc, err := mb.try(ctx, cpath) 782 if err != nil { 783 t.Fatalf("unexpected error while setting up hgSource for test repo: %s", err) 784 } 785 786 err = isrc.initLocal(ctx) 787 if err != nil { 788 t.Fatalf("Error on cloning bzr repo: %s", err) 789 } 790 791 src, ok := isrc.(*bzrSource) 792 if !ok { 793 t.Fatalf("expected a bzrSource, got a %T", isrc) 794 } 795 796 if err := src.exportRevisionTo(ctx, rev, repoPath); err != nil { 797 t.Fatalf("unexpected error: %v", err) 798 } 799 800 _, err = os.Stat(filepath.Join(repoPath, ".bzr")) 801 if err == nil { 802 t.Fatal("expected .bzr/ to not exists") 803 } else if !os.IsNotExist(err) { 804 t.Fatalf("unexpected error: %v", err) 805 } 806 } 807 808 func Test_hgSource_exportRevisionTo_removeVcsFiles(t *testing.T) { 809 t.Parallel() 810 811 // This test is slow, so skip it on -short 812 if testing.Short() { 813 t.Skip("Skipping hg source version fetching test in short mode") 814 } 815 requiresBins(t, "hg") 816 817 h := test.NewHelper(t) 818 defer h.Cleanup() 819 h.TempDir("smcache") 820 cpath := h.Path("smcache") 821 repoPath := filepath.Join(h.Path("."), "repo") 822 823 rev := Revision("6f55e1f03d91f8a7cce35d1968eb60a2352e4d59") 824 n := "bitbucket.org/golang-dep/dep-test" 825 un := "https://" + n 826 u, err := url.Parse(un) 827 if err != nil { 828 t.Errorf("URL was bad, lolwut? errtext: %s", err) 829 return 830 } 831 mb := maybeHgSource{u} 832 833 ctx := context.Background() 834 isrc, err := mb.try(ctx, cpath) 835 if err != nil { 836 t.Fatalf("unexpected error while setting up hgSource for test repo: %s", err) 837 } 838 839 err = isrc.initLocal(ctx) 840 if err != nil { 841 t.Fatalf("Error on cloning hg repo: %s", err) 842 } 843 844 src, ok := isrc.(*hgSource) 845 if !ok { 846 t.Fatalf("expected a hgSource, got a %T", isrc) 847 } 848 849 if err := src.exportRevisionTo(ctx, rev, repoPath); err != nil { 850 t.Fatalf("unexpected error: %v", err) 851 } 852 853 _, err = os.Stat(filepath.Join(repoPath, ".hg")) 854 if err == nil { 855 t.Fatal("expected .hg/ to not exists") 856 } else if !os.IsNotExist(err) { 857 t.Fatalf("unexpected error: %v", err) 858 } 859 } 860 861 // Fail a test if the specified binaries aren't installed. 862 func requiresBins(t *testing.T, bins ...string) { 863 for _, b := range bins { 864 _, err := exec.LookPath(b) 865 if err != nil { 866 t.Fatalf("%s is not installed", b) 867 } 868 } 869 }