Open twpayne opened 2 months ago
Related Issues and Documentation
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Copying in my comment from the mailing list thread:
We do not want to record all aspects of the external environment that could possibly affect the test. That would be too much. So we need some way to know what should be recorded and what should not. What should that be? Our current approach is simple: we record environment variables that the test reads and we record files opened within the module but not files opened outside of the module. Note that if a test opens some file outside of the module, we cache the test results even if that file changes.
What approach should we use for test caching that will tell us that umask should be cached?
Firstly, thank you Ian for your patience and open mind in discussing this!
We do not want to record all aspects of the external environment that could possibly affect the test. That would be too much.
Agreed.
So we need some way to know what should be recorded and what should not. What should that be?
Given that, as there is so much external state, it is impossible in practice for the go tooling to know what should be recorded.
As a crazy idea, how about enabling the tests themselves to say what should be recorded?
Our current approach is simple: we record environment variables that the test reads and we record files opened within the module but not files opened outside of the module.
This is fair but also a slight simplification. Currently, the go test cache only checks these files sizes and modification times.
For sure, we all agree that reading the full state that the cache depends on is prohibitively expensive, and that cache invalidation is a hard problem.
What approach should we use for test caching that will tell us that umask should be cached?
So, radical idea. What if tests could explicitly declare what they depend on?
Say I could write, for my tests that depend on umask, something like:
func TestThatDependsOnUmask(t *testing.T) {
t.DependsOn("umask " + getUmask().String())
// ...
}
where testing.T.DependsOn(s string)
adds s
to the test input IDs (i.e. modifies the test cache key).
This totally frees the Go authors from having to decide what to include or exclude from the test input ID. Instead, the decision is deferred to users, who are the people who know their test cache requirements best.
Thoughts?
It's an interesting idea but I think it would require cmd/go/internal/test/test.go to recognize the "umask" command. So DependsOn
seems too flexible: it would be too easy to add a dependency that would not be recognized.
As a separate concern, more knobs is harder to use. It's already straightforward to test differing umask values within a test. And if someone wants to set umask outside of the test binary, it's easy to disable caching by passing -test.count=1
. So I don't yet see the compelling argument for this approach.
Go version
go version go1.23.1 darwin/arm64
Output of
go env
in your module/workspace:What did you do?
I have several tests that create files and check the permissions of the created files. On UNIX systems, the permissions of the created files depend on the value of umask, which is a process-global variable managed by the OS, the same way that environment variables are process-global variables managed by the OS.
I expect to be able to change umask, run
go test
, and havego test
re-run my tests with the new umask. However, after changing umask,go test
incorrectly re-uses its cached test results:The example test is:
Note that Go creates a test input ID that includes the values of environment variables and the mtimes and sizes of files accessed by the test. This test input ID should also include the initial umask value. I will create a CL that fixes this.
What did you see happen?
go test
re-used a cached test result, when it should not have.What did you expect to see?
go test
should not re-use cached test results when the umask is changed.