Home | History | Annotate | Download | only in go
      1 // Copyright 2015 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 // Tests for vendoring semantics.
      6 
      7 package main_test
      8 
      9 import (
     10 	"bytes"
     11 	"fmt"
     12 	"internal/testenv"
     13 	"path/filepath"
     14 	"regexp"
     15 	"strings"
     16 	"testing"
     17 )
     18 
     19 func TestVendorImports(t *testing.T) {
     20 	tg := testgo(t)
     21 	defer tg.cleanup()
     22 	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
     23 	tg.run("list", "-f", "{{.ImportPath}} {{.Imports}}", "vend/...", "vend/vendor/...", "vend/x/vendor/...")
     24 	want := `
     25 		vend [vend/vendor/p r]
     26 		vend/dir1 []
     27 		vend/hello [fmt vend/vendor/strings]
     28 		vend/subdir [vend/vendor/p r]
     29 		vend/x [vend/x/vendor/p vend/vendor/q vend/x/vendor/r vend/dir1 vend/vendor/vend/dir1/dir2]
     30 		vend/x/invalid [vend/x/invalid/vendor/foo]
     31 		vend/vendor/p []
     32 		vend/vendor/q []
     33 		vend/vendor/strings []
     34 		vend/vendor/vend/dir1/dir2 []
     35 		vend/x/vendor/p []
     36 		vend/x/vendor/p/p [notfound]
     37 		vend/x/vendor/r []
     38 	`
     39 	want = strings.Replace(want+"\t", "\n\t\t", "\n", -1)
     40 	want = strings.TrimPrefix(want, "\n")
     41 
     42 	have := tg.stdout.String()
     43 
     44 	if have != want {
     45 		t.Errorf("incorrect go list output:\n%s", diffSortedOutputs(have, want))
     46 	}
     47 }
     48 
     49 func TestVendorBuild(t *testing.T) {
     50 	tg := testgo(t)
     51 	defer tg.cleanup()
     52 	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
     53 	tg.run("build", "vend/x")
     54 }
     55 
     56 func TestVendorRun(t *testing.T) {
     57 	tg := testgo(t)
     58 	defer tg.cleanup()
     59 	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
     60 	tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
     61 	tg.run("run", "hello.go")
     62 	tg.grepStdout("hello, world", "missing hello world output")
     63 }
     64 
     65 func TestVendorGOPATH(t *testing.T) {
     66 	tg := testgo(t)
     67 	defer tg.cleanup()
     68 	changeVolume := func(s string, f func(s string) string) string {
     69 		vol := filepath.VolumeName(s)
     70 		return f(vol) + s[len(vol):]
     71 	}
     72 	gopath := changeVolume(filepath.Join(tg.pwd(), "testdata"), strings.ToLower)
     73 	tg.setenv("GOPATH", gopath)
     74 	cd := changeVolume(filepath.Join(tg.pwd(), "testdata/src/vend/hello"), strings.ToUpper)
     75 	tg.cd(cd)
     76 	tg.run("run", "hello.go")
     77 	tg.grepStdout("hello, world", "missing hello world output")
     78 }
     79 
     80 func TestVendorTest(t *testing.T) {
     81 	tg := testgo(t)
     82 	defer tg.cleanup()
     83 	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
     84 	tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
     85 	tg.run("test", "-v")
     86 	tg.grepStdout("TestMsgInternal", "missing use in internal test")
     87 	tg.grepStdout("TestMsgExternal", "missing use in external test")
     88 }
     89 
     90 func TestVendorInvalid(t *testing.T) {
     91 	tg := testgo(t)
     92 	defer tg.cleanup()
     93 	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
     94 
     95 	tg.runFail("build", "vend/x/invalid")
     96 	tg.grepStderr("must be imported as foo", "missing vendor import error")
     97 }
     98 
     99 func TestVendorImportError(t *testing.T) {
    100 	tg := testgo(t)
    101 	defer tg.cleanup()
    102 	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
    103 
    104 	tg.runFail("build", "vend/x/vendor/p/p")
    105 
    106 	re := regexp.MustCompile(`cannot find package "notfound" in any of:
    107 	.*[\\/]testdata[\\/]src[\\/]vend[\\/]x[\\/]vendor[\\/]notfound \(vendor tree\)
    108 	.*[\\/]testdata[\\/]src[\\/]vend[\\/]vendor[\\/]notfound
    109 	.*[\\/]src[\\/]notfound \(from \$GOROOT\)
    110 	.*[\\/]testdata[\\/]src[\\/]notfound \(from \$GOPATH\)`)
    111 
    112 	if !re.MatchString(tg.stderr.String()) {
    113 		t.Errorf("did not find expected search list in error text")
    114 	}
    115 }
    116 
    117 // diffSortedOutput prepares a diff of the already sorted outputs haveText and wantText.
    118 // The diff shows common lines prefixed by a tab, lines present only in haveText
    119 // prefixed by "unexpected: ", and lines present only in wantText prefixed by "missing: ".
    120 func diffSortedOutputs(haveText, wantText string) string {
    121 	var diff bytes.Buffer
    122 	have := splitLines(haveText)
    123 	want := splitLines(wantText)
    124 	for len(have) > 0 || len(want) > 0 {
    125 		if len(want) == 0 || len(have) > 0 && have[0] < want[0] {
    126 			fmt.Fprintf(&diff, "unexpected: %s\n", have[0])
    127 			have = have[1:]
    128 			continue
    129 		}
    130 		if len(have) == 0 || len(want) > 0 && want[0] < have[0] {
    131 			fmt.Fprintf(&diff, "missing: %s\n", want[0])
    132 			want = want[1:]
    133 			continue
    134 		}
    135 		fmt.Fprintf(&diff, "\t%s\n", want[0])
    136 		want = want[1:]
    137 		have = have[1:]
    138 	}
    139 	return diff.String()
    140 }
    141 
    142 func splitLines(s string) []string {
    143 	x := strings.Split(s, "\n")
    144 	if x[len(x)-1] == "" {
    145 		x = x[:len(x)-1]
    146 	}
    147 	return x
    148 }
    149 
    150 func TestVendorGet(t *testing.T) {
    151 	tooSlow(t)
    152 	tg := testgo(t)
    153 	defer tg.cleanup()
    154 	tg.tempFile("src/v/m.go", `
    155 		package main
    156 		import ("fmt"; "vendor.org/p")
    157 		func main() {
    158 			fmt.Println(p.C)
    159 		}`)
    160 	tg.tempFile("src/v/m_test.go", `
    161 		package main
    162 		import ("fmt"; "testing"; "vendor.org/p")
    163 		func TestNothing(t *testing.T) {
    164 			fmt.Println(p.C)
    165 		}`)
    166 	tg.tempFile("src/v/vendor/vendor.org/p/p.go", `
    167 		package p
    168 		const C = 1`)
    169 	tg.setenv("GOPATH", tg.path("."))
    170 	tg.cd(tg.path("src/v"))
    171 	tg.run("run", "m.go")
    172 	tg.run("test")
    173 	tg.run("list", "-f", "{{.Imports}}")
    174 	tg.grepStdout("v/vendor/vendor.org/p", "import not in vendor directory")
    175 	tg.run("list", "-f", "{{.TestImports}}")
    176 	tg.grepStdout("v/vendor/vendor.org/p", "test import not in vendor directory")
    177 	tg.run("get", "-d")
    178 	tg.run("get", "-t", "-d")
    179 }
    180 
    181 func TestVendorGetUpdate(t *testing.T) {
    182 	testenv.MustHaveExternalNetwork(t)
    183 
    184 	tg := testgo(t)
    185 	defer tg.cleanup()
    186 	tg.makeTempdir()
    187 	tg.setenv("GOPATH", tg.path("."))
    188 	tg.run("get", "github.com/rsc/go-get-issue-11864")
    189 	tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
    190 }
    191 
    192 func TestVendorGetU(t *testing.T) {
    193 	testenv.MustHaveExternalNetwork(t)
    194 
    195 	tg := testgo(t)
    196 	defer tg.cleanup()
    197 	tg.makeTempdir()
    198 	tg.setenv("GOPATH", tg.path("."))
    199 	tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
    200 }
    201 
    202 func TestVendorGetTU(t *testing.T) {
    203 	testenv.MustHaveExternalNetwork(t)
    204 
    205 	tg := testgo(t)
    206 	defer tg.cleanup()
    207 	tg.makeTempdir()
    208 	tg.setenv("GOPATH", tg.path("."))
    209 	tg.run("get", "-t", "-u", "github.com/rsc/go-get-issue-11864/...")
    210 }
    211 
    212 func TestVendorGetBadVendor(t *testing.T) {
    213 	testenv.MustHaveExternalNetwork(t)
    214 
    215 	for _, suffix := range []string{"bad/imp", "bad/imp2", "bad/imp3", "..."} {
    216 		t.Run(suffix, func(t *testing.T) {
    217 			tg := testgo(t)
    218 			defer tg.cleanup()
    219 			tg.makeTempdir()
    220 			tg.setenv("GOPATH", tg.path("."))
    221 			tg.runFail("get", "-t", "-u", "github.com/rsc/go-get-issue-18219/"+suffix)
    222 			tg.grepStderr("must be imported as", "did not find error about vendor import")
    223 			tg.mustNotExist(tg.path("src/github.com/rsc/vendor"))
    224 		})
    225 	}
    226 }
    227 
    228 func TestGetSubmodules(t *testing.T) {
    229 	testenv.MustHaveExternalNetwork(t)
    230 
    231 	tg := testgo(t)
    232 	defer tg.cleanup()
    233 	tg.makeTempdir()
    234 	tg.setenv("GOPATH", tg.path("."))
    235 	tg.run("get", "-d", "github.com/rsc/go-get-issue-12612")
    236 	tg.run("get", "-u", "-d", "github.com/rsc/go-get-issue-12612")
    237 	tg.mustExist(tg.path("src/github.com/rsc/go-get-issue-12612/vendor/golang.org/x/crypto/.git"))
    238 }
    239 
    240 func TestVendorCache(t *testing.T) {
    241 	tg := testgo(t)
    242 	defer tg.cleanup()
    243 	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor"))
    244 	tg.runFail("build", "p")
    245 	tg.grepStderr("must be imported as x", "did not fail to build p")
    246 }
    247 
    248 func TestVendorTest2(t *testing.T) {
    249 	testenv.MustHaveExternalNetwork(t)
    250 
    251 	tg := testgo(t)
    252 	defer tg.cleanup()
    253 	tg.makeTempdir()
    254 	tg.setenv("GOPATH", tg.path("."))
    255 	tg.run("get", "github.com/rsc/go-get-issue-11864")
    256 
    257 	// build -i should work
    258 	tg.run("build", "-i", "github.com/rsc/go-get-issue-11864")
    259 	tg.run("build", "-i", "github.com/rsc/go-get-issue-11864/t")
    260 
    261 	// test -i should work like build -i (golang.org/issue/11988)
    262 	tg.run("test", "-i", "github.com/rsc/go-get-issue-11864")
    263 	tg.run("test", "-i", "github.com/rsc/go-get-issue-11864/t")
    264 
    265 	// test should work too
    266 	tg.run("test", "github.com/rsc/go-get-issue-11864")
    267 	tg.run("test", "github.com/rsc/go-get-issue-11864/t")
    268 
    269 	// external tests should observe internal test exports (golang.org/issue/11977)
    270 	tg.run("test", "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2")
    271 }
    272 
    273 func TestVendorTest3(t *testing.T) {
    274 	testenv.MustHaveExternalNetwork(t)
    275 
    276 	tg := testgo(t)
    277 	defer tg.cleanup()
    278 	tg.makeTempdir()
    279 	tg.setenv("GOPATH", tg.path("."))
    280 	tg.run("get", "github.com/clsung/go-vendor-issue-14613")
    281 
    282 	tg.run("build", "-o", tg.path("a.out"), "-i", "github.com/clsung/go-vendor-issue-14613")
    283 
    284 	// test folder should work
    285 	tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613")
    286 	tg.run("test", "github.com/clsung/go-vendor-issue-14613")
    287 
    288 	// test with specified _test.go should work too
    289 	tg.cd(filepath.Join(tg.path("."), "src"))
    290 	tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613/vendor_test.go")
    291 	tg.run("test", "github.com/clsung/go-vendor-issue-14613/vendor_test.go")
    292 
    293 	// test with imported and not used
    294 	tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go")
    295 	tg.runFail("test", "github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go")
    296 	tg.grepStderr("imported and not used:", `should say "imported and not used"`)
    297 }
    298 
    299 func TestVendorList(t *testing.T) {
    300 	testenv.MustHaveExternalNetwork(t)
    301 
    302 	tg := testgo(t)
    303 	defer tg.cleanup()
    304 	tg.makeTempdir()
    305 	tg.setenv("GOPATH", tg.path("."))
    306 	tg.run("get", "github.com/rsc/go-get-issue-11864")
    307 
    308 	tg.run("list", "-f", `{{join .TestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/t")
    309 	tg.grepStdout("go-get-issue-11864/vendor/vendor.org/p", "did not find vendor-expanded p")
    310 
    311 	tg.run("list", "-f", `{{join .XTestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/tx")
    312 	tg.grepStdout("go-get-issue-11864/vendor/vendor.org/p", "did not find vendor-expanded p")
    313 
    314 	tg.run("list", "-f", `{{join .XTestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2")
    315 	tg.grepStdout("go-get-issue-11864/vendor/vendor.org/tx2", "did not find vendor-expanded tx2")
    316 
    317 	tg.run("list", "-f", `{{join .XTestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3")
    318 	tg.grepStdout("go-get-issue-11864/vendor/vendor.org/tx3", "did not find vendor-expanded tx3")
    319 }
    320 
    321 func TestVendor12156(t *testing.T) {
    322 	// Former index out of range panic.
    323 	tg := testgo(t)
    324 	defer tg.cleanup()
    325 	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor2"))
    326 	tg.cd(filepath.Join(tg.pwd(), "testdata/testvendor2/src/p"))
    327 	tg.runFail("build", "p.go")
    328 	tg.grepStderrNot("panic", "panicked")
    329 	tg.grepStderr(`cannot find package "x"`, "wrong error")
    330 }
    331