Skip to content

Commit 169a85e

Browse files
committed
test: create / delete snapshot unit tests
1 parent 76f4841 commit 169a85e

File tree

1 file changed

+182
-0
lines changed

1 file changed

+182
-0
lines changed

pkg/nfs/controllerserver_test.go

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"golang.org/x/net/context"
3434
"google.golang.org/grpc/codes"
3535
"google.golang.org/grpc/status"
36+
"google.golang.org/protobuf/types/known/timestamppb"
3637
mount "k8s.io/mount-utils"
3738
)
3839

@@ -827,3 +828,184 @@ func TestCopyVolume(t *testing.T) {
827828
})
828829
}
829830
}
831+
832+
func TestCreateSnapshot(t *testing.T) {
833+
cases := []struct {
834+
desc string
835+
req *csi.CreateSnapshotRequest
836+
expResp *csi.CreateSnapshotResponse
837+
expectErr bool
838+
prepare func() error
839+
cleanup func() error
840+
}{
841+
{
842+
desc: "create snapshot with valid request",
843+
req: &csi.CreateSnapshotRequest{
844+
SourceVolumeId: "nfs-server.default.svc.cluster.local#share#subdir#src-pv-name",
845+
Name: "snapshot-name",
846+
},
847+
expResp: &csi.CreateSnapshotResponse{
848+
Snapshot: &csi.Snapshot{
849+
SnapshotId: "nfs-server.default.svc.cluster.local#share#snapshot-name#snapshot-name#src-pv-name",
850+
SourceVolumeId: "nfs-server.default.svc.cluster.local#share#subdir#src-pv-name",
851+
ReadyToUse: true,
852+
SizeBytes: 1, // doesn't match exact size, just denotes non-zero size expected
853+
CreationTime: timestamppb.Now(), // doesn't match exact timestamp, just denotes non-zero ts expected
854+
},
855+
},
856+
prepare: func() error { return os.MkdirAll("/tmp/src-pv-name/subdir", 0777) },
857+
cleanup: func() error { return os.RemoveAll("/tmp/src-pv-name") },
858+
},
859+
{
860+
desc: "create snapshot from nonexisting volume",
861+
req: &csi.CreateSnapshotRequest{
862+
SourceVolumeId: "nfs-server.default.svc.cluster.local#share#subdir#src-pv-name",
863+
Name: "snapshot-name",
864+
},
865+
expectErr: true,
866+
},
867+
}
868+
for _, test := range cases {
869+
t.Run(test.desc, func(t *testing.T) {
870+
if test.prepare != nil {
871+
if err := test.prepare(); err != nil {
872+
t.Errorf(`[test: %s] prepare failed: "%v"`, test.desc, err)
873+
}
874+
}
875+
cs := initTestController(t)
876+
resp, err := cs.CreateSnapshot(context.TODO(), test.req)
877+
if (err == nil) == test.expectErr {
878+
t.Errorf(`[test: %s] Error expectation mismatch, expected error: "%v", received: %q`, test.desc, test.expectErr, err)
879+
}
880+
if err := matchCreateSnapshotResponse(test.expResp, resp); err != nil {
881+
t.Errorf("[test: %s] failed %q: got resp %+v, expected %+v", test.desc, err, resp, test.expResp)
882+
}
883+
if test.cleanup != nil {
884+
if err := test.cleanup(); err != nil {
885+
t.Errorf(`[test: %s] cleanup failed: "%v"`, test.desc, err)
886+
}
887+
}
888+
})
889+
}
890+
}
891+
892+
func TestDeleteSnapshot(t *testing.T) {
893+
cases := []struct {
894+
desc string
895+
req *csi.DeleteSnapshotRequest
896+
expResp *csi.DeleteSnapshotResponse
897+
expectErr bool
898+
prepare func() error
899+
cleanup func() error
900+
}{
901+
{
902+
desc: "delete valid snapshot",
903+
req: &csi.DeleteSnapshotRequest{
904+
SnapshotId: "nfs-server.default.svc.cluster.local#share#snapshot-name#snapshot-name#src-pv-name",
905+
},
906+
expResp: &csi.DeleteSnapshotResponse{},
907+
prepare: func() error {
908+
if err := os.MkdirAll("/tmp/snapshot-name/snapshot-name/", 0777); err != nil {
909+
return err
910+
}
911+
f, err := os.OpenFile("/tmp/snapshot-name/snapshot-name/src-pv-name.tar.gz", os.O_CREATE, 0777)
912+
if err != nil {
913+
return err
914+
}
915+
return f.Close()
916+
},
917+
cleanup: func() error { return os.RemoveAll("/tmp/snapshot-name") },
918+
},
919+
{
920+
desc: "delete nonexisting snapshot",
921+
req: &csi.DeleteSnapshotRequest{
922+
SnapshotId: "nfs-server.default.svc.cluster.local#share#snapshot-name#snapshot-name#src-pv-name",
923+
},
924+
expResp: &csi.DeleteSnapshotResponse{},
925+
},
926+
{
927+
desc: "delete snapshot with improper id",
928+
req: &csi.DeleteSnapshotRequest{
929+
SnapshotId: "incorrect-snap-id",
930+
},
931+
expResp: &csi.DeleteSnapshotResponse{},
932+
},
933+
{
934+
desc: "delete valid snapshot with mount options",
935+
req: &csi.DeleteSnapshotRequest{
936+
SnapshotId: "nfs-server.default.svc.cluster.local#share#snapshot-name#snapshot-name#src-pv-name",
937+
Secrets: map[string]string{"mountoptions": "nfsvers=4.1"},
938+
},
939+
expResp: &csi.DeleteSnapshotResponse{},
940+
prepare: func() error {
941+
if err := os.MkdirAll("/tmp/snapshot-name/snapshot-name/", 0777); err != nil {
942+
return err
943+
}
944+
f, err := os.OpenFile("/tmp/snapshot-name/snapshot-name/src-pv-name.tar.gz", os.O_CREATE, 0777)
945+
if err != nil {
946+
return err
947+
}
948+
return f.Close()
949+
},
950+
cleanup: func() error { return os.RemoveAll("/tmp/snapshot-name") },
951+
},
952+
}
953+
for _, test := range cases {
954+
t.Run(test.desc, func(t *testing.T) {
955+
if test.prepare != nil {
956+
if err := test.prepare(); err != nil {
957+
t.Errorf(`[test: %s] prepare failed: "%v"`, test.desc, err)
958+
}
959+
}
960+
cs := initTestController(t)
961+
resp, err := cs.DeleteSnapshot(context.TODO(), test.req)
962+
if (err == nil) == test.expectErr {
963+
t.Errorf(`[test: %s] Error expectation mismatch, expected error: "%v", received: %q`, test.desc, test.expectErr, err)
964+
}
965+
if !reflect.DeepEqual(test.expResp, resp) {
966+
t.Errorf("[test: %s] got resp %+v, expected %+v", test.desc, resp, test.expResp)
967+
}
968+
if test.cleanup != nil {
969+
if err := test.cleanup(); err != nil {
970+
t.Errorf(`[test: %s] cleanup failed: "%v"`, test.desc, err)
971+
}
972+
}
973+
})
974+
}
975+
}
976+
977+
func matchCreateSnapshotResponse(e, r *csi.CreateSnapshotResponse) error {
978+
if e == nil && r == nil {
979+
return nil
980+
}
981+
if e == nil || e.Snapshot == nil {
982+
return fmt.Errorf("expected nil response")
983+
}
984+
if r == nil || r.Snapshot == nil {
985+
return fmt.Errorf("unexpected nil response")
986+
}
987+
es, rs := e.Snapshot, r.Snapshot
988+
989+
var errs []string
990+
// comparing ts and size just for presence, not the exact value
991+
if es.CreationTime.IsValid() != rs.CreationTime.IsValid() {
992+
errs = append(errs, "CreationTime")
993+
}
994+
if (es.SizeBytes == 0) != (rs.SizeBytes == 0) {
995+
errs = append(errs, "SizeBytes")
996+
}
997+
// comparing remaining fields for exact match
998+
if es.ReadyToUse != rs.ReadyToUse {
999+
errs = append(errs, "ReadyToUse")
1000+
}
1001+
if es.SnapshotId != rs.SnapshotId {
1002+
errs = append(errs, "SnapshotId")
1003+
}
1004+
if es.SourceVolumeId != rs.SourceVolumeId {
1005+
errs = append(errs, "SourceVolumeId")
1006+
}
1007+
if len(errs) == 0 {
1008+
return nil
1009+
}
1010+
return fmt.Errorf("mismatch CreateSnapshotResponse in fields: %v", strings.Join(errs, ", "))
1011+
}

0 commit comments

Comments
 (0)