你正在使用的Go版本是什么( go version
)?
$ go version
go version go1.18.2 linux/amd64
这个问题在最新版本中是否重现?
是的
你正在使用什么操作系统和处理器架构( go env
)?
go env
输出
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/fhenneke/.cache/go-build"
GOENV="/home/fhenneke/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/fhenneke/go/pkg/mod"
GONOPROXY="code-intelligence.com/*"
GONOSUMDB="code-intelligence.com/*"
GOOS="linux"
GOPATH="/home/fhenneke/go"
GOPRIVATE="code-intelligence.com/*"
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.18.2"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/fhenneke/git/cifuzz/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2057125203=/tmp/go-build -gno-record-gcc-switches"
你做了什么?
- 进行一些访问包含子目录
subdir
的测试数据,该子目录包含一个文件foo
。 - 运行
go test ./...
。 - 更改
foo
。 - 运行
go test ./...
。
你期望看到什么?
由于数据依赖项发生了变化,尽管启用了缓存,测试仍会重新运行。
你看到了什么?
测试没有再次运行。
根本原因
在 test.go
中的缓存失效逻辑列出了 testdata
中的所有条目,并在 go/src/cmd/go/internal/test/test.go 的第 1737 行调用 hashWriteStat 对它们进行操作(在这种情况下,对 testdata/subdir
进行操作)。此函数记录了 stat
的结果,包括目录的 mtime。但是,当它包含的任何文件发生更改时,目录的 mtime 不会更新。
相反,逻辑可以对目录进行完整的递归遍历,收集其内容的各个 mtime。
9条答案
按热度按时间bihw5rsg1#
你如何在测试中使用文件?如何修改文件?
我无法重现描述的行为
fcipmucu2#
你是如何使用tests/目录下的文件的?我无法复现描述的行为
在我原来的示例中,我在访问Go测试的testdata目录后,在testdata目录上运行一个外部工具。我将这个简化为一个复现器:
./test.sh
jqjz2hbq3#
我看到数据的读取是通过一个外部命令(
exec.Command(bash, -c, cat file)
)进行的,这就是为什么更改没有被跟踪的原因。wztqucjr4#
确实如此。一般来说,Go测试过程必须接触到所有应该用作缓存输入的数据,因为它没有其他程序的仪器。
jmo0nnb35#
确实。一般来说,Go测试过程必须接触到所有应该用作缓存输入的数据,因为它没有其他程序的仪器。我不指望Go只捕获外部工具触及的文件的更改。让我感到惊讶并导致我打开这个问题的是,从Go测试中触及一个目录会导致某些该目录内容的更改,从而使缓存失效,但不是所有这样的更改。
8yoxcaq76#
我认为我们在这里可能最好做的是提供一些库函数,这些函数可以处理当前包(https://go.dev/play/p/cnjP1PbosLa)中
testdata
子目录下的所有文件。也许在默认情况下,这对testing
包是有意义的?shstlldc7#
让我感到惊讶并引发我提出这个问题的是,从Go测试结果中触摸一个目录会导致该目录内容的某些更改,从而使缓存失效,但并非所有这样的更改都会使缓存失效。
如果(并且仅当)更改了由Go测试进程调用的函数的结果,那么更改应该使缓存失效。我同意,当涉及到子进程时,这有时会令人惊讶。 😅
bfhwhh0e8#
我认为我们在这里可能最好做的是提供一些库函数,这些函数可以处理当前包(https://go.dev/play/p/cnjP1PbosLa)中
testdata
子目录下的所有文件。也许在testing
包中默认这样做是有意义的?这听起来很好。这正是我采用的解决方法(当然,除了为
testing
启用此功能默认值之外;-))ivqmmu1c9#
或者只有当使用exec时才可能?这听起来像是一项非常昂贵的操作,尤其是如果有一个仅供外部工具使用的深层层次结构。