test(grpc): TypeScript wire-level contract suite + codecov integration coverage - #58
Conversation
An off-BEAM client can send any integer in an enum field; protobuf decodes it verbatim and instance_type/1 / arch/1 had no clause for it, so the promised INVALID_ARGUMENT surfaced as an INTERNAL crash.
State.stop/1 only flipped the gen_statem to :stopping -- a stub state whose teardown nobody performed, so the guest kept running and GetVm resolved it forever. Route StopVm through a new Hyper.stop_vm/1 that resolves the VM's supervisor from the routing registry and terminates it on the owning node via Hyper.Node.stop_image_vm/1.
# Conflicts: # .github/workflows/ci.yml # codecov.yml
❌ 1 Tests Failed:
View the full list of 1 ❄️ flaky test(s)
To view more test analytics, go to the Test Analytics Dashboard |
Test Results 4 files + 1 163 suites +4 2m 4s ⏱️ -28s For more details on these failures, see this check. Results for commit 53864ed. ± Comparison against base commit ef7243a. ♻️ This comment has been updated with latest results. |
Final-review wave: the finally-block StopVm no longer masks the try block's original failure when the VM is already gone; npm output streams line-by-line instead of buffering until exit; the wrapper's timeout reflects its real 25-minute ceiling and the CI job budget gets headroom above the sum of its parts.
|
Status: branch is review-complete and ready to merge on its own scope. The integration job's remaining red is main's new metering assertion (vm_lifecycle_test.exs:66): a pre-existing Meter blind spot — a VM living under the 1s sample interval never writes a usage row because the first Accumulator observation only sets the baseline. This suite exposes it by warming the alpine image cache (the VM's whole lifecycle drops to ~1s). Being fixed separately per Marko. The integration coverage upload step (flag |
Summary
A TypeScript integration suite (
test/grpc/) that exercises the public gRPC surface (hyper.grpc.v0.Hyper) over the real wire, from outside the BEAM — driven by an ExUnit:integrationwrapper so the server-side Elixir coverage it produces flows to Codecov.@grpc/grpc-js+@grpc/proto-loader, vitest): loads the committedproto/hyper/grpc/v0/hyper.protodirectly; generated TS types are gitignored and rebuilt by npm scripts (repo codegen rule).errors.test.ts— 7 tests pinning the proto's documented status-code contracts (NOT_FOUND ×3, INVALID_ARGUMENT ×4).lifecycle.test.ts— LoadImage → RESOURCE_EXHAUSTED probe (TERA) → CreateVm → GetVm → ListVms → GetVmUsage → StopVm → polls GetVm to NOT_FOUND.test/e2e/grpc_contract_test.exsstarts the gRPC server on port 50061 under the booted app tree and shells out tonpm test.fix(grpc): unrecognised enum ints (e.g.instance_type: 999— only producible by an off-BEAM client) raisedFunctionClauseError→ INTERNAL; now INVALID_ARGUMENT per the proto contract.fix(grpc): StopVm never tore the VM down — it flipped the gen_statem to the stub:stoppingstate and nothing terminated the supervisor, leaving the guest running and GetVm resolving forever. NewHyper.stop_vm/1resolves the VM's supervisor via the routing registry and terminates it on the owning node.mix coveralls.jsonand uploads under a newintegrationflag, plus vitest JUnit → Test Analytics undergrpc-ts.Test plan