]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test-execute: Fix systemd escaping and shell issues 1834/head
authorFilipe Brandenburger <filbranden@google.com>
Sun, 8 Nov 2015 18:19:45 +0000 (10:19 -0800)
committerFilipe Brandenburger <filbranden@google.com>
Tue, 10 Nov 2015 15:58:29 +0000 (07:58 -0800)
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.

37 files changed:
test/test-execute/exec-capabilityboundingset-invert.service
test/test-execute/exec-capabilityboundingset-merge.service
test/test-execute/exec-capabilityboundingset-reset.service
test/test-execute/exec-capabilityboundingset-simple.service
test/test-execute/exec-environment-empty.service
test/test-execute/exec-environment-multiple.service
test/test-execute/exec-environment.service
test/test-execute/exec-environmentfile.service
test/test-execute/exec-group.service
test/test-execute/exec-ignoresigpipe-no.service
test/test-execute/exec-ignoresigpipe-yes.service
test/test-execute/exec-ioschedulingclass-best-effort.service
test/test-execute/exec-ioschedulingclass-idle.service
test/test-execute/exec-ioschedulingclass-none.service
test/test-execute/exec-ioschedulingclass-realtime.service
test/test-execute/exec-oomscoreadjust-negative.service
test/test-execute/exec-oomscoreadjust-positive.service
test/test-execute/exec-personality-s390.service
test/test-execute/exec-personality-x86-64.service
test/test-execute/exec-personality-x86.service
test/test-execute/exec-privatedevices-no.service
test/test-execute/exec-privatedevices-yes.service
test/test-execute/exec-privatenetwork-yes.service
test/test-execute/exec-privatetmp-no.service
test/test-execute/exec-privatetmp-yes.service
test/test-execute/exec-runtimedirectory-mode.service
test/test-execute/exec-runtimedirectory-owner.service
test/test-execute/exec-runtimedirectory.service
test/test-execute/exec-systemcallerrornumber.service
test/test-execute/exec-systemcallfilter-failing.service
test/test-execute/exec-systemcallfilter-failing2.service
test/test-execute/exec-systemcallfilter-not-failing.service
test/test-execute/exec-systemcallfilter-not-failing2.service
test/test-execute/exec-umask-0177.service
test/test-execute/exec-umask-default.service
test/test-execute/exec-user.service
test/test-execute/exec-workingdirectory.service

index e2b09e1550a3ce5f7cda32b265cf6cfd2704125a..fd5d248702f43257ce963b8499b33bcd7ebab613 100644 (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
index b0f4732529ce72e71243164db3e0502f851668d7..5c7fcaf437242d5ab8901ede3de7e7076e44542a 100644 (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
index 51092ab0d5e5f4a2e79fe9719148f46492afb1e5..d7d33202044e377a25d8ad8756b55c752f108f02 100644 (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=
index b9037a0ddfbac57bd801cbfa6f01b961df1ea9d3..bf1a7f575af9d02ccf5d4ebe5624d38b9f1fe6d4 100644 (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
index 0219ca4fd79186d8972e2671516c4f0165a6dc98..9c92d4bc8113e882d83ae1b76b122314b876322f 100644 (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=
index 479005a5d876a0b98dfabd33b73575e26a1b2247..b9bc225635a9a1697ebba4dc044e9a199cef324d 100644 (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"
index 4586b4c4a9fe24398ca8e6c25481ca7b08b24a7f..06e77af220000365837161950704efe28cc4a72e 100644 (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"
index 848f2a120cde368a5ceeac18ec8d3ba7fcf83063..f6b8462719db069590078bc8cec08e112cd809fe 100644 (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
index 1aa04b5bd26cc956366fe98ebea3da2acda0c4b7..be7c7969127835ffab3854906d836fa0984b8211 100644 (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
index 69b2e9d8a8458a2ae50ae090c52bccb589b7b463..73addf5f05500bb0b6ed546bfe60d99fdb6e5ee7 100644 (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
index 877ec8aed01854f9dff5bae77979ecd14abf46fb..f81c01719e9ad74b790d5add5e1ae9fde90b5d24 100644 (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
index 56e27185057e11056c962fed6501104a317e6d55..29bb8510b42cf9287f5e710874974a19e92b8214 100644 (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
index b45795cab7b5b11d7a505aa815158c1a1b97835b..87dbed14c1a991024c1f71cd35ab738c77a05266 100644 (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
index 36b546ca01325c45a3ead938890005dbcb019ccc..b6af122a1efe95e37e4e370c1f7b19d18076bf49 100644 (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
index 74936d80798baef2a6b232d9dc89bfd05acdf65f..d920d5c687396ada38382e927bcd06d8c848c158 100644 (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
index 63ab501c63f6a3f42a2b1e8542071f7498ba6986..2234c53c3ff36472e0d534299eaab92f629f7f73 100644 (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
index e47a4f139294cb4b267677106e6b5feaf1de9cb2..456a8f80cf8b0a7cb5807389d2e077a18d0ba8ea 100644 (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
index f3c3b03e3d83036d72e3b9f0f203b1bdf7c51e19..89f7de89d03b3fae82c12cbfacbeb1a1d1e1ee3e 100644 (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
index 5bb5d910d0dd41b8e00d2cb44d835ccfd5ad97ae..433e69a6d10d818a1f07ed3bf21c282218691a41 100644 (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
index 0b370a6480eebb17d95ec3fe2c8d6404a6d7974a..a623a08cbedaad967afaec5d5632e172428bf067 100644 (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
index cf4f275fb62cce24e4d191e6adddade69385da32..77aeb951b5dbbfb9bd892763ef078418b6a99822 100644 (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
index 85b3f4f9810e3d7b6a268e290d6c8807b25a58e1..ab958b646eda7f0eeff403dc1f03ab6c081f6104 100644 (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
index 494712e6a741445599c1eccf7f89fc2fdeec945a..3df543ec93c19cd258efc92765f8f20421ef51b5 100644 (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
index d69e552a63de41bf02ecfb581b4c58db41b64254..59f60f47557b63a7cf08be9dd04fa05fb52ae65a 100644 (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
index 881a040b87e1a69c62e6f5d5d65adddf8f75b9b4..907c291b81c9f0bebad0b59a3109b57d78a2a5e4 100644 (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
index ba6d7ee39ff60a173778c7653f75aefd3aaf1a9b..842721d5c2e0a051b8acee70e151f77792ed27f3 100644 (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
index 077e08d1c58827866131db4d6458b5c48b18ddc0..1f438c182e83cc28ecd9412df9c6b2d719a58067 100644 (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
index c12a6c63d68da26c99412b90298dae9d401bd517..ec46c9d49b2bbf22d40aa51f300e492142270117 100644 (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
index b11a952bd62f1d51d2bf75dbc6862488b21d24f5..ff7da3c1a49c20156693dbc7c147ad48106c9e94 100644 (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
index c6ce9368c91435a8359e28884c9005f16da3a3a9..5c6422f0fd5ba36ef1fb70234539b1572de4a6e1 100644 (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
index b7f7c2aff99ec66a146d04f7296013a0c1413e0c..3516078e1ffb94395cf4f1591e8c5abb6b3a3ee0 100644 (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
index feb206ab6d0b7fd3aec48bdfda0478a14cdebae6..c794b67edd89fc3560e1e0524771e8a1d0a2a703 100644 (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
index cca469aa3dc2ba4260a15ebbe530d4fb4de26980..a62c81bd488596c1cf9581142ab2311ca0bb9a9b 100644 (file)
@@ -3,4 +3,5 @@ Description=Test for SystemCallFilter
 
 [Service]
 ExecStart=/bin/echo "Foo bar"
+Type=oneshot
 SystemCallFilter=
index af9295888e222779e138201c5b4cd6f0f1509818..a5e8fc4dbc61015e77d59b72adab582169814ff6 100644 (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
index 41e20a60a1929fb9b8318aa67d498f469f0f55a5..487f5e9b9466729336e5128d97a4f89c265da90e 100644 (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
index 2ca08ebb42726b2061be6e87d7f82fc7ef49b31b..0a00c1abc4394713bd2c7ba780599fec30fb8fe2 100644 (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
index 10855d682ad108b5b2c35fb1cc6e64d2c218a8bb..fe3c420d2d3c3ef1496ea61055e7c20479ef0b0e 100644 (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