Skip to content

Commit

Permalink
cmd/go: add a regression test for package import cycles guarded by bu…
Browse files Browse the repository at this point in the history
…ild 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 <[email protected]>
Reviewed-by: Jay Conrod <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
  • Loading branch information
Bryan C. Mills committed Feb 21, 2020
1 parent 8c09e8a commit cf6739c
Showing 1 changed file with 106 additions and 0 deletions.
106 changes: 106 additions & 0 deletions src/cmd/go/testdata/script/mod_tagged_import_cycle.txt
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit cf6739c

Please sign in to comment.