Skip to content

Commit

Permalink
test: Fix TestNodeStageVolume on Windows
Browse files Browse the repository at this point in the history
Signed-off-by: Mayank Shah <[email protected]>
  • Loading branch information
mayankshah1607 authored and Mayank Shah committed Sep 10, 2020
1 parent 2680298 commit 194d551
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 27 deletions.
7 changes: 7 additions & 0 deletions pkg/smb/fake_mounter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import (
)

func TestMount(t *testing.T) {
targetTest := "./target_test"
sourceTest := "./source_test"

tests := []struct {
desc string
source string
Expand Down Expand Up @@ -65,6 +68,9 @@ func TestMount(t *testing.T) {
}

func TestMountSensitive(t *testing.T) {
targetTest := "./target_test"
sourceTest := "./source_test"

tests := []struct {
desc string
source string
Expand Down Expand Up @@ -105,6 +111,7 @@ func TestMountSensitive(t *testing.T) {
}

func TestIsLikelyNotMountPoint(t *testing.T) {
targetTest := "./target_test"
tests := []struct {
desc string
file string
Expand Down
2 changes: 1 addition & 1 deletion pkg/smb/nodeserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe

isDirMounted, err := d.ensureMountPoint(targetPath)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not mount target %q: %v", targetPath, err)
return nil, status.Errorf(codes.Internal, "Could not mount target %s: %v", targetPath, err)
}

if !isDirMounted {
Expand Down
73 changes: 48 additions & 25 deletions pkg/smb/nodeserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,25 @@ import (
"syscall"
"testing"

"github.com/kubernetes-csi/csi-driver-smb/test/utils/testutil"

"github.com/container-storage-interface/spec/lib/go/csi"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"k8s.io/utils/mount"
)

const (
sourceTest = "./source_test"
targetTest = "./target_test"
)

func TestNodeStageVolume(t *testing.T) {
skipIfTestingOnWindows(t)

stdVolCap := csi.VolumeCapability{
AccessType: &csi.VolumeCapability_Mount{
Mount: &csi.VolumeCapability_MountVolume{},
},
}

errorMountSensSource := "./error_mount_sens_source"
smbFile := "./smb.go"
errorMountSensSource := testutil.GetWorkDirPath("error_mount_sens_source", t)
smbFile := testutil.GetWorkDirPath("smb.go", t)
sourceTest := testutil.GetWorkDirPath("source_test", t)

volContext := map[string]string{
sourceField: "test_source",
Expand All @@ -61,52 +57,72 @@ func TestNodeStageVolume(t *testing.T) {
tests := []struct {
desc string
req csi.NodeStageVolumeRequest
expectedErr error
expectedErr testutil.TestError
}{
{
desc: "[Error] Volume ID missing",
req: csi.NodeStageVolumeRequest{},
expectedErr: status.Error(codes.InvalidArgument, "Volume ID missing in request"),
desc: "[Error] Volume ID missing",
req: csi.NodeStageVolumeRequest{},
expectedErr: testutil.TestError{
DefaultError: 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] Volume capabilities missing",
req: csi.NodeStageVolumeRequest{VolumeId: "vol_1"},
expectedErr: testutil.TestError{
DefaultError: 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] Stage target path missing",
req: csi.NodeStageVolumeRequest{VolumeId: "vol_1", VolumeCapability: &stdVolCap},
expectedErr: testutil.TestError{
DefaultError: 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[]"),
expectedErr: testutil.TestError{
DefaultError: 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"),
expectedErr: testutil.TestError{
DefaultError: status.Error(codes.Internal, fmt.Sprintf("MkdirAll %s failed with error: mkdir %s: not a directory", smbFile, smbFile)),
WindowsError: status.Error(codes.Internal, fmt.Sprintf("Could not mount target %s: mkdir %s: The system cannot find the path specified.", smbFile, smbFile)),
},
},
{
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"),
expectedErr: testutil.TestError{
DefaultError: status.Errorf(codes.Internal,
fmt.Sprintf("volume(vol_1##) mount \"test_source\" on \"%s\" failed with fake MountSensitive: target error",
errorMountSensSource)),
// todo: Not a desired error. This will need a better fix
WindowsError: fmt.Errorf("prepare stage path failed for %s with error: could not cast to csi proxy class", errorMountSensSource),
},
},
{
desc: "[Success] Valid request",
req: csi.NodeStageVolumeRequest{VolumeId: "vol_1##", StagingTargetPath: sourceTest,
VolumeCapability: &stdVolCap,
VolumeContext: volContext,
Secrets: secrets},
expectedErr: nil,
expectedErr: testutil.TestError{
// todo: Not a desired error. This will need a better fix
WindowsError: fmt.Errorf("prepare stage path failed for %s with error: could not cast to csi proxy class", sourceTest),
},
},
}

Expand All @@ -120,8 +136,8 @@ func TestNodeStageVolume(t *testing.T) {
}

_, err := d.NodeStageVolume(context.Background(), &test.req)
if !reflect.DeepEqual(err, test.expectedErr) {
t.Errorf("test case: %s, Unexpected error: %v", test.desc, err)
if !testutil.AssertError(&test.expectedErr, err) {
t.Errorf("test case: %s, \nUnexpected error: %v\n Expected: %v", test.desc, err, test.expectedErr.GetExpectedError())
}
}

Expand Down Expand Up @@ -187,6 +203,8 @@ func TestNodePublishVolume(t *testing.T) {
errorMountSource := "./error_mount_source"
alreadyMountedTarget := "./false_is_likely_exist_target"
smbFile := "./smb.go"
sourceTest := "./source_test"
targetTest := "./target_test"

tests := []struct {
desc string
Expand Down Expand Up @@ -289,6 +307,7 @@ func TestNodeUnpublishVolume(t *testing.T) {
skipIfTestingOnWindows(t)
errorTarget := "./error_is_likely_target"
targetFile := "./abc.go"
targetTest := "./target_test"

tests := []struct {
desc string
Expand Down Expand Up @@ -341,6 +360,7 @@ func TestNodeUnstageVolume(t *testing.T) {
skipIfTestingOnWindows(t)
errorTarget := "./error_is_likely_target"
targetFile := "./abc.go"
targetTest := "./target_test"

tests := []struct {
desc string
Expand Down Expand Up @@ -394,6 +414,7 @@ func TestEnsureMountPoint(t *testing.T) {
alreadyExistTarget := "./false_is_likely_exist_target"
falseTarget := "./false_is_likely_target"
smbFile := "./smb.go"
targetTest := "./target_test"

tests := []struct {
desc string
Expand Down Expand Up @@ -450,6 +471,8 @@ func TestEnsureMountPoint(t *testing.T) {
}

func TestMakeDir(t *testing.T) {
targetTest := "./target_test"

//Successfully create directory
err := makeDir(targetTest)
assert.NoError(t, err)
Expand Down
46 changes: 45 additions & 1 deletion test/utils/testutil/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,53 @@ limitations under the License.

package testutil

import "os"
import (
"fmt"
"os"
"reflect"
"runtime"
"testing"
)

// TestError holds the different errors for Windows and Linux
type TestError struct {
WindowsError error
DefaultError error
}

// GetExpectedError returns the expected error depending on OS
func (t TestError) GetExpectedError() error {
if isWindows() {
return t.WindowsError
}
return t.DefaultError
}

// AssertError matches the actual and expected errors
func AssertError(actual *TestError, expected error) bool {
if isWindows() {
if actual.WindowsError == nil {
return reflect.DeepEqual(actual.DefaultError, expected)
}
return reflect.DeepEqual(actual.WindowsError, expected)
}
return reflect.DeepEqual(actual.DefaultError, expected)
}

func IsRunningInProw() bool {
_, ok := os.LookupEnv("AZURE_CREDENTIALS")
return ok
}

func isWindows() bool {
return runtime.GOOS == "windows"
}

// GetWorkDirPath returns the path to the current working directory
func GetWorkDirPath(dir string, t *testing.T) string {
path, err := os.Getwd()
if err != nil {
t.Fatalf("failed to get working directory: %s", err)
}
return fmt.Sprintf("%s%c%s", path, os.PathSeparator, dir)
}

0 comments on commit 194d551

Please sign in to comment.