Skip to content

Commit 3773aa9

Browse files
committed
test(kubevirt): add tests for vm_lifecycle tool
Add tests for the vm_lifecycle tool Code was assisted by Cursor AI. Signed-off-by: Karel Simon <ksimon@redhat.com>
1 parent 88ced6a commit 3773aa9

File tree

3 files changed

+581
-0
lines changed

3 files changed

+581
-0
lines changed

pkg/kubevirt/vm_test.go

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
package kubevirt
2+
3+
import (
4+
"context"
5+
"strings"
6+
"testing"
7+
8+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
9+
"k8s.io/apimachinery/pkg/runtime"
10+
"k8s.io/client-go/dynamic/fake"
11+
)
12+
13+
// createTestVM creates a test VirtualMachine with the given name, namespace, and runStrategy
14+
func createTestVM(name, namespace string, runStrategy RunStrategy) *unstructured.Unstructured {
15+
vm := &unstructured.Unstructured{}
16+
vm.SetUnstructuredContent(map[string]interface{}{
17+
"apiVersion": "kubevirt.io/v1",
18+
"kind": "VirtualMachine",
19+
"metadata": map[string]interface{}{
20+
"name": name,
21+
"namespace": namespace,
22+
},
23+
"spec": map[string]interface{}{
24+
"runStrategy": string(runStrategy),
25+
},
26+
})
27+
return vm
28+
}
29+
30+
func TestStartVM(t *testing.T) {
31+
tests := []struct {
32+
name string
33+
initialVM *unstructured.Unstructured
34+
wantStarted bool
35+
wantError bool
36+
errorContains string
37+
}{
38+
{
39+
name: "Start VM that is Halted",
40+
initialVM: createTestVM("test-vm", "default", RunStrategyHalted),
41+
wantStarted: true,
42+
wantError: false,
43+
},
44+
{
45+
name: "Start VM that is already running (Always)",
46+
initialVM: createTestVM("test-vm", "default", RunStrategyAlways),
47+
wantStarted: false,
48+
wantError: false,
49+
},
50+
{
51+
name: "Start VM without runStrategy",
52+
initialVM: &unstructured.Unstructured{
53+
Object: map[string]interface{}{
54+
"apiVersion": "kubevirt.io/v1",
55+
"kind": "VirtualMachine",
56+
"metadata": map[string]interface{}{
57+
"name": "test-vm",
58+
"namespace": "default",
59+
},
60+
"spec": map[string]interface{}{},
61+
},
62+
},
63+
wantStarted: true,
64+
wantError: false,
65+
},
66+
}
67+
68+
for _, tt := range tests {
69+
t.Run(tt.name, func(t *testing.T) {
70+
scheme := runtime.NewScheme()
71+
client := fake.NewSimpleDynamicClient(scheme, tt.initialVM)
72+
ctx := context.Background()
73+
74+
vm, wasStarted, err := StartVM(ctx, client, tt.initialVM.GetNamespace(), tt.initialVM.GetName())
75+
76+
if tt.wantError {
77+
if err == nil {
78+
t.Errorf("Expected error, got nil")
79+
return
80+
}
81+
if tt.errorContains != "" && !strings.Contains(err.Error(), tt.errorContains) {
82+
t.Errorf("Error = %v, want to contain %q", err, tt.errorContains)
83+
}
84+
return
85+
}
86+
87+
if err != nil {
88+
t.Errorf("Unexpected error: %v", err)
89+
return
90+
}
91+
92+
if vm == nil {
93+
t.Errorf("Expected non-nil VM, got nil")
94+
return
95+
}
96+
97+
if wasStarted != tt.wantStarted {
98+
t.Errorf("wasStarted = %v, want %v", wasStarted, tt.wantStarted)
99+
}
100+
101+
// Verify the VM's runStrategy is Always
102+
strategy, found, err := GetVMRunStrategy(vm)
103+
if err != nil {
104+
t.Errorf("Failed to get runStrategy: %v", err)
105+
return
106+
}
107+
if !found {
108+
t.Errorf("runStrategy not found")
109+
return
110+
}
111+
if strategy != RunStrategyAlways {
112+
t.Errorf("Strategy = %q, want %q", strategy, RunStrategyAlways)
113+
}
114+
})
115+
}
116+
}
117+
118+
func TestStartVMNotFound(t *testing.T) {
119+
scheme := runtime.NewScheme()
120+
client := fake.NewSimpleDynamicClient(scheme)
121+
ctx := context.Background()
122+
123+
_, _, err := StartVM(ctx, client, "default", "non-existent-vm")
124+
if err == nil {
125+
t.Errorf("Expected error for non-existent VM, got nil")
126+
return
127+
}
128+
if !strings.Contains(err.Error(), "failed to get VirtualMachine") {
129+
t.Errorf("Error = %v, want to contain 'failed to get VirtualMachine'", err)
130+
}
131+
}
132+
133+
func TestStopVM(t *testing.T) {
134+
tests := []struct {
135+
name string
136+
initialVM *unstructured.Unstructured
137+
wantStopped bool
138+
wantError bool
139+
errorContains string
140+
}{
141+
{
142+
name: "Stop VM that is running (Always)",
143+
initialVM: createTestVM("test-vm", "default", RunStrategyAlways),
144+
wantStopped: true,
145+
wantError: false,
146+
},
147+
{
148+
name: "Stop VM that is already stopped (Halted)",
149+
initialVM: createTestVM("test-vm", "default", RunStrategyHalted),
150+
wantStopped: false,
151+
wantError: false,
152+
},
153+
{
154+
name: "Stop VM without runStrategy",
155+
initialVM: &unstructured.Unstructured{
156+
Object: map[string]interface{}{
157+
"apiVersion": "kubevirt.io/v1",
158+
"kind": "VirtualMachine",
159+
"metadata": map[string]interface{}{
160+
"name": "test-vm",
161+
"namespace": "default",
162+
},
163+
"spec": map[string]interface{}{},
164+
},
165+
},
166+
wantStopped: true,
167+
wantError: false,
168+
},
169+
}
170+
171+
for _, tt := range tests {
172+
t.Run(tt.name, func(t *testing.T) {
173+
scheme := runtime.NewScheme()
174+
client := fake.NewSimpleDynamicClient(scheme, tt.initialVM)
175+
ctx := context.Background()
176+
177+
vm, wasStopped, err := StopVM(ctx, client, tt.initialVM.GetNamespace(), tt.initialVM.GetName())
178+
179+
if tt.wantError {
180+
if err == nil {
181+
t.Errorf("Expected error, got nil")
182+
return
183+
}
184+
if tt.errorContains != "" && !strings.Contains(err.Error(), tt.errorContains) {
185+
t.Errorf("Error = %v, want to contain %q", err, tt.errorContains)
186+
}
187+
return
188+
}
189+
190+
if err != nil {
191+
t.Errorf("Unexpected error: %v", err)
192+
return
193+
}
194+
195+
if vm == nil {
196+
t.Errorf("Expected non-nil VM, got nil")
197+
return
198+
}
199+
200+
if wasStopped != tt.wantStopped {
201+
t.Errorf("wasStopped = %v, want %v", wasStopped, tt.wantStopped)
202+
}
203+
204+
// Verify the VM's runStrategy is Halted
205+
strategy, found, err := GetVMRunStrategy(vm)
206+
if err != nil {
207+
t.Errorf("Failed to get runStrategy: %v", err)
208+
return
209+
}
210+
if !found {
211+
t.Errorf("runStrategy not found")
212+
return
213+
}
214+
if strategy != RunStrategyHalted {
215+
t.Errorf("Strategy = %q, want %q", strategy, RunStrategyHalted)
216+
}
217+
})
218+
}
219+
}
220+
221+
func TestStopVMNotFound(t *testing.T) {
222+
scheme := runtime.NewScheme()
223+
client := fake.NewSimpleDynamicClient(scheme)
224+
ctx := context.Background()
225+
226+
_, _, err := StopVM(ctx, client, "default", "non-existent-vm")
227+
if err == nil {
228+
t.Errorf("Expected error for non-existent VM, got nil")
229+
return
230+
}
231+
if !strings.Contains(err.Error(), "failed to get VirtualMachine") {
232+
t.Errorf("Error = %v, want to contain 'failed to get VirtualMachine'", err)
233+
}
234+
}
235+
236+
func TestRestartVM(t *testing.T) {
237+
tests := []struct {
238+
name string
239+
initialVM *unstructured.Unstructured
240+
wantError bool
241+
errorContains string
242+
}{
243+
{
244+
name: "Restart VM that is running (Always)",
245+
initialVM: createTestVM("test-vm", "default", RunStrategyAlways),
246+
wantError: false,
247+
},
248+
{
249+
name: "Restart VM that is stopped (Halted)",
250+
initialVM: createTestVM("test-vm", "default", RunStrategyHalted),
251+
wantError: false,
252+
},
253+
{
254+
name: "Restart VM without runStrategy",
255+
initialVM: &unstructured.Unstructured{
256+
Object: map[string]interface{}{
257+
"apiVersion": "kubevirt.io/v1",
258+
"kind": "VirtualMachine",
259+
"metadata": map[string]interface{}{
260+
"name": "test-vm",
261+
"namespace": "default",
262+
},
263+
"spec": map[string]interface{}{},
264+
},
265+
},
266+
wantError: false,
267+
},
268+
}
269+
270+
for _, tt := range tests {
271+
t.Run(tt.name, func(t *testing.T) {
272+
scheme := runtime.NewScheme()
273+
client := fake.NewSimpleDynamicClient(scheme, tt.initialVM)
274+
ctx := context.Background()
275+
276+
vm, err := RestartVM(ctx, client, tt.initialVM.GetNamespace(), tt.initialVM.GetName())
277+
278+
if tt.wantError {
279+
if err == nil {
280+
t.Errorf("Expected error, got nil")
281+
return
282+
}
283+
if tt.errorContains != "" && !strings.Contains(err.Error(), tt.errorContains) {
284+
t.Errorf("Error = %v, want to contain %q", err, tt.errorContains)
285+
}
286+
return
287+
}
288+
289+
if err != nil {
290+
t.Errorf("Unexpected error: %v", err)
291+
return
292+
}
293+
294+
if vm == nil {
295+
t.Errorf("Expected non-nil VM, got nil")
296+
return
297+
}
298+
299+
// Verify the VM's runStrategy is Always (after restart)
300+
strategy, found, err := GetVMRunStrategy(vm)
301+
if err != nil {
302+
t.Errorf("Failed to get runStrategy: %v", err)
303+
return
304+
}
305+
if !found {
306+
t.Errorf("runStrategy not found")
307+
return
308+
}
309+
if strategy != RunStrategyAlways {
310+
t.Errorf("Strategy = %q, want %q after restart", strategy, RunStrategyAlways)
311+
}
312+
})
313+
}
314+
}
315+
316+
func TestRestartVMNotFound(t *testing.T) {
317+
scheme := runtime.NewScheme()
318+
client := fake.NewSimpleDynamicClient(scheme)
319+
ctx := context.Background()
320+
321+
_, err := RestartVM(ctx, client, "default", "non-existent-vm")
322+
if err == nil {
323+
t.Errorf("Expected error for non-existent VM, got nil")
324+
return
325+
}
326+
if !strings.Contains(err.Error(), "failed to get VirtualMachine") {
327+
t.Errorf("Error = %v, want to contain 'failed to get VirtualMachine'", err)
328+
}
329+
}

0 commit comments

Comments
 (0)