Skip to content

Commit

Permalink
testutil: support empty string cmd args
Browse files Browse the repository at this point in the history
FakeCommand allows unit tests to check which command-line arguments
were passed, by recording a log of calls with their arguments.

The following examples cannot be tested with FakeCommand:

1. shutdown -r "+0" ""

2. echo ""

3. configure --program-prefix ""

The empty string command confuses the command parser in testutil.

The issue is that both the argument (\000) and command delimiter
(\000\000) uses null characters, which makes the command split
operation split on the first occurrence of two null chars. This
is an invalid assumption for an empty string argument, which will
be presented as two argument delimiters, without anything in
between, appearing like a command delimiter.

To add support for this:

- Change the command delimiter from \000\000 => \000\f\n\r (new magic sequence)

- Update the Calls() function to split the lines correctly.
  • Loading branch information
flotter committed Jun 22, 2023
1 parent 8902cbe commit 4a3e3e5
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 5 deletions.
10 changes: 5 additions & 5 deletions internals/testutil/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,18 @@ type FakeCmd struct {
// faking commands that need "\n" in their args (like zenity)
// we use the following convention:
// - generate \0 to separate args
// - generate \0\0 to separate commands
// - generate \0\f\n\r magic sequence to separate commands
var scriptTpl = `#!/bin/bash
printf "%%s" "$(basename "$0")" >> %[1]q
printf '\0' >> %[1]q
for arg in "$@"; do
printf "%%s" "$arg" >> %[1]q
printf '\0' >> %[1]q
done
printf '\0' >> %[1]q
printf '\f\n\r' >> %[1]q
%s
`

Expand Down Expand Up @@ -176,12 +177,11 @@ func (cmd *FakeCmd) Calls() [][]string {
if err != nil {
panic(err)
}
logContent := strings.TrimSuffix(string(raw), "\000")
logContent := strings.TrimSuffix(string(raw), "\000\f\n\r")

allCalls := [][]string{}
calls := strings.Split(logContent, "\000\000")
calls := strings.Split(logContent, "\000\f\n\r")
for _, call := range calls {
call = strings.TrimSuffix(call, "\000")
allCalls = append(allCalls, strings.Split(call, "\000"))
}
return allCalls
Expand Down
6 changes: 6 additions & 0 deletions internals/testutil/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@ func (s *fakeCommandSuite) TestFakeCommand(c *check.C) {
c.Assert(err, check.IsNil)
err = exec.Command("cmd", "second-run", "--arg1", "arg2", "a %s").Run()
c.Assert(err, check.IsNil)
err = exec.Command("cmd", "third-run", "--arg1", "arg2", "").Run()
c.Assert(err, check.IsNil)
err = exec.Command("cmd", "forth-run", "--arg1", "arg2", "", "a %s").Run()
c.Assert(err, check.IsNil)
c.Assert(fake.Calls(), check.DeepEquals, [][]string{
{"cmd", "first-run", "--arg1", "arg2", "a space"},
{"cmd", "second-run", "--arg1", "arg2", "a %s"},
{"cmd", "third-run", "--arg1", "arg2", ""},
{"cmd", "forth-run", "--arg1", "arg2", "", "a %s"},
})
}

Expand Down

0 comments on commit 4a3e3e5

Please sign in to comment.