github.com/mangodowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/cmd/go/vendor_test.go (about)

     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  	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")
   178  	tg.run("get", "-t")
   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  
   332  // Module legacy support does path rewriting very similar to vendoring.
   333  
   334  func TestModLegacy(t *testing.T) {
   335  	tg := testgo(t)
   336  	defer tg.cleanup()
   337  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/modlegacy"))
   338  	tg.run("list", "-f", "{{.Imports}}", "old/p1")
   339  	tg.grepStdout("new/p1", "old/p1 should import new/p1")
   340  	tg.run("list", "-f", "{{.Imports}}", "new/p1")
   341  	tg.grepStdout("new/p2", "new/p1 should import new/p2 (not new/v2/p2)")
   342  	tg.grepStdoutNot("new/v2", "new/p1 should NOT import new/v2*")
   343  	tg.grepStdout("new/sub/x/v1/y", "new/p1 should import new/sub/x/v1/y (not new/sub/v2/x/v1/y)")
   344  	tg.grepStdoutNot("new/sub/v2", "new/p1 should NOT import new/sub/v2*")
   345  	tg.grepStdout("new/sub/inner/x", "new/p1 should import new/sub/inner/x (no rewrites)")
   346  	tg.run("build", "old/p1", "new/p1")
   347  }
   348  
   349  func TestModLegacyGet(t *testing.T) {
   350  	testenv.MustHaveExternalNetwork(t)
   351  
   352  	tg := testgo(t)
   353  	defer tg.cleanup()
   354  	tg.makeTempdir()
   355  	tg.setenv("GOPATH", tg.path("d1"))
   356  	tg.run("get", "vcs-test.golang.org/git/modlegacy1-old.git/p1")
   357  	tg.run("list", "-f", "{{.Deps}}", "vcs-test.golang.org/git/modlegacy1-old.git/p1")
   358  	tg.grepStdout("new.git/p2", "old/p1 should depend on new/p2")
   359  	tg.grepStdoutNot("new.git/v2/p2", "old/p1 should NOT depend on new/v2/p2")
   360  	tg.run("build", "vcs-test.golang.org/git/modlegacy1-old.git/p1", "vcs-test.golang.org/git/modlegacy1-new.git/p1")
   361  
   362  	tg.setenv("GOPATH", tg.path("d2"))
   363  
   364  	tg.must(os.RemoveAll(tg.path("d2")))
   365  	tg.run("get", "github.com/rsc/vgotest5")
   366  	tg.run("get", "github.com/rsc/vgotest4")
   367  	tg.run("get", "github.com/myitcv/vgo_example_compat")
   368  
   369  	if testing.Short() {
   370  		return
   371  	}
   372  
   373  	tg.must(os.RemoveAll(tg.path("d2")))
   374  	tg.run("get", "github.com/rsc/vgotest4")
   375  	tg.run("get", "github.com/rsc/vgotest5")
   376  	tg.run("get", "github.com/myitcv/vgo_example_compat")
   377  
   378  	tg.must(os.RemoveAll(tg.path("d2")))
   379  	tg.run("get", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5")
   380  	tg.run("get", "github.com/myitcv/vgo_example_compat")
   381  
   382  	tg.must(os.RemoveAll(tg.path("d2")))
   383  	tg.run("get", "github.com/rsc/vgotest5", "github.com/rsc/vgotest4")
   384  	tg.run("get", "github.com/myitcv/vgo_example_compat")
   385  
   386  	tg.must(os.RemoveAll(tg.path("d2")))
   387  	tg.run("get", "github.com/myitcv/vgo_example_compat")
   388  	tg.run("get", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5")
   389  
   390  	pkgs := []string{"github.com/myitcv/vgo_example_compat", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5"}
   391  	for i := 0; i < 3; i++ {
   392  		for j := 0; j < 3; j++ {
   393  			for k := 0; k < 3; k++ {
   394  				if i == j || i == k || k == j {
   395  					continue
   396  				}
   397  				tg.must(os.RemoveAll(tg.path("d2")))
   398  				tg.run("get", pkgs[i], pkgs[j], pkgs[k])
   399  			}
   400  		}
   401  	}
   402  }