Skip to content

controller/vm: add unit tests for VM Controller state machine#2634

Open
shreyanshjain7174 wants to merge 1 commit intomicrosoft:mainfrom
shreyanshjain7174:controller/vm-unit-tests
Open

controller/vm: add unit tests for VM Controller state machine#2634
shreyanshjain7174 wants to merge 1 commit intomicrosoft:mainfrom
shreyanshjain7174:controller/vm-unit-tests

Conversation

@shreyanshjain7174
Copy link
Copy Markdown
Contributor

@shreyanshjain7174 shreyanshjain7174 commented Mar 18, 2026

Depends on #2627 — must merge first.

Adds unit tests for the VM Controller state machine (internal/controller/vm/). To make the Manager testable, two field types are changed to their existing interfaces (vmmanager.LifetimeManager, combined GuestManager). Mocks are generated with mockgen following the internal/windows/mock/ pattern.

Tests are biased toward production failure paths — resource cleanup, state corruption, and half-started scenarios — rather than guard-check permutations.

30 test cases covering: TerminateVM transitions (idempotency, Created/Running→Terminated, Close fail→Invalid, Invalid recovery, Terminate() error swallowed with Close still called, CloseConnection() error swallowed with Close still called), CreateVM duplicate-call rejection, StartVM failure paths (uvm.Start fails→Invalid, listener/connection failure→Invalid, idempotency when already Running, wrong-state rejection), ExecIntoHost (terminal+stderr precondition, success, exec error), DumpStacks (supported, not supported, dump error), StartTime/ExitStatus for relevant states, representative guard checks (one per method for realistic wrong-state calls), and State.String() for all values. All tests run without admin or HCS.

@shreyanshjain7174 shreyanshjain7174 force-pushed the controller/vm-unit-tests branch from eeccba4 to 687d39e Compare March 20, 2026 06:32
@shreyanshjain7174 shreyanshjain7174 force-pushed the controller/vm-unit-tests branch from 687d39e to ef82816 Compare March 20, 2026 06:53
@shreyanshjain7174 shreyanshjain7174 marked this pull request as ready for review March 20, 2026 07:13
@shreyanshjain7174 shreyanshjain7174 requested a review from a team as a code owner March 20, 2026 07:13
@shreyanshjain7174 shreyanshjain7174 force-pushed the controller/vm-unit-tests branch 3 times, most recently from e8cacd2 to 4718b32 Compare March 24, 2026 14:28
@shreyanshjain7174 shreyanshjain7174 force-pushed the controller/vm-unit-tests branch from 4718b32 to 09f8fa8 Compare March 30, 2026 09:25
@shreyanshjain7174 shreyanshjain7174 force-pushed the controller/vm-unit-tests branch 2 times, most recently from e179fe0 to aba0d5f Compare April 6, 2026 11:23
@shreyanshjain7174 shreyanshjain7174 force-pushed the controller/vm-unit-tests branch 4 times, most recently from 3d5fad6 to fbae1c6 Compare April 29, 2026 05:22
@shreyanshjain7174 shreyanshjain7174 force-pushed the controller/vm-unit-tests branch 2 times, most recently from 35ea6c5 to a470ed1 Compare April 29, 2026 18:05
Defines per-platform vmLifetime and guestManager seam interfaces over
*vmmanager.UtilityVM and *guestmanager.Guest. Each interface is a superset
of the methods Controller invokes directly plus the device methods consumed
by the wired-in sub-controllers (vpci/network/plan9/scsi). *vmmanager and
*guestmanager satisfy these via Go structural typing; no concrete sister
fields needed.

The per-platform split is necessary because:
  - AddPlan9 / RemovePlan9 are LCOW-only on *vmmanager.UtilityVM.
  - Guest network signatures differ across LCOW and WCOW.
  - vPCI guest and Plan9 guest methods are LCOW-only.
  - UpdateHvSocketAddress is WCOW-only.

Guest() uses a type assertion to preserve its concrete return type.

30 tests covering:

Idempotency (3): duplicate StartVM no-op, TerminateVM from Terminated
  and NotCreated.

State guards (8): StartVM rejects NotCreated/Terminated/Invalid,
  ExecIntoHost rejects Terminated, terminal+stderr input validation,
  Update methods reject non-Running (4 subtests), Stats rejects
  Terminated, Wait rejects NotCreated, DumpStacks rejects Terminated,
  UpdateCPUGroup rejects empty ID.

TerminateVM cleanup chain (6): full Terminate->CloseConnection->Close
  ordering, guest close failure swallowed, uvm.Terminate failure
  swallowed, uvm.Close failure -> StateInvalid, recovery from Invalid,
  retry failure stays Invalid.

Error propagation (4): ExecIntoHost guest error, DumpStacks guest error,
  UpdatePolicyFragment guest error, ExitStatus not-terminated error.

API delegation (4): ExecIntoHost exit code forwarding, DumpStacks
  with and without capability, ExitStatus value assembly.

Wait + background goroutine (5): Wait from Terminated with log drain,
  Wait context cancelled during log drain, Wait Running happy path,
  waitForVMExit Running->Terminated transition, waitForVMExit
  overwrites Invalid->Terminated (pins current behaviour).

Mocks generated per-platform (mocks/mock_lcow_vm.go, mock_wcow_vm.go)
with matching //go:build constraints.

Signed-off-by: Shreyansh Sancheti <shsancheti@microsoft.com>
@shreyanshjain7174 shreyanshjain7174 force-pushed the controller/vm-unit-tests branch from a470ed1 to 1611cc8 Compare April 30, 2026 05:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant