...
Run Format

Source file src/cmd/go/vendor_test.go

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

View as plain text