From eedf3782d2da7fd66c265f42b3ee542a9215db32 Mon Sep 17 00:00:00 2001 From: Santosh Pillai Date: Sun, 16 Jan 2022 19:45:53 +0530 Subject: [PATCH] test: add tests for volume group utility Signed-off-by: Santosh Pillai --- pkg/internal/test/mock_exec.go | 24 +++++ pkg/vgmanager/lvm_test.go | 188 +++++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 pkg/internal/test/mock_exec.go create mode 100644 pkg/vgmanager/lvm_test.go diff --git a/pkg/internal/test/mock_exec.go b/pkg/internal/test/mock_exec.go new file mode 100644 index 000000000..7d962d103 --- /dev/null +++ b/pkg/internal/test/mock_exec.go @@ -0,0 +1,24 @@ +package test + +type MockExecutor struct { + MockExecuteCommandWithOutput func(command string, arg ...string) (string, error) + MockExecuteCommandWithOutputAsHost func(command string, arg ...string) (string, error) +} + +// ExecuteCommandWithOutput mocks ExecuteCommandWithOutput +func (e *MockExecutor) ExecuteCommandWithOutput(command string, arg ...string) (string, error) { + if e.MockExecuteCommandWithOutput != nil { + return e.MockExecuteCommandWithOutput(command, arg...) + } + + return "", nil +} + +// ExecuteCommandWithOutputAsHost mocks ExecuteCommandWithOutputAsHost +func (e *MockExecutor) ExecuteCommandWithOutputAsHost(command string, arg ...string) (string, error) { + if e.MockExecuteCommandWithOutputAsHost != nil { + return e.MockExecuteCommandWithOutputAsHost(command, arg...) + } + + return "", nil +} diff --git a/pkg/vgmanager/lvm_test.go b/pkg/vgmanager/lvm_test.go new file mode 100644 index 000000000..6fe4794bb --- /dev/null +++ b/pkg/vgmanager/lvm_test.go @@ -0,0 +1,188 @@ +package vgmanager + +import ( + "fmt" + "strings" + "testing" + + mockExec "github.com/red-hat-storage/lvm-operator/pkg/internal/test" + "github.com/stretchr/testify/assert" +) + +var mockVgsOutput = `{ + "report": [ + { + "vg": [ + {"vg_name":"vg1", "pv_count":"3", "lv_count":"3", "snap_count":"0", "vg_attr":"wz--n-", "vg_size":"<475.94g", "vg_free":"0 "}, + {"vg_name":"vg2", "pv_count":"3", "lv_count":"3", "snap_count":"0", "vg_attr":"wz--n-", "vg_size":"<475.94g", "vg_free":"0 "} + ] + } + ] +}` + +var mockPvsOutputForVG1 = ` +{ + "report": [ + { + "pv": [ + {"pv_name":"/dev/sda", "vg_name":"vg1", "pv_fmt":"lvm2", "pv_attr":"a--", "pv_size":"<475.94g", "pv_free":"0 "}, + {"pv_name":"/dev/sdb", "vg_name":"vg1", "pv_fmt":"lvm2", "pv_attr":"a--", "pv_size":"<475.94g", "pv_free":"0 "}, + {"pv_name":"/dev/sdc", "vg_name":"vg1", "pv_fmt":"lvm2", "pv_attr":"a--", "pv_size":"<475.94g", "pv_free":"0 "} + ] + } + ] +} +` + +var mockPvsOutputForVG2 = ` +{ + "report": [ + { + "pv": [ + {"pv_name":"/dev/sdd", "vg_name":"vg2", "pv_fmt":"lvm2", "pv_attr":"a--", "pv_size":"<475.94g", "pv_free":"0 "}, + {"pv_name":"/dev/sde", "vg_name":"vg2", "pv_fmt":"lvm2", "pv_attr":"a--", "pv_size":"<475.94g", "pv_free":"0 "} + ] + } + ] +} +` + +func TestGetVolumeGroup(t *testing.T) { + tests := []struct { + name string + vgName string + pvCount int + wantErr bool + }{ + {"Invalid volume group name", "invald-vg", 0, true}, + {"Valid volume group name", "vg1", 3, false}, + {"Valid volume group name", "vg2", 2, false}, + } + executor := &mockExec.MockExecutor{ + MockExecuteCommandWithOutputAsHost: func(command string, args ...string) (string, error) { + if args[0] == "vgs" { + return mockVgsOutput, nil + } else if args[0] == "pvs" { + if strings.HasSuffix(args[2], "vg1") { + return mockPvsOutputForVG1, nil + } else if strings.HasSuffix(args[2], "vg2") { + return mockPvsOutputForVG2, nil + } + } + return "", fmt.Errorf("invalid args %q", args[0]) + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + vg, err := GetVolumeGroup(executor, tt.vgName) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.vgName, vg.Name) + assert.Equal(t, tt.pvCount, len(vg.PVs)) + } + }) + } +} + +func TestListVolumeGroup(t *testing.T) { + tests := []struct { + name string + wantErr bool + }{ + {"List all volume groups", false}, + } + executor := &mockExec.MockExecutor{ + MockExecuteCommandWithOutputAsHost: func(command string, args ...string) (string, error) { + if args[0] == "vgs" { + return mockVgsOutput, nil + } else if args[0] == "pvs" { + if strings.HasSuffix(args[2], "vg1") { + return mockPvsOutputForVG1, nil + } else if strings.HasSuffix(args[2], "vg2") { + return mockPvsOutputForVG2, nil + } + } + return "", fmt.Errorf("invalid args %q", args[0]) + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + vgs, err := ListVolumeGroups(executor) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + for _, vg := range vgs { + if vg.Name == "vg1" { + assert.Equal(t, 3, len(vg.PVs)) + } else if vg.Name == "vg2" { + assert.Equal(t, 2, len(vg.PVs)) + } + } + } + }) + } +} + +func TestCreateVolumeGroup(t *testing.T) { + tests := []struct { + name string + volumeGroup *VolumeGroup + pvs []string + wantErr bool + }{ + {"No Volume Group Name", &VolumeGroup{}, []string{}, true}, + {"No Physical Volumes", &VolumeGroup{Name: "vg1"}, []string{}, true}, + {"Volume Group created successfully", &VolumeGroup{Name: "vg1"}, []string{"/dev/sdb"}, false}, + } + + executor := &mockExec.MockExecutor{ + MockExecuteCommandWithOutputAsHost: func(command string, args ...string) (string, error) { + return "", nil + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.volumeGroup.Create(executor, tt.pvs) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} + +func TestExtendVolumeGroup(t *testing.T) { + tests := []struct { + name string + volumeGroup *VolumeGroup + PVs []string + wantErr bool + }{ + {"No PVs are available", &VolumeGroup{Name: "vg1"}, []string{}, true}, + {"New PVs are available", &VolumeGroup{Name: "vg1"}, []string{"/dev/sdb", "/dev/sdc"}, false}, + } + + executor := &mockExec.MockExecutor{ + MockExecuteCommandWithOutputAsHost: func(command string, args ...string) (string, error) { + return "", nil + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.volumeGroup.Extend(executor, tt.PVs) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +}