// Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package gps import ( "bytes" "context" "errors" "fmt" "net/url" "reflect" "testing" ) type pathDeductionFixture struct { in string root string rerr error mb maybeSources srcerr error } // helper func to generate testing *url.URLs, panicking on err func mkurl(s string) (u *url.URL) { var err error u, err = url.Parse(s) if err != nil { panic(fmt.Sprint("string is not a valid URL:", s)) } return } var pathDeductionFixtures = map[string][]pathDeductionFixture{ "github": { { in: "github.com/sdboyer/gps", root: "github.com/sdboyer/gps", mb: maybeSources{ maybeGitSource{url: mkurl("https://github.com/sdboyer/gps")}, maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer/gps")}, maybeGitSource{url: mkurl("git://github.com/sdboyer/gps")}, maybeGitSource{url: mkurl("http://github.com/sdboyer/gps")}, }, }, { in: "github.com/sdboyer/gps/foo", root: "github.com/sdboyer/gps", mb: maybeSources{ maybeGitSource{url: mkurl("https://github.com/sdboyer/gps")}, maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer/gps")}, maybeGitSource{url: mkurl("git://github.com/sdboyer/gps")}, maybeGitSource{url: mkurl("http://github.com/sdboyer/gps")}, }, }, { // TODO(sdboyer) is this a problem for enforcing uniqueness? do we // need to collapse these extensions? in: "github.com/sdboyer/gps.git/foo", root: "github.com/sdboyer/gps.git", mb: maybeSources{ maybeGitSource{url: mkurl("https://github.com/sdboyer/gps.git")}, maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer/gps.git")}, maybeGitSource{url: mkurl("git://github.com/sdboyer/gps.git")}, maybeGitSource{url: mkurl("http://github.com/sdboyer/gps.git")}, }, }, { in: "git@github.com:sdboyer/gps", root: "github.com/sdboyer/gps", mb: maybeSources{ maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer/gps")}, }, }, { in: "https://github.com/sdboyer/gps", root: "github.com/sdboyer/gps", mb: maybeSources{ maybeGitSource{url: mkurl("https://github.com/sdboyer/gps")}, }, }, { in: "https://github.com/sdboyer/gps/foo/bar", root: "github.com/sdboyer/gps", mb: maybeSources{ maybeGitSource{url: mkurl("https://github.com/sdboyer/gps")}, }, }, { in: "github.com/sdboyer-/gps/foo", root: "github.com/sdboyer-/gps", mb: maybeSources{ maybeGitSource{url: mkurl("https://github.com/sdboyer-/gps")}, maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer-/gps")}, maybeGitSource{url: mkurl("git://github.com/sdboyer-/gps")}, maybeGitSource{url: mkurl("http://github.com/sdboyer-/gps")}, }, }, { in: "github.com/a/gps/foo", root: "github.com/a/gps", mb: maybeSources{ maybeGitSource{url: mkurl("https://github.com/a/gps")}, maybeGitSource{url: mkurl("ssh://git@github.com/a/gps")}, maybeGitSource{url: mkurl("git://github.com/a/gps")}, maybeGitSource{url: mkurl("http://github.com/a/gps")}, }, }, // some invalid github username patterns { in: "github.com/-sdboyer/gps/foo", rerr: errors.New("github.com/-sdboyer/gps/foo is not a valid path for a source on github.com"), }, { in: "github.com/sdbo.yer/gps/foo", rerr: errors.New("github.com/sdbo.yer/gps/foo is not a valid path for a source on github.com"), }, { in: "github.com/sdbo_yer/gps/foo", rerr: errors.New("github.com/sdbo_yer/gps/foo is not a valid path for a source on github.com"), }, // Regression - gh does allow two-letter usernames { in: "github.com/kr/pretty", root: "github.com/kr/pretty", mb: maybeSources{ maybeGitSource{url: mkurl("https://github.com/kr/pretty")}, maybeGitSource{url: mkurl("ssh://git@github.com/kr/pretty")}, maybeGitSource{url: mkurl("git://github.com/kr/pretty")}, maybeGitSource{url: mkurl("http://github.com/kr/pretty")}, }, }, }, "gopkg.in": { { in: "gopkg.in/sdboyer/gps.v0", root: "gopkg.in/sdboyer/gps.v0", mb: maybeSources{ maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v0", url: mkurl("https://github.com/sdboyer/gps"), major: 0}, maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v0", url: mkurl("http://github.com/sdboyer/gps"), major: 0}, }, }, { in: "gopkg.in/sdboyer/gps.v0/foo", root: "gopkg.in/sdboyer/gps.v0", mb: maybeSources{ maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v0", url: mkurl("https://github.com/sdboyer/gps"), major: 0}, maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v0", url: mkurl("http://github.com/sdboyer/gps"), major: 0}, }, }, { in: "gopkg.in/sdboyer/gps.v1/foo/bar", root: "gopkg.in/sdboyer/gps.v1", mb: maybeSources{ maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v1", url: mkurl("https://github.com/sdboyer/gps"), major: 1}, maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v1", url: mkurl("http://github.com/sdboyer/gps"), major: 1}, }, }, { in: "gopkg.in/yaml.v1", root: "gopkg.in/yaml.v1", mb: maybeSources{ maybeGopkginSource{opath: "gopkg.in/yaml.v1", url: mkurl("https://github.com/go-yaml/yaml"), major: 1}, maybeGopkginSource{opath: "gopkg.in/yaml.v1", url: mkurl("http://github.com/go-yaml/yaml"), major: 1}, }, }, { in: "gopkg.in/yaml.v1/foo/bar", root: "gopkg.in/yaml.v1", mb: maybeSources{ maybeGopkginSource{opath: "gopkg.in/yaml.v1", url: mkurl("https://github.com/go-yaml/yaml"), major: 1}, maybeGopkginSource{opath: "gopkg.in/yaml.v1", url: mkurl("http://github.com/go-yaml/yaml"), major: 1}, }, }, { in: "gopkg.in/inf.v0", root: "gopkg.in/inf.v0", mb: maybeSources{ maybeGopkginSource{opath: "gopkg.in/inf.v0", url: mkurl("https://github.com/go-inf/inf"), major: 0}, maybeGopkginSource{opath: "gopkg.in/inf.v0", url: mkurl("http://github.com/go-inf/inf"), major: 0}, }, }, { // gopkg.in only allows specifying major version in import path in: "gopkg.in/yaml.v1.2", rerr: errors.New("gopkg.in/yaml.v1.2 is not a valid import path; gopkg.in only allows major versions (\"v1\" instead of \"v1.2\")"), }, }, "jazz": { // IBM hub devops services - fixtures borrowed from go get { in: "hub.jazz.net/git/user1/pkgname", root: "hub.jazz.net/git/user1/pkgname", mb: maybeSources{ maybeGitSource{url: mkurl("https://hub.jazz.net/git/user1/pkgname")}, }, }, { in: "hub.jazz.net/git/user1/pkgname/submodule/submodule/submodule", root: "hub.jazz.net/git/user1/pkgname", mb: maybeSources{ maybeGitSource{url: mkurl("https://hub.jazz.net/git/user1/pkgname")}, }, }, { in: "hub.jazz.net/someotherprefix", rerr: errors.New("hub.jazz.net/someotherprefix is not a valid path for a source on hub.jazz.net"), }, { in: "hub.jazz.net/someotherprefix/user1/packagename", rerr: errors.New("hub.jazz.net/someotherprefix/user1/packagename is not a valid path for a source on hub.jazz.net"), }, // Spaces are not valid in user names or package names { in: "hub.jazz.net/git/User 1/pkgname", rerr: errors.New("hub.jazz.net/git/User 1/pkgname is not a valid path for a source on hub.jazz.net"), }, { in: "hub.jazz.net/git/user1/pkg name", rerr: errors.New("hub.jazz.net/git/user1/pkg name is not a valid path for a source on hub.jazz.net"), }, // Dots are not valid in user names { in: "hub.jazz.net/git/user.1/pkgname", rerr: errors.New("hub.jazz.net/git/user.1/pkgname is not a valid path for a source on hub.jazz.net"), }, { in: "hub.jazz.net/git/user1/pkg.name", root: "hub.jazz.net/git/user1/pkg.name", mb: maybeSources{ maybeGitSource{url: mkurl("https://hub.jazz.net/git/user1/pkg.name")}, }, }, // User names cannot have uppercase letters { in: "hub.jazz.net/git/USER/pkgname", rerr: errors.New("hub.jazz.net/git/USER/pkgname is not a valid path for a source on hub.jazz.net"), }, }, "bitbucket": { { in: "bitbucket.org/sdboyer/reporoot", root: "bitbucket.org/sdboyer/reporoot", mb: maybeSources{ maybeHgSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, maybeHgSource{url: mkurl("ssh://hg@bitbucket.org/sdboyer/reporoot")}, maybeHgSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot")}, maybeGitSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, maybeGitSource{url: mkurl("ssh://git@bitbucket.org/sdboyer/reporoot")}, maybeGitSource{url: mkurl("git://bitbucket.org/sdboyer/reporoot")}, maybeGitSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot")}, }, }, { in: "bitbucket.org/sdboyer/reporoot/foo/bar", root: "bitbucket.org/sdboyer/reporoot", mb: maybeSources{ maybeHgSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, maybeHgSource{url: mkurl("ssh://hg@bitbucket.org/sdboyer/reporoot")}, maybeHgSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot")}, maybeGitSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, maybeGitSource{url: mkurl("ssh://git@bitbucket.org/sdboyer/reporoot")}, maybeGitSource{url: mkurl("git://bitbucket.org/sdboyer/reporoot")}, maybeGitSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot")}, }, }, { in: "https://bitbucket.org/sdboyer/reporoot/foo/bar", root: "bitbucket.org/sdboyer/reporoot", mb: maybeSources{ maybeHgSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, maybeGitSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, }, }, // Less standard behaviors possible due to the hg/git ambiguity { in: "bitbucket.org/sdboyer/reporoot.git", root: "bitbucket.org/sdboyer/reporoot.git", mb: maybeSources{ maybeGitSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot.git")}, maybeGitSource{url: mkurl("ssh://git@bitbucket.org/sdboyer/reporoot.git")}, maybeGitSource{url: mkurl("git://bitbucket.org/sdboyer/reporoot.git")}, maybeGitSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot.git")}, }, }, { in: "git@bitbucket.org:sdboyer/reporoot.git", root: "bitbucket.org/sdboyer/reporoot.git", mb: maybeSources{ maybeGitSource{url: mkurl("ssh://git@bitbucket.org/sdboyer/reporoot.git")}, }, }, { in: "bitbucket.org/sdboyer/reporoot.hg", root: "bitbucket.org/sdboyer/reporoot.hg", mb: maybeSources{ maybeHgSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot.hg")}, maybeHgSource{url: mkurl("ssh://hg@bitbucket.org/sdboyer/reporoot.hg")}, maybeHgSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot.hg")}, }, }, { in: "hg@bitbucket.org:sdboyer/reporoot", root: "bitbucket.org/sdboyer/reporoot", mb: maybeSources{ maybeHgSource{url: mkurl("ssh://hg@bitbucket.org/sdboyer/reporoot")}, }, }, { in: "git://bitbucket.org/sdboyer/reporoot.hg", root: "bitbucket.org/sdboyer/reporoot.hg", srcerr: errors.New("git is not a valid scheme for accessing an hg repository"), }, }, "launchpad": { // tests for launchpad, mostly bazaar // TODO(sdboyer) need more tests to deal w/launchpad's oddities { in: "launchpad.net/govcstestbzrrepo", root: "launchpad.net/govcstestbzrrepo", mb: maybeSources{ maybeBzrSource{url: mkurl("https://launchpad.net/govcstestbzrrepo")}, maybeBzrSource{url: mkurl("bzr+ssh://launchpad.net/govcstestbzrrepo")}, maybeBzrSource{url: mkurl("bzr://launchpad.net/govcstestbzrrepo")}, maybeBzrSource{url: mkurl("http://launchpad.net/govcstestbzrrepo")}, }, }, { in: "launchpad.net/govcstestbzrrepo/foo/bar", root: "launchpad.net/govcstestbzrrepo", mb: maybeSources{ maybeBzrSource{url: mkurl("https://launchpad.net/govcstestbzrrepo")}, maybeBzrSource{url: mkurl("bzr+ssh://launchpad.net/govcstestbzrrepo")}, maybeBzrSource{url: mkurl("bzr://launchpad.net/govcstestbzrrepo")}, maybeBzrSource{url: mkurl("http://launchpad.net/govcstestbzrrepo")}, }, }, { in: "launchpad.net/repo root", rerr: errors.New("launchpad.net/repo root is not a valid path for a source on launchpad.net"), }, }, "git.launchpad": { { in: "git.launchpad.net/reporoot", root: "git.launchpad.net/reporoot", mb: maybeSources{ maybeGitSource{url: mkurl("https://git.launchpad.net/reporoot")}, maybeGitSource{url: mkurl("ssh://git.launchpad.net/reporoot")}, maybeGitSource{url: mkurl("git://git.launchpad.net/reporoot")}, maybeGitSource{url: mkurl("http://git.launchpad.net/reporoot")}, }, }, { in: "git.launchpad.net/reporoot/foo/bar", root: "git.launchpad.net/reporoot", mb: maybeSources{ maybeGitSource{url: mkurl("https://git.launchpad.net/reporoot")}, maybeGitSource{url: mkurl("ssh://git.launchpad.net/reporoot")}, maybeGitSource{url: mkurl("git://git.launchpad.net/reporoot")}, maybeGitSource{url: mkurl("http://git.launchpad.net/reporoot")}, }, }, { in: "git.launchpad.net/repo root", rerr: errors.New("git.launchpad.net/repo root is not a valid path for a source on git.launchpad.net"), }, }, "apache": { { in: "git.apache.org/package-name.git", root: "git.apache.org/package-name.git", mb: maybeSources{ maybeGitSource{url: mkurl("https://git.apache.org/package-name.git")}, maybeGitSource{url: mkurl("ssh://git.apache.org/package-name.git")}, maybeGitSource{url: mkurl("git://git.apache.org/package-name.git")}, maybeGitSource{url: mkurl("http://git.apache.org/package-name.git")}, }, }, { in: "git.apache.org/package-name.git/foo/bar", root: "git.apache.org/package-name.git", mb: maybeSources{ maybeGitSource{url: mkurl("https://git.apache.org/package-name.git")}, maybeGitSource{url: mkurl("ssh://git.apache.org/package-name.git")}, maybeGitSource{url: mkurl("git://git.apache.org/package-name.git")}, maybeGitSource{url: mkurl("http://git.apache.org/package-name.git")}, }, }, }, "vcsext": { // VCS extension-based syntax { in: "foobar.com/baz.git", root: "foobar.com/baz.git", mb: maybeSources{ maybeGitSource{url: mkurl("https://foobar.com/baz.git")}, maybeGitSource{url: mkurl("ssh://foobar.com/baz.git")}, maybeGitSource{url: mkurl("git://foobar.com/baz.git")}, maybeGitSource{url: mkurl("http://foobar.com/baz.git")}, }, }, { in: "foobar.com/baz.git/extra/path", root: "foobar.com/baz.git", mb: maybeSources{ maybeGitSource{url: mkurl("https://foobar.com/baz.git")}, maybeGitSource{url: mkurl("ssh://foobar.com/baz.git")}, maybeGitSource{url: mkurl("git://foobar.com/baz.git")}, maybeGitSource{url: mkurl("http://foobar.com/baz.git")}, }, }, { in: "foobar.com/baz.bzr", root: "foobar.com/baz.bzr", mb: maybeSources{ maybeBzrSource{url: mkurl("https://foobar.com/baz.bzr")}, maybeBzrSource{url: mkurl("bzr+ssh://foobar.com/baz.bzr")}, maybeBzrSource{url: mkurl("bzr://foobar.com/baz.bzr")}, maybeBzrSource{url: mkurl("http://foobar.com/baz.bzr")}, }, }, { in: "foo-bar.com/baz.hg", root: "foo-bar.com/baz.hg", mb: maybeSources{ maybeHgSource{url: mkurl("https://foo-bar.com/baz.hg")}, maybeHgSource{url: mkurl("ssh://foo-bar.com/baz.hg")}, maybeHgSource{url: mkurl("http://foo-bar.com/baz.hg")}, }, }, { in: "git@foobar.com:baz.git", root: "foobar.com/baz.git", mb: maybeSources{ maybeGitSource{url: mkurl("ssh://git@foobar.com/baz.git")}, }, }, { in: "bzr+ssh://foobar.com/baz.bzr", root: "foobar.com/baz.bzr", mb: maybeSources{ maybeBzrSource{url: mkurl("bzr+ssh://foobar.com/baz.bzr")}, }, }, { in: "ssh://foobar.com/baz.bzr", root: "foobar.com/baz.bzr", mb: maybeSources{ maybeBzrSource{url: mkurl("ssh://foobar.com/baz.bzr")}, }, }, { in: "https://foobar.com/baz.hg", root: "foobar.com/baz.hg", mb: maybeSources{ maybeHgSource{url: mkurl("https://foobar.com/baz.hg")}, }, }, { in: "git://foobar.com/baz.hg", root: "foobar.com/baz.hg", srcerr: errors.New("git is not a valid scheme for accessing hg repositories (path foobar.com/baz.hg)"), }, // who knows why anyone would do this, but having a second vcs ext // shouldn't throw us off - only the first one counts { in: "foobar.com/baz.git/quark/quizzle.bzr/quorum", root: "foobar.com/baz.git", mb: maybeSources{ maybeGitSource{url: mkurl("https://foobar.com/baz.git")}, maybeGitSource{url: mkurl("ssh://foobar.com/baz.git")}, maybeGitSource{url: mkurl("git://foobar.com/baz.git")}, maybeGitSource{url: mkurl("http://foobar.com/baz.git")}, }, }, }, "vanity": { // Vanity imports { in: "golang.org/x/exp", root: "golang.org/x/exp", mb: maybeSources{ maybeGitSource{url: mkurl("https://go.googlesource.com/exp")}, }, }, { in: "golang.org/x/exp/inotify", root: "golang.org/x/exp", mb: maybeSources{ maybeGitSource{url: mkurl("https://go.googlesource.com/exp")}, }, }, { in: "golang.org/x/net/html", root: "golang.org/x/net", mb: maybeSources{ maybeGitSource{url: mkurl("https://go.googlesource.com/net")}, }, }, }, } func TestDeduceFromPath(t *testing.T) { do := func(typ string, fixtures []pathDeductionFixture, t *testing.T) { t.Run(typ, func(t *testing.T) { t.Parallel() var deducer pathDeducer switch typ { case "github": deducer = githubDeducer{regexp: ghRegex} case "gopkg.in": deducer = gopkginDeducer{regexp: gpinNewRegex} case "jazz": deducer = jazzDeducer{regexp: jazzRegex} case "bitbucket": deducer = bitbucketDeducer{regexp: bbRegex} case "launchpad": deducer = launchpadDeducer{regexp: lpRegex} case "git.launchpad": deducer = launchpadGitDeducer{regexp: glpRegex} case "apache": deducer = apacheDeducer{regexp: apacheRegex} case "vcsext": deducer = vcsExtensionDeducer{regexp: vcsExtensionRegex} default: // Should just be the vanity imports, which we do elsewhere t.Log("skipping") t.SkipNow() } printmb := func(mb maybeSources) string { var buf bytes.Buffer fmt.Fprintf(&buf, "%v maybeSources:", len(mb)) for _, elem := range mb { fmt.Fprintf(&buf, "\n\t\t%s", elem) } return buf.String() } for _, fix := range fixtures { fix := fix t.Run(fix.in, func(t *testing.T) { t.Parallel() u, in, uerr := normalizeURI(fix.in) if uerr != nil { if fix.rerr == nil { t.Errorf("bad input URI %s", uerr) } t.SkipNow() } root, rerr := deducer.deduceRoot(in) if fix.rerr != nil { if rerr == nil { t.Errorf("Expected error on deducing root, got none:\n\t(WNT) %s", fix.rerr) } else if fix.rerr.Error() != rerr.Error() { t.Errorf("Got unexpected error on deducing root:\n\t(GOT) %s\n\t(WNT) %s", rerr, fix.rerr) } } else if rerr != nil { t.Errorf("Got unexpected error on deducing root:\n\t(GOT) %s", rerr) } else if root != fix.root { t.Errorf("Deducer did not return expected root:\n\t(GOT) %s\n\t(WNT) %s", root, fix.root) } mb, mberr := deducer.deduceSource(in, u) if fix.srcerr != nil { if mberr == nil { t.Errorf("Expected error on deducing source, got none:\n\t(WNT) %s", fix.srcerr) } else if fix.srcerr.Error() != mberr.Error() { t.Errorf("Got unexpected error on deducing source:\n\t(GOT) %s\n\t(WNT) %s", mberr, fix.srcerr) } } else if mberr != nil { // don't complain the fix already expected an rerr if fix.rerr == nil { t.Errorf("Got unexpected error on deducing source:\n\t(GOT) %s", mberr) } } else if !reflect.DeepEqual(mb, fix.mb) { if mb == nil { t.Errorf("Deducer returned source maybes, but none expected:\n\t(GOT) (none)\n\t(WNT) %s", printmb(fix.mb)) } else if fix.mb == nil { t.Errorf("Deducer returned source maybes, but none expected:\n\t(GOT) %s\n\t(WNT) (none)", printmb(mb)) } else { t.Errorf("Deducer did not return expected source:\n\t(GOT) %s\n\t(WNT) %s", printmb(mb), printmb(fix.mb)) } } }) } }) } runSet := func(t *testing.T) { for typ, fixtures := range pathDeductionFixtures { do(typ, fixtures, t) } } t.Run("first", runSet) // Run the test set twice to ensure results are correct for both cached // and uncached deductions. t.Run("second", runSet) } func TestVanityDeduction(t *testing.T) { if testing.Short() { t.Skip("Skipping slow test in short mode") } sm, clean := mkNaiveSM(t) defer clean() vanities := pathDeductionFixtures["vanity"] // group to avoid sourcemanager cleanup ctx := context.Background() do := func(t *testing.T) { for _, fix := range vanities { fix := fix t.Run(fix.in, func(t *testing.T) { t.Parallel() pr, err := sm.DeduceProjectRoot(fix.in) if err != nil { t.Errorf("Unexpected err on deducing project root: %s", err) return } else if string(pr) != fix.root { t.Errorf("Deducer did not return expected root:\n\t(GOT) %s\n\t(WNT) %s", pr, fix.root) } pd, err := sm.deduceCoord.deduceRootPath(ctx, fix.in) if err != nil { t.Errorf("Unexpected err on deducing source: %s", err) return } if len(pd.mb) != 1 { t.Errorf("Expected single maybeSource, but found: %d", len(pd.mb)) return } goturl, wanturl := pd.mb[0].(maybeGitSource).url.String(), fix.mb[0].(maybeGitSource).url.String() if goturl != wanturl { t.Errorf("Deduced repo ident does not match fixture:\n\t(GOT) %s\n\t(WNT) %s", goturl, wanturl) } urls, err := sm.SourceURLsForPath(fix.in) if err != nil { t.Errorf("Unexpected err on deducing source urls: %s", err) return } if len(urls) != 1 { t.Errorf("Deduced source URLs count for a vanity import should be 1, got %d", len(urls)) } goturl = urls[0].String() if goturl != wanturl { t.Errorf("Deduced source URL does not match fixture:\n\t(GOT) %s\n\t(WNT) %s", goturl, wanturl) } }) } } // Run twice, to ensure correctness of cache t.Run("first", do) t.Run("second", do) } func TestVanityDeductionSchemeMismatch(t *testing.T) { if testing.Short() { t.Skip("Skipping slow test in short mode") } ctx := context.Background() cm := newSupervisor(ctx) dc := newDeductionCoordinator(cm) _, err := dc.deduceRootPath(ctx, "ssh://golang.org/exp") // TODO(sdboyer) this is not actually the error that it should be if err == nil { t.Error("should have errored on scheme mismatch between input and go-get metadata") } }