-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
What version of Go are you using (go version)?
$ go version go version go1.16 darwin/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env)?
go env Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/Users/aron/Library/Caches/go-build" GOENV="/Users/aron/Library/Application Support/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOINSECURE="" GOMODCACHE="/Users/aron/go/pkg/mod" GONOPROXY="" GONOSUMDB="" GOOS="darwin" GOPATH="/Users/aron/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64" GOVCS="" GOVERSION="go1.16" GCCGO="gccgo" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="/Users/aron/go/src/foo/go.mod" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/h8/bl1lkr792xz68jzf9s70jzwm0000gn/T/go-build2392571666=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
This is a three-package layout with foo, foo/a and foo/b. Both sub-packages have identical non-test code, but slightly different test code. The foo package uses code from a and b in identical ways. The foo package only has test code (to simplify the example; the real situation has code in all three packages).
foo- uses values initialized from environment variables infoo/aandfoo/bfoo/a- uses value initialized from environment variable; test code contains additional environment variable readfoo/b- uses value initialized from environment variable
Code to exercise issue
// file: foo_test.go
package foo
import (
"testing"
"foo/a"
"foo/b"
)
func TestA(t *testing.T) {
cur := a.IsConfigured()
if cur != a.Configured {
t.Errorf("Configured = %v; want %v", cur, a.Configured)
}
}
func TestB(t *testing.T) {
cur := b.IsConfigured()
if cur != b.Configured {
t.Errorf("Configured = %v; want %v", cur, b.Configured)
}
}// file: foo/a.go
package a
import "os"
var Configured bool
func init() {
Configured = os.Getenv("SETTING") == "ok"
}
func IsConfigured() bool {
return Configured
}// file: foo/a_test.go
package a
import "os"
import "testing"
func TestConfigured(t *testing.T) {
raw := os.Getenv("SETTING")
cur := IsConfigured()
if cur != Configured {
t.Errorf("Configured = %v; want %v; raw %v", cur, Configured, raw)
}
}// file: foo/b.go
package b
import "os"
var Configured bool
func init() {
Configured = os.Getenv("SETTING") == "ok"
}
func IsConfigured() bool {
return Configured
}// file: b_test.go
package b
import "testing"
func TestConfigured(t *testing.T) {
cur := IsConfigured()
if cur != Configured {
t.Errorf("Configured = %v; want %v", cur, Configured)
}
}Testing these packages with and without the SETTING environment variable uses a cached result for the foo and foo/b packages. The foo/a package, in contrast, runs each time SETTING is changed.
$ go clean -testcache
$ go test foo/...
ok foo 0.062s
ok foo/a 0.105s
ok foo/b 0.149s
$ SETTING=ok go test foo/...
ok foo (cached)
ok foo/a 0.059s
ok foo/b (cached)
$ SETTING=not-ok go test foo/...
ok foo (cached)
ok foo/a 0.057s
ok foo/b (cached)What did you expect to see?
All packages that use SETTING, either directly or indirectly, should be run for each change to the SETTING value.
What did you see instead?
Only foo/a, with a read of SETTING from test code, is run each time SETTING is changed. The other packages are skipped with cached results.