@@ -15,9 +15,9 @@ limitations under the License.
15
15
package gceGCEDriver
16
16
17
17
import (
18
+ "context"
18
19
"testing"
19
20
20
- "context"
21
21
csi "github.com/container-storage-interface/spec/lib/go/csi"
22
22
"google.golang.org/grpc/codes"
23
23
"google.golang.org/grpc/status"
@@ -38,9 +38,9 @@ func getTestGCEDriver(t *testing.T) *GCEDriver {
38
38
return gceDriver
39
39
}
40
40
41
- func getTestBlockingGCEDriver (t * testing.T , mountToRun chan mountmanager. MountSourceAndTarget , readyToMount chan struct {}) * GCEDriver {
41
+ func getTestBlockingGCEDriver (t * testing.T , readyToExecute chan chan struct {}) * GCEDriver {
42
42
gceDriver := GetGCEDriver ()
43
- err := gceDriver .SetupGCEDriver (nil , mountmanager .NewFakeSafeBlockingMounter (mountToRun , readyToMount ), mountmanager .NewFakeDeviceUtils (), metadataservice .NewFakeService (), driver , "test-vendor" )
43
+ err := gceDriver .SetupGCEDriver (nil , mountmanager .NewFakeSafeBlockingMounter (readyToExecute ), mountmanager .NewFakeDeviceUtils (), metadataservice .NewFakeService (), driver , "test-vendor" )
44
44
if err != nil {
45
45
t .Fatalf ("Failed to setup GCE Driver: %v" , err )
46
46
}
@@ -389,12 +389,10 @@ func TestNodeGetCapabilities(t *testing.T) {
389
389
}
390
390
391
391
func TestConcurrentNodeOperations (t * testing.T ) {
392
- mountToRun := make (chan mountmanager.MountSourceAndTarget , 3 )
393
- readyToMount := make (chan struct {}, 2 )
394
- reqFinished := make (chan error , 2 )
395
-
396
- gceDriver := getTestBlockingGCEDriver (t , mountToRun , readyToMount )
392
+ readyToExecute := make (chan chan struct {}, 1 )
393
+ gceDriver := getTestBlockingGCEDriver (t , readyToExecute )
397
394
ns := gceDriver .ns
395
+
398
396
vol1PublishTargetAReq := & csi.NodePublishVolumeRequest {
399
397
VolumeId : defaultVolumeID + "1" ,
400
398
TargetPath : defaultTargetPath + "a" ,
@@ -417,52 +415,51 @@ func TestConcurrentNodeOperations(t *testing.T) {
417
415
VolumeCapability : stdVolCap ,
418
416
}
419
417
420
- runRequestInBackground := func (req * csi.NodePublishVolumeRequest ) {
421
- _ , err := ns .NodePublishVolume (context .Background (), req )
422
- reqFinished <- err
418
+ runRequest := func (req * csi.NodePublishVolumeRequest ) chan error {
419
+ response := make (chan error )
420
+ go func () {
421
+ _ , err := ns .NodePublishVolume (context .Background (), req )
422
+ response <- err
423
+ }()
424
+ return response
423
425
}
424
426
425
- // Start first valid request vol1PublishTargetAReq and block until it reaches the Mount
426
- go runRequestInBackground (vol1PublishTargetAReq )
427
- <- readyToMount
427
+ // Start first valid request vol1PublishTargetA and block until it reaches the Mount
428
+ vol1PublishTargetAResp := runRequest (vol1PublishTargetAReq )
429
+ execVol1PublishTargetA := <- readyToExecute
428
430
429
- // Check that vol1PublishTargetBReq is rejected, due to same volume ID
430
- // Also allow vol1PublishTargetBReq to complete, in case it is allowed to Mount
431
- mountToRun <- mountmanager.MountSourceAndTarget {
432
- Source : vol1PublishTargetBReq .StagingTargetPath ,
433
- Target : vol1PublishTargetBReq .TargetPath ,
434
- }
435
- _ , err := ns .NodePublishVolume (context .Background (), vol1PublishTargetBReq )
436
- if err != nil {
437
- serverError , ok := status .FromError (err )
438
- if ! ok {
439
- t .Fatalf ("Could not get error status code from err: %v" , err )
440
- }
441
- if serverError .Code () != codes .Aborted {
442
- t .Fatalf ("Expected error code: %v, got: %v. err : %v" , codes .Aborted , serverError .Code (), err )
431
+ // Start vol1PublishTargetB and allow it to execute to completion. Then check for Aborted error.
432
+ // If a non Abort error is received or if the operation was started, then there is a problem
433
+ // with volume locking.
434
+ vol1PublishTargetBResp := runRequest (vol1PublishTargetBReq )
435
+ select {
436
+ case err := <- vol1PublishTargetBResp :
437
+ if err != nil {
438
+ serverError , ok := status .FromError (err )
439
+ if ! ok {
440
+ t .Fatalf ("Could not get error status code from err: %v" , err )
441
+ }
442
+ if serverError .Code () != codes .Aborted {
443
+ t .Fatalf ("Expected error code: %v, got: %v. err : %v" , codes .Aborted , serverError .Code (), err )
444
+ }
445
+ } else {
446
+ t .Fatalf ("Expected error: %v, got no error" , codes .Aborted )
443
447
}
444
- } else {
445
- t .Fatalf ( "Expected error: %v, got no error" , codes . Aborted )
448
+ case <- readyToExecute :
449
+ t .Fatal ( "The operation for vol1PublishTargetB should have been aborted, but was started" )
446
450
}
447
451
448
- // Start second valid request vol2PublishTargetCReq
449
- go runRequestInBackground (vol2PublishTargetCReq )
450
-
451
- // Allow the vol2PublishTargetCReq to complete, which it can concurrently with vol1PublishTargetAReq
452
- mountToRun <- mountmanager.MountSourceAndTarget {
453
- Source : vol2PublishTargetCReq .StagingTargetPath ,
454
- Target : vol2PublishTargetCReq .TargetPath ,
455
- }
456
- if err = <- reqFinished ; err != nil {
452
+ // Start vol2PublishTargetC and allow it to execute to completion. Then check for success.
453
+ vol2PublishTargetCResp := runRequest (vol2PublishTargetCReq )
454
+ execVol2PublishTargetC := <- readyToExecute
455
+ execVol2PublishTargetC <- struct {}{}
456
+ if err := <- vol2PublishTargetCResp ; err != nil {
457
457
t .Fatalf ("Unexpected error: %v" , err )
458
458
}
459
459
460
- // To clean up, allow the vol1PublishTargetAReq to complete
461
- mountToRun <- mountmanager.MountSourceAndTarget {
462
- Source : vol1PublishTargetAReq .StagingTargetPath ,
463
- Target : vol1PublishTargetAReq .TargetPath ,
464
- }
465
- if err = <- reqFinished ; err != nil {
460
+ // To clean up, allow the vol1PublishTargetA to complete
461
+ execVol1PublishTargetA <- struct {}{}
462
+ if err := <- vol1PublishTargetAResp ; err != nil {
466
463
t .Fatalf ("Unexpected error: %v" , err )
467
464
}
468
465
}
0 commit comments