Skip to content

test(hypervisors): cover Qemu.BuildExecCmd#597

Open
parthdagia05 wants to merge 2 commits into
urunc-dev:mainfrom
parthdagia05:test/hypervisors-qemu-buildexeccmd
Open

test(hypervisors): cover Qemu.BuildExecCmd#597
parthdagia05 wants to merge 2 commits into
urunc-dev:mainfrom
parthdagia05:test/hypervisors-qemu-buildexeccmd

Conversation

@parthdagia05
Copy link
Copy Markdown

Description

Qemu.BuildExecCmd in pkg/unikontainers/hypervisors/qemu.go didn't have any direct unit-test coverage, so this PR adds qemu_test.go that walks through the main branches the function actually exercises:

  • Static flags that should always be present
  • Memory default fallback and custom values
  • vCPU handling (omits -smp when zero, sets it correctly otherwise)
  • Seccomp on / off
  • Architecture-specific machine type (-M virt on arm64)
  • Networking: empty TapDev, generic tap setup, custom MonitorNetCli, and vhost on/off
  • Initrd present / absent
  • Sharedfs: 9pfs, virtiofs, and none
  • Block devices: no blocks, generic, and ExactArgs verbatim path
  • MonitorCli extras (ExtraInitrd, OtherArgs)
  • vsock with VAccelType set
  • The -append rule for the kernel command line

A small fakeUnikernel stub keeps the tests focused on BuildExecCmd itself rather than pulling in any real unikernel implementation.

Related issues

  • Fixes #

How was this tested?

  • go test ./pkg/unikontainers/hypervisors/... passes locally
  • go build ./... passes
  • All sub-tests use t.Parallel() and assert against the joined command string

LLM usage

Used Anthropic's Claude Opus 4.6 to help research the function's branches and shape the test cases around the actual code paths.

Checklist

  • I have read the contribution guide.
  • The linter passes locally (make lint).
  • The e2e tests of at least one tool pass locally (make test_ctr, make test_nerdctl, make test_docker, make test_crictl).
  • If LLMs were used: I have read the llm policy.

Walks through the main code paths the function exercises — static flags,
memory, vCPUs, network (incl. vhost), initrd, sharedfs, block devices,
vsock, and the kernel command append rule.

Signed-off-by: Parth Dagia <parth.24bcs10414@sst.scaler.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented May 1, 2026

Deploy Preview for urunc canceled.

Name Link
🔨 Latest commit dadd62b
🔍 Latest deploy log https://app.netlify.com/projects/urunc/deploys/69f9baa00935b400085d1244

Copy link
Copy Markdown
Contributor

@cmainas cmainas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @parthdagia05 ,

thank you for this PR. Please do not use multiple test functions for the same test and:

Per review feedback: collapses the per-feature test functions into a
single TestQemuBuildExecCmd with table-driven subtests, so each case
calls BuildExecCmd exactly once and runs all of its assertions on the
result.

Signed-off-by: Parth Dagia <parth.24bcs10414@sst.scaler.com>
@parthdagia05
Copy link
Copy Markdown
Author

@cmainas the per-feature test functions are now collapsed into a single TestQemuBuildExecCmd, the coverage is same as before

Copy link
Copy Markdown
Contributor

@cmainas cmainas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @parthdagia05 ,

the new version is very complex without any reason. We want to test one function, which takes a struct as an argument. The struct which we pass as an argument controls the result. However, not all the fields of the struct affect the result. Therefore, we can focus only in the fields that affect the result.

Also, there are some specific values, like the qemu binary name or the argument of -kernel. These can be tested in a single test.


// withArgs returns defaultArgs() after applying the given modifier, so that
// each table case can declare only the fields it cares about.
func withArgs(modify func(*types.ExecArgs)) types.ExecArgs {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to pass a function to change the value of a struct.

mustContain: []string{"-smp 1"},
},
{
name: "VCPUs=4 emits -smp 4",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same test as the above.

mustContain: []string{"-smp 4"},
},
{
name: "VCPUs=16 emits -smp 16",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same test as the above.

@parthdagia05
Copy link
Copy Markdown
Author

Hi @cmainas, thanks for your feedback, I think I jumped into writing tests before fully understanding the patterns. Let me take a proper look through rest of the existing tests and update accordingly. I'd rather slow down and get the structure right than ship another iteration that misses something obvious.

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.

2 participants