afero
afero copied to clipboard
MemMapFs MkdirAll error in parallel tests after go 1.18
Creating a MemMapFs
in a table driven test running in parallel can cause an internal compiler error.
Minimal reproduction test code:
func TestMkdirAll_fails(t *testing.T) {
var tests = []struct {
fs afero.Fs
}{
{
fs: func() afero.Fs {
fs := afero.NewMemMapFs()
fs.MkdirAll("/home/alice", 0755)
return fs
}(),
},
}
for _, tc := range tests {
tc := tc // capture range variable
t.Run("sub_test", func(t *testing.T) {
_ = tc.fs
})
}
}
Produces the error:
./mkdirall_test.go:16:16: internal compiler error: order.stmt CALLMETH
Please file a bug report including a short program that triggers the error.
https://go.dev/issue/new
Versions
This works without error on golang 1.17.13. It fails for me on go 1.18.8 and go 1.19.3.
I have tried on an older afero 1.2.2 as well as the current afero 1.9.3 with the same results.
Workaround
A workaround is to make sure the fs is created inside the test Run()
rather than in the declaration of the test cases. Such as:
func TestMkdirAll_ok(t *testing.T) {
var tests = []struct {
path string
createFs func() afero.Fs
}{
{
createFs: func() afero.Fs {
fs := afero.NewMemMapFs()
fs.MkdirAll("/home/alice", 0755)
return fs
},
},
}
for _, tc := range tests {
tc := tc // capture range variable
t.Run("sub_test", func(t *testing.T) {
_ = tc.createFs()
})
}
}
To be honest, I'm not convinced my original code that was trying to share the fs between different goroutines was sensible. If this is not to be fixed, perhaps it would be worth mentioning in the readme that a MemMapFs cannot be passed between goroutines.