Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Enhance test coverage for controller server #37

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
303 changes: 215 additions & 88 deletions pkg/driver/controller_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Loading