#! /bin/sh # $NetBSD: logging-test.sh,v 1.7 2019/05/22 20:47:05 rillig Exp $ # Up to March 2019, the command logging for the wrapped tools didn't properly # quote the command line arguments. This meant the logging did not reflect # the actual tool command line. set -eu mydir=`dirname "$0"` . "${mydir}/tests.subr" tools_log="./tools.log" nopath_log="./nopath.log" rm -f "$tools_log" "$nopath_log" test_case() { test_name="$1" } # usage: run_tool $tool $args... run_tool() { TOOLS_WRAPPER_LOG="$tools_log" export TOOLS_WRAPPER_LOG # The exec makes sure that the tool from the tools directory is # called, even for shell builtins. (exec "$@") unset TOOLS_WRAPPER_LOG } # usage: assert_log <<EOF ... EOF assert_log() { # Replace the variable parts from the output with placeholders. sed < "$tools_log" > "$nopath_log" \ -e 's,/.*/\.tools/,WRKDIR/.tools/,' \ -e 's,^<.> /[^ ]*/,<.> BINDIR/,' actual=`cat "$nopath_log"` expected=`cat` assert_equal "$test_name" "$expected" "$actual" || exit $? rm -f "$tools_log" "$nopath_log" unset test_name } test_case "TOOLS_PATH without TOOLS_ARGS" { # The "*" ensure that there is no accidental file expansion. run_tool echo "begin" "*" "*" "*" "end" run_tool echo "dquot" "\"" "end" run_tool echo "squot" "'" "end" run_tool echo "five" '\\\\\' "end" # In the <.> lines there are 2 spaces between echo and its first # argument. This is because the echo command doesn't get any # additional arguments by the tool wrapper (TOOLS_ARGS.echo). assert_log <<'EOF' [*] WRKDIR/.tools/bin/echo begin '*' '*' '*' end <.> echo begin '*' '*' '*' end [*] WRKDIR/.tools/bin/echo dquot '"' end <.> echo dquot '"' end [*] WRKDIR/.tools/bin/echo squot ''\''' end <.> echo squot ''\''' end [*] WRKDIR/.tools/bin/echo five '\\\\\' end <.> echo five '\\\\\' end EOF } test_case "TOOLS_PATH with TOOLS_ARGS" { # The mkdir tool always gets the -p option. run_tool mkdir "directory with spaces" # The TOOLS_ARGS are already quoted, therefore they all look # different in the log. The actual arguments, on the other hand, # all look the same. assert_log <<'EOF' [*] WRKDIR/.tools/bin/mkdir 'directory with spaces' <.> BINDIR/mkdir -p 'directory with spaces' EOF } test_case "TOOLS_PATH with TOOLS_ARGS containing double quotes" { run_tool path-args-dquot "and" \" "\"" '"' assert_log <<'EOF' [*] WRKDIR/.tools/bin/path-args-dquot and '"' '"' '"' <.> echo \" "\"" '"' and '"' '"' '"' EOF } test_case "TOOLS_PATH with TOOLS_ARGS containing special characters" { run_tool path-args "and" " \"'\\\$" "*" assert_log <<'EOF' [*] WRKDIR/.tools/bin/path-args and ' "'\''\$' '*' <.> echo " \"'\\$" "*" and ' "'\''\$' '*' EOF } test_case "TOOLS_SCRIPT with dquot" { run_tool script-dquot assert_log <<'EOF' [*] WRKDIR/.tools/bin/script-dquot <.> set args; shift; echo "hello; world" EOF } test_case "TOOLS_SCRIPT with backslashes" { run_tool script-backslash assert_log <<'EOF' [*] WRKDIR/.tools/bin/script-backslash <.> set args; shift; echo hello\;\ world EOF } test_case "TOOLS_SCRIPT with complicated replacement" { run_tool for-loop "one" "two" "three" # The actual command is written to the log in a form as close as # possible to replay it. Since the command may do anything with # its arguments, it's the safest way to set them first and then # just log the command verbatim. # # In this example, the $0 becomes unrealistic when the command # is replayed. In practice $0 is seldom used. assert_log <<'EOF' [*] WRKDIR/.tools/bin/for-loop one two three <.> set args one two three; shift; printf '%s' "$0"; for arg in "$@"; do printf ' <%s>' "$arg"; done; printf '\n' EOF } test_case "TOOLS_SCRIPT with actual arguments containing quotes" { run_tool for-loop \ -DSD='"a b"' \ -DSS=''\''a b'\''' \ -DDD="\"a b\"" \ -DB=\"a\ b\" assert_log <<'EOF' [*] WRKDIR/.tools/bin/for-loop -DSD='"a b"' -DSS=''\''a b'\''' -DDD='"a b"' -DB='"a b"' <.> set args -DSD='"a b"' -DSS=''\''a b'\''' -DDD='"a b"' -DB='"a b"'; shift; printf '%s' "$0"; for arg in "$@"; do printf ' <%s>' "$arg"; done; printf '\n' EOF }