Skip to content

Commit 09f8fa8

Browse files
author
Shreyansh Sancheti
committed
controller/vm: add unit tests for VM Controller state machine
Add 42 test cases for the VM Controller covering state transitions, guard checks, idempotency, and method behavior. Change Manager.uvm and Manager.guest to interface types to enable mock injection. Tests: TerminateVM transitions, ExecIntoHost, DumpStacks, StartTime, ExitStatus, StartVM idempotency, State.String(), and guard checks for all state-dependent methods. Generated mocks for LifetimeManager, GuestManager, and GuestDefinedCapabilities using mockgen. Signed-off-by: Shreyansh Sancheti <shreyanshjain7174@gmail.com> Signed-off-by: Shreyansh Sancheti <shsancheti@microsoft.com>
1 parent 5a0252a commit 09f8fa8

File tree

10 files changed

+1286
-4
lines changed

10 files changed

+1286
-4
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//go:build windows
2+
3+
package vm
4+
5+
import (
6+
"github.com/Microsoft/hcsshim/internal/vm/vmmanager"
7+
)
8+
9+
// SetManagerForTest configures a Manager with injected dependencies for testing.
10+
// This is only available in test builds.
11+
//
12+
// MUST be called during test setup before any concurrent operations on the Manager.
13+
//
14+
// Note: logOutputDone is initialized by NewController() and is NOT reset here.
15+
// Tests that exercise Wait() in Running/Terminated state must close the channel
16+
// manually or the Wait call will block on the logOutputDone select.
17+
func (c *Manager) SetManagerForTest(uvm vmmanager.LifetimeManager, guest GuestManager, state State) {
18+
c.uvm = uvm
19+
c.guest = guest
20+
c.vmState = state
21+
}

internal/controller/vm/interface.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
package vm
44

5+
//go:generate go tool mockgen -source=interface.go -build_constraint=windows -package=mockvmcontroller -destination=../../test/mock/vmcontroller/mock_interface.go
6+
57
import (
68
"context"
79
"time"
@@ -15,9 +17,18 @@ import (
1517
"github.com/Microsoft/go-winio/pkg/guid"
1618
)
1719

20+
// GuestManager defines the guest operations required by the VM Controller.
21+
// It combines the core guest manager, security policy, and HvSocket interfaces
22+
// from the guestmanager package into a single interface for dependency injection.
23+
type GuestManager interface {
24+
guestmanager.Manager
25+
guestmanager.SecurityPolicyManager
26+
guestmanager.HVSocketManager
27+
}
28+
1829
type Controller interface {
1930
// Guest returns the guest manager instance for this VM.
20-
Guest() *guestmanager.Guest
31+
Guest() GuestManager
2132

2233
// State returns the current VM state.
2334
State() State
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//go:build windows
2+
3+
package vm_test
4+
5+
import (
6+
"testing"
7+
8+
vm "github.com/Microsoft/hcsshim/internal/controller/vm"
9+
)
10+
11+
func TestStateString(t *testing.T) {
12+
tests := []struct {
13+
state vm.State
14+
want string
15+
}{
16+
{vm.StateNotCreated, "NotCreated"},
17+
{vm.StateCreated, "Created"},
18+
{vm.StateRunning, "Running"},
19+
{vm.StateTerminated, "Terminated"},
20+
{vm.StateInvalid, "Invalid"},
21+
{vm.State(99), "Unknown"},
22+
{vm.State(-1), "Unknown"},
23+
}
24+
25+
for _, tt := range tests {
26+
t.Run(tt.want, func(t *testing.T) {
27+
t.Parallel()
28+
if got := tt.state.String(); got != tt.want {
29+
t.Errorf("State(%d).String() = %q, want %q", tt.state, got, tt.want)
30+
}
31+
})
32+
}
33+
}

internal/controller/vm/vm.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ import (
3333
// and its associated resources.
3434
type Manager struct {
3535
vmID string
36-
uvm *vmmanager.UtilityVM
37-
guest *guestmanager.Guest
36+
uvm vmmanager.LifetimeManager
37+
guest GuestManager
3838

3939
// vmState tracks the current state of the VM lifecycle.
4040
// Access must be guarded by mu.
@@ -70,7 +70,7 @@ func NewController() *Manager {
7070

7171
// Guest returns the guest manager instance for this VM.
7272
// The guest manager provides access to guest-host communication.
73-
func (c *Manager) Guest() *guestmanager.Guest {
73+
func (c *Manager) Guest() GuestManager {
7474
return c.guest
7575
}
7676

0 commit comments

Comments
 (0)