afero icon indicating copy to clipboard operation
afero copied to clipboard

MemMapFs MkdirAll error in parallel tests after go 1.18

Open biinari opened this issue 2 years ago • 0 comments

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.

biinari avatar Nov 17 '22 04:11 biinari