From 98f9e594788efec8d70b77c8fd92000127f498c8 Mon Sep 17 00:00:00 2001 From: Praveen Date: Fri, 6 Dec 2024 01:52:13 +0530 Subject: [PATCH] test: enhance test coverage for controller server Introduce Table Driven Tests --- pkg/driver/controller_server_test.go | 303 +++++++++++++++++++-------- 1 file changed, 215 insertions(+), 88 deletions(-) diff --git a/pkg/driver/controller_server_test.go b/pkg/driver/controller_server_test.go index fb6c9ce..ddfcbb9 100644 --- a/pkg/driver/controller_server_test.go +++ b/pkg/driver/controller_server_test.go @@ -11,112 +11,239 @@ import ( ) func TestCreateVolume(t *testing.T) { - t.Run("Create a default size volume", func(t *testing.T) { - d, _ := driver.NewTestDriver(nil) - - resp, err := d.CreateVolume(context.Background(), &csi.CreateVolumeRequest{ - Name: "foo", - VolumeCapabilities: []*csi.VolumeCapability{ - { - AccessType: &csi.VolumeCapability_Mount{}, - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + tests := []struct { + name string + req *csi.CreateVolumeRequest + existingVolume *civogo.VolumeConfig + expectedError bool + expectedVolumeID string + expectedSizeGB int + expectedErrorMsg string + }{ + { + name: "Create a default size volume", + req: &csi.CreateVolumeRequest{ + Name: "foo", + VolumeCapabilities: []*csi.VolumeCapability{ + { + AccessType: &csi.VolumeCapability_Mount{}, + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, }, }, }, - }) - assert.Nil(t, err) - - volumes, _ := d.CivoClient.ListVolumes() - assert.Equal(t, "foo", volumes[0].Name) - assert.Equal(t, 10, volumes[0].SizeGigabytes) - assert.Equal(t, volumes[0].ID, resp.Volume.VolumeId) - }) - - t.Run("Disallow block volumes", func(t *testing.T) { - d, _ := driver.NewTestDriver(nil) - - _, err := d.CreateVolume(context.Background(), &csi.CreateVolumeRequest{ - Name: "foo", - VolumeCapabilities: []*csi.VolumeCapability{ - { - AccessType: &csi.VolumeCapability_Block{}, - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + expectedError: false, + expectedSizeGB: 10, + }, + { + name: "Disallow block volumes", + req: &csi.CreateVolumeRequest{ + Name: "foo", + VolumeCapabilities: []*csi.VolumeCapability{ + { + AccessType: &csi.VolumeCapability_Block{}, + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, }, }, }, - }) - assert.NotNil(t, err) - }) - - t.Run("Create a specified size volume", func(t *testing.T) { - d, _ := driver.NewTestDriver(nil) - - _, err := d.CreateVolume(context.Background(), &csi.CreateVolumeRequest{ - Name: "foo", - VolumeCapabilities: []*csi.VolumeCapability{ - { - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + expectedError: true, + expectedErrorMsg: "CreateVolume block types aren't supported, only mount types", + }, + { + name: "Create a specified size volume", + req: &csi.CreateVolumeRequest{ + Name: "foo", + VolumeCapabilities: []*csi.VolumeCapability{ + { + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, }, }, + CapacityRange: &csi.CapacityRange{ + RequiredBytes: 26843545600, // 25GB + }, }, - CapacityRange: &csi.CapacityRange{ - RequiredBytes: 26843545600, + expectedError: false, + expectedSizeGB: 25, + }, + { + name: "Don't create if the volume already exists and just return it", + req: &csi.CreateVolumeRequest{ + Name: "foo", + VolumeCapabilities: []*csi.VolumeCapability{ + { + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, + }, + }, }, - }) - assert.Nil(t, err) - - volumes, _ := d.CivoClient.ListVolumes() - assert.Equal(t, 25, volumes[0].SizeGigabytes) - }) - - t.Run("Don't create if the volume already exists and just return it", func(t *testing.T) { - d, _ := driver.NewTestDriver(nil) - - volume, err := d.CivoClient.NewVolume(&civogo.VolumeConfig{ - Name: "foo", - SizeGigabytes: 10, - }) - assert.Nil(t, err) - - resp, err := d.CreateVolume(context.Background(), &csi.CreateVolumeRequest{ - Name: "foo", - VolumeCapabilities: []*csi.VolumeCapability{ - { - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + existingVolume: &civogo.VolumeConfig{ + Name: "foo", + SizeGigabytes: 10, + }, + expectedError: false, + expectedSizeGB: 10, + }, + { + name: "Empty Name", + req: &csi.CreateVolumeRequest{ + Name: "", + VolumeCapabilities: []*csi.VolumeCapability{ + { + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, + }, + }, + }, + expectedError: true, + expectedErrorMsg: "CreateVolume Name must be provided", + }, + { + name: "Missing VolumeCapabilities", + req: &csi.CreateVolumeRequest{ + Name: "foo", + }, + expectedError: true, + expectedErrorMsg: "CreateVolume Volume capabilities must be provided", + }, + { + name: "Unsupported Access Mode", + req: &csi.CreateVolumeRequest{ + Name: "foo", + VolumeCapabilities: []*csi.VolumeCapability{ + { + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_UNKNOWN, + }, + }, + }, + }, + expectedError: true, + expectedErrorMsg: "CreateVolume access mode isn't supported", + }, + { + name: "Desired volume capacity exceeding the DiskGigabytesLimit", + req: &csi.CreateVolumeRequest{ + Name: "foo", + VolumeCapabilities: []*csi.VolumeCapability{ + { + AccessMode: &csi.VolumeCapability_AccessMode{ + Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, }, }, + CapacityRange: &csi.CapacityRange{ + RequiredBytes: 161061273600, // 150GB, DiskGigabytesLimit: 100GB for fakeClient + }, }, + expectedError: true, + expectedErrorMsg: "Requested volume would exceed volume space quota by 50 GB", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Setup driver and environment + d, _ := driver.NewTestDriver(nil) + + // Create existing volume if needed + if tt.existingVolume != nil { + volume, err := d.CivoClient.NewVolume(tt.existingVolume) + assert.Nil(t, err) + tt.expectedVolumeID = volume.ID + } + + // Call CreateVolume + resp, err := d.CreateVolume(context.Background(), tt.req) + + if tt.expectedError { + assert.NotNil(t, err) + assert.Contains(t, err.Error(), tt.expectedErrorMsg) + return + } + + assert.Nil(t, err) + assert.NotNil(t, resp) + assert.NotEmpty(t, resp.Volume.VolumeId) + + if tt.expectedVolumeID != "" { + assert.Equal(t, tt.expectedVolumeID, resp.Volume.VolumeId) + } + + // Validate volume creation + volumes, _ := d.CivoClient.ListVolumes() + assert.Equal(t, 1, len(volumes)) + assert.Equal(t, tt.req.Name, volumes[0].Name) + assert.Equal(t, tt.expectedSizeGB, volumes[0].SizeGigabytes) + assert.Equal(t, resp.Volume.VolumeId, volumes[0].ID) }) - assert.Nil(t, err) - - assert.Equal(t, volume.ID, resp.Volume.VolumeId) - - volumes, _ := d.CivoClient.ListVolumes() - assert.Equal(t, 1, len(volumes)) - }) + } } func TestDeleteVolume(t *testing.T) { - t.Run("Delete a volume", func(t *testing.T) { - d, _ := driver.NewTestDriver(nil) - - volume, err := d.CivoClient.NewVolume(&civogo.VolumeConfig{ - Name: "foo", - }) - assert.Nil(t, err) - - _, err = d.DeleteVolume(context.Background(), &csi.DeleteVolumeRequest{ - VolumeId: volume.ID, + tests := []struct{ + name string + existingVolume *civogo.VolumeConfig + req *csi.DeleteVolumeRequest + expectedError bool + expectedErrorMsg string + }{ + { + name: "Delete an existing volume", + existingVolume: &civogo.VolumeConfig{ + Name: "civolume", + }, + req: &csi.DeleteVolumeRequest{}, + expectedError: false, + }, + { + name: "Delete a non-existent volume", + req: &csi.DeleteVolumeRequest{ + VolumeId: "non-existent-id", + }, + expectedError: false, // Non-existance is treated as success + }, + { + name: "Delete with empty VolumeId", + req: &csi.DeleteVolumeRequest{VolumeId: ""}, + expectedError: true, + expectedErrorMsg: "must provide a VolumeId to DeleteVolume", + }, + } + + for _, tt := range tests{ + t.Run(tt.name, func(t *testing.T) { + d, _ := driver.NewTestDriver(nil) + + // setup existing volume if specified + if tt.existingVolume != nil{ + v, err := d.CivoClient.NewVolume(tt.existingVolume) + assert.Nil(t, err) + tt.req.VolumeId = v.ID // assign dynamically + } + + // Perform the delete operation + _, err := d.DeleteVolume(context.Background(), tt.req) + + // validate the error + if tt.expectedError{ + assert.NotNil(t, err) + assert.Contains(t, err.Error(), tt.expectedErrorMsg) + }else{ + assert.Nil(t, err) + } + + // Check remaining volumes + volumes, _ := d.CivoClient.ListVolumes() + assert.Equal(t, 0, len(volumes)) }) - assert.Nil(t, err) - - volumes, _ := d.CivoClient.ListVolumes() - assert.Equal(t, 0, len(volumes)) - }) + } } func TestControllerPublishVolume(t *testing.T) {