Skip to content

Commit

Permalink
test: create / delete snapshot unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
wozniakjan committed Mar 28, 2023
1 parent 76f4841 commit 169a85e
Showing 1 changed file with 182 additions and 0 deletions.
182 changes: 182 additions & 0 deletions pkg/nfs/controllerserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"golang.org/x/net/context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
mount "k8s.io/mount-utils"
)

Expand Down Expand Up @@ -827,3 +828,184 @@ func TestCopyVolume(t *testing.T) {
})
}
}

func TestCreateSnapshot(t *testing.T) {
cases := []struct {
desc string
req *csi.CreateSnapshotRequest
expResp *csi.CreateSnapshotResponse
expectErr bool
prepare func() error
cleanup func() error
}{
{
desc: "create snapshot with valid request",
req: &csi.CreateSnapshotRequest{
SourceVolumeId: "nfs-server.default.svc.cluster.local#share#subdir#src-pv-name",
Name: "snapshot-name",
},
expResp: &csi.CreateSnapshotResponse{
Snapshot: &csi.Snapshot{
SnapshotId: "nfs-server.default.svc.cluster.local#share#snapshot-name#snapshot-name#src-pv-name",
SourceVolumeId: "nfs-server.default.svc.cluster.local#share#subdir#src-pv-name",
ReadyToUse: true,
SizeBytes: 1, // doesn't match exact size, just denotes non-zero size expected
CreationTime: timestamppb.Now(), // doesn't match exact timestamp, just denotes non-zero ts expected
},
},
prepare: func() error { return os.MkdirAll("/tmp/src-pv-name/subdir", 0777) },
cleanup: func() error { return os.RemoveAll("/tmp/src-pv-name") },
},
{
desc: "create snapshot from nonexisting volume",
req: &csi.CreateSnapshotRequest{
SourceVolumeId: "nfs-server.default.svc.cluster.local#share#subdir#src-pv-name",
Name: "snapshot-name",
},
expectErr: true,
},
}
for _, test := range cases {
t.Run(test.desc, func(t *testing.T) {
if test.prepare != nil {
if err := test.prepare(); err != nil {
t.Errorf(`[test: %s] prepare failed: "%v"`, test.desc, err)
}
}
cs := initTestController(t)
resp, err := cs.CreateSnapshot(context.TODO(), test.req)
if (err == nil) == test.expectErr {
t.Errorf(`[test: %s] Error expectation mismatch, expected error: "%v", received: %q`, test.desc, test.expectErr, err)
}
if err := matchCreateSnapshotResponse(test.expResp, resp); err != nil {
t.Errorf("[test: %s] failed %q: got resp %+v, expected %+v", test.desc, err, resp, test.expResp)
}
if test.cleanup != nil {
if err := test.cleanup(); err != nil {
t.Errorf(`[test: %s] cleanup failed: "%v"`, test.desc, err)
}
}
})
}
}

func TestDeleteSnapshot(t *testing.T) {
cases := []struct {
desc string
req *csi.DeleteSnapshotRequest
expResp *csi.DeleteSnapshotResponse
expectErr bool
prepare func() error
cleanup func() error
}{
{
desc: "delete valid snapshot",
req: &csi.DeleteSnapshotRequest{
SnapshotId: "nfs-server.default.svc.cluster.local#share#snapshot-name#snapshot-name#src-pv-name",
},
expResp: &csi.DeleteSnapshotResponse{},
prepare: func() error {
if err := os.MkdirAll("/tmp/snapshot-name/snapshot-name/", 0777); err != nil {
return err
}
f, err := os.OpenFile("/tmp/snapshot-name/snapshot-name/src-pv-name.tar.gz", os.O_CREATE, 0777)
if err != nil {
return err
}
return f.Close()
},
cleanup: func() error { return os.RemoveAll("/tmp/snapshot-name") },
},
{
desc: "delete nonexisting snapshot",
req: &csi.DeleteSnapshotRequest{
SnapshotId: "nfs-server.default.svc.cluster.local#share#snapshot-name#snapshot-name#src-pv-name",
},
expResp: &csi.DeleteSnapshotResponse{},
},
{
desc: "delete snapshot with improper id",
req: &csi.DeleteSnapshotRequest{
SnapshotId: "incorrect-snap-id",
},
expResp: &csi.DeleteSnapshotResponse{},
},
{
desc: "delete valid snapshot with mount options",
req: &csi.DeleteSnapshotRequest{
SnapshotId: "nfs-server.default.svc.cluster.local#share#snapshot-name#snapshot-name#src-pv-name",
Secrets: map[string]string{"mountoptions": "nfsvers=4.1"},
},
expResp: &csi.DeleteSnapshotResponse{},
prepare: func() error {
if err := os.MkdirAll("/tmp/snapshot-name/snapshot-name/", 0777); err != nil {
return err
}
f, err := os.OpenFile("/tmp/snapshot-name/snapshot-name/src-pv-name.tar.gz", os.O_CREATE, 0777)
if err != nil {
return err
}
return f.Close()
},
cleanup: func() error { return os.RemoveAll("/tmp/snapshot-name") },
},
}
for _, test := range cases {
t.Run(test.desc, func(t *testing.T) {
if test.prepare != nil {
if err := test.prepare(); err != nil {
t.Errorf(`[test: %s] prepare failed: "%v"`, test.desc, err)
}
}
cs := initTestController(t)
resp, err := cs.DeleteSnapshot(context.TODO(), test.req)
if (err == nil) == test.expectErr {
t.Errorf(`[test: %s] Error expectation mismatch, expected error: "%v", received: %q`, test.desc, test.expectErr, err)
}
if !reflect.DeepEqual(test.expResp, resp) {
t.Errorf("[test: %s] got resp %+v, expected %+v", test.desc, resp, test.expResp)
}
if test.cleanup != nil {
if err := test.cleanup(); err != nil {
t.Errorf(`[test: %s] cleanup failed: "%v"`, test.desc, err)
}
}
})
}
}

func matchCreateSnapshotResponse(e, r *csi.CreateSnapshotResponse) error {
if e == nil && r == nil {
return nil
}
if e == nil || e.Snapshot == nil {
return fmt.Errorf("expected nil response")
}
if r == nil || r.Snapshot == nil {
return fmt.Errorf("unexpected nil response")
}
es, rs := e.Snapshot, r.Snapshot

var errs []string
// comparing ts and size just for presence, not the exact value
if es.CreationTime.IsValid() != rs.CreationTime.IsValid() {
errs = append(errs, "CreationTime")
}
if (es.SizeBytes == 0) != (rs.SizeBytes == 0) {
errs = append(errs, "SizeBytes")
}
// comparing remaining fields for exact match
if es.ReadyToUse != rs.ReadyToUse {
errs = append(errs, "ReadyToUse")
}
if es.SnapshotId != rs.SnapshotId {
errs = append(errs, "SnapshotId")
}
if es.SourceVolumeId != rs.SourceVolumeId {
errs = append(errs, "SourceVolumeId")
}
if len(errs) == 0 {
return nil
}
return fmt.Errorf("mismatch CreateSnapshotResponse in fields: %v", strings.Join(errs, ", "))
}

0 comments on commit 169a85e

Please sign in to comment.