test-execute: Fix systemd escaping and shell issues

In most cases, systemd requires escaping $ (for systemd variable
substitution) and % (for specifiers) by doubling them. This was somewhat
of an issue in tests like exec-environment*.service where systemd was
doing the substitutions and we were not really checking that those were
available in the actual environment of the command. Fix that.

Expressions such as `exit $(test ...)` are incorrect. They only work
because $(test ...) will produce no output, so the command will become a
bare "exit" which will exit with the status of the latest executed
command which turns out to be the test... The direct approach is simply
calling "test" as the last command, for which the shell will propagate
the exit status.

One situation where this was breaking tests was on `exit $(test ...) &&
$(test ...) && $(test ...)` where the second and third tests were not
really executing, since the first command is actually `exit` so && was
doing nothing there. Fixed it by just using `test ... && test ... &&
test ...` as it was initially intended.

Pass -x to all shell executions for them to produce useful debugging
output to stderr. Consequently, removed most of the explicit `echo`s
that are no longer needed.

Mark all units as Type=oneshot explicitly.

Also made sure all shell variables are properly quoted.

v2: Added an explicit LC_ALL=C to ionice invocations since some locales
(such as French) will add a space before the colon in the output.

Tested by running `sudo ./test-execute` and confirming all tests enabled
on my system (essentially all of them except for the s390 one) passed.
Tweaked the variables or options or expected values and confirmed the
tests do indeed fail when the values are not exactly the expected ones.

v2: Also tested with `LANG=fr_FR.UTF-8 sudo ./test-execute` to confirm
it still works in a different locale.
This commit is contained in:
Filipe Brandenburger 2015-11-08 10:19:45 -08:00
parent 8f84882240
commit cdaf507048
37 changed files with 52 additions and 35 deletions

View File

@ -2,5 +2,6 @@
Description=Test for CapabilityBoundingSet
[Service]
ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | grep "cap_chown"); echo $c; exit $(test -z $c)'
ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "^Bounding set .*cap_chown"); test -z "$$c"'
Type=oneshot
CapabilityBoundingSet=~CAP_CHOWN

View File

@ -2,6 +2,7 @@
Description=Test for CapabilityBoundingSet
[Service]
ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test $c = "cap_chown,cap_fowner,cap_kill")'
ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set =cap_chown,cap_fowner,cap_kill"'
Type=oneshot
CapabilityBoundingSet=CAP_FOWNER
CapabilityBoundingSet=CAP_KILL CAP_CHOWN

View File

@ -2,6 +2,7 @@
Description=Test for CapabilityBoundingSet
[Service]
ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test -z $c)'
ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set ="'
Type=oneshot
CapabilityBoundingSet=CAP_FOWNER CAP_KILL
CapabilityBoundingSet=

View File

@ -2,5 +2,6 @@
Description=Test for CapabilityBoundingSet
[Service]
ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test $c = "cap_fowner,cap_kill")'
ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set =cap_fowner,cap_kill"'
Type=oneshot
CapabilityBoundingSet=CAP_FOWNER CAP_KILL

View File

@ -2,6 +2,7 @@
Description=Test for Environment
[Service]
ExecStart=/bin/sh -c 'exit $(test ! "$VAR1" = "word1 word2") && $(test ! "$VAR2" = word3) && $(test ! "$VAR3" = \'$word 5 6\')'
ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset"'
Type=oneshot
Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6"
Environment=

View File

@ -2,6 +2,7 @@
Description=Test for Environment
[Service]
ExecStart=/bin/sh -c 'exit $(test "$VAR1" = "word1 word2") && $(test "$VAR2" = word3) && $(test "$VAR3" = foobar)'
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = foobar'
Type=oneshot
Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6"
Environment="VAR3=foobar"

View File

@ -2,5 +2,6 @@
Description=Test for Environment
[Service]
ExecStart=/bin/sh -c 'exit $(test "$VAR1" = "word1 word2") && $(test "$VAR2" = word3) && $(test "$VAR3" = \'$word 5 6\')'
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"'
Type=oneshot
Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6"

View File

@ -2,6 +2,6 @@
Description=Test for EnvironmentFile
[Service]
ExecStart=/bin/sh -c 'exit $(test "$VAR1" = "word1 word2") && $(test "$VAR2" = word3) && $(test "$VAR3" = \'$word 5 6\')'
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"'
Type=oneshot
EnvironmentFile=/tmp/test-exec_environmentfile.conf

View File

@ -2,5 +2,6 @@
Description=Test for Group
[Service]
ExecStart=/bin/sh -c 'exit $(test $(id -n -g) = nobody)'
ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "nobody"'
Type=oneshot
Group=nobody

View File

@ -2,6 +2,6 @@
Description=Test for IgnoreSIGPIPE=no
[Service]
ExecStart=/bin/sh -c 'kill -PIPE 0'
ExecStart=/bin/sh -x -c 'kill -PIPE 0'
Type=oneshot
IgnoreSIGPIPE=no

View File

@ -2,6 +2,6 @@
Description=Test for IgnoreSIGPIPE=yes
[Service]
ExecStart=/bin/sh -c 'kill -PIPE 0'
ExecStart=/bin/sh -x -c 'kill -PIPE 0'
Type=oneshot
IgnoreSIGPIPE=yes

View File

@ -2,6 +2,6 @@
Description=Test for IOSchedulingClass=best-effort
[Service]
ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == best-effort* ]]'
ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "best-effort"'
Type=oneshot
IOSchedulingClass=best-effort

View File

@ -2,6 +2,6 @@
Description=Test for IOSchedulingClass=idle
[Service]
ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == idle* ]]'
ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "idle"'
Type=oneshot
IOSchedulingClass=idle

View File

@ -2,6 +2,6 @@
Description=Test for IOSchedulingClass=none
[Service]
ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == none* ]]'
ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "none"'
Type=oneshot
IOSchedulingClass=none

View File

@ -2,6 +2,6 @@
Description=Test for IOSchedulingClass=realtime
[Service]
ExecStart=/bin/bash -c 'c=$(ionice); echo $c; [[ "$c" == realtime* ]]'
ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "realtime"'
Type=oneshot
IOSchedulingClass=realtime

View File

@ -2,6 +2,6 @@
Description=Test for OOMScoreAdjust
[Service]
ExecStart=/bin/bash -c 'c=$(cat /proc/self/oom_score_adj); echo $c; exit $(test $c -eq -100)'
OOMScoreAdjust=-100
ExecStart=/bin/sh -x -c 'c=$$(cat /proc/self/oom_score_adj); test "$$c" -eq -100'
Type=oneshot
OOMScoreAdjust=-100

View File

@ -2,6 +2,6 @@
Description=Test for OOMScoreAdjust
[Service]
ExecStart=/bin/bash -c 'c=$(cat /proc/self/oom_score_adj); echo $c; exit $(test $c -eq 100)'
OOMScoreAdjust=100
ExecStart=/bin/sh -x -c 'c=$$(cat /proc/self/oom_score_adj); test "$$c" -eq 100'
Type=oneshot
OOMScoreAdjust=100

View File

@ -2,6 +2,6 @@
Description=Test for Personality=s390
[Service]
ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "s390")'
ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "s390"'
Type=oneshot
Personality=s390

View File

@ -2,6 +2,6 @@
Description=Test for Personality=x86-64
[Service]
ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "x86_64")'
ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "x86_64"'
Type=oneshot
Personality=x86-64

View File

@ -2,6 +2,6 @@
Description=Test for Personality=x86
[Service]
ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "i686")'
ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "i686"'
Type=oneshot
Personality=x86

View File

@ -2,6 +2,6 @@
Description=Test for PrivateDev=no
[Service]
ExecStart=/bin/sh -c 'exit $(test -c /dev/mem)'
ExecStart=/bin/sh -x -c 'test -c /dev/mem'
Type=oneshot
PrivateDevices=no

View File

@ -2,6 +2,6 @@
Description=Test for PrivateDev=yes
[Service]
ExecStart=/bin/sh -c 'exit $(test ! -c /dev/mem)'
ExecStart=/bin/sh -c 'test ! -c /dev/mem'
Type=oneshot
PrivateDevices=yes

View File

@ -2,5 +2,6 @@
Description=Test for PrivateNetwork
[Service]
ExecStart=/bin/sh -c 'i=$(ip link | grep ": " | grep -v lo); echo $i; exit $(test -z $i)'
ExecStart=/bin/sh -x -c 'i=$$(ip link | grep ": " | grep -v ": lo:"); test -z "$$i"'
Type=oneshot
PrivateNetwork=yes

View File

@ -2,6 +2,6 @@
Description=Test for PrivateTmp=no
[Service]
ExecStart=/bin/sh -c 'exit $(test -f /tmp/test-exec_privatetmp)'
ExecStart=/bin/sh -x -c 'test -f /tmp/test-exec_privatetmp'
Type=oneshot
PrivateTmp=no

View File

@ -2,6 +2,6 @@
Description=Test for PrivateTmp=yes
[Service]
ExecStart=/bin/sh -c 'exit $(test ! -f /tmp/test-exec_privatetmp)'
ExecStart=/bin/sh -x -c 'test ! -f /tmp/test-exec_privatetmp'
Type=oneshot
PrivateTmp=yes

View File

@ -2,7 +2,7 @@
Description=Test for RuntimeDirectoryMode
[Service]
ExecStart=/bin/sh -c 's=$(stat -c %a /tmp/test-exec_runtimedirectory-mode); echo $s; exit $(test $s = "750")'
ExecStart=/bin/sh -x -c 'mode=$$(stat -c %%a /tmp/test-exec_runtimedirectory-mode); test "$$mode" = "750"'
Type=oneshot
RuntimeDirectory=test-exec_runtimedirectory-mode
RuntimeDirectoryMode=0750

View File

@ -2,7 +2,7 @@
Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set)
[Service]
ExecStart=/bin/sh -c 'f=/tmp/test-exec_runtimedirectory-owner;g=$(stat -c %G $f); echo "$g"; exit $(test $g = "nobody")'
ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G /tmp/test-exec_runtimedirectory-owner); test "$$group" = "nobody"'
Type=oneshot
Group=nobody
User=root

View File

@ -2,6 +2,6 @@
Description=Test for RuntimeDirectory
[Service]
ExecStart=/bin/sh -c 'exit $(test -d /tmp/test-exec_runtimedirectory)'
ExecStart=/bin/sh -x -c 'test -d /tmp/test-exec_runtimedirectory'
Type=oneshot
RuntimeDirectory=test-exec_runtimedirectory

View File

@ -2,6 +2,7 @@
Description=Test for SystemCallErrorNumber
[Service]
ExecStart=/bin/sh -c 'uname -a'
ExecStart=/bin/sh -x -c 'uname -a'
Type=oneshot
SystemCallFilter=~uname
SystemCallErrorNumber=EACCES

View File

@ -3,6 +3,7 @@ Description=Test for SystemCallFilter
[Service]
ExecStart=/bin/echo "This should not be seen"
Type=oneshot
SystemCallFilter=ioperm
SystemCallFilter=~ioperm
SystemCallFilter=ioperm

View File

@ -3,4 +3,5 @@ Description=Test for SystemCallFilter
[Service]
ExecStart=/bin/echo "This should not be seen"
Type=oneshot
SystemCallFilter=~write open execve exit_group close mmap munmap fstat DONOTEXIST

View File

@ -3,6 +3,7 @@ Description=Test for SystemCallFilter
[Service]
ExecStart=/bin/echo "Foo bar"
Type=oneshot
SystemCallFilter=~read write open execve ioperm
SystemCallFilter=ioctl
SystemCallFilter=read write open execve

View File

@ -3,4 +3,5 @@ Description=Test for SystemCallFilter
[Service]
ExecStart=/bin/echo "Foo bar"
Type=oneshot
SystemCallFilter=

View File

@ -2,6 +2,7 @@
Description=Test for UMask
[Service]
ExecStart=/bin/sh -c 'touch /tmp/test-exec-umask; s=$(stat -c %a /tmp/test-exec-umask); echo $s; exit $(test $s = "600")'
ExecStart=/bin/sh -x -c 'touch /tmp/test-exec-umask; mode=$$(stat -c %%a /tmp/test-exec-umask); test "$$mode" = "600"'
Type=oneshot
UMask=0177
PrivateTmp=yes

View File

@ -2,5 +2,6 @@
Description=Test for UMask default
[Service]
ExecStart=/bin/sh -c 'touch /tmp/test-exec-umask; s=$(stat -c %a /tmp/test-exec-umask); echo $s; exit $(test $s = "644")'
ExecStart=/bin/sh -x -c 'touch /tmp/test-exec-umask; mode=$$(stat -c %%a /tmp/test-exec-umask); test "$$mode" = "644"'
Type=oneshot
PrivateTmp=yes

View File

@ -2,5 +2,6 @@
Description=Test for User
[Service]
ExecStart=/bin/sh -c 'exit $(test "$USER" = nobody)'
ExecStart=/bin/sh -x -c 'test "$$USER" = "nobody"'
Type=oneshot
User=nobody

View File

@ -2,6 +2,6 @@
Description=Test for WorkingDirectory
[Service]
ExecStart=/bin/sh -c 'echo $PWD; exit $(test $PWD = "/tmp/test-exec_workingdirectory")'
ExecStart=/bin/sh -x -c 'test "$$PWD" = "/tmp/test-exec_workingdirectory"'
Type=oneshot
WorkingDirectory=/tmp/test-exec_workingdirectory