Skip to content

Commit 15d9d4a

Browse files
author
Bryan C. Mills
committed
cmd/go: add tests illustrating what happens when Go 1.16 is used in a Go 1.17 main module
For #46141 Updates #46160 Change-Id: Ib22435b8051aaf3fa74d43d3b7f2d091e67f05e2 Reviewed-on: https://go-review.googlesource.com/c/go/+/320172 Trust: Bryan C. Mills <[email protected]> Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent 873401d commit 15d9d4a

File tree

4 files changed

+441
-0
lines changed

4 files changed

+441
-0
lines changed

Diff for: src/cmd/go/testdata/script/mod_tidy_compat.txt

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
2+
# default preserve enough checksums for the module to be used by Go 1.16.
3+
#
4+
# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
5+
# 'go' version in the go.mod file to 1.16, without actually updating the
6+
# requirements to match.
7+
8+
[short] skip
9+
10+
env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
11+
12+
13+
# This module has the same module dependency graph in Go 1.16 as in Go 1.17,
14+
# but in 1.16 requires (checksums for) additional (irrelevant) go.mod files.
15+
#
16+
# The module graph under both versions looks like:
17+
#
18+
# m ---- example.com/version v1.1.0
19+
# |
20+
# + ---- example.net/lazy v0.1.0 ---- example.com/version v1.0.1
21+
#
22+
# Go 1.17 avoids loading the go.mod file for example.com/version v1.0.1
23+
# (because it is lower than the verison explicitly required by m,
24+
# and the module that requires it — m — specifies 'go 1.17').
25+
#
26+
# That go.mod file happens not to affect the final 1.16 module graph anyway,
27+
# so the pruned graph is equivalent to the unpruned one.
28+
29+
cp go.mod go.mod.orig
30+
go mod tidy
31+
cmp go.mod go.mod.orig
32+
33+
go list -m all
34+
cmp stdout m_all.txt
35+
36+
go mod edit -go=1.16
37+
! go list -m all
38+
stderr '^go list -m: example.net/[email protected] requires\n\texample.com/[email protected]: missing go.sum entry; to add it:\n\tgo mod download example.com/version$'
39+
40+
41+
# If we combine a Go 1.16 go.sum file...
42+
go mod tidy -go=1.16
43+
44+
# ...with a Go 1.17 go.mod file...
45+
cp go.mod.orig go.mod
46+
47+
# ...then Go 1.17 continues to work...
48+
go list -m all
49+
cmp stdout m_all.txt
50+
51+
# ...and now 1.16 can load the same build list!
52+
go mod edit -go=1.16
53+
go list -m all
54+
cmp stdout m_all.txt
55+
56+
57+
# TODO(#46141): Add a cleaner way to tidy a Go 1.17 module while preserving
58+
# the checksums needed to work within it with Go 1.16.
59+
60+
61+
-- go.mod --
62+
// Module m happens to have the exact same build list as what would be
63+
// selected under Go 1.16, but computes that build list without looking at
64+
// as many go.mod files.
65+
module example.com/m
66+
67+
go 1.17
68+
69+
replace example.net/lazy v0.1.0 => ./lazy
70+
71+
require (
72+
example.com/version v1.1.0
73+
example.net/lazy v0.1.0
74+
)
75+
-- m_all.txt --
76+
example.com/m
77+
example.com/version v1.1.0
78+
example.net/lazy v0.1.0 => ./lazy
79+
-- compatible.go --
80+
package compatible
81+
82+
import (
83+
_ "example.com/version"
84+
_ "example.net/lazy"
85+
)
86+
-- lazy/go.mod --
87+
// Module lazy requires example.com/version v1.0.1.
88+
//
89+
// However, since this module is lazy, its dependents
90+
// should not need checksums for that version of the module
91+
// unless they actually import packages from it.
92+
module example.net/lazy
93+
94+
go 1.17
95+
96+
require example.com/version v1.0.1
97+
-- lazy/lazy.go --
98+
package lazy
99+
100+
import _ "example.com/version"
+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
2+
# default preserve enough checksums for the module to be used by Go 1.16.
3+
#
4+
# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
5+
# 'go' version in the go.mod file to 1.16, without actually updating the
6+
# requirements to match.
7+
8+
[short] skip
9+
10+
env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
11+
12+
13+
# For this module, Go 1.16 selects the same versions of all explicit dependencies
14+
# as Go 1.17 does. However, Go 1.16 selects a higher version of an *implicit*
15+
# dependency, imported by a test of one of the (external) imported packages.
16+
# As a result, Go 1.16 also needs checksums for the module sources for that higher
17+
# version.
18+
#
19+
# The Go 1.16 module graph looks like:
20+
#
21+
# m ---- lazy v0.1.0 ---- incompatible v1.0.0
22+
# |
23+
# + ------------- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
24+
#
25+
# The Go 1.17 module graph is the same except that the dependencies of
26+
# requireincompatible are pruned out (because the module that requires
27+
# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
28+
# the main module).
29+
30+
cp go.mod go.mod.orig
31+
go mod tidy
32+
cmp go.mod go.mod.orig
33+
34+
go list -deps -test -f $MODFMT all
35+
stdout '^example\.com/retract/incompatible v1\.0\.0$'
36+
37+
go mod edit -go=1.16
38+
! go list -deps -test -f $MODFMT all
39+
40+
# TODO(#46160): -count=1 instead of -count=2.
41+
stderr -count=2 '^go: example\.net/lazy@v0\.1\.0 requires\n\texample\.com/retract/incompatible@v1\.0\.0: missing go\.sum entry; to add it:\n\tgo mod download example\.com/retract/incompatible$'
42+
43+
44+
# If we combine a Go 1.16 go.sum file...
45+
go mod tidy -go=1.16
46+
47+
# ...with a Go 1.17 go.mod file...
48+
cp go.mod.orig go.mod
49+
50+
# ...then Go 1.17 no longer works. 😞
51+
! go list -deps -test -f $MODFMT all
52+
stderr -count=1 '^can''t load test package: lazy/lazy_test.go:3:8: missing go\.sum entry for module providing package example\.com/retract/incompatible \(imported by example\.net/lazy\); to add:\n\tgo get -t example.net/lazy@v0\.1\.0$'
53+
54+
55+
# However, if we take the union of the go.sum files...
56+
go list -mod=mod -deps -test all
57+
cmp go.mod go.mod.orig
58+
59+
# ...then Go 1.17 continues to work...
60+
go list -deps -test -f $MODFMT all
61+
stdout '^example\.com/retract/incompatible v1\.0\.0$'
62+
63+
# ...and 1.16 also works(‽), but selects a different version for the
64+
# external-test dependency.
65+
go mod edit -go=1.16
66+
go list -deps -test -f $MODFMT all
67+
stdout '^example\.com/retract/incompatible v2\.0\.0\+incompatible$'
68+
69+
70+
# TODO(#46100): In compatibility mode, should we reject the above difference as
71+
# incompatible, or save checksums for both possible versions of the test
72+
# dependency?
73+
74+
75+
-- go.mod --
76+
// Module m imports packages from the same versions under Go 1.17
77+
// as under Go 1.16, but under 1.16 its (implicit) external test dependencies
78+
// are higher.
79+
module example.com/m
80+
81+
go 1.17
82+
83+
replace (
84+
example.net/lazy v0.1.0 => ./lazy
85+
example.net/requireincompatible v0.1.0 => ./requireincompatible
86+
)
87+
88+
require example.net/lazy v0.1.0
89+
-- implicit.go --
90+
package implicit
91+
92+
import _ "example.net/lazy"
93+
-- lazy/go.mod --
94+
// Module lazy requires example.com/retract/incompatible v1.0.0.
95+
//
96+
// When viewed from the outside it also has a transitive dependency
97+
// on v2.0.0+incompatible, but in lazy mode that transitive dependency
98+
// is pruned out.
99+
module example.net/lazy
100+
101+
go 1.17
102+
103+
exclude example.com/retract/incompatible v2.0.0+incompatible
104+
105+
require (
106+
example.com/retract/incompatible v1.0.0
107+
example.net/requireincompatible v0.1.0
108+
)
109+
-- lazy/lazy.go --
110+
package lazy
111+
-- lazy/lazy_test.go --
112+
package lazy_test
113+
114+
import _ "example.com/retract/incompatible"
115+
-- requireincompatible/go.mod --
116+
module example.net/requireincompatible
117+
118+
go 1.15
119+
120+
require example.com/retract/incompatible v2.0.0+incompatible
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
2+
# default preserve enough checksums for the module to be used by Go 1.16.
3+
#
4+
# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
5+
# 'go' version in the go.mod file to 1.16, without actually updating the
6+
# requirements to match.
7+
8+
[short] skip
9+
10+
env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
11+
12+
13+
# For this module, Go 1.17 prunes out a (transitive and otherwise-irrelevant)
14+
# requirement on a retracted higher version of a dependency.
15+
# However, when Go 1.16 reads the same requirements from the go.mod file,
16+
# it does not prune out that requirement, and selects the retracted version.
17+
#
18+
# The Go 1.16 module graph looks like:
19+
#
20+
# m ---- lazy v0.1.0 ---- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
21+
# | |
22+
# + -------+------------- incompatible v1.0.0
23+
#
24+
# The Go 1.17 module graph is the same except that the dependencies of
25+
# requireincompatible are pruned out (because the module that requires
26+
# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
27+
# the main module).
28+
29+
30+
# TODO(#46141): 'go mod tidy' should by default diagnose the difference in
31+
# dependencies as an error, but it should still be possible to simply drop
32+
# compatibility with Go 1.16 by passing an appropriate '-compat' flag.
33+
34+
cp go.mod go.mod.orig
35+
go mod tidy
36+
cmp go.mod go.mod.orig
37+
38+
go mod edit -go=1.16
39+
! go list -f $MODFMT -deps ./...
40+
# TODO(#46160): -count=1 instead of -count=2.
41+
stderr -count=2 '^go: example\.net/lazy@v0\.1\.0 requires\n\texample\.net/requireincompatible@v0\.1\.0 requires\n\texample\.com/retract/incompatible@v2\.0\.0\+incompatible: missing go.sum entry; to add it:\n\tgo mod download example.com/retract/incompatible$'
42+
43+
44+
# There are two ways for the module author to bring the two into alignment.
45+
# One is to *explicitly* 'exclude' the version that is already *implicitly*
46+
# pruned out under 1.17.
47+
go mod edit -exclude=example.com/retract/[email protected]+incompatible
48+
go list -f $MODFMT -deps ./...
49+
stdout '^example.com/retract/incompatible v1\.0\.0$'
50+
! stdout 'v2\.0\.0'
51+
52+
53+
# The other is to explicitly upgrade the version required under Go 1.17
54+
# to match the version selected by Go 1.16.
55+
cp go.mod.orig go.mod
56+
57+
go get -d example.com/retract/[email protected]+incompatible
58+
# Note that we are not running 'go mod tidy' here: we need to preserve
59+
# the checksum for v1.0.0 because it is also still in the module graph
60+
# as seen by Go 1.16.
61+
62+
go mod edit -go=1.16
63+
go list -f $MODFMT -deps ./...
64+
stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$'
65+
! stdout 'v1\.0\.0'
66+
67+
68+
-- go.mod --
69+
// Module m indirectly imports a package from
70+
// example.com/retract/incompatible. Its selected version of
71+
// that module is lower under Go 1.17 semantics than under Go 1.16.
72+
module example.com/m
73+
74+
go 1.17
75+
76+
replace (
77+
example.net/lazy v0.1.0 => ./lazy
78+
example.net/requireincompatible v0.1.0 => ./requireincompatible
79+
)
80+
81+
require (
82+
example.com/retract/incompatible v1.0.0 // indirect
83+
example.net/lazy v0.1.0
84+
)
85+
-- incompatible.go --
86+
package incompatible
87+
88+
import _ "example.net/lazy"
89+
90+
-- lazy/go.mod --
91+
// Module lazy requires example.com/retract/incompatible v1.0.0.
92+
//
93+
// When viewed from the outside it also has a transitive dependency
94+
// on v2.0.0+incompatible, but in lazy mode that transitive dependency
95+
// is pruned out.
96+
module example.net/lazy
97+
98+
go 1.17
99+
100+
exclude example.com/retract/incompatible v2.0.0+incompatible
101+
102+
require (
103+
example.com/retract/incompatible v1.0.0
104+
example.net/requireincompatible v0.1.0
105+
)
106+
-- lazy/lazy.go --
107+
package lazy
108+
109+
import _ "example.com/retract/incompatible"
110+
111+
-- requireincompatible/go.mod --
112+
module example.net/requireincompatible
113+
114+
go 1.15
115+
116+
require example.com/retract/incompatible v2.0.0+incompatible

0 commit comments

Comments
 (0)