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 <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
diff --git a/src/cmd/go/testdata/script/mod_all.txt b/src/cmd/go/testdata/script/mod_all.txt
index a219913..9f4b0a4 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 @@
 # 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/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/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 @@
 # '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/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 @@
 	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 @@
 	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 @@
 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 @@
 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 aade00d..4ad8cbf 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 b7e3e6c..0000000
--- 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 76b915a..02935bf 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 --
 module example.com/lazy
 
-go 1.14
+go 1.15
 
 require example.com/a v0.1.0
 
@@ -56,7 +74,7 @@
 -- a/go.mod --
 module example.com/a
 
-go 1.14
+go 1.15
 
 require (
 	example.com/b v0.1.0
@@ -71,19 +89,19 @@
 -- 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 4ce9fb1..0000000
--- 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 29fc0aa..9cdfad7 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 @@
 -- 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 bbb0772..ca6c550 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 @@
 # '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 @@
 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 @@
 -- 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 @@
 -- 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 @@
 -- 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.