1 # This file demonstrates the effect of lazy loading on the reproducibility of
2 # tests (and tests of test dependencies) outside the main module.
3 #
4 # It is similar to the cases in mod_all.txt and mod_lazy_test_horizon.txt, but
5 # focuses on the effect of "go test" on specific packages instead of the "all"
6 # pattern.
7
8 # The package import graph used in this test looks like:
9 #
10 # lazy ---- a
11 # |
12 # a_test ---- b
13 # |
14 # b_test ---- c
15 #
16 # And the non-lazy module dependency graph looks like:
17 #
18 # lazy ---- a.1 ---- b.1 ---- c.1
19
20 cp go.mod go.mod.old
21 go mod tidy
22 cmp go.mod go.mod.old
23
24
25 # In Go 1.15 mode, 'go list -m all' includes modules needed by the
26 # transitive closure of tests of dependencies of tests of dependencies of ….
27
28 go list -m all
29 stdout '^example.com/b v0.1.0 '
30 stdout '^example.com/c v0.1.0 '
31 cmp go.mod go.mod.old
32
33 # 'go test' (or equivalent) of any such dependency, no matter how remote, does
34 # not update the go.mod file.
35
36 go list -test -deps example.com/a
37 stdout example.com/b
38 ! stdout example.com/c
39
40 [!short] go test -c -o $devnull example.com/a
41 [!short] cmp go.mod go.mod.old
42
43 go list -test -deps example.com/b
44 stdout example.com/c
45
46 [!short] go test -c -o $devnull example.com/b
47 [!short] cmp go.mod go.mod.old
48
49 go mod edit -go=1.17 a/go.mod
50 go mod edit -go=1.17 b1/go.mod
51 go mod edit -go=1.17 b2/go.mod
52 go mod edit -go=1.17 c1/go.mod
53 go mod edit -go=1.17 c2/go.mod
54 go mod edit -go=1.17
55
56
57 # After changing to 'go 1.17` uniformly, 'go list -m all' should prune out
58 # example.com/c, because it is not imported by any package (or test of a package)
59 # transitively imported by the main module.
60 #
61 # example.com/a is imported,
62 # and example.com/b is needed in order to run 'go test example.com/a',
63 # but example.com/c is not needed because we don't expect the user to need to run
64 # 'go test example.com/b'.
65
66 # If we skip directly to adding a new import of c, the dependency is too far
67 # away for a deepening scan to find, which is fine because the package whose
68 # test imported it wasn't even it "all". It should resolve from the latest
69 # version of its module.
70
71 # However, if we reach c by running successive tests starting from the main
72 # module, we should end up with exactly the version required by b, with an update
73 # to the go.mod file as soon as we test a test dependency that is not itself in
74 # "all".
75
76 cp go.mod go.mod.117
77 go mod tidy
78 cmp go.mod go.mod.117
79
80 go list -m all
81 stdout '^example.com/b v0.1.0 '
82 ! stdout '^example.com/c '
83
84 # 'go test' of a package (transitively) imported by the main module
85 # should work without changes to the go.mod file.
86
87 go list -test -deps example.com/a
88 stdout example.com/b
89 ! stdout example.com/c
90
91 [!short] go test -c -o $devnull example.com/a
92
93 # However, 'go test' of a package that is itself a dependency should require an
94 # update to the go.mod file.
95 ! go list -test -deps example.com/b
96
97 # TODO(#36460): The hint here is wrong. We should suggest
98 # 'go get -t example.com/b@v0.1.0' instead of 'go mod tidy'.
99 stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
100
101 [!short] ! go test -c -o $devnull example.com/b
102 [!short] stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
103
104 go get -t example.com/b@v0.1.0
105 go list -test -deps example.com/b
106 stdout example.com/c
107
108 [!short] go test -c -o $devnull example.com/b
109
110 # The update should bring the version required by b, not the latest version of c.
111
112 go list -m example.com/c
113 stdout '^example.com/c v0.1.0 '
114
115 cmp go.mod go.mod.b
116
117
118 # We should reach the same state if we arrive at it via `go test -mod=mod`.
119
120 cp go.mod.117 go.mod
121
122 [short] go list -mod=mod -test -deps example.com/a
123 [!short] go test -mod=mod -c -o $devnull example.com/a
124
125 [short] go list -mod=mod -test -deps example.com/b
126 [!short] go test -mod=mod -c -o $devnull example.com/b
127
128 cmp go.mod go.mod.b
129
130
131
132 -- go.mod --
133 module example.com/lazy
134
135 go 1.15
136
137 require example.com/a v0.1.0
138
139 replace (
140 example.com/a v0.1.0 => ./a
141 example.com/b v0.1.0 => ./b1
142 example.com/b v0.2.0 => ./b2
143 example.com/c v0.1.0 => ./c1
144 example.com/c v0.2.0 => ./c2
145 )
146 -- go.mod.b --
147 module example.com/lazy
148
149 go 1.17
150
151 require example.com/a v0.1.0
152
153 require example.com/b v0.1.0 // indirect
154
155 replace (
156 example.com/a v0.1.0 => ./a
157 example.com/b v0.1.0 => ./b1
158 example.com/b v0.2.0 => ./b2
159 example.com/c v0.1.0 => ./c1
160 example.com/c v0.2.0 => ./c2
161 )
162 -- lazy.go --
163 package lazy
164
165 import (
166 _ "example.com/a"
167 )
168 -- a/go.mod --
169 module example.com/a
170
171 go 1.15
172
173 require example.com/b v0.1.0
174 -- a/a.go --
175 package a
176 -- a/a_test.go --
177 package a
178
179 import (
180 "testing"
181
182 _ "example.com/b"
183 )
184
185 func TestUsingB(t *testing.T) {
186 // …
187 }
188 -- b1/go.mod --
189 module example.com/b
190
191 go 1.15
192
193 require example.com/c v0.1.0
194 -- b1/b.go --
195 package b
196 -- b1/b_test.go --
197 package b
198
199 import _ "example.com/c"
200 -- b2/go.mod --
201 module example.com/b
202
203 go 1.15
204
205 require example.com/c v0.1.0
206 -- b2/b.go --
207 package b
208 This file should not be used, so this syntax error should be ignored.
209 -- b2/b_test.go --
210 package b
211 This file should not be used, so this syntax error should be ignored.
212 -- c1/go.mod --
213 module example.com/c
214
215 go 1.15
216 -- c1/c.go --
217 package c
218 -- c2/go.mod --
219 module example.com/c
220
221 go 1.15
222 -- c2/c.go --
223 package c
224 This file should not be used, so this syntax error should be ignored.
225
View as plain text