Change:
/kind bug /sig storage What happened: CSI unit tests occasionally end up with data race: How to reproduce it (as minimally and precisely as possible): to get CSI unit tests into a binary: the binary 500 times in parallel until it breaks: . Use different argument to really load your machine, it should not be idle! . On my Linux, I got 3 failures in ~1000 runs. puts stderr of failed runs into .
/assign
I make a Fix: PTAL

Discussion:
} func TestAttacherWaitForVolumeAttachment(t *testing.T) { <del> plug, fakeWatcher, tmpDir := newTestWatchPlugin(t) defer os.RemoveAll(tmpDir) attacher, err := plug.NewAttacher() if err != nil { t.Fatalf("failed to create new attacher: %v", err) } csiAttacher := attacher.(*csiAttacher) </del> nodeName := "test-node" testCases := []struct { name                 string initAttached         bool

trigerWatchEventTime time.Duration initAttachErr        *storage.VolumeError finalAttachErr       *storage.VolumeError <del> sleepTime            time.Duration </del> timeout              time.Duration shouldFail           bool }{ { name:         "attach success at get", initAttached: true, <del> sleepTime:    10 * time.Millisecond, </del> timeout:      50 * time.Millisecond, shouldFail:   false, }, { name:          "attachment error ant get", initAttachErr: &storage.VolumeError{Message: "missing volume"}, <del> sleepTime:     10 * time.Millisecond, </del> timeout:       30 * time.Millisecond, shouldFail:    true, },

finalAttached:        true, trigerWatchEventTime: 5 * time.Millisecond, timeout:              50 * time.Millisecond, <del> sleepTime:            5 * time.Millisecond, </del> shouldFail:           false, }, {

finalAttached:        false, finalAttachErr:       &storage.VolumeError{Message: "missing volume"}, trigerWatchEventTime: 5 * time.Millisecond, <del> sleepTime:            10 * time.Millisecond, </del> timeout:              30 * time.Millisecond, shouldFail:           true, },

finalAttached:        true, trigerWatchEventTime: 100 * time.Millisecond, timeout:              50 * time.Millisecond, <del> sleepTime:            5 * time.Millisecond, </del> shouldFail:           true, }, } for i, tc := range testCases { <del> fakeWatcher.Reset() </del> <ins> plug, fakeWatcher, tmpDir := newTestWatchPlugin(t) defer os.RemoveAll(tmpDir) attacher, err := plug.NewAttacher() if err != nil { t.Fatalf("failed to create new attacher: %v", err) } csiAttacher := attacher.(*csiAttacher) </ins> t.Logf("running test: %v", tc.name) pvName := fmt.Sprintf("test-pv-%d", i) volID := fmt.Sprintf("test-vol-%d", i)

attachment := makeTestAttachment(attachID, nodeName, pvName) attachment.Status.Attached = tc.initAttached attachment.Status.AttachError = tc.initAttachErr <del> csiAttacher.waitSleepTime = tc.sleepTime _, err := csiAttacher.k8s.StorageV1beta1().VolumeAttachments().Create(attachment) </del> <ins> _, err = csiAttacher.k8s.StorageV1beta1().VolumeAttachments().Create(attachment) </ins> if err != nil { t.Fatalf("failed to attach: %v", err) } <ins> trigerWatchEventTime := tc.trigerWatchEventTime finalAttached := tc.finalAttached finalAttachErr := tc.finalAttachErr </ins> // after timeout, fakeWatcher will be closed by csiAttacher.waitForVolumeAttachment if tc.trigerWatchEventTime > 0 && tc.trigerWatchEventTime < tc.timeout { go func() { <del> time.Sleep(tc.trigerWatchEventTime) attachment.Status.Attached = tc.finalAttached attachment.Status.AttachError = tc.finalAttachErr </del> <ins> time.Sleep(trigerWatchEventTime) attachment := makeTestAttachment(attachID, nodeName, pvName) attachment.Status.Attached = finalAttached attachment.Status.AttachError = finalAttachErr </ins> fakeWatcher.Modify(attachment) }() }

} // create a plugin mgr to load plugins and setup a fake client <del> func newTestWatchPlugin(t *testing.T) (*csiPlugin, *watch.FakeWatcher, string) { </del> <ins> func newTestWatchPlugin(t *testing.T) (*csiPlugin, *watch.RaceFreeFakeWatcher, string) { </ins> tmpDir, err := utiltesting.MkTmpdir("csi-test") if err != nil { t.Fatalf("can't create temp dir: %v", err) } fakeClient := fakeclient.NewSimpleClientset() <del> fakeWatcher := watch.NewFake() </del> <ins> fakeWatcher := watch.NewRaceFreeFake() </ins> fakeClient.Fake.PrependWatchReactor("*", core.DefaultWatchReactor(fakeWatcher, nil)) fakeClient.Fake.WatchReactionChain = fakeClient.Fake.WatchReactionChain[:1] host := volumetest.NewFakeVolumeHost(