From: Bryan C. Mills Date: Tue, 1 Sep 2020 03:15:05 +0000 (-0400) Subject: cmd/go: simplify and document lazy-loading test cases X-Git-Tag: go1.16beta1~1145 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b0369225ebfdc355c61abbbb2663316388c60895;p=gostls13.git cmd/go: simplify and document lazy-loading test cases I decided to add package and module diagrams to the test cases to make them easier to follow. While adding those diagrams, I noticed some strong similarities among a couple of the graphs, so I consolidated those cases (and deleted the redundant tests). For #36460 Change-Id: Id6cd04fc871379b83851c2d1af89ea9296a0f3e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/251997 Run-TryBot: Bryan C. Mills TryBot-Result: Gobot Gobot Reviewed-by: Jay Conrod Reviewed-by: Michael Matloob --- diff --git a/src/cmd/go/testdata/script/mod_all.txt b/src/cmd/go/testdata/script/mod_all.txt index a219913094..9f4b0a4e4d 100644 --- a/src/cmd/go/testdata/script/mod_all.txt +++ b/src/cmd/go/testdata/script/mod_all.txt @@ -1,6 +1,38 @@ # This test illustrates the relationship between the 'all' pattern and # the dependencies of the main module. +# The package import graph used in this test looks like: +# +# main --------- a --------- b +# | | +# | a_test ---- c +# | | +# | c_test ---- d +# | +# main_test ---- t --------- u +# | +# t_test ---- w +# | +# w_test ---- x +# +# main/testonly_test ---- q --------- r +# | +# q_test ---- s +# +# And the module dependency graph looks like: +# +# main --- a.1 ---- b.1 +# \ \ \ +# \ \ c.1 -- d.1 +# \ \ +# \ t.1 ---- u.1 +# \ \ +# \ w.1 -- x.1 +# \ +# q.1 ---- r.1 +# \ +# s.1 + env PKGFMT='{{if .Module}}{{.ImportPath}}{{end}}' env MODFMT='{{.Path}}' @@ -41,10 +73,11 @@ stdout '^example.com/u$' # variants of those packages. go list -f $PKGFMT all -stdout -count=11 '^.' +stdout -count=13 '^.' stdout '^example.com/a$' stdout '^example.com/b$' stdout '^example.com/c$' +stdout '^example.com/d$' stdout '^example.com/main$' stdout '^example.com/main/testonly$' stdout '^example.com/q$' @@ -53,20 +86,22 @@ stdout '^example.com/s$' stdout '^example.com/t$' stdout '^example.com/u$' stdout '^example.com/w$' +stdout '^example.com/x$' # 'go list -test all' is equivalent to 'go list -test $(go list all)' # and both should include tests for every package in 'all'. -go list -test -f $PKGFMT example.com/a example.com/b example.com/c example.com/main example.com/main/testonly example.com/q example.com/r example.com/s example.com/t example.com/u example.com/w +go list -test -f $PKGFMT example.com/a example.com/b example.com/c example.com/d example.com/main example.com/main/testonly example.com/q example.com/r example.com/s example.com/t example.com/u example.com/w example.com/x cp stdout list-test-explicit.txt go list -test -f $PKGFMT all cmp stdout list-test-explicit.txt -stdout -count=34 '^.' +stdout -count=36 '^.' stdout '^example.com/a$' stdout '^example.com/b$' stdout '^example.com/c$' +stdout '^example.com/d$' stdout '^example.com/main$' stdout '^example.com/main/testonly$' stdout '^example.com/q$' @@ -75,6 +110,7 @@ stdout '^example.com/s$' stdout '^example.com/t$' stdout '^example.com/u$' stdout '^example.com/w$' +stdout '^example.com/x$' stdout '^example.com/a.test$' stdout '^example.com/a_test \[example.com/a.test\]$' stdout '^example.com/b.test$' @@ -103,10 +139,11 @@ stdout '^example.com/w_test \[example.com/w.test\]$' # 'go list -m all' covers the packages in 'go list -test -deps all'. go list -m -f $MODFMT all -stdout -count=10 '^.' +stdout -count=12 '^.' stdout '^example.com/a$' stdout '^example.com/b$' stdout '^example.com/c$' +stdout '^example.com/d$' stdout '^example.com/main$' stdout '^example.com/q$' stdout '^example.com/r$' @@ -114,6 +151,7 @@ stdout '^example.com/s$' stdout '^example.com/t$' stdout '^example.com/u$' stdout '^example.com/w$' +stdout '^example.com/x$' # 'go mod vendor' copies in only the packages transitively imported by the main @@ -176,12 +214,14 @@ replace ( example.com/a v0.1.0 => ./a example.com/b v0.1.0 => ./b example.com/c v0.1.0 => ./c + example.com/d v0.1.0 => ./d example.com/q v0.1.0 => ./q example.com/r v0.1.0 => ./r example.com/s v0.1.0 => ./s example.com/t v0.1.0 => ./t example.com/u v0.1.0 => ./u example.com/w v0.1.0 => ./w + example.com/x v0.1.0 => ./x ) -- main.go -- package main @@ -207,11 +247,11 @@ require ( example.com/c v0.1.0 ) -- a/a.go -- -package x +package a import _ "example.com/b" -- a/a_test.go -- -package x_test +package a_test import _ "example.com/c" -- b/go.mod -- @@ -226,10 +266,20 @@ package b_test module example.com/c go 1.15 + +require example.com/d v0.1.0 -- c/c.go -- package c -- c/c_test.go -- package c_test + +import _ "example.com/d" +-- d/go.mod -- +module example.com/d + +go 1.15 +-- d/d.go -- +package d -- q/go.mod -- module example.com/q @@ -290,7 +340,17 @@ package u_test module example.com/w go 1.15 + +require example.com/x v0.1.0 -- w/w.go -- package w -- w/w_test.go -- package w_test + +import _ "example.com/x" +-- x/go.mod -- +module example.com/x + +go 1.15 +-- x/x.go -- +package x diff --git a/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt b/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt index aade00d602..4ad8cbf8ee 100644 --- a/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt +++ b/src/cmd/go/testdata/script/mod_lazy_import_allmod.txt @@ -1,4 +1,4 @@ -# This file demonstrates dependency resolution when the main module imports a +# This test demonstrates dependency resolution when the main module imports a # new package from a previously-test-only dependency. # # When lazy loading is active, the loader will not load dependencies of any @@ -6,6 +6,23 @@ # the main module is changed to import a package from such a module, the # dependencies of that module will need to be reloaded. +# The import graph used in this test looks like: +# +# m ---- a +# \ | +# \ a_test ---- b/x +# \ +# --------------b/y (new) ---- c +# +# Where b/x and b/y are disjoint packages, but both contained in module b. +# +# The module dependency graph initially looks like: +# +# m ---- a.1 ---- b.1 ---- c.1 +# +# This configuration is similar to that used in mod_lazy_new_import, +# but the new import is from what is initially a test-only dependency. + # Control case: in Go 1.14, the original go.mod is tidy, # and the dependency on c is eagerly loaded. diff --git a/src/cmd/go/testdata/script/mod_lazy_import_test_dep.txt b/src/cmd/go/testdata/script/mod_lazy_import_test_dep.txt deleted file mode 100644 index b7e3e6cb08..0000000000 --- a/src/cmd/go/testdata/script/mod_lazy_import_test_dep.txt +++ /dev/null @@ -1,159 +0,0 @@ -# This file demonstrates the go.mod changes needed to ensure reproducibility -# when running 'go test' on a sequence of packages for which each package in the -# sequence is a test-only dependency of the previous package, as a user might do -# if they encounter a test failure while fixing a bug found in one of their -# dependencies. - -cp go.mod go.mod.old -cp lazy.go lazy.go.old -go mod tidy -cmp go.mod go.mod.old - -# Before adding a new import, the go.mod file should -# enumerate modules for all packages already imported. -go list -m all -stdout '^example.com/d v0.1.0' # not v0.2.0 as would be resolved by 'latest' -cp stdout list.old -cmp go.mod go.mod.old - -# Following the chain of dependencies by listing test dependencies -# or running tests should not change the go.mod file. -go list -test -deps example.com/a -stdout '^example.com/a' -stdout '^example.com/b' -! stdout '^example.com/c' -[!short] go test -c example.com/a -cmp go.mod go.mod.old - -go list -test -deps example.com/b -stdout '^example.com/b' -stdout '^example.com/c' -! stdout '^example.com/d' -[!short] go test -c example.com/b -cmp go.mod go.mod.old - -go list -test -deps example.com/c -stdout '^example.com/c' -stdout '^example.com/d' -[!short] go test -c example.com/c -cmp go.mod go.mod.old - -# When we add a new import of a package already imported by a test of a test of -# a dependency, and that dependency is already tidy, its transitive dependencies -# should already be present. -cp lazy.go.new lazy.go -go list all -go list -m all -cmp stdout list.old -cmp go.mod go.mod.new # Indirect dependency promoted to direct. - -# TODO(#36460): - -cp lazy.go.old lazy.go -cp go.mod.old go.mod -go mod edit -go=1.16 - -# If we reach d by running successive tests, we should end up with exactly the -# version required by c, with an update to the go.mod file as soon as we load a -# dependency not found in the deepening scan. - -# However, if we skip directly to adding a new import of d, the dependency is -# too far away for a deepening scan to find, which is fine because the package -# whose test imported it wasn't even in "all". It should resolve from the latest -# version of its module. - --- go.mod -- -module example.com/lazy - -go 1.14 - -require example.com/a v0.1.0 - -replace ( - example.com/a v0.1.0 => ./a - example.com/b v0.1.0 => ./b - example.com/c v0.1.0 => ./c - example.com/d v0.1.0 => ./d1 - example.com/d v0.2.0 => ./d2 -) --- go.mod.new -- -module example.com/lazy - -go 1.14 - -require ( - example.com/a v0.1.0 - example.com/d v0.1.0 -) - -replace ( - example.com/a v0.1.0 => ./a - example.com/b v0.1.0 => ./b - example.com/c v0.1.0 => ./c - example.com/d v0.1.0 => ./d1 - example.com/d v0.2.0 => ./d2 -) --- lazy.go -- -package lazy - -import ( - _ "example.com/a" -) - -func main() {} --- lazy.go.new -- -package lazy - -import ( - _ "example.com/a" - "example.com/d" -) - -func main() { - println(d.Version) -} --- a/go.mod -- -module example.com/a - -go 1.14 - -require example.com/b v0.1.0 --- a/a.go -- -package a -import _ "example.com/b" --- b/go.mod -- -module example.com/b - -go 1.16 - -require example.com/c v0.1.0 --- b/b.go -- -package b --- b/b_test.go -- -package b -import _ "example.com/c" --- c/go.mod -- -module example.com/c - -go 1.16 - -require example.com/d v0.1.0 --- c/c.go -- -package c --- c/c_test.go -- -package c -import _ "example.com/d" --- d1/go.mod -- -module example.com/d - -go 1.16 --- d1/d.go -- -package d -const Version = "v0.1.0" --- d2/go.mod -- -module example.com/d - -go 1.16 --- d2/d.go -- -package d -const Version = "v0.2.0" diff --git a/src/cmd/go/testdata/script/mod_lazy_new_import.txt b/src/cmd/go/testdata/script/mod_lazy_new_import.txt index 76b915afaa..02935bf236 100644 --- a/src/cmd/go/testdata/script/mod_lazy_new_import.txt +++ b/src/cmd/go/testdata/script/mod_lazy_new_import.txt @@ -1,3 +1,21 @@ +# This test illustrates the use of a deepening scan to resolve transitive +# imports of imports of new packages from within existing dependencies. + +# The package import graph used in this test looks like: +# +# lazy ---- a/x ---- b +# \ +# ---- a/y ---- c +# +# Where a/x and x/y are disjoint packages, but both contained in module a. +# +# The module dependency graph initially looks like: +# +# lazy ---- a.1 ---- b.1 +# \ +# c.1 + + cp go.mod go.mod.old cp lazy.go lazy.go.old go mod tidy @@ -30,7 +48,7 @@ go mod edit -go=1.16 -- go.mod -- module example.com/lazy -go 1.14 +go 1.15 require example.com/a v0.1.0 @@ -56,7 +74,7 @@ import ( -- a/go.mod -- module example.com/a -go 1.14 +go 1.15 require ( example.com/b v0.1.0 @@ -71,19 +89,19 @@ import _ "example.com/c" -- b/go.mod -- module example.com/b -go 1.14 +go 1.15 -- b/b.go -- package b -- c1/go.mod -- module example.com/c -go 1.14 +go 1.15 -- c1/c.go -- package c -- c2/go.mod -- module example.com/c -go 1.14 +go 1.15 -- c2/c.go -- package c This file should not be used, so this syntax error should be ignored. diff --git a/src/cmd/go/testdata/script/mod_lazy_test_all.txt b/src/cmd/go/testdata/script/mod_lazy_test_all.txt deleted file mode 100644 index 4ce9fb167b..0000000000 --- a/src/cmd/go/testdata/script/mod_lazy_test_all.txt +++ /dev/null @@ -1,125 +0,0 @@ -cp go.mod go.mod.old -go mod tidy -cmp go.mod go.mod.old - -# 'go list -m all' includes modules that cover the test dependencies of -# the packages imported by the main module. - -go list -m all -stdout 'example.com/b v0.1.0' -stdout 'example.com/c v0.1.0' -cmp go.mod go.mod.old - -# 'go test' (or equivalent) of any package in 'all' should use its existing -# dependencies without updating the go.mod file. - -go list all # Control case: example.com/b really is in 'all'. -stdout '^example.com/b$' -cmp go.mod go.mod.old # Already tidy, so dependencies shouldn't change. - -go list -test -deps example.com/b -stdout '^example.com/b$' -stdout '^example.com/c$' -! stdout '^example.com/d$' - -[!short] go test -c example.com/b - -cmp go.mod go.mod.old # Should have resolved the above without modifying go.mod. - - -# TODO(#36460): - -# 'go list -m all' should include modules that cover the test dependencies of -# the packages imported by the main module, found via a deepening scan. - -# 'go test' of any package in 'all' should use its existing dependencies without -# updating the go.mod file. This requires that we consider _dependencies of_ the -# explicit dependencies of the main module, and that we not record those -# dependencies explicitly after loading them. - - --- go.mod -- -module example.com/lazy - -go 1.14 - -require example.com/a v0.1.0 - -replace ( - example.com/a v0.1.0 => ./a - example.com/b v0.1.0 => ./b1 - example.com/b v0.2.0 => ./b2 - example.com/c v0.1.0 => ./c - example.com/d v0.1.0 => ./d -) --- lazy.go -- -package lazy - -import ( - _ "example.com/a/x" -) --- a/go.mod -- -module example.com/a - -go 1.14 - -require example.com/b v0.1.0 --- a/x/x.go -- -package x --- a/x/x_test.go -- -package x - -import ( - "testing" - - _ "example.com/b" -) - -func TestUsingB(t *testing.T) { - // … -} --- b1/go.mod -- -module example.com/b - -go 1.14 - -require example.com/c v0.1.0 --- b1/b.go -- -package b --- b1/b_test.go -- -package b - -import _ "example.com/c" --- b2/go.mod -- -module example.com/b - -go 1.14 - -require example.com/c v0.1.0 --- b2/b.go -- -package b --- b2/b_test.go -- -package b - -import _ "example.com/c" - -This file should not be used, so this syntax error should be ignored. --- c/go.mod -- -module example.com/c - -go 1.14 - -require example.com/d v0.1.0 --- c/c.go -- -package c --- c/c_test.go -- -package c -import _ "example.com/d" -This file should not be used, so this syntax error should be ignored. --- d/go.mod -- -module example.com/d - -go 1.14 --- d/d.go -- -package d -This file should not be used, so this syntax error should be ignored. diff --git a/src/cmd/go/testdata/script/mod_lazy_test_horizon.txt b/src/cmd/go/testdata/script/mod_lazy_test_horizon.txt index 29fc0aaa74..9cdfad79f6 100644 --- a/src/cmd/go/testdata/script/mod_lazy_test_horizon.txt +++ b/src/cmd/go/testdata/script/mod_lazy_test_horizon.txt @@ -1,7 +1,23 @@ # This file demonstrates the effect of lazy loading on the selected # versions of test dependencies. -# Control case: in Go 1.14, the version of c imported by 'go test x' is the +# The package import graph used in this test looks like: +# +# m ---- a +# \ | +# \ a_test ---- b +# \ | +# x b_test +# | \ +# x_test -------------- c +# +# And the module dependency graph looks like: +# +# m -- a.1 -- b.1 -- c.2 +# \ +# x.1 ------------ c.1 + +# Control case: in Go 1.15, the version of c imported by 'go test x' is the # version required by module b, even though b_test is not relevant to the main # module. (The main module imports a, and a_test imports b, but all of the # packages and tests in the main module can be built without b.) @@ -33,7 +49,7 @@ import ( -- go.mod -- module m -go 1.14 +go 1.15 require ( a v0.1.0 diff --git a/src/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt b/src/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt index bbb0772303..ca6c55040e 100644 --- a/src/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt +++ b/src/cmd/go/testdata/script/mod_lazy_test_of_test_dep.txt @@ -1,8 +1,27 @@ +# This file demonstrates the effect of lazy loading on the reproducibility of +# tests (and tests of test dependencies) outside the main module. +# +# It is similar to the cases in mod_all.txt and mod_lazy_test_horizon.txt, but +# focuses on the effect of "go test" on specific packages instead of the "all" +# pattern. + +# The package import graph used in this test looks like: +# +# lazy ---- a +# | +# a_test ---- b +# | +# b_test ---- c +# +# And the non-lazy module dependency graph looks like: +# +# lazy ---- a.1 ---- b.1 ---- c.1 + cp go.mod go.mod.old go mod tidy cmp go.mod go.mod.old -# In Go 1.14 mode, 'go list -m all' includes modules needed by the +# In Go 1.15 mode, 'go list -m all' includes modules needed by the # transitive closure of tests of dependencies of tests of dependencies of …. go list -m all @@ -13,36 +32,44 @@ cmp go.mod go.mod.old # 'go test' (or equivalent) of any such dependency, no matter how remote, does # not update the go.mod file. -go list all -stdout example.com/a/x -stdout example.com/b # Test dependency of example.com/a/x. -stdout example.com/c # Test dependency of example.com/b. - -go list -test -deps all +go list -test -deps example.com/a stdout example.com/b -stdout example.com/c -cmp go.mod go.mod.old +! stdout example.com/c -[!short] go test example.com/a/x +[!short] go test -c example.com/a [!short] cmp go.mod go.mod.old -[!short] go test example.com/b +go list -test -deps example.com/b +stdout example.com/c + +[!short] go test -c example.com/b [!short] cmp go.mod go.mod.old # TODO(#36460): -# After changing to 'go 1.15` uniformly, 'go list -m all' should prune out +# After changing to 'go 1.16` uniformly, 'go list -m all' should prune out # example.com/c, because it is not imported by any package (or test of a package) # transitively imported by the main module. -# example.com/a/x is transitively imported, -# and example.com/b is needed in order to run 'go test example.com/a/x', +# +# example.com/a is imported, +# and example.com/b is needed in order to run 'go test example.com/a', # but example.com/c is not needed because we don't expect the user to need to run # 'go test example.com/b'. +# If we skip directly to adding a new import of c, the dependency is too far +# away for a deepening scan to find, which is fine because the package whose +# test imported it wasn't even it "all". It should resolve from the latest +# version of its module. + +# However, if we reach c by running successive tests starting from the main +# module, we should end up with exactly the version require by c, with an update +# to the go.mod file as soon as we test a test dependency that is not itself in +# "all". + -- go.mod -- module example.com/lazy -go 1.14 +go 1.15 require example.com/a v0.1.0 @@ -57,18 +84,18 @@ replace ( package lazy import ( - _ "example.com/a/x" + _ "example.com/a" ) -- a/go.mod -- module example.com/a -go 1.14 +go 1.15 require example.com/b v0.1.0 --- a/x/x.go -- -package x --- a/x/x_test.go -- -package x +-- a/a.go -- +package a +-- a/a_test.go -- +package a import ( "testing" @@ -82,7 +109,7 @@ func TestUsingB(t *testing.T) { -- b1/go.mod -- module example.com/b -go 1.14 +go 1.15 require example.com/c v0.1.0 -- b1/b.go -- @@ -94,7 +121,7 @@ import _ "example.com/c" -- b2/go.mod -- module example.com/b -go 1.14 +go 1.15 require example.com/c v0.1.0 -- b2/b.go -- @@ -106,13 +133,13 @@ This file should not be used, so this syntax error should be ignored. -- c1/go.mod -- module example.com/c -go 1.14 +go 1.15 -- c1/c.go -- package c -- c2/go.mod -- module example.com/c -go 1.14 +go 1.15 -- c2/c.go -- package c This file should not be used, so this syntax error should be ignored.