Merge pull request #55 from animeshk08/unit-tests
test: Add unit test for nodeserver
This commit is contained in:
commit
047ea76a72
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
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"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/utils/mount"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fakeMounter struct {
|
||||||
|
mount.FakeMounter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount overrides mount.FakeMounter.Mount.
|
||||||
|
func (f *fakeMounter) Mount(source string, target string, fstype string, options []string) error {
|
||||||
|
if strings.Contains(source, "error_mount") {
|
||||||
|
return fmt.Errorf("fake Mount: source error")
|
||||||
|
} else if strings.Contains(target, "error_mount") {
|
||||||
|
return fmt.Errorf("fake Mount: target error")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MountSensitive overrides mount.FakeMounter.MountSensitive.
|
||||||
|
func (f *fakeMounter) MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
|
||||||
|
if strings.Contains(source, "error_mount_sens") {
|
||||||
|
return fmt.Errorf("fake MountSensitive: source error")
|
||||||
|
} else if strings.Contains(target, "error_mount_sens") {
|
||||||
|
return fmt.Errorf("fake MountSensitive: target error")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//IsLikelyNotMountPoint overrides mount.FakeMounter.IsLikelyNotMountPoint.
|
||||||
|
func (f *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||||
|
if strings.Contains(file, "error_is_likely") {
|
||||||
|
return false, fmt.Errorf("fake IsLikelyNotMountPoint: fake error")
|
||||||
|
}
|
||||||
|
if strings.Contains(file, "false_is_likely") {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
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"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/utils/mount"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMount(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
desc string
|
||||||
|
source string
|
||||||
|
target string
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "[Error] Mocked source error",
|
||||||
|
source: "./error_mount_source",
|
||||||
|
target: targetTest,
|
||||||
|
expectedErr: fmt.Errorf("fake Mount: source error"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Mocked target error",
|
||||||
|
source: sourceTest,
|
||||||
|
target: "./error_mount_target",
|
||||||
|
expectedErr: fmt.Errorf("fake Mount: target error"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Successful run",
|
||||||
|
source: sourceTest,
|
||||||
|
target: targetTest,
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
d := NewFakeDriver()
|
||||||
|
fakeMounter := &fakeMounter{}
|
||||||
|
d.mounter = &mount.SafeFormatAndMount{
|
||||||
|
Interface: fakeMounter,
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
err := d.mounter.Mount(test.source, test.target, "", nil)
|
||||||
|
if !reflect.DeepEqual(err, test.expectedErr) {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMountSensitive(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
desc string
|
||||||
|
source string
|
||||||
|
target string
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "[Error] Mocked source error",
|
||||||
|
source: "./error_mount_sens_source",
|
||||||
|
target: targetTest,
|
||||||
|
expectedErr: fmt.Errorf("fake MountSensitive: source error"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Mocked target error",
|
||||||
|
source: sourceTest,
|
||||||
|
target: "./error_mount_sens_target",
|
||||||
|
expectedErr: fmt.Errorf("fake MountSensitive: target error"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Successful run",
|
||||||
|
source: sourceTest,
|
||||||
|
target: targetTest,
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
d := NewFakeDriver()
|
||||||
|
fakeMounter := &fakeMounter{}
|
||||||
|
d.mounter = &mount.SafeFormatAndMount{
|
||||||
|
Interface: fakeMounter,
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
err := d.mounter.MountSensitive(test.source, test.target, "", nil, nil)
|
||||||
|
if !reflect.DeepEqual(err, test.expectedErr) {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsLikelyNotMountPoint(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
desc string
|
||||||
|
file string
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "[Error] Mocked file error",
|
||||||
|
file: "./error_is_likely_target",
|
||||||
|
expectedErr: fmt.Errorf("fake IsLikelyNotMountPoint: fake error"),
|
||||||
|
},
|
||||||
|
{desc: "[Success] Successful run",
|
||||||
|
file: targetTest,
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Successful run not a mount",
|
||||||
|
file: "./false_is_likely_target",
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
d := NewFakeDriver()
|
||||||
|
fakeMounter := &fakeMounter{}
|
||||||
|
d.mounter = &mount.SafeFormatAndMount{
|
||||||
|
Interface: fakeMounter,
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
_, err := d.mounter.IsLikelyNotMountPoint(test.file)
|
||||||
|
if !reflect.DeepEqual(err, test.expectedErr) {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -53,8 +53,10 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
|
||||||
if len(req.GetVolumeId()) == 0 {
|
if len(req.GetVolumeId()) == 0 {
|
||||||
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
return nil, status.Error(codes.InvalidArgument, "Volume ID missing in request")
|
||||||
}
|
}
|
||||||
if len(req.GetTargetPath()) == 0 {
|
|
||||||
return nil, status.Error(codes.InvalidArgument, "Target path missing in request")
|
target := req.GetTargetPath()
|
||||||
|
if len(target) == 0 {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "Target path not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
source := req.GetStagingTargetPath()
|
source := req.GetStagingTargetPath()
|
||||||
|
|
@ -62,11 +64,6 @@ func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolu
|
||||||
return nil, status.Error(codes.InvalidArgument, "Staging target not provided")
|
return nil, status.Error(codes.InvalidArgument, "Staging target not provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
target := req.GetTargetPath()
|
|
||||||
if len(target) == 0 {
|
|
||||||
return nil, status.Error(codes.InvalidArgument, "Target path not provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
mountOptions := []string{"bind"}
|
mountOptions := []string{"bind"}
|
||||||
if req.GetReadonly() {
|
if req.GetReadonly() {
|
||||||
mountOptions = append(mountOptions, "ro")
|
mountOptions = append(mountOptions, "ro")
|
||||||
|
|
@ -227,7 +224,7 @@ func (d *Driver) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolu
|
||||||
|
|
||||||
klog.V(2).Infof("NodeUnstageVolume: CleanupMountPoint %s", stagingTargetPath)
|
klog.V(2).Infof("NodeUnstageVolume: CleanupMountPoint %s", stagingTargetPath)
|
||||||
if err := CleanupSMBMountPoint(d.mounter, stagingTargetPath, false); err != nil {
|
if err := CleanupSMBMountPoint(d.mounter, stagingTargetPath, false); err != nil {
|
||||||
return nil, status.Errorf(codes.Internal, "failed to unmount staing target %q: %v", stagingTargetPath, err)
|
return nil, status.Errorf(codes.Internal, "failed to unmount staging target %q: %v", stagingTargetPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(2).Infof("NodeUnstageVolume: unmount %s successfully", stagingTargetPath)
|
klog.V(2).Infof("NodeUnstageVolume: unmount %s successfully", stagingTargetPath)
|
||||||
|
|
|
||||||
|
|
@ -17,71 +17,117 @@ limitations under the License.
|
||||||
package smb
|
package smb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
"k8s.io/klog"
|
"k8s.io/utils/mount"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sourceTest = "./source_test"
|
||||||
|
targetTest = "./target_test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNodeStageVolume(t *testing.T) {
|
func TestNodeStageVolume(t *testing.T) {
|
||||||
klog.InitFlags(nil)
|
stdVolCap := csi.VolumeCapability{
|
||||||
if e := flag.Set("logtostderr", "false"); e != nil {
|
AccessType: &csi.VolumeCapability_Mount{
|
||||||
t.Error(e)
|
Mount: &csi.VolumeCapability_MountVolume{},
|
||||||
}
|
|
||||||
if e := flag.Set("alsologtostderr", "false"); e != nil {
|
|
||||||
t.Error(e)
|
|
||||||
}
|
|
||||||
if e := flag.Set("v", "100"); e != nil {
|
|
||||||
t.Error(e)
|
|
||||||
}
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
klog.SetOutput(buf)
|
|
||||||
|
|
||||||
d := NewFakeDriver()
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
req *csi.NodeStageVolumeRequest
|
|
||||||
expStr string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"with secrets",
|
|
||||||
&csi.NodeStageVolumeRequest{
|
|
||||||
VolumeId: "vol_1",
|
|
||||||
Secrets: map[string]string{
|
|
||||||
"password": "testpassword",
|
|
||||||
"username": "testuser",
|
|
||||||
},
|
|
||||||
VolumeCapability: &csi.VolumeCapability{},
|
|
||||||
XXX_sizecache: 100,
|
|
||||||
},
|
|
||||||
`NodeStageVolume called with request {vol_1 map[] map[password:**** username:testuser] map[] {} [] 100}`,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
errorMountSensSource := "./error_mount_sens_source"
|
||||||
t.Run(test.name, func(t *testing.T) {
|
smbFile := "./smb.go"
|
||||||
// EXECUTE
|
|
||||||
_, _ = d.NodeStageVolume(context.Background(), test.req)
|
|
||||||
klog.Flush()
|
|
||||||
|
|
||||||
//ASSERT
|
volContext := map[string]string{
|
||||||
assert.Contains(t, buf.String(), test.expStr)
|
sourceField: "test_source",
|
||||||
|
}
|
||||||
// CLEANUP
|
secrets := map[string]string{
|
||||||
buf.Reset()
|
usernameField: "test_username",
|
||||||
})
|
passwordField: "test_password",
|
||||||
|
domainField: "test_doamin",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
desc string
|
||||||
|
req csi.NodeStageVolumeRequest
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "[Error] Volume ID missing",
|
||||||
|
req: csi.NodeStageVolumeRequest{},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Volume ID missing in request"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Volume capabilities missing",
|
||||||
|
req: csi.NodeStageVolumeRequest{VolumeId: "vol_1"},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Volume capability not provided"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Stage target path missing",
|
||||||
|
req: csi.NodeStageVolumeRequest{VolumeId: "vol_1", VolumeCapability: &stdVolCap},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Staging target not provided"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Source field is missing in context",
|
||||||
|
req: csi.NodeStageVolumeRequest{VolumeId: "vol_1", StagingTargetPath: sourceTest,
|
||||||
|
VolumeCapability: &stdVolCap},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "source field is missing, current context: map[]"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Not a Directory",
|
||||||
|
req: csi.NodeStageVolumeRequest{VolumeId: "vol_1##", StagingTargetPath: smbFile,
|
||||||
|
VolumeCapability: &stdVolCap,
|
||||||
|
VolumeContext: volContext,
|
||||||
|
Secrets: secrets},
|
||||||
|
expectedErr: status.Error(codes.Internal, "MkdirAll ./smb.go failed with error: mkdir ./smb.go: not a directory"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Failed SMB mount mocked by MountSensitive",
|
||||||
|
req: csi.NodeStageVolumeRequest{VolumeId: "vol_1##", StagingTargetPath: errorMountSensSource,
|
||||||
|
VolumeCapability: &stdVolCap,
|
||||||
|
VolumeContext: volContext,
|
||||||
|
Secrets: secrets},
|
||||||
|
expectedErr: status.Errorf(codes.Internal, "volume(vol_1##) mount \"test_source\" on \"./error_mount_sens_source\" failed with fake MountSensitive: target error"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Valid request",
|
||||||
|
req: csi.NodeStageVolumeRequest{VolumeId: "vol_1##", StagingTargetPath: sourceTest,
|
||||||
|
VolumeCapability: &stdVolCap,
|
||||||
|
VolumeContext: volContext,
|
||||||
|
Secrets: secrets},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
d := NewFakeDriver()
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
fakeMounter := &fakeMounter{}
|
||||||
|
d.mounter = &mount.SafeFormatAndMount{
|
||||||
|
Interface: fakeMounter,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := d.NodeStageVolume(context.Background(), &test.req)
|
||||||
|
if !reflect.DeepEqual(err, test.expectedErr) {
|
||||||
|
t.Errorf("test case: %s, Unexpected error: %v", test.desc, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
err := os.RemoveAll(sourceTest)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = os.RemoveAll(errorMountSensSource)
|
||||||
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNodeGetInfo(t *testing.T) {
|
func TestNodeGetInfo(t *testing.T) {
|
||||||
|
|
@ -132,3 +178,285 @@ func TestNodeExpandVolume(t *testing.T) {
|
||||||
t.Errorf("Unexpected error: %v", err)
|
t.Errorf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNodePublishVolume(t *testing.T) {
|
||||||
|
volumeCap := csi.VolumeCapability_AccessMode{Mode: csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER}
|
||||||
|
errorMountSource := "./error_mount_source"
|
||||||
|
alreadyMountedTarget := "./false_is_likely_exist_target"
|
||||||
|
smbFile := "./smb.go"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
desc string
|
||||||
|
req csi.NodePublishVolumeRequest
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "[Error] Volume capabilities missing",
|
||||||
|
req: csi.NodePublishVolumeRequest{},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Volume capability missing in request"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Volume ID missing",
|
||||||
|
req: csi.NodePublishVolumeRequest{VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap}},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Volume ID missing in request"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Target path missing",
|
||||||
|
req: csi.NodePublishVolumeRequest{VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
|
||||||
|
VolumeId: "vol_1"},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Target path not provided"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Stage target path missing",
|
||||||
|
req: csi.NodePublishVolumeRequest{VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
|
||||||
|
VolumeId: "vol_1",
|
||||||
|
TargetPath: targetTest},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Staging target not provided"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Not a directory",
|
||||||
|
req: csi.NodePublishVolumeRequest{VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
|
||||||
|
VolumeId: "vol_1",
|
||||||
|
TargetPath: smbFile,
|
||||||
|
StagingTargetPath: sourceTest,
|
||||||
|
Readonly: true},
|
||||||
|
expectedErr: status.Errorf(codes.Internal, "Could not mount target \"./smb.go\": mkdir ./smb.go: not a directory"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Mount error mocked by Mount",
|
||||||
|
req: csi.NodePublishVolumeRequest{VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
|
||||||
|
VolumeId: "vol_1",
|
||||||
|
TargetPath: targetTest,
|
||||||
|
StagingTargetPath: errorMountSource,
|
||||||
|
Readonly: true},
|
||||||
|
expectedErr: status.Errorf(codes.Internal, "Could not mount \"./error_mount_source\" at \"./target_test\": fake Mount: source error"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Valid request read only",
|
||||||
|
req: csi.NodePublishVolumeRequest{VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
|
||||||
|
VolumeId: "vol_1",
|
||||||
|
TargetPath: targetTest,
|
||||||
|
StagingTargetPath: sourceTest,
|
||||||
|
Readonly: true},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Valid request already mounted",
|
||||||
|
req: csi.NodePublishVolumeRequest{VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
|
||||||
|
VolumeId: "vol_1",
|
||||||
|
TargetPath: alreadyMountedTarget,
|
||||||
|
StagingTargetPath: sourceTest,
|
||||||
|
Readonly: true},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Valid request",
|
||||||
|
req: csi.NodePublishVolumeRequest{VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
|
||||||
|
VolumeId: "vol_1",
|
||||||
|
TargetPath: targetTest,
|
||||||
|
StagingTargetPath: sourceTest,
|
||||||
|
Readonly: true},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
_ = makeDir(alreadyMountedTarget)
|
||||||
|
d := NewFakeDriver()
|
||||||
|
fakeMounter := &fakeMounter{}
|
||||||
|
d.mounter = &mount.SafeFormatAndMount{
|
||||||
|
Interface: fakeMounter,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
_, err := d.NodePublishVolume(context.Background(), &test.req)
|
||||||
|
if !reflect.DeepEqual(err, test.expectedErr) {
|
||||||
|
t.Errorf("test case: %s, Unexpected error: %v", test.desc, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
err := os.RemoveAll(targetTest)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = os.RemoveAll(alreadyMountedTarget)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNodeUnpublishVolume(t *testing.T) {
|
||||||
|
errorTarget := "./error_is_likely_target"
|
||||||
|
targetFile := "./abc.go"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
desc string
|
||||||
|
req csi.NodeUnpublishVolumeRequest
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "[Error] Volume ID missing",
|
||||||
|
req: csi.NodeUnpublishVolumeRequest{TargetPath: targetTest},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Volume ID missing in request"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Target missing",
|
||||||
|
req: csi.NodeUnpublishVolumeRequest{VolumeId: "vol_1"},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Target path missing in request"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Unmount error mocked by IsLikelyNotMountPoint",
|
||||||
|
req: csi.NodeUnpublishVolumeRequest{TargetPath: errorTarget, VolumeId: "vol_1"},
|
||||||
|
expectedErr: status.Error(codes.Internal, "failed to unmount target \"./error_is_likely_target\": fake IsLikelyNotMountPoint: fake error"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Valid request",
|
||||||
|
req: csi.NodeUnpublishVolumeRequest{TargetPath: targetFile, VolumeId: "vol_1"},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
_ = makeDir(errorTarget)
|
||||||
|
d := NewFakeDriver()
|
||||||
|
fakeMounter := &fakeMounter{}
|
||||||
|
d.mounter = &mount.SafeFormatAndMount{
|
||||||
|
Interface: fakeMounter,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
_, err := d.NodeUnpublishVolume(context.Background(), &test.req)
|
||||||
|
if !reflect.DeepEqual(err, test.expectedErr) {
|
||||||
|
t.Errorf("test case: %s, Unexpected error: %v", test.desc, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
err := os.RemoveAll(errorTarget)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNodeUnstageVolume(t *testing.T) {
|
||||||
|
errorTarget := "./error_is_likely_target"
|
||||||
|
targetFile := "./abc.go"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
desc string
|
||||||
|
req csi.NodeUnstageVolumeRequest
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "[Error] Volume ID missing",
|
||||||
|
req: csi.NodeUnstageVolumeRequest{StagingTargetPath: targetTest},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Volume ID missing in request"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Target missing",
|
||||||
|
req: csi.NodeUnstageVolumeRequest{VolumeId: "vol_1"},
|
||||||
|
expectedErr: status.Error(codes.InvalidArgument, "Staging target not provided"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] CleanupMountPoint error mocked by IsLikelyNotMountPoint",
|
||||||
|
req: csi.NodeUnstageVolumeRequest{StagingTargetPath: errorTarget, VolumeId: "vol_1"},
|
||||||
|
expectedErr: status.Error(codes.Internal, "failed to unmount staging target \"./error_is_likely_target\": fake IsLikelyNotMountPoint: fake error"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Valid request",
|
||||||
|
req: csi.NodeUnstageVolumeRequest{StagingTargetPath: targetFile, VolumeId: "vol_1"},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
_ = makeDir(errorTarget)
|
||||||
|
d := NewFakeDriver()
|
||||||
|
fakeMounter := &fakeMounter{}
|
||||||
|
d.mounter = &mount.SafeFormatAndMount{
|
||||||
|
Interface: fakeMounter,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
_, err := d.NodeUnstageVolume(context.Background(), &test.req)
|
||||||
|
if !reflect.DeepEqual(err, test.expectedErr) {
|
||||||
|
t.Errorf("test case: %s, Unexpected error: %v", test.desc, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
err := os.RemoveAll(errorTarget)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnsureMountPoint(t *testing.T) {
|
||||||
|
errorTarget := "./error_is_likely_target"
|
||||||
|
alreadyExistTarget := "./false_is_likely_exist_target"
|
||||||
|
falseTarget := "./false_is_likely_target"
|
||||||
|
smbFile := "./smb.go"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
desc string
|
||||||
|
target string
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "[Error] Mocked by IsLikelyNotMountPoint",
|
||||||
|
target: errorTarget,
|
||||||
|
expectedErr: fmt.Errorf("fake IsLikelyNotMountPoint: fake error"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Error opening file",
|
||||||
|
target: falseTarget,
|
||||||
|
expectedErr: &os.PathError{Op: "open", Path: "./false_is_likely_target", Err: syscall.ENOENT},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Error] Not a directory",
|
||||||
|
target: smbFile,
|
||||||
|
expectedErr: &os.PathError{Op: "mkdir", Path: "./smb.go", Err: syscall.ENOTDIR},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Successful run",
|
||||||
|
target: targetTest,
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "[Success] Already existing mount",
|
||||||
|
target: alreadyExistTarget,
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
_ = makeDir(alreadyExistTarget)
|
||||||
|
d := NewFakeDriver()
|
||||||
|
fakeMounter := &fakeMounter{}
|
||||||
|
d.mounter = &mount.SafeFormatAndMount{
|
||||||
|
Interface: fakeMounter,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
_, err := d.ensureMountPoint(test.target)
|
||||||
|
if !reflect.DeepEqual(err, test.expectedErr) {
|
||||||
|
t.Errorf("test case: %s, Unexpected error: %v", test.desc, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
err := os.RemoveAll(alreadyExistTarget)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = os.RemoveAll(targetTest)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMakeDir(t *testing.T) {
|
||||||
|
//Successfully create directory
|
||||||
|
err := makeDir(targetTest)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
//Failed case
|
||||||
|
err = makeDir("./smb.go")
|
||||||
|
var e *os.PathError
|
||||||
|
if !errors.As(err, &e) {
|
||||||
|
t.Errorf("Unexpected Error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the directory created
|
||||||
|
err = os.RemoveAll(targetTest)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue