From 15a3603501a95564c4c7644817eb8c482acab166 Mon Sep 17 00:00:00 2001 From: Animesh Kumar Date: Sat, 6 Jun 2020 21:49:25 +0530 Subject: [PATCH] Tests: Add Tests for csi-common and smb Signed-off-by: Animesh Kumar --- .../controllerserver-default_test.go | 67 +++++++++ pkg/csi-common/driver_test.go | 134 +++++++++++++++++- pkg/csi-common/identityserver-default_test.go | 76 ++++++++-- pkg/csi-common/utils_test.go | 110 +++++++++++++- pkg/smb/controllerserver_test.go | 39 +++++ pkg/smb/identityserver_test.go | 92 ++++++++++++ pkg/smb/version_test.go | 60 ++++++++ 7 files changed, 567 insertions(+), 11 deletions(-) create mode 100644 pkg/csi-common/controllerserver-default_test.go create mode 100644 pkg/smb/controllerserver_test.go create mode 100644 pkg/smb/identityserver_test.go create mode 100644 pkg/smb/version_test.go diff --git a/pkg/csi-common/controllerserver-default_test.go b/pkg/csi-common/controllerserver-default_test.go new file mode 100644 index 000000000..51cccc395 --- /dev/null +++ b/pkg/csi-common/controllerserver-default_test.go @@ -0,0 +1,67 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package csicommon + +import ( + "context" + "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestValidateVolumeCapabilities(t *testing.T) { + d := NewFakeDriver() + d.AddVolumeCapabilityAccessModes([]csi.VolumeCapability_AccessMode_Mode{ + csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY, + csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY, + }) + + capability := []*csi.VolumeCapability{ + {AccessMode: NewVolumeCapabilityAccessMode(csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER)}, + {AccessMode: NewVolumeCapabilityAccessMode(csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY)}, + {AccessMode: NewVolumeCapabilityAccessMode(csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY)}, + } + capabilityDisjoint := []*csi.VolumeCapability{ + {AccessMode: NewVolumeCapabilityAccessMode(csi.VolumeCapability_AccessMode_MULTI_NODE_SINGLE_WRITER)}, + } + + ns := NewDefaultControllerServer(d) + + // Test when there are common capabilities + req := csi.ValidateVolumeCapabilitiesRequest{VolumeCapabilities: capability} + resp, err := ns.ValidateVolumeCapabilities(context.Background(), &req) + assert.NoError(t, err) + assert.Equal(t, resp.XXX_sizecache, int32(0)) + + // Test when there are no common capabilities + req = csi.ValidateVolumeCapabilitiesRequest{VolumeCapabilities: capabilityDisjoint} + resp, err = ns.ValidateVolumeCapabilities(context.Background(), &req) + assert.NotNil(t, resp) + assert.Error(t, err) +} + +func TestControllerGetCapabilities(t *testing.T) { + d := NewFakeDriver() + ns := NewDefaultControllerServer(d) + + // Test valid request + req := csi.ControllerGetCapabilitiesRequest{} + resp, err := ns.ControllerGetCapabilities(context.Background(), &req) + assert.NoError(t, err) + assert.Equal(t, resp.XXX_sizecache, int32(0)) +} diff --git a/pkg/csi-common/driver_test.go b/pkg/csi-common/driver_test.go index 820fd1c33..66b3eaa44 100644 --- a/pkg/csi-common/driver_test.go +++ b/pkg/csi-common/driver_test.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2020 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ limitations under the License. package csicommon import ( + "reflect" "testing" "github.com/container-storage-interface/spec/lib/go/csi" @@ -47,6 +48,59 @@ func TestNewFakeDriver(t *testing.T) { assert.Nil(t, d) } +func TestNewCSIDriver(t *testing.T) { + tests := []struct { + desc string + name string + version string + nodeID string + expectedResp *CSIDriver + }{ + { + desc: "Successful", + name: fakeDriverName, + version: vendorVersion, + nodeID: fakeNodeID, + expectedResp: &CSIDriver{ + Name: fakeDriverName, + Version: vendorVersion, + NodeID: fakeNodeID, + }, + }, + { + desc: "Missing driver name", + name: "", + version: vendorVersion, + nodeID: fakeNodeID, + expectedResp: nil, + }, + { + desc: "Missing node ID", + name: fakeDriverName, + version: vendorVersion, + nodeID: "", + expectedResp: nil, + }, + { + desc: "Missing driver version", + name: fakeDriverName, + version: "", + nodeID: fakeNodeID, + expectedResp: &CSIDriver{ + Name: fakeDriverName, + Version: "", + NodeID: fakeNodeID, + }, + }, + } + for _, test := range tests { + resp := NewCSIDriver(test.name, test.version, test.nodeID) + if !reflect.DeepEqual(resp, test.expectedResp) { + t.Errorf("Unexpected driver: %v", resp) + } + } +} + func TestGetVolumeCapabilityAccessModes(t *testing.T) { d := NewFakeDriver() @@ -102,3 +156,81 @@ func TestValidateControllerServiceRequest(t *testing.T) { assert.NoError(t, err) } + +func TestValidateNodeServiceRequest(t *testing.T) { + d := NewFakeDriver() + d.NSCap = []*csi.NodeServiceCapability{ + NewNodeServiceCapability(csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME), + NewNodeServiceCapability(csi.NodeServiceCapability_RPC_GET_VOLUME_STATS), + } + tests := []struct { + desc string + cap csi.NodeServiceCapability_RPC_Type + expectedErr error + }{ + { + desc: "Node service capabailtiy unknown", + cap: csi.NodeServiceCapability_RPC_UNKNOWN, + expectedErr: nil, + }, + { + desc: "Successful request", + cap: csi.NodeServiceCapability_RPC_GET_VOLUME_STATS, + expectedErr: nil, + }, + { + desc: "Invalid argument", + cap: csi.NodeServiceCapability_RPC_EXPAND_VOLUME, + expectedErr: status.Error(codes.InvalidArgument, "EXPAND_VOLUME"), + }, + } + + for _, test := range tests { + err := d.ValidateNodeServiceRequest(test.cap) + if !reflect.DeepEqual(err, test.expectedErr) { + t.Errorf("Unexpected error: %v", err) + } + } +} + +func TestAddControllerServiceCapabilities(t *testing.T) { + d := NewFakeDriver() + expectedCapList := []*csi.ControllerServiceCapability{ + NewControllerServiceCapability(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME), + NewControllerServiceCapability(csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME), + } + capList := []csi.ControllerServiceCapability_RPC_Type{ + csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME, + csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME, + } + d.AddControllerServiceCapabilities(capList) + assert.Equal(t, d.Cap, expectedCapList) +} + +func TestAddNodeServiceCapabilities(t *testing.T) { + d := NewFakeDriver() + expectedCapList := []*csi.NodeServiceCapability{ + NewNodeServiceCapability(csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME), + NewNodeServiceCapability(csi.NodeServiceCapability_RPC_GET_VOLUME_STATS), + } + capList := []csi.NodeServiceCapability_RPC_Type{ + csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME, + csi.NodeServiceCapability_RPC_GET_VOLUME_STATS, + } + d.AddNodeServiceCapabilities(capList) + assert.Equal(t, d.NSCap, expectedCapList) +} + +func TestAddVolumeCapabilityAccessModes(t *testing.T) { + d := NewFakeDriver() + expectedCapList := []*csi.VolumeCapability_AccessMode{ + NewVolumeCapabilityAccessMode(csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER), + NewVolumeCapabilityAccessMode(csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY), + } + capList := []csi.VolumeCapability_AccessMode_Mode{ + csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER, + csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY, + } + d.AddVolumeCapabilityAccessModes(capList) + assert.Equal(t, d.VC, expectedCapList) +} diff --git a/pkg/csi-common/identityserver-default_test.go b/pkg/csi-common/identityserver-default_test.go index 81512dcf4..c7f42920f 100644 --- a/pkg/csi-common/identityserver-default_test.go +++ b/pkg/csi-common/identityserver-default_test.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2020 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -18,6 +18,9 @@ package csicommon import ( "context" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "reflect" "testing" "github.com/container-storage-interface/spec/lib/go/csi" @@ -25,13 +28,68 @@ import ( ) func TestGetPluginInfo(t *testing.T) { - d := NewFakeDriver() - - ids := NewDefaultIdentityServer(d) - req := csi.GetPluginInfoRequest{} - resp, err := ids.GetPluginInfo(context.Background(), &req) - assert.NoError(t, err) - assert.Equal(t, resp.GetName(), fakeDriverName) - assert.Equal(t, resp.GetVendorVersion(), vendorVersion) + emptyNameDriver := NewFakeDriver() + emptyNameDriver.Name = "" + emptyVersionDriver := NewFakeDriver() + emptyVersionDriver.Version = "" + tests := []struct { + desc string + driver *CSIDriver + expectedErr error + }{ + { + desc: "Successful request", + driver: NewFakeDriver(), + expectedErr: nil, + }, + { + desc: "Driver name missing", + driver: emptyNameDriver, + expectedErr: status.Error(codes.Unavailable, "Driver name not configured"), + }, + { + desc: "Driver version missing", + driver: emptyVersionDriver, + expectedErr: status.Error(codes.Unavailable, "Driver is missing version"), + }, + } + + for _, test := range tests { + ids := NewDefaultIdentityServer(test.driver) + _, err := ids.GetPluginInfo(context.Background(), &req) + if !reflect.DeepEqual(err, test.expectedErr) { + t.Errorf("Unexpecter error: %v", err) + } + } +} + +func TestProbe(t *testing.T) { + d := NewFakeDriver() + ids := NewDefaultIdentityServer(d) + req := csi.ProbeRequest{} + resp, err := ids.Probe(context.Background(), &req) + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, resp.XXX_sizecache, int32(0)) +} + +func TestGetPluginCapabilities(t *testing.T) { + expectedCap := []*csi.PluginCapability{ + { + Type: &csi.PluginCapability_Service_{ + Service: &csi.PluginCapability_Service{ + Type: csi.PluginCapability_Service_CONTROLLER_SERVICE, + }, + }, + }, + } + d := NewFakeDriver() + req := csi.GetPluginCapabilitiesRequest{} + ids := NewDefaultIdentityServer(d) + resp, err := ids.GetPluginCapabilities(context.Background(), &req) + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, resp.XXX_sizecache, int32(0)) + assert.Equal(t, resp.Capabilities, expectedCap) } diff --git a/pkg/csi-common/utils_test.go b/pkg/csi-common/utils_test.go index c1b34f0c2..c60bef409 100644 --- a/pkg/csi-common/utils_test.go +++ b/pkg/csi-common/utils_test.go @@ -1,5 +1,5 @@ /* -Copyright 2017 The Kubernetes Authors. +Copyright 2020 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -145,3 +145,111 @@ func TestLogGRPC(t *testing.T) { }) } } + +func TestNewDefaultNodeServer(t *testing.T) { + d := NewFakeDriver() + resp := NewDefaultNodeServer(d) + assert.NotNil(t, resp) + assert.Equal(t, resp.Driver.Name, fakeDriverName) + assert.Equal(t, resp.Driver.NodeID, fakeNodeID) + assert.Equal(t, resp.Driver.Version, vendorVersion) +} + +func TestNewDefaultIdentityServer(t *testing.T) { + d := NewFakeDriver() + resp := NewDefaultIdentityServer(d) + assert.NotNil(t, resp) + assert.Equal(t, resp.Driver.Name, fakeDriverName) + assert.Equal(t, resp.Driver.NodeID, fakeNodeID) + assert.Equal(t, resp.Driver.Version, vendorVersion) +} + +func TestNewDefaultControllerServer(t *testing.T) { + d := NewFakeDriver() + resp := NewDefaultControllerServer(d) + assert.NotNil(t, resp) + assert.Equal(t, resp.Driver.Name, fakeDriverName) + assert.Equal(t, resp.Driver.NodeID, fakeNodeID) + assert.Equal(t, resp.Driver.Version, vendorVersion) +} + +func TestNewVolumeCapabilityAccessMode(t *testing.T) { + tests := []struct { + mode csi.VolumeCapability_AccessMode_Mode + }{ + { + mode: csi.VolumeCapability_AccessMode_UNKNOWN, + }, + { + mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, + }, + { + mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY, + }, + { + mode: csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY, + }, + { + mode: csi.VolumeCapability_AccessMode_MULTI_NODE_SINGLE_WRITER, + }, + { + mode: csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER, + }, + } + for _, test := range tests { + resp := NewVolumeCapabilityAccessMode(test.mode) + assert.NotNil(t, resp) + assert.Equal(t, resp.Mode, test.mode) + } +} + +func TestNewControllerServiceCapability(t *testing.T) { + tests := []struct { + cap csi.ControllerServiceCapability_RPC_Type + }{ + { + cap: csi.ControllerServiceCapability_RPC_UNKNOWN, + }, + { + cap: csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME, + }, + { + cap: csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME, + }, + { + cap: csi.ControllerServiceCapability_RPC_LIST_VOLUMES, + }, + { + cap: csi.ControllerServiceCapability_RPC_GET_CAPACITY, + }, + } + for _, test := range tests { + resp := NewControllerServiceCapability(test.cap) + assert.NotNil(t, resp) + assert.Equal(t, resp.XXX_sizecache, int32(0)) + } +} + +func TestNewNodeServiceCapability(t *testing.T) { + tests := []struct { + cap csi.NodeServiceCapability_RPC_Type + }{ + { + cap: csi.NodeServiceCapability_RPC_UNKNOWN, + }, + { + cap: csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME, + }, + { + cap: csi.NodeServiceCapability_RPC_GET_VOLUME_STATS, + }, + { + cap: csi.NodeServiceCapability_RPC_EXPAND_VOLUME, + }, + } + for _, test := range tests { + resp := NewNodeServiceCapability(test.cap) + assert.NotNil(t, resp) + assert.Equal(t, resp.XXX_sizecache, int32(0)) + } +} diff --git a/pkg/smb/controllerserver_test.go b/pkg/smb/controllerserver_test.go new file mode 100644 index 000000000..5b1f6621a --- /dev/null +++ b/pkg/smb/controllerserver_test.go @@ -0,0 +1,39 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package smb + +import ( + "context" + "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestControllerGetCapabilities(t *testing.T) { + d := NewFakeDriver() + controlCap := []*csi.ControllerServiceCapability{ + { + Type: &csi.ControllerServiceCapability_Rpc{}, + }, + } + d.Cap = controlCap + req := csi.ControllerGetCapabilitiesRequest{} + resp, err := d.ControllerGetCapabilities(context.Background(), &req) + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, resp.Capabilities, controlCap) +} diff --git a/pkg/smb/identityserver_test.go b/pkg/smb/identityserver_test.go new file mode 100644 index 000000000..9960ea551 --- /dev/null +++ b/pkg/smb/identityserver_test.go @@ -0,0 +1,92 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package smb + +import ( + "context" + "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/stretchr/testify/assert" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "reflect" + "testing" +) + +func TestGetPluginInfo(t *testing.T) { + req := csi.GetPluginInfoRequest{} + emptyNameDriver := NewFakeDriver() + emptyNameDriver.Name = "" + emptyVersionDriver := NewFakeDriver() + emptyVersionDriver.Version = "" + tests := []struct { + desc string + driver *Driver + expectedErr error + }{ + { + desc: "Successful request", + driver: NewFakeDriver(), + expectedErr: nil, + }, + { + desc: "Driver name missing", + driver: emptyNameDriver, + expectedErr: status.Error(codes.Unavailable, "Driver name not configured"), + }, + { + desc: "Driver version missing", + driver: emptyVersionDriver, + expectedErr: status.Error(codes.Unavailable, "Driver is missing version"), + }, + } + + for _, test := range tests { + _, err := test.driver.GetPluginInfo(context.Background(), &req) + if !reflect.DeepEqual(err, test.expectedErr) { + t.Errorf("Unexpecter error: %v", err) + } + } +} + +func TestProbe(t *testing.T) { + d := NewFakeDriver() + req := csi.ProbeRequest{} + resp, err := d.Probe(context.Background(), &req) + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, resp.XXX_sizecache, int32(0)) + assert.Equal(t, resp.Ready.Value, true) +} + +func TestGetPluginCapabilities(t *testing.T) { + expectedCap := []*csi.PluginCapability{ + { + Type: &csi.PluginCapability_Service_{ + Service: &csi.PluginCapability_Service{ + Type: csi.PluginCapability_Service_CONTROLLER_SERVICE, + }, + }, + }, + } + d := NewFakeDriver() + req := csi.GetPluginCapabilitiesRequest{} + resp, err := d.GetPluginCapabilities(context.Background(), &req) + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, resp.XXX_sizecache, int32(0)) + assert.Equal(t, resp.Capabilities, expectedCap) +} diff --git a/pkg/smb/version_test.go b/pkg/smb/version_test.go new file mode 100644 index 000000000..7b31ce523 --- /dev/null +++ b/pkg/smb/version_test.go @@ -0,0 +1,60 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package smb + +import ( + "fmt" + "reflect" + "runtime" + "strings" + "testing" + + "sigs.k8s.io/yaml" +) + +func TestGetVersion(t *testing.T) { + version := GetVersion() + + expected := VersionInfo{ + DriverName: DriverName, + DriverVersion: "N/A", + GitCommit: "N/A", + BuildDate: "N/A", + GoVersion: runtime.Version(), + Compiler: runtime.Compiler, + Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), + } + + if !reflect.DeepEqual(version, expected) { + t.Errorf("Unexpected error. \n Expected: %v \n Found: %v", expected, version) + } + +} + +func TestGetVersionYAML(t *testing.T) { + resp, err := GetVersionYAML() + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + versionInfo := GetVersion() + marshalled, _ := yaml.Marshal(&versionInfo) + expected := strings.TrimSpace(string(marshalled)) + + if resp != expected { + t.Fatalf("Unexpected error. \n Expected:%v\nFound:%v", expected, resp) + } +}