service: add unit tests for LCOW v2 shim service layer#2649
Conversation
72ac4ca to
c703ec9
Compare
c703ec9 to
d0fa692
Compare
6612341 to
5315f01
Compare
affc35e to
0f930d4
Compare
2729c12 to
14234dd
Compare
Defines a narrow vmController interface in the service package and threads it through Service in place of the concrete *vm.Controller field. Production passes vm.New(); tests pass a generated gomock. The interface includes the methods pod.New requires (Guest, SCSIController, VPCIController, Plan9Controller, NetworkController) so the same field satisfies both Service's direct calls and pod.New's narrower interface via Go structural typing. Tests cover the production failure paths through the service RPC surface: Sandbox API (23 tests): - duplicate Create rejection, missing config.json, VM create / start failure - sandbox-id mismatch guards - stop success / failure / idempotency - wait clean / error / wait-failure / exit-status-failure exits - status mapping for every state, ping not-implemented - shutdown idempotency, running-VM termination, terminate-error swallowed - metrics success and stats failure Shimdiag API (10 tests): - pid passthrough, exec-in-host success / failure - tasks / share / stacks state guards - share missing host-path validation - stacks dump-failure and success Task API (16 tests): - consolidated state-guard and unknown-container guard tables - not-implemented surfaces, shutdown no-op - update validation: nil resources rejected, dispatch by resource type, per-resource failure surfaces - enrichNotFoundError pass-through and ErrNotFound preservation Mocks committed at mocks/mock_service.go with the standard build tag (windows && lcow). Standardising mock generation across controllers is tracked in microsoft#2707. Signed-off-by: Shreyansh Sancheti <shsancheti@microsoft.com>
…rt grouping Signed-off-by: Shreyansh Sancheti <shsancheti@microsoft.com>
…empDir() for missing-path test Signed-off-by: Shreyansh Sancheti <shsancheti@microsoft.com>
14234dd to
055c422
Compare
rawahars
left a comment
There was a problem hiding this comment.
service_task_internal_test.go does not include tests for-
createInternal
startInternal
stateInternal
deleteInternal
pidsInternal
killInternal
execInternal
resizePtyInternal
closeIOInternal
waitInternal
statsInternal
| } | ||
| } | ||
|
|
||
| // ─── diagShareInternal tests ────────────────────────────────────────────── |
There was a problem hiding this comment.
Add a success case as well. In the mock request, ensure that the params received by the controller are same as what were set in the test.
| } | ||
| } | ||
|
|
||
| // ─── diagTasksInternal tests ────────────────────────────────────────────── |
There was a problem hiding this comment.
Add a success case as well. In the mock request, ensure that the params received by the controller are same as what were set in the test.
| svc, mockCtrl := newTestService(t) | ||
|
|
||
| req := &shimdiag.ExecProcessRequest{Args: []string{"/bin/ls"}, Workdir: "/"} | ||
| mockCtrl.EXPECT().ExecIntoHost(gomock.Any(), req).Return(42, nil) |
There was a problem hiding this comment.
Can you verify in this mock request that the params received by the controller are same as the ones set in test?
| } | ||
| } | ||
|
|
||
| // ─── createSandboxInternal tests ────────────────────────────────────────── |
There was a problem hiding this comment.
Add a success case as well. In the mock request, ensure that the params received by the controller are same as what were set in the test.
| // over the concrete VM controller, so that the vmController interface only | ||
| // needs to declare the methods the service itself calls; the VM guest and | ||
| // device accessors that pod.New consumes are not surfaced on that interface. | ||
| newPod func(podID, networkNamespaceID string) *pod.Controller |
There was a problem hiding this comment.
Please don't introduce new abstractions in service struct. Please use pod.New itself.
|
|
||
| // NewService creates a new instance of the Service with the shared state. | ||
| func NewService(ctx context.Context, eventsPublisher shim.Publisher, sd shutdown.Service) *Service { | ||
| vmc := vm.New() |
There was a problem hiding this comment.
Why move this outside the struct?
Addresses review feedback (rawahars): createSandboxInternal had only error-path coverage (duplicate, missing config.json, CreateVM failure). Adds a happy-path test that asserts the CreateOptions forwarded to vmController.CreateVM are derived from the request (ID, Owner, BundlePath, parsed SandboxSpec) instead of matching gomock.Any(), and that sandboxID is recorded only after CreateVM succeeds. Signed-off-by: Shreyansh Sancheti <shsancheti@microsoft.com>
Introduce a consumer-side containerController interface that *linuxcontainer.Controller satisfies as-is: the child getters keep returning the concrete *process.Controller, so the production controller needs no adapter or wrapper. Make getContainerController an injectable package-level function variable so unit tests can substitute a mock container controller without building a real pod/container chain. Add success-path tests for the one-hop delegation methods (Pids, Stats, DeleteProcess exec, Kill single-container, Update container, Start init), asserting the forwarded arguments and response mapping. Methods that take a second hop through the process controller are intentionally left to functional coverage. Signed-off-by: Shreyansh Sancheti <shsancheti@microsoft.com>
f23d623 to
d53820f
Compare
|
Added success-path unit tests for the one-hop container-delegation methods ( On why the rest don't get success-path unit tests: |
Adds unit tests for the LCOW v2 shim service layer. The service orchestrates sandbox lifecycle (create / start / stop / wait / shutdown / status / metrics) by delegating to
vm.Controller; without these tests every code change had to be validated against a live HCS environment.Design
The
Servicestruct holds a singlevmControllerinterface field (defined intypes.go). Production passes*vm.Controller; tests pass a generated mock. The interface is a superset that includes the methodspod.Newneeds (Guest(),SCSIController(),Plan9Controller(),NetworkController()etc.) so the same field satisfies bothService's direct calls andpod.New's narrower interface via Go structural typing - no concrete-pointer leakage. This mirrors the mergedinternal/controller/podpattern.Coverage
49 tests across three files matching the production layout:
service_sandbox_internal_test.go(23): duplicate sandbox rejection, missingconfig.json, VM create / start failure, sandbox-id mismatch guards, stop success / failure / idempotency, wait clean / error / wait-failure / exit-status-failure exits, status mapping for every state, ping not-implemented, shutdown idempotency / running-VM termination / terminate-error swallowed, metrics success and stats failure.service_shimdiag_internal_test.go(10): pid passthrough, exec-in-host success / failure, tasks / share / stacks state guards, share missing host-path validation, stacks dump-failure and success.service_task_internal_test.go(16): consolidated state-guard and unknown-container guard tables, not-implemented surfaces, shutdown no-op, update validation (nil resources rejected, dispatch by resource type, per-resource failure surfaces),enrichNotFoundErrorpass-through andErrNotFoundpreservation.Out of scope
CreateSandbox->BuildSandboxConfig->CreateVMpath is exercised byinternal/builder/vm/lcow/tests and thetest/parity/vm/parity suite; the service-level surface is the orchestration logic only.StartSandboxpath reads boot files from disk; belongs infunctionaltagged tests.Mocks
mocks/mock_service.gois checked in. Standardising mock generation (directive in test file + CI drift validation) is tracked in #2707.