blob: e3f2561f5e367b663cb68e068a6f8967de46105e [file] [log] [blame]
# https://golang.org/issue/45094: 'go mod tidy' now accepts a '-go' flag
# to change the language version in use.
#
# The package import graph used in this test looks like:
#
# m --- a --- b
# |
# b_test --- c
# |
# c_test --- d
#
# The module diagram looks like:
#
# m --- a --- b
# |
# + --- c
# |
# + --- d
#
# Module b omits its dependency on c, and module c omits its dependency on d.
#
# In go 1.15, the tidy main module must require a (because it is direct),
# c (because it is a missing test dependency of an imported package),
# and d (because it is a missing transitive test dependency).
#
# In go 1.16, the tidy main module can omit d because it is no longer
# included in "all".
#
# In go 1.17, the main module must explicitly require b
# (because it is transitively imported by the main module).
cp go.mod go.mod.orig
# Pretend we're a release version so that we can theoretically
# write our version in toolchain lines.
env goversion=1.99.0
env TESTGO_VERSION=go${goversion}
# An invalid argument should be rejected.
! go mod tidy -go=bananas
stderr '^invalid value "bananas" for flag -go: expecting a Go version like "'$goversion'"$'
cmp go.mod go.mod.orig
! go mod tidy -go=0.9
stderr '^invalid value "0.9" for flag -go: expecting a Go version like "'$goversion'"$'
! go mod tidy -go=2000.0
stderr '^invalid value "2000.0" for flag -go: maximum supported Go version is '$goversion'$'
# Supported versions should change the go.mod file to be tidy according to the
# indicated version.
go mod tidy -go=1.15
cmp go.mod go.mod.115
go mod tidy
cmp go.mod go.mod.115
go mod tidy -go=1.16
cmp go.mod go.mod.116
go mod tidy
cmp go.mod go.mod.116
go mod tidy -go=1.17
cmp go.mod go.mod.117
go mod tidy
cmp go.mod go.mod.117
# If we downgrade back to 1.15, we should re-resolve d to v0.2.0 instead
# of the original v0.1.0 (because the original requirement is lost).
go mod tidy -go=1.15
cmp go.mod go.mod.115-2
# -go= (with an empty argument) maintains the existing version or adds the
# default version (just like omitting the flag).
go mod tidy -go=''
cmp go.mod go.mod.115-2
cp go.mod.orig go.mod
go mod tidy -go=''
cmpenv go.mod go.mod.latest
# Repeat with go get go@ instead of mod tidy.
# Go 1.16 -> 1.17 should be a no-op.
cp go.mod.116 go.mod
go get go@1.16
cmp go.mod go.mod.116
# Go 1.17 -> 1.16 should leave b (go get is not tidy).
cp go.mod.117 go.mod
go get go@1.16
cmp go.mod go.mod.116from117
# Go 1.15 -> 1.16 should leave d (go get is not tidy).
cp go.mod.115 go.mod
go get go@1.16
cmp go.mod go.mod.116from115
# Go 1.16 -> 1.17 should add b.
cp go.mod.116 go.mod
go get go@1.17
stderr '^\tnote: expanded dependencies to upgrade to go 1.17 or higher; run ''go mod tidy'' to clean up'
cmp go.mod go.mod.117
# Go 1.16 -> 1.15 should add d,
# but 'go get' doesn't load enough packages to know that.
# (This leaves the module untidy, but the user can fix it by running 'go mod tidy'.)
cp go.mod.116 go.mod
go get go@1.15 toolchain@none
cmp go.mod go.mod.115from116
go mod tidy
cmp go.mod go.mod.115-2
# Updating the go line to 1.21 or higher also updates the toolchain line,
# only if the toolchain is higher than what would be implied by the go line.
cp go.mod.117 go.mod
go mod tidy -go=$goversion
cmpenv go.mod go.mod.latest
cp go.mod.117 go.mod
go mod tidy -go=1.21.0 # lower than $goversion
cmpenv go.mod go.mod.121toolchain
-- go.mod --
module example.com/m
require example.net/a v0.1.0
require (
example.net/c v0.1.0 // indirect
example.net/d v0.1.0 // indirect
)
replace (
example.net/a v0.1.0 => ./a
example.net/a v0.2.0 => ./a
example.net/b v0.1.0 => ./b
example.net/b v0.2.0 => ./b
example.net/c v0.1.0 => ./c
example.net/c v0.2.0 => ./c
example.net/d v0.1.0 => ./d
example.net/d v0.2.0 => ./d
)
-- m.go --
package m
import _ "example.net/a"
-- go.mod.115 --
module example.com/m
go 1.15
require example.net/a v0.1.0
require (
example.net/c v0.1.0 // indirect
example.net/d v0.1.0 // indirect
)
replace (
example.net/a v0.1.0 => ./a
example.net/a v0.2.0 => ./a
example.net/b v0.1.0 => ./b
example.net/b v0.2.0 => ./b
example.net/c v0.1.0 => ./c
example.net/c v0.2.0 => ./c
example.net/d v0.1.0 => ./d
example.net/d v0.2.0 => ./d
)
-- go.mod.115from116 --
module example.com/m
go 1.15
require example.net/a v0.1.0
require example.net/c v0.1.0 // indirect
replace (
example.net/a v0.1.0 => ./a
example.net/a v0.2.0 => ./a
example.net/b v0.1.0 => ./b
example.net/b v0.2.0 => ./b
example.net/c v0.1.0 => ./c
example.net/c v0.2.0 => ./c
example.net/d v0.1.0 => ./d
example.net/d v0.2.0 => ./d
)
-- go.mod.116from115 --
module example.com/m
go 1.16
require example.net/a v0.1.0
require (
example.net/c v0.1.0 // indirect
example.net/d v0.1.0 // indirect
)
replace (
example.net/a v0.1.0 => ./a
example.net/a v0.2.0 => ./a
example.net/b v0.1.0 => ./b
example.net/b v0.2.0 => ./b
example.net/c v0.1.0 => ./c
example.net/c v0.2.0 => ./c
example.net/d v0.1.0 => ./d
example.net/d v0.2.0 => ./d
)
-- go.mod.115-2 --
module example.com/m
go 1.15
require example.net/a v0.1.0
require (
example.net/c v0.1.0 // indirect
example.net/d v0.2.0 // indirect
)
replace (
example.net/a v0.1.0 => ./a
example.net/a v0.2.0 => ./a
example.net/b v0.1.0 => ./b
example.net/b v0.2.0 => ./b
example.net/c v0.1.0 => ./c
example.net/c v0.2.0 => ./c
example.net/d v0.1.0 => ./d
example.net/d v0.2.0 => ./d
)
-- go.mod.116 --
module example.com/m
go 1.16
require example.net/a v0.1.0
require example.net/c v0.1.0 // indirect
replace (
example.net/a v0.1.0 => ./a
example.net/a v0.2.0 => ./a
example.net/b v0.1.0 => ./b
example.net/b v0.2.0 => ./b
example.net/c v0.1.0 => ./c
example.net/c v0.2.0 => ./c
example.net/d v0.1.0 => ./d
example.net/d v0.2.0 => ./d
)
-- go.mod.117 --
module example.com/m
go 1.17
require example.net/a v0.1.0
require (
example.net/b v0.1.0 // indirect
example.net/c v0.1.0 // indirect
)
replace (
example.net/a v0.1.0 => ./a
example.net/a v0.2.0 => ./a
example.net/b v0.1.0 => ./b
example.net/b v0.2.0 => ./b
example.net/c v0.1.0 => ./c
example.net/c v0.2.0 => ./c
example.net/d v0.1.0 => ./d
example.net/d v0.2.0 => ./d
)
-- go.mod.116from117 --
module example.com/m
go 1.16
require example.net/a v0.1.0
require (
example.net/b v0.1.0 // indirect
example.net/c v0.1.0 // indirect
)
replace (
example.net/a v0.1.0 => ./a
example.net/a v0.2.0 => ./a
example.net/b v0.1.0 => ./b
example.net/b v0.2.0 => ./b
example.net/c v0.1.0 => ./c
example.net/c v0.2.0 => ./c
example.net/d v0.1.0 => ./d
example.net/d v0.2.0 => ./d
)
-- go.mod.latest --
module example.com/m
go $goversion
require example.net/a v0.1.0
require (
example.net/b v0.1.0 // indirect
example.net/c v0.1.0 // indirect
)
replace (
example.net/a v0.1.0 => ./a
example.net/a v0.2.0 => ./a
example.net/b v0.1.0 => ./b
example.net/b v0.2.0 => ./b
example.net/c v0.1.0 => ./c
example.net/c v0.2.0 => ./c
example.net/d v0.1.0 => ./d
example.net/d v0.2.0 => ./d
)
-- go.mod.121toolchain --
module example.com/m
go 1.21.0
toolchain $TESTGO_VERSION
require example.net/a v0.1.0
require (
example.net/b v0.1.0 // indirect
example.net/c v0.1.0 // indirect
)
replace (
example.net/a v0.1.0 => ./a
example.net/a v0.2.0 => ./a
example.net/b v0.1.0 => ./b
example.net/b v0.2.0 => ./b
example.net/c v0.1.0 => ./c
example.net/c v0.2.0 => ./c
example.net/d v0.1.0 => ./d
example.net/d v0.2.0 => ./d
)
-- a/go.mod --
module example.net/a
go 1.15
require example.net/b v0.1.0
-- a/a.go --
package a
import _ "example.net/b"
-- b/go.mod --
module example.net/b
go 1.15
-- b/b.go --
package b
-- b/b_test.go --
package b_test
import _ "example.net/c"
-- c/go.mod --
module example.net/c
go 1.15
-- c/c.go --
package c
-- c/c_test.go --
package c_test
import _ "example.net/d"
-- d/go.mod --
module example.net/d
go 1.15
-- d/d.go --
package d