test(hypervisors): cover Qemu.BuildExecCmd#597
Conversation
✅ Deploy Preview for urunc canceled.
|
There was a problem hiding this comment.
Hello @parthdagia05 ,
thank you for this PR. Please do not use multiple test functions for the same test and:
- The tests could be a single test with subtests using table driven tests (See https://github.com/parthdagia05/urunc/blob/test/hypervisors-qemu-buildexeccmd/pkg/unikontainers/vaccel_test.go#L23 for reference).
- There is no reason to call
q.BuildExecCmdmultiple times with the same parameters. - In one tests you can have multiple checks, See https://github.com/parthdagia05/urunc/blob/test/hypervisors-qemu-buildexeccmd/pkg/unikontainers/block_test.go for example.
|
@cmainas the per-feature test functions are now collapsed into a single TestQemuBuildExecCmd, the coverage is same as before |
cmainas
left a comment
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
This is the same test as the above.
| mustContain: []string{"-smp 4"}, | ||
| }, | ||
| { | ||
| name: "VCPUs=16 emits -smp 16", |
There was a problem hiding this comment.
This is the same test as the above.
|
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. |
|
@cmainas done with the changes. |
cmainas
left a comment
There was a problem hiding this comment.
Thank you @parthdagia05 for the changes.
I believe we can remove the "extra" check defined in two tests and perform the same tests either directly in the test loop or with mustContain.
| } else { | ||
| assert.NotContains(t, strings.Join(out, " "), archFlag) | ||
| } | ||
| }, |
There was a problem hiding this comment.
No reason for this to be an "extra" check. We can check it in the subtest loop instead.
| extra: func(t *testing.T, out []string) { | ||
| assert.GreaterOrEqual(t, len(out), 2) | ||
| assert.Equal(t, "-append", out[len(out)-2]) | ||
| assert.Equal(t, "init=/bin/sh root=/dev/vda console=ttyS0", out[len(out)-1]) |
There was a problem hiding this comment.
We do not need an "extra test for this". If we include the whole command in mustContain, then we can be sure that it is a single argument.
|
@cmainas removed the extra check |
cmainas
left a comment
There was a problem hiding this comment.
Hello @parthdagia05 ,
I have one more question. Sorry for not checking this earlier.
|
|
||
| // Invariants that hold for every call to BuildExecCmd. | ||
| assert.Equal(t, testQemuBinary, out[0], "binary path must be the first element") | ||
| joined := strings.Join(out, " ") |
There was a problem hiding this comment.
Is there a reason for joining the string, instead of check if out contains the respective strings?
There was a problem hiding this comment.
Because BuildExecCmd does strings.Split(cmdString, " ") (qemu.go-140th line), multi-word flags like -m 256M end up as two separate slice elements, so assert.Contains(out, "-m 256M") wouldn't match so i thought joining back is the simplest way to substring-check them as one piece.
There was a problem hiding this comment.
Yeah, this makes sense. We need to come up with a better scheme for the construction of the cli args.
|
Thank you @parthdagia05 for the changes. Can you rebase over main and squash your commits so we can merge? |
Adds a table-driven test that covers the main branches of BuildExecCmd: static flags, memory default and custom value, vCPUs, seccomp, the architecture machine flag, networking (no-net, generic tap, custom MonitorNetCli, vhost), initrd, sharedfs (9pfs / virtiofs), block devices (generic and ExactArgs), MonitorCli extras, vsock, and the kernel command append rule. A small fakeUnikernel stub keeps the tests focused on BuildExecCmd itself. Signed-off-by: Parth Dagia <parth.24bcs10414@sst.scaler.com>
8396e65 to
4aee235
Compare
|
Done @cmainas |
cmainas
left a comment
There was a problem hiding this comment.
Thank you @parthdagia05 for the tests.
Adds a table-driven test that covers the main branches of BuildExecCmd: static flags, memory default and custom value, vCPUs, seccomp, the architecture machine flag, networking (no-net, generic tap, custom MonitorNetCli, vhost), initrd, sharedfs (9pfs / virtiofs), block devices (generic and ExactArgs), MonitorCli extras, vsock, and the kernel command append rule. A small fakeUnikernel stub keeps the tests focused on BuildExecCmd itself. PR: #597 Signed-off-by: Parth Dagia <parth.24bcs10414@sst.scaler.com> Reviewed-by: Charalampos Mainas <cmainas@nubificus.co.uk> Approved-by: Charalampos Mainas <cmainas@nubificus.co.uk>
Adds a table-driven test that covers the main branches of BuildExecCmd: static flags, memory default and custom value, vCPUs, seccomp, the architecture machine flag, networking (no-net, generic tap, custom MonitorNetCli, vhost), initrd, sharedfs (9pfs / virtiofs), block devices (generic and ExactArgs), MonitorCli extras, vsock, and the kernel command append rule. A small fakeUnikernel stub keeps the tests focused on BuildExecCmd itself. PR: #597 Signed-off-by: Parth Dagia <parth.24bcs10414@sst.scaler.com> Reviewed-by: Charalampos Mainas <cmainas@nubificus.co.uk> Approved-by: Charalampos Mainas <cmainas@nubificus.co.uk>
Description
Qemu.BuildExecCmdinpkg/unikontainers/hypervisors/qemu.godidn't have any direct unit-test coverage, so this PR addsqemu_test.gothat walks through the main branches the function actually exercises:-smpwhen zero, sets it correctly otherwise)-M virton arm64)MonitorNetCli, and vhost on/offExactArgsverbatim pathMonitorCliextras (ExtraInitrd,OtherArgs)VAccelTypeset-appendrule for the kernel command lineA small
fakeUnikernelstub keeps the tests focused onBuildExecCmditself rather than pulling in any real unikernel implementation.Related issues
How was this tested?
go test ./pkg/unikontainers/hypervisors/...passes locallygo build ./...passest.Parallel()and assert against the joined command stringLLM 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
make lint).make test_ctr,make test_nerdctl,make test_docker,make test_crictl).