Skip to content

Commit

Permalink
testutil: support empty string args in fakecommand
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 (magic sequence)

- Update the Calls() function to split the lines correctly.

Testutil can now be used for testing the following command, including the
case where msg is an empty string for the wall message:

shutdown [OPTIONS...] [TIME] [WALL...]

cmd := exec.Command("shutdown", "-r", fmt.Sprintf("+%d", mins), msg)
  • Loading branch information
flotter committed Jun 22, 2023
1 parent 8902cbe commit 12acc94
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 5 deletions.
9 changes: 4 additions & 5 deletions internals/testutil/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ 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
Expand All @@ -102,7 +102,7 @@ for arg in "$@"; do
printf '\0' >> %[1]q
done
printf '\0' >> %[1]q
printf '\f\n\r' >> %[1]q
%s
`

Expand Down Expand Up @@ -176,12 +176,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 12acc94

Please sign in to comment.