cmd/go: add a regression test for package import cycles guarded by build tags

I've been thinking about the relationship between the package import
graph and the module import graph, and realized that the package
import graph is not always acyclic. (The package import graph must be
acyclic given a specific set of build tags, but the 'mod' subcommands
intentionally ignore build tags.)

I'm not sure whether we have any existing regression tests that cover
this sort of cycle, so I'm adding one now. Thankfully, it passes!

Updates #36460

Change-Id: I7679320994ee169855241efa51cd45f71315f7f5
Reviewed-on: https://go-review.googlesource.com/c/go/+/217557
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Jay Conrod <jayconrod@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Bryan C. Mills 2020-02-03 13:40:14 -05:00
parent 8c09e8af36
commit cf6739caad
1 changed files with 106 additions and 0 deletions

View File

@ -0,0 +1,106 @@
# Because 'go mod' subcommands ignore build constraints, they can encounter
# package-import cycles that are not possible in an ordinary build. This test
# verifies that such cycles are handled even when they cross module boundaries.
# First, verify that the import graph depends on build tags as expected.
go list -deps example.com/left
stdout '^example.com/right$'
go list -deps example.com/right
! stdout left
env GOFLAGS=-tags=mirror
go list -deps example.com/left
! stdout right
go list -deps example.com/right
stdout '^example.com/left$'
env GOFLAGS=''
# 'go mod why' should be agnostic to build tags.
go mod why example.com/left
stdout '^example.com/chiral$\n^example.com/left$'
go mod why example.com/right
stdout '^example.com/chiral$\n^example.com/right$'
env GOFLAGS='-tags=mirror'
go mod why example.com/left
stdout '^example.com/chiral$\n^example.com/left$'
go mod why example.com/right
stdout '^example.com/chiral$\n^example.com/right$'
env GOFLAGS=''
# 'go mod tidy' should successfully handle the cycle.
env GOFLAGS=-mod=readonly
go mod tidy
# 'go mod vendor' should copy in both packages without crashing.
go mod vendor
exists vendor/example.com/left/default.go
exists vendor/example.com/left/mirror.go
exists vendor/example.com/right/default.go
exists vendor/example.com/right/mirror.go
-- go.mod --
module example.com/chiral
go 1.14
require (
example.com/left v0.1.0
example.com/right v0.1.0
)
replace (
example.com/left => ./left
example.com/right => ./right
)
-- chiral.go --
// Package chiral imports packages in an order that depends on build tags.
package chiral
-- default.go --
// +build !mirror
package chiral
import _ "example.com/left"
-- mirror.go --
// +build mirror
package chiral
import _ "example.com/right"
-- left/go.mod --
module example.com/left
go 1.14
require example.com/right v0.1.0
replace example.com/right v0.1.0 => ../right
-- left/default.go --
// +build !mirror
package left
import _ "example.com/right"
-- left/mirror.go --
// +build mirror
package left
-- right/go.mod --
module example.com/right
go 1.14
require example.com/left v0.1.0
replace example.com/left v0.1.0 => ../left
-- right/default.go --
// +build !mirror
package right
-- right/mirror.go --
// +build mirror
package right
import _ "example.com/left"