summaryrefslogtreecommitdiffstats
path: root/test/test-execute
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 13:00:47 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 13:00:47 +0000
commit2cb7e0aaedad73b076ea18c6900b0e86c5760d79 (patch)
treeda68ca54bb79f4080079bf0828acda937593a4e1 /test/test-execute
parentInitial commit. (diff)
downloadsystemd-2cb7e0aaedad73b076ea18c6900b0e86c5760d79.tar.xz
systemd-2cb7e0aaedad73b076ea18c6900b0e86c5760d79.zip
Adding upstream version 247.3.upstream/247.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'test/test-execute')
-rw-r--r--test/test-execute/exec-ambientcapabilities-merge-nfsnobody.service9
-rw-r--r--test/test-execute/exec-ambientcapabilities-merge-nobody.service9
-rw-r--r--test/test-execute/exec-ambientcapabilities-merge.service9
-rw-r--r--test/test-execute/exec-ambientcapabilities-nfsnobody.service8
-rw-r--r--test/test-execute/exec-ambientcapabilities-nobody.service8
-rw-r--r--test/test-execute/exec-ambientcapabilities.service8
-rw-r--r--test/test-execute/exec-basic.service16
-rw-r--r--test/test-execute/exec-bindpaths.service17
-rw-r--r--test/test-execute/exec-capabilityboundingset-invert.service8
-rw-r--r--test/test-execute/exec-capabilityboundingset-merge.service8
-rw-r--r--test/test-execute/exec-capabilityboundingset-reset.service8
-rw-r--r--test/test-execute/exec-capabilityboundingset-simple.service7
-rw-r--r--test/test-execute/exec-condition-failed.service11
-rw-r--r--test/test-execute/exec-condition-skip.service15
-rw-r--r--test/test-execute/exec-cpuaffinity1.service6
-rw-r--r--test/test-execute/exec-cpuaffinity2.service8
-rw-r--r--test/test-execute/exec-cpuaffinity3.service7
-rw-r--r--test/test-execute/exec-dynamicuser-fixeduser-adm.service11
-rw-r--r--test/test-execute/exec-dynamicuser-fixeduser-games.service11
-rw-r--r--test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service10
-rw-r--r--test/test-execute/exec-dynamicuser-fixeduser.service9
-rw-r--r--test/test-execute/exec-dynamicuser-runtimedirectory1.service11
-rw-r--r--test/test-execute/exec-dynamicuser-runtimedirectory2.service12
-rw-r--r--test/test-execute/exec-dynamicuser-runtimedirectory3.service11
-rw-r--r--test/test-execute/exec-dynamicuser-statedir-migrate-step1.service17
-rw-r--r--test/test-execute/exec-dynamicuser-statedir-migrate-step2.service25
-rw-r--r--test/test-execute/exec-dynamicuser-statedir.service20
-rw-r--r--test/test-execute/exec-dynamicuser-supplementarygroups.service10
-rw-r--r--test/test-execute/exec-environment-empty.service8
-rw-r--r--test/test-execute/exec-environment-multiple.service8
-rw-r--r--test/test-execute/exec-environment-no-substitute.service8
-rw-r--r--test/test-execute/exec-environment.service7
-rw-r--r--test/test-execute/exec-environmentfile.service7
-rw-r--r--test/test-execute/exec-group-nfsnobody.service7
-rw-r--r--test/test-execute/exec-group-nobody.service7
-rw-r--r--test/test-execute/exec-group-nogroup.service7
-rw-r--r--test/test-execute/exec-group.service7
-rw-r--r--test/test-execute/exec-ignoresigpipe-no.service7
-rw-r--r--test/test-execute/exec-ignoresigpipe-yes.service7
-rw-r--r--test/test-execute/exec-inaccessiblepaths-mount-propagation.service7
-rw-r--r--test/test-execute/exec-inaccessiblepaths-sys.service7
-rw-r--r--test/test-execute/exec-ioschedulingclass-best-effort.service7
-rw-r--r--test/test-execute/exec-ioschedulingclass-idle.service7
-rw-r--r--test/test-execute/exec-ioschedulingclass-none.service7
-rw-r--r--test/test-execute/exec-ioschedulingclass-realtime.service7
-rw-r--r--test/test-execute/exec-oomscoreadjust-negative.service7
-rw-r--r--test/test-execute/exec-oomscoreadjust-positive.service7
-rw-r--r--test/test-execute/exec-passenvironment-absent.service7
-rw-r--r--test/test-execute/exec-passenvironment-empty.service8
-rw-r--r--test/test-execute/exec-passenvironment-repeated.service10
-rw-r--r--test/test-execute/exec-passenvironment.service7
-rw-r--r--test/test-execute/exec-personality-aarch64.service7
-rw-r--r--test/test-execute/exec-personality-ppc64.service7
-rw-r--r--test/test-execute/exec-personality-ppc64le.service7
-rw-r--r--test/test-execute/exec-personality-s390.service7
-rw-r--r--test/test-execute/exec-personality-x86-64.service7
-rw-r--r--test/test-execute/exec-personality-x86.service7
-rw-r--r--test/test-execute/exec-privatedevices-disabled-by-prefix.service8
-rw-r--r--test/test-execute/exec-privatedevices-no-capability-mknod.service8
-rw-r--r--test/test-execute/exec-privatedevices-no-capability-sys-rawio.service8
-rw-r--r--test/test-execute/exec-privatedevices-no.service7
-rw-r--r--test/test-execute/exec-privatedevices-yes-capability-mknod.service8
-rw-r--r--test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service8
-rw-r--r--test/test-execute/exec-privatedevices-yes-with-group.service16
-rw-r--r--test/test-execute/exec-privatedevices-yes.service7
-rw-r--r--test/test-execute/exec-privatenetwork-yes.service7
-rw-r--r--test/test-execute/exec-privatetmp-disabled-by-prefix.service8
-rw-r--r--test/test-execute/exec-privatetmp-no.service7
-rw-r--r--test/test-execute/exec-privatetmp-yes.service7
-rw-r--r--test/test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service9
-rw-r--r--test/test-execute/exec-protectkernellogs-no-capabilities.service8
-rw-r--r--test/test-execute/exec-protectkernellogs-yes-capabilities.service8
-rw-r--r--test/test-execute/exec-protectkernelmodules-no-capabilities.service8
-rw-r--r--test/test-execute/exec-protectkernelmodules-yes-capabilities.service8
-rw-r--r--test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service7
-rw-r--r--test/test-execute/exec-readonlypaths-mount-propagation.service7
-rw-r--r--test/test-execute/exec-readonlypaths-simple.service11
-rw-r--r--test/test-execute/exec-readonlypaths-with-bindpaths.service8
-rw-r--r--test/test-execute/exec-readonlypaths.service9
-rw-r--r--test/test-execute/exec-readwritepaths-mount-propagation.service7
-rw-r--r--test/test-execute/exec-restrictnamespaces-merge-all.service8
-rw-r--r--test/test-execute/exec-restrictnamespaces-merge-and.service9
-rw-r--r--test/test-execute/exec-restrictnamespaces-merge-or.service9
-rw-r--r--test/test-execute/exec-restrictnamespaces-mnt-deny-list.service7
-rw-r--r--test/test-execute/exec-restrictnamespaces-mnt.service7
-rw-r--r--test/test-execute/exec-restrictnamespaces-no.service7
-rw-r--r--test/test-execute/exec-restrictnamespaces-yes.service7
-rw-r--r--test/test-execute/exec-runtimedirectory-mode.service9
-rw-r--r--test/test-execute/exec-runtimedirectory-owner-nfsnobody.service9
-rw-r--r--test/test-execute/exec-runtimedirectory-owner-nobody.service9
-rw-r--r--test/test-execute/exec-runtimedirectory-owner-nogroup.service9
-rw-r--r--test/test-execute/exec-runtimedirectory-owner.service9
-rw-r--r--test/test-execute/exec-runtimedirectory.service10
-rw-r--r--test/test-execute/exec-specifier-interpolation.service6
-rw-r--r--test/test-execute/exec-specifier.service31
-rw-r--r--test/test-execute/exec-specifier@.service29
-rw-r--r--test/test-execute/exec-standardinput-data.service19
-rw-r--r--test/test-execute/exec-standardinput-file-cat.service9
-rw-r--r--test/test-execute/exec-standardinput-file.service7
-rw-r--r--test/test-execute/exec-standardoutput-append.service13
-rw-r--r--test/test-execute/exec-standardoutput-file.service13
-rw-r--r--test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service11
-rw-r--r--test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service11
-rw-r--r--test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service10
-rw-r--r--test/test-execute/exec-supplementarygroups-single-group-user.service10
-rw-r--r--test/test-execute/exec-supplementarygroups-single-group.service9
-rw-r--r--test/test-execute/exec-supplementarygroups.service8
-rw-r--r--test/test-execute/exec-systemcallerrornumber-name.service8
-rw-r--r--test/test-execute/exec-systemcallerrornumber-number.service8
-rw-r--r--test/test-execute/exec-systemcallfilter-failing.service10
-rw-r--r--test/test-execute/exec-systemcallfilter-failing2.service8
-rw-r--r--test/test-execute/exec-systemcallfilter-not-failing.service10
-rw-r--r--test/test-execute/exec-systemcallfilter-not-failing2.service7
-rw-r--r--test/test-execute/exec-systemcallfilter-override-error-action.service8
-rw-r--r--test/test-execute/exec-systemcallfilter-override-error-action2.service8
-rw-r--r--test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service11
-rw-r--r--test/test-execute/exec-systemcallfilter-system-user-nobody.service11
-rw-r--r--test/test-execute/exec-systemcallfilter-system-user.service11
-rw-r--r--test/test-execute/exec-systemcallfilter-with-errno-multi.service9
-rw-r--r--test/test-execute/exec-systemcallfilter-with-errno-name.service8
-rw-r--r--test/test-execute/exec-systemcallfilter-with-errno-number.service8
-rw-r--r--test/test-execute/exec-temporaryfilesystem-options.service16
-rw-r--r--test/test-execute/exec-temporaryfilesystem-ro.service36
-rw-r--r--test/test-execute/exec-temporaryfilesystem-rw.service36
-rw-r--r--test/test-execute/exec-temporaryfilesystem-usr.service15
-rw-r--r--test/test-execute/exec-umask-0177.service8
-rw-r--r--test/test-execute/exec-umask-default.service7
-rw-r--r--test/test-execute/exec-unsetenvironment.service8
-rw-r--r--test/test-execute/exec-user-nfsnobody.service7
-rw-r--r--test/test-execute/exec-user-nobody.service7
-rw-r--r--test/test-execute/exec-user.service7
-rw-r--r--test/test-execute/exec-workingdirectory-trailing-dot.service7
-rw-r--r--test/test-execute/exec-workingdirectory.service7
133 files changed, 1289 insertions, 0 deletions
diff --git a/test/test-execute/exec-ambientcapabilities-merge-nfsnobody.service b/test/test-execute/exec-ambientcapabilities-merge-nfsnobody.service
new file mode 100644
index 0000000..d2cadeb
--- /dev/null
+++ b/test/test-execute/exec-ambientcapabilities-merge-nfsnobody.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for AmbientCapabilities
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"'
+Type=oneshot
+User=nfsnobody
+AmbientCapabilities=CAP_CHOWN
+AmbientCapabilities=CAP_NET_RAW
diff --git a/test/test-execute/exec-ambientcapabilities-merge-nobody.service b/test/test-execute/exec-ambientcapabilities-merge-nobody.service
new file mode 100644
index 0000000..545081d
--- /dev/null
+++ b/test/test-execute/exec-ambientcapabilities-merge-nobody.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for AmbientCapabilities
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"'
+Type=oneshot
+User=nobody
+AmbientCapabilities=CAP_CHOWN
+AmbientCapabilities=CAP_NET_RAW
diff --git a/test/test-execute/exec-ambientcapabilities-merge.service b/test/test-execute/exec-ambientcapabilities-merge.service
new file mode 100644
index 0000000..2e3fe59
--- /dev/null
+++ b/test/test-execute/exec-ambientcapabilities-merge.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for AmbientCapabilities (daemon)
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"'
+Type=oneshot
+User=daemon
+AmbientCapabilities=CAP_CHOWN
+AmbientCapabilities=CAP_NET_RAW
diff --git a/test/test-execute/exec-ambientcapabilities-nfsnobody.service b/test/test-execute/exec-ambientcapabilities-nfsnobody.service
new file mode 100644
index 0000000..9377ee1
--- /dev/null
+++ b/test/test-execute/exec-ambientcapabilities-nfsnobody.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for AmbientCapabilities
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"'
+Type=oneshot
+User=nfsnobody
+AmbientCapabilities=CAP_CHOWN CAP_NET_RAW
diff --git a/test/test-execute/exec-ambientcapabilities-nobody.service b/test/test-execute/exec-ambientcapabilities-nobody.service
new file mode 100644
index 0000000..07a6c75
--- /dev/null
+++ b/test/test-execute/exec-ambientcapabilities-nobody.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for AmbientCapabilities
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"'
+Type=oneshot
+User=nobody
+AmbientCapabilities=CAP_CHOWN CAP_NET_RAW
diff --git a/test/test-execute/exec-ambientcapabilities.service b/test/test-execute/exec-ambientcapabilities.service
new file mode 100644
index 0000000..d91cc09
--- /dev/null
+++ b/test/test-execute/exec-ambientcapabilities.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for AmbientCapabilities (daemon)
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"'
+Type=oneshot
+User=daemon
+AmbientCapabilities=CAP_CHOWN CAP_NET_RAW
diff --git a/test/test-execute/exec-basic.service b/test/test-execute/exec-basic.service
new file mode 100644
index 0000000..60c5be6
--- /dev/null
+++ b/test/test-execute/exec-basic.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Test for basic execution
+ConditionKernelVersion=">=3.0"
+ConditionKernelVersion=">=2.0" "<=60" "!=1.4"
+ConditionKernelVersion=" >= 2.0" " <= 60 " "!= 1.4"
+ConditionKernelVersion=" >= 2.0" " * " "*.*"
+
+[Service]
+ExecStart=touch /tmp/a ; /bin/sh -c 'touch /tmp/b' ; touch /tmp/c
+ExecStart=test -f /tmp/a
+ExecStart=!test -f /tmp/b
+ExecStart=!!test -f /tmp/c
+ExecStartPost=rm /tmp/a /tmp/b /tmp/c
+
+PrivateTmp=true
+Type=oneshot
diff --git a/test/test-execute/exec-bindpaths.service b/test/test-execute/exec-bindpaths.service
new file mode 100644
index 0000000..edab18b
--- /dev/null
+++ b/test/test-execute/exec-bindpaths.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=Test for BindPaths= and BindReadOnlyPaths=
+
+[Service]
+Type=oneshot
+# Create a file in /tmp/test-exec-bindpaths
+ExecStart=touch /tmp/test-exec-bindpaths/thisisasimpletest
+# Then, the file can be access through /tmp
+ExecStart=test -f /tmp/thisisasimpletest
+# Also, through /tmp/test-exec-bindreadonlypaths
+ExecStart=test -f /tmp/test-exec-bindreadonlypaths/thisisasimpletest
+# The file cannot modify through /tmp/test-exec-bindreadonlypaths
+ExecStart=/bin/sh -x -c '! touch /tmp/test-exec-bindreadonlypaths/thisisasimpletest'
+# Cleanup
+ExecStart=rm /tmp/thisisasimpletest
+BindPaths=/tmp:/tmp/test-exec-bindpaths
+BindReadOnlyPaths=/tmp:/tmp/test-exec-bindreadonlypaths
diff --git a/test/test-execute/exec-capabilityboundingset-invert.service b/test/test-execute/exec-capabilityboundingset-invert.service
new file mode 100644
index 0000000..4486f6c
--- /dev/null
+++ b/test/test-execute/exec-capabilityboundingset-invert.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for CapabilityBoundingSet
+
+[Service]
+# sed: remove dropped (cap_xxx-[epi]) and IAB capabilities from the output
+ExecStart=/bin/sh -x -c '! capsh --print | sed -re "s/[^ ]+?\-[epi]+//g" -e '/IAB/d' | grep "^Bounding set .*cap_chown"'
+Type=oneshot
+CapabilityBoundingSet=~CAP_CHOWN
diff --git a/test/test-execute/exec-capabilityboundingset-merge.service b/test/test-execute/exec-capabilityboundingset-merge.service
new file mode 100644
index 0000000..5c7fcaf
--- /dev/null
+++ b/test/test-execute/exec-capabilityboundingset-merge.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for CapabilityBoundingSet
+
+[Service]
+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
diff --git a/test/test-execute/exec-capabilityboundingset-reset.service b/test/test-execute/exec-capabilityboundingset-reset.service
new file mode 100644
index 0000000..d7d3320
--- /dev/null
+++ b/test/test-execute/exec-capabilityboundingset-reset.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for CapabilityBoundingSet
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set ="'
+Type=oneshot
+CapabilityBoundingSet=CAP_FOWNER CAP_KILL
+CapabilityBoundingSet=
diff --git a/test/test-execute/exec-capabilityboundingset-simple.service b/test/test-execute/exec-capabilityboundingset-simple.service
new file mode 100644
index 0000000..bf1a7f5
--- /dev/null
+++ b/test/test-execute/exec-capabilityboundingset-simple.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for CapabilityBoundingSet
+
+[Service]
+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
diff --git a/test/test-execute/exec-condition-failed.service b/test/test-execute/exec-condition-failed.service
new file mode 100644
index 0000000..4a406dc
--- /dev/null
+++ b/test/test-execute/exec-condition-failed.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for exec condition that fails the unit
+
+[Service]
+Type=oneshot
+
+# exit 255 will fail the unit
+ExecCondition=/bin/sh -c 'exit 255'
+
+# This should not get run
+ExecStart=/bin/sh -c 'true'
diff --git a/test/test-execute/exec-condition-skip.service b/test/test-execute/exec-condition-skip.service
new file mode 100644
index 0000000..9450e84
--- /dev/null
+++ b/test/test-execute/exec-condition-skip.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Test for exec condition that triggers skipping
+
+[Service]
+Type=oneshot
+
+# exit codes [1, 254] will result in skipping the rest of execution
+ExecCondition=/bin/sh -c 'exit 0'
+ExecCondition=/bin/sh -c 'exit 254'
+
+# This would normally fail the unit but will not get run due to the skip above
+ExecCondition=/bin/sh -c 'exit 255'
+
+# This should not get run
+ExecStart=/bin/sh -c 'true'
diff --git a/test/test-execute/exec-cpuaffinity1.service b/test/test-execute/exec-cpuaffinity1.service
new file mode 100644
index 0000000..84d550a
--- /dev/null
+++ b/test/test-execute/exec-cpuaffinity1.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=Test for CPUAffinity (simple)
+
+[Service]
+ExecStart=/bin/sh -c 'test $$(cat /proc/self/status | grep Cpus_allowed: | rev | cut -c 1) = 1'
+CPUAffinity=0
diff --git a/test/test-execute/exec-cpuaffinity2.service b/test/test-execute/exec-cpuaffinity2.service
new file mode 100644
index 0000000..0dda77f
--- /dev/null
+++ b/test/test-execute/exec-cpuaffinity2.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for CPUAffinity (reset)
+
+[Service]
+ExecStart=/bin/sh -c 'test $$(cat /proc/self/status | grep Cpus_allowed: | rev | cut -c 1) = 1'
+CPUAffinity=0-1 3
+CPUAffinity=
+CPUAffinity=0
diff --git a/test/test-execute/exec-cpuaffinity3.service b/test/test-execute/exec-cpuaffinity3.service
new file mode 100644
index 0000000..4a45d3b
--- /dev/null
+++ b/test/test-execute/exec-cpuaffinity3.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for CPUAffinity (merge)
+
+[Service]
+ExecStart=/bin/sh -c 'test $$(cat /proc/self/status | grep Cpus_allowed: | rev | cut -c 1) = 7'
+CPUAffinity=0,1
+CPUAffinity=1-2
diff --git a/test/test-execute/exec-dynamicuser-fixeduser-adm.service b/test/test-execute/exec-dynamicuser-fixeduser-adm.service
new file mode 100644
index 0000000..90040ee
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-fixeduser-adm.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test DynamicUser with static User= whose uid and gid are different
+# On Fedora, user adm has uid==3 and gid==4.
+
+[Service]
+Type=oneshot
+ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "adm" && test "$$(id -ng)" = "adm" && test "$$(id -nu)" = "adm"'
+# Multiple ExecStart= lines causes the issue #9702.
+ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "adm" && test "$$(id -ng)" = "adm" && test "$$(id -nu)" = "adm"'
+DynamicUser=yes
+User=adm
diff --git a/test/test-execute/exec-dynamicuser-fixeduser-games.service b/test/test-execute/exec-dynamicuser-fixeduser-games.service
new file mode 100644
index 0000000..1cc9518
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-fixeduser-games.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test DynamicUser with static User= whose uid and gid are different
+# On Ubuntu or Debian, user games has uid==5 and gid==60.
+
+[Service]
+Type=oneshot
+ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "games" && test "$$(id -ng)" = "games" && test "$$(id -nu)" = "games"'
+# Multiple ExecStart= lines causes the issue #9702.
+ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "games" && test "$$(id -ng)" = "games" && test "$$(id -nu)" = "games"'
+DynamicUser=yes
+User=games
diff --git a/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service b/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service
new file mode 100644
index 0000000..bd7881d
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Test DynamicUser with User= and SupplementaryGroups=
+
+[Service]
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "1"'
+Type=oneshot
+User=1
+DynamicUser=yes
+SupplementaryGroups=1
diff --git a/test/test-execute/exec-dynamicuser-fixeduser.service b/test/test-execute/exec-dynamicuser-fixeduser.service
new file mode 100644
index 0000000..f28078f
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-fixeduser.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test DynamicUser with User=
+
+[Service]
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "1"'
+Type=oneshot
+User=1
+DynamicUser=yes
diff --git a/test/test-execute/exec-dynamicuser-runtimedirectory1.service b/test/test-execute/exec-dynamicuser-runtimedirectory1.service
new file mode 100644
index 0000000..a3e5662
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-runtimedirectory1.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for RuntimeDirectory with RuntimeDirectoryPreserve=yes and DynamicUser=yes
+
+[Service]
+ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectorypreserve'
+ExecStart=/bin/sh -x -c 'test "$$RUNTIME_DIRECTORY" = "%t/test-exec_runtimedirectorypreserve"'
+ExecStart=/bin/sh -x -c 'touch $$RUNTIME_DIRECTORY/test'
+Type=oneshot
+RuntimeDirectory=test-exec_runtimedirectorypreserve
+RuntimeDirectoryPreserve=yes
+DynamicUser=yes
diff --git a/test/test-execute/exec-dynamicuser-runtimedirectory2.service b/test/test-execute/exec-dynamicuser-runtimedirectory2.service
new file mode 100644
index 0000000..d7af699
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-runtimedirectory2.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Test for RuntimeDirectory with RuntimeDirectoryPreserve=yes and DynamicUser=yes 2nd trial
+
+[Service]
+ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectorypreserve'
+ExecStart=/bin/sh -x -c 'test "$$RUNTIME_DIRECTORY" = "%t/test-exec_runtimedirectorypreserve"'
+ExecStart=/bin/sh -x -c 'test -f $$RUNTIME_DIRECTORY/test'
+ExecStart=/bin/sh -x -c 'touch $$RUNTIME_DIRECTORY/test'
+Type=oneshot
+RuntimeDirectory=test-exec_runtimedirectorypreserve
+RuntimeDirectoryPreserve=yes
+DynamicUser=yes
diff --git a/test/test-execute/exec-dynamicuser-runtimedirectory3.service b/test/test-execute/exec-dynamicuser-runtimedirectory3.service
new file mode 100644
index 0000000..1ea47ef
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-runtimedirectory3.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for RuntimeDirectory with DynamicUser=yes migrated from RuntimeDirectoryPreserve=yes
+
+[Service]
+ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectorypreserve'
+ExecStart=/bin/sh -x -c 'test "$$RUNTIME_DIRECTORY" = "%t/test-exec_runtimedirectorypreserve"'
+ExecStart=/bin/sh -x -c 'test -f $$RUNTIME_DIRECTORY/test'
+ExecStart=/bin/sh -x -c 'touch $$RUNTIME_DIRECTORY/test'
+Type=oneshot
+RuntimeDirectory=test-exec_runtimedirectorypreserve
+DynamicUser=yes
diff --git a/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service b/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service
new file mode 100644
index 0000000..5efc548
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=Test DynamicUser= migrate StateDirectory= (preparation)
+
+[Service]
+ExecStart=test -w /var/lib/test-dynamicuser-migrate
+ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test ! -L /var/lib/test-dynamicuser-migrate
+ExecStart=test ! -L /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -d /var/lib/test-dynamicuser-migrate
+ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=touch /var/lib/test-dynamicuser-migrate/yay
+ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/test-dynamicuser-migrate:%S/test-dynamicuser-migrate2/hoge"'
+
+Type=oneshot
+DynamicUser=no
+StateDirectory=test-dynamicuser-migrate test-dynamicuser-migrate2/hoge
diff --git a/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service b/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service
new file mode 100644
index 0000000..c72302f
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service
@@ -0,0 +1,25 @@
+[Unit]
+Description=Test DynamicUser= migrate StateDirectory=
+
+[Service]
+ExecStart=test -w /var/lib/test-dynamicuser-migrate
+ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -L /var/lib/test-dynamicuser-migrate
+ExecStart=test -L /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -d /var/lib/test-dynamicuser-migrate
+ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge
+ExecStart=test -f /var/lib/test-dynamicuser-migrate/yay
+ExecStart=test -f /var/lib/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=test -d /var/lib/private/test-dynamicuser-migrate
+ExecStart=test -d /var/lib/private/test-dynamicuser-migrate2/hoge
+ExecStart=test -f /var/lib/private/test-dynamicuser-migrate/yay
+ExecStart=test -f /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=touch /var/lib/test-dynamicuser-migrate/yay
+ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=touch /var/lib/private/test-dynamicuser-migrate/yay
+ExecStart=touch /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay
+ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/test-dynamicuser-migrate:%S/test-dynamicuser-migrate2/hoge"'
+
+Type=oneshot
+DynamicUser=yes
+StateDirectory=test-dynamicuser-migrate test-dynamicuser-migrate2/hoge
diff --git a/test/test-execute/exec-dynamicuser-statedir.service b/test/test-execute/exec-dynamicuser-statedir.service
new file mode 100644
index 0000000..6103193
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-statedir.service
@@ -0,0 +1,20 @@
+[Unit]
+Description=Test DynamicUser= with StateDirectory=
+
+[Service]
+ExecStart=test -w /var/lib/waldo
+ExecStart=test -w /var/lib/quux/pief
+ExecStart=touch /var/lib/waldo/yay
+ExecStart=touch /var/lib/quux/pief/yayyay
+ExecStart=test -f /var/lib/waldo/yay
+ExecStart=test -f /var/lib/quux/pief/yayyay
+ExecStart=test -f /var/lib/private/waldo/yay
+ExecStart=test -f /var/lib/private/quux/pief/yayyay
+ExecStart=sh -x -c 'test "$$STATE_DIRECTORY" = "%S/waldo:%S/quux/pief"'
+
+# Make sure that /var/lib/private/waldo is really the only writable directory besides the obvious candidates
+ExecStart=sh -x -c 'test $$(find / \\( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf -o -path /dev/.lxc \\) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d "\\\\n") = /var/lib/private/quux/pief/var/lib/private/waldo'
+
+Type=oneshot
+DynamicUser=yes
+StateDirectory=waldo quux/pief
diff --git a/test/test-execute/exec-dynamicuser-supplementarygroups.service b/test/test-execute/exec-dynamicuser-supplementarygroups.service
new file mode 100644
index 0000000..e3549c2
--- /dev/null
+++ b/test/test-execute/exec-dynamicuser-supplementarygroups.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Test DynamicUser with SupplementaryGroups=
+
+[Service]
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1'
+Type=oneshot
+DynamicUser=yes
+SupplementaryGroups=1 2 3
diff --git a/test/test-execute/exec-environment-empty.service b/test/test-execute/exec-environment-empty.service
new file mode 100644
index 0000000..9c92d4b
--- /dev/null
+++ b/test/test-execute/exec-environment-empty.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for Environment
+
+[Service]
+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=
diff --git a/test/test-execute/exec-environment-multiple.service b/test/test-execute/exec-environment-multiple.service
new file mode 100644
index 0000000..b9bc225
--- /dev/null
+++ b/test/test-execute/exec-environment-multiple.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for Environment
+
+[Service]
+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"
diff --git a/test/test-execute/exec-environment-no-substitute.service b/test/test-execute/exec-environment-no-substitute.service
new file mode 100644
index 0000000..6a2e60e
--- /dev/null
+++ b/test/test-execute/exec-environment-no-substitute.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for No Environment Variable Substitution
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2}" = "word3" && test "$${VAR3-unset}" = \'$word 5 6\''
+ExecStart=:/bin/sh -x -c 'test "$${VAR1-unset}" != "unset" && test "$${VAR2}" != "word3" && test "$${VAR3-unset}" != \'$word 5 6\''
+Type=oneshot
+Environment="VAR2=word3" "VAR3=$word 5 6"
diff --git a/test/test-execute/exec-environment.service b/test/test-execute/exec-environment.service
new file mode 100644
index 0000000..06e77af
--- /dev/null
+++ b/test/test-execute/exec-environment.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Environment
+
+[Service]
+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"
diff --git a/test/test-execute/exec-environmentfile.service b/test/test-execute/exec-environmentfile.service
new file mode 100644
index 0000000..9bcb133
--- /dev/null
+++ b/test/test-execute/exec-environmentfile.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for EnvironmentFile
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes'
+Type=oneshot
+EnvironmentFile=/tmp/test-exec_environmentfile.conf
diff --git a/test/test-execute/exec-group-nfsnobody.service b/test/test-execute/exec-group-nfsnobody.service
new file mode 100644
index 0000000..e02100a
--- /dev/null
+++ b/test/test-execute/exec-group-nfsnobody.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Group
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "nfsnobody"'
+Type=oneshot
+Group=nfsnobody
diff --git a/test/test-execute/exec-group-nobody.service b/test/test-execute/exec-group-nobody.service
new file mode 100644
index 0000000..be7c796
--- /dev/null
+++ b/test/test-execute/exec-group-nobody.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Group
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "nobody"'
+Type=oneshot
+Group=nobody
diff --git a/test/test-execute/exec-group-nogroup.service b/test/test-execute/exec-group-nogroup.service
new file mode 100644
index 0000000..cf07732
--- /dev/null
+++ b/test/test-execute/exec-group-nogroup.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Group
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "nogroup"'
+Type=oneshot
+Group=nogroup
diff --git a/test/test-execute/exec-group.service b/test/test-execute/exec-group.service
new file mode 100644
index 0000000..be55992
--- /dev/null
+++ b/test/test-execute/exec-group.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Group (daemon)
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "daemon"'
+Type=oneshot
+Group=daemon
diff --git a/test/test-execute/exec-ignoresigpipe-no.service b/test/test-execute/exec-ignoresigpipe-no.service
new file mode 100644
index 0000000..73addf5
--- /dev/null
+++ b/test/test-execute/exec-ignoresigpipe-no.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for IgnoreSIGPIPE=no
+
+[Service]
+ExecStart=/bin/sh -x -c 'kill -PIPE 0'
+Type=oneshot
+IgnoreSIGPIPE=no
diff --git a/test/test-execute/exec-ignoresigpipe-yes.service b/test/test-execute/exec-ignoresigpipe-yes.service
new file mode 100644
index 0000000..f81c017
--- /dev/null
+++ b/test/test-execute/exec-ignoresigpipe-yes.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for IgnoreSIGPIPE=yes
+
+[Service]
+ExecStart=/bin/sh -x -c 'kill -PIPE 0'
+Type=oneshot
+IgnoreSIGPIPE=yes
diff --git a/test/test-execute/exec-inaccessiblepaths-mount-propagation.service b/test/test-execute/exec-inaccessiblepaths-mount-propagation.service
new file mode 100644
index 0000000..430a6b7
--- /dev/null
+++ b/test/test-execute/exec-inaccessiblepaths-mount-propagation.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test to make sure that InaccessiblePaths= disconnect mount propagation
+
+[Service]
+InaccessiblePaths=-/i-dont-exist
+ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo'
+Type=oneshot
diff --git a/test/test-execute/exec-inaccessiblepaths-sys.service b/test/test-execute/exec-inaccessiblepaths-sys.service
new file mode 100644
index 0000000..5ff6f36
--- /dev/null
+++ b/test/test-execute/exec-inaccessiblepaths-sys.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test to make sure that mount namespace setup works properly with the 'InaccessiblePaths=/proc' option
+
+[Service]
+InaccessiblePaths=/sys
+ExecStart=/bin/sh -x -c 'test "$$(stat -c %%a /sys)" = "0"'
+Type=oneshot
diff --git a/test/test-execute/exec-ioschedulingclass-best-effort.service b/test/test-execute/exec-ioschedulingclass-best-effort.service
new file mode 100644
index 0000000..29bb851
--- /dev/null
+++ b/test/test-execute/exec-ioschedulingclass-best-effort.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for IOSchedulingClass=best-effort
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "best-effort"'
+Type=oneshot
+IOSchedulingClass=best-effort
diff --git a/test/test-execute/exec-ioschedulingclass-idle.service b/test/test-execute/exec-ioschedulingclass-idle.service
new file mode 100644
index 0000000..87dbed1
--- /dev/null
+++ b/test/test-execute/exec-ioschedulingclass-idle.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for IOSchedulingClass=idle
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "idle"'
+Type=oneshot
+IOSchedulingClass=idle
diff --git a/test/test-execute/exec-ioschedulingclass-none.service b/test/test-execute/exec-ioschedulingclass-none.service
new file mode 100644
index 0000000..b6af122
--- /dev/null
+++ b/test/test-execute/exec-ioschedulingclass-none.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for IOSchedulingClass=none
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "none"'
+Type=oneshot
+IOSchedulingClass=none
diff --git a/test/test-execute/exec-ioschedulingclass-realtime.service b/test/test-execute/exec-ioschedulingclass-realtime.service
new file mode 100644
index 0000000..d920d5c
--- /dev/null
+++ b/test/test-execute/exec-ioschedulingclass-realtime.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for IOSchedulingClass=realtime
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "realtime"'
+Type=oneshot
+IOSchedulingClass=realtime
diff --git a/test/test-execute/exec-oomscoreadjust-negative.service b/test/test-execute/exec-oomscoreadjust-negative.service
new file mode 100644
index 0000000..2234c53
--- /dev/null
+++ b/test/test-execute/exec-oomscoreadjust-negative.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for OOMScoreAdjust
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(cat /proc/self/oom_score_adj); test "$$c" -eq -100'
+Type=oneshot
+OOMScoreAdjust=-100
diff --git a/test/test-execute/exec-oomscoreadjust-positive.service b/test/test-execute/exec-oomscoreadjust-positive.service
new file mode 100644
index 0000000..456a8f8
--- /dev/null
+++ b/test/test-execute/exec-oomscoreadjust-positive.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for OOMScoreAdjust
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(cat /proc/self/oom_score_adj); test "$$c" -eq 100'
+Type=oneshot
+OOMScoreAdjust=100
diff --git a/test/test-execute/exec-passenvironment-absent.service b/test/test-execute/exec-passenvironment-absent.service
new file mode 100644
index 0000000..d257e48
--- /dev/null
+++ b/test/test-execute/exec-passenvironment-absent.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for PassEnvironment with variables absent from the execution environment
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset" && test "$${VAR4-unset}" = "unset" && test "$${VAR5-unset}" = "unset"'
+Type=oneshot
+PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
diff --git a/test/test-execute/exec-passenvironment-empty.service b/test/test-execute/exec-passenvironment-empty.service
new file mode 100644
index 0000000..291259a
--- /dev/null
+++ b/test/test-execute/exec-passenvironment-empty.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for PassEnvironment and erasing the variable list
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset" && test "$${VAR4-unset}" = "unset" && test "$${VAR5-unset}" = "unset"'
+Type=oneshot
+PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
+PassEnvironment=
diff --git a/test/test-execute/exec-passenvironment-repeated.service b/test/test-execute/exec-passenvironment-repeated.service
new file mode 100644
index 0000000..e886998
--- /dev/null
+++ b/test/test-execute/exec-passenvironment-repeated.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Test for PassEnvironment with a variable name repeated
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes'
+Type=oneshot
+PassEnvironment=VAR1 VAR2
+PassEnvironment=VAR1 VAR3
+PassEnvironment=VAR1 VAR4
+PassEnvironment=VAR1 VAR5
diff --git a/test/test-execute/exec-passenvironment.service b/test/test-execute/exec-passenvironment.service
new file mode 100644
index 0000000..05c1bdf
--- /dev/null
+++ b/test/test-execute/exec-passenvironment.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for PassEnvironment
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes'
+Type=oneshot
+PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
diff --git a/test/test-execute/exec-personality-aarch64.service b/test/test-execute/exec-personality-aarch64.service
new file mode 100644
index 0000000..8511174
--- /dev/null
+++ b/test/test-execute/exec-personality-aarch64.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Personality=aarch64
+
+[Service]
+ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "aarch64")'
+Type=oneshot
+Personality=aarch64
diff --git a/test/test-execute/exec-personality-ppc64.service b/test/test-execute/exec-personality-ppc64.service
new file mode 100644
index 0000000..ccc2c8d
--- /dev/null
+++ b/test/test-execute/exec-personality-ppc64.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Personality=ppc64
+
+[Service]
+ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "ppc64")'
+Type=oneshot
+Personality=ppc64
diff --git a/test/test-execute/exec-personality-ppc64le.service b/test/test-execute/exec-personality-ppc64le.service
new file mode 100644
index 0000000..2a76250
--- /dev/null
+++ b/test/test-execute/exec-personality-ppc64le.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Personality=ppc64le
+
+[Service]
+ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "ppc64le")'
+Type=oneshot
+Personality=ppc64le
diff --git a/test/test-execute/exec-personality-s390.service b/test/test-execute/exec-personality-s390.service
new file mode 100644
index 0000000..89f7de8
--- /dev/null
+++ b/test/test-execute/exec-personality-s390.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Personality=s390
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "s390"'
+Type=oneshot
+Personality=s390
diff --git a/test/test-execute/exec-personality-x86-64.service b/test/test-execute/exec-personality-x86-64.service
new file mode 100644
index 0000000..433e69a
--- /dev/null
+++ b/test/test-execute/exec-personality-x86-64.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Personality=x86-64
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "x86_64"'
+Type=oneshot
+Personality=x86-64
diff --git a/test/test-execute/exec-personality-x86.service b/test/test-execute/exec-personality-x86.service
new file mode 100644
index 0000000..4ece7de
--- /dev/null
+++ b/test/test-execute/exec-personality-x86.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for Personality=x86
+
+[Service]
+ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "i686" -o "$$c" = "x86_64"'
+Type=oneshot
+Personality=x86
diff --git a/test/test-execute/exec-privatedevices-disabled-by-prefix.service b/test/test-execute/exec-privatedevices-disabled-by-prefix.service
new file mode 100644
index 0000000..19b1da5
--- /dev/null
+++ b/test/test-execute/exec-privatedevices-disabled-by-prefix.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for PrivateDevices=yes with prefix
+
+[Service]
+ExecStart=/bin/sh -x -c '! test -c /dev/kmsg'
+ExecStart=+/bin/sh -x -c 'test -c /dev/kmsg'
+Type=oneshot
+PrivateDevices=yes
diff --git a/test/test-execute/exec-privatedevices-no-capability-mknod.service b/test/test-execute/exec-privatedevices-no-capability-mknod.service
new file mode 100644
index 0000000..8f135be
--- /dev/null
+++ b/test/test-execute/exec-privatedevices-no-capability-mknod.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test CAP_MKNOD capability for PrivateDevices=no
+
+[Service]
+PrivateDevices=no
+# sed: remove dropped (cap_xxx-[epi]) and IAB capabilities from the output
+ExecStart=/bin/sh -x -c 'capsh --print | sed -re "s/[^ ]+?\-[epi]+//g" -e '/IAB/d' | grep cap_mknod'
+Type=oneshot
diff --git a/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service b/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service
new file mode 100644
index 0000000..30ce549
--- /dev/null
+++ b/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test CAP_SYS_RAWIO capability for PrivateDevices=no
+
+[Service]
+PrivateDevices=no
+# sed: remove dropped (cap_xxx-[epi]) and IAB capabilities from the output
+ExecStart=/bin/sh -x -c 'capsh --print | sed -re "s/[^ ]+?\-[epi]+//g" -e '/IAB/d' | grep cap_sys_rawio'
+Type=oneshot
diff --git a/test/test-execute/exec-privatedevices-no.service b/test/test-execute/exec-privatedevices-no.service
new file mode 100644
index 0000000..4ddbf18
--- /dev/null
+++ b/test/test-execute/exec-privatedevices-no.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for PrivateDevices=no
+
+[Service]
+ExecStart=/bin/sh -x -c 'test -c /dev/kmsg'
+Type=oneshot
+PrivateDevices=no
diff --git a/test/test-execute/exec-privatedevices-yes-capability-mknod.service b/test/test-execute/exec-privatedevices-yes-capability-mknod.service
new file mode 100644
index 0000000..b98cfb5
--- /dev/null
+++ b/test/test-execute/exec-privatedevices-yes-capability-mknod.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test CAP_MKNOD capability for PrivateDevices=yes
+
+[Service]
+PrivateDevices=yes
+# sed: remove dropped (cap_xxx-[epi]) and IAB capabilities from the output
+ExecStart=/bin/sh -x -c '! capsh --print | sed -re "s/[^ ]+?\-[epi]+//g" -e '/IAB/d' | grep cap_mknod'
+Type=oneshot
diff --git a/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service b/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service
new file mode 100644
index 0000000..5b0c070
--- /dev/null
+++ b/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test CAP_SYS_RAWIO capability for PrivateDevices=yes
+
+[Service]
+PrivateDevices=yes
+# sed: remove dropped (cap_xxx-[epi]) and IAB capabilities from the output
+ExecStart=/bin/sh -x -c '! capsh --print | sed -re "s/[^ ]+?\-[epi]+//g" -e '/IAB/d' | grep cap_sys_rawio'
+Type=oneshot
diff --git a/test/test-execute/exec-privatedevices-yes-with-group.service b/test/test-execute/exec-privatedevices-yes-with-group.service
new file mode 100644
index 0000000..70a7ed2
--- /dev/null
+++ b/test/test-execute/exec-privatedevices-yes-with-group.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Test Group=group is applied after PrivateDevices=yes
+
+[Service]
+PrivateDevices=yes
+Group=daemon
+Type=oneshot
+
+# Check the group applied
+ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "daemon"'
+
+# Check that the namespace applied
+ExecStart=/bin/sh -c 'test ! -c /dev/kmsg'
+
+# Check that the owning group of a node is not daemon (should be the host root)
+ExecStart=/bin/sh -x -c 'test ! "$$(stat -c %%G /dev/stderr)" = "daemon"'
diff --git a/test/test-execute/exec-privatedevices-yes.service b/test/test-execute/exec-privatedevices-yes.service
new file mode 100644
index 0000000..3516667
--- /dev/null
+++ b/test/test-execute/exec-privatedevices-yes.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for PrivateDevices=yes
+
+[Service]
+ExecStart=/bin/sh -c 'test ! -c /dev/kmsg'
+Type=oneshot
+PrivateDevices=yes
diff --git a/test/test-execute/exec-privatenetwork-yes.service b/test/test-execute/exec-privatenetwork-yes.service
new file mode 100644
index 0000000..8f5cbad
--- /dev/null
+++ b/test/test-execute/exec-privatenetwork-yes.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for PrivateNetwork
+
+[Service]
+ExecStart=/bin/sh -x -c '! ip link | grep -E "^[0-9]+: " | grep -Ev ": (lo|(erspan|gre|gretap|ip_vti|ip6_vti|ip6gre|ip6tnl|sit|tunl)0@.*):"'
+Type=oneshot
+PrivateNetwork=yes
diff --git a/test/test-execute/exec-privatetmp-disabled-by-prefix.service b/test/test-execute/exec-privatetmp-disabled-by-prefix.service
new file mode 100644
index 0000000..009e6be
--- /dev/null
+++ b/test/test-execute/exec-privatetmp-disabled-by-prefix.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for PrivateTmp=yes with prefix
+
+[Service]
+ExecStart=/bin/sh -x -c 'test ! -f /tmp/test-exec_privatetmp'
+ExecStart=+/bin/sh -x -c 'test -f /tmp/test-exec_privatetmp'
+Type=oneshot
+PrivateTmp=yes
diff --git a/test/test-execute/exec-privatetmp-no.service b/test/test-execute/exec-privatetmp-no.service
new file mode 100644
index 0000000..59f60f4
--- /dev/null
+++ b/test/test-execute/exec-privatetmp-no.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for PrivateTmp=no
+
+[Service]
+ExecStart=/bin/sh -x -c 'test -f /tmp/test-exec_privatetmp'
+Type=oneshot
+PrivateTmp=no
diff --git a/test/test-execute/exec-privatetmp-yes.service b/test/test-execute/exec-privatetmp-yes.service
new file mode 100644
index 0000000..907c291
--- /dev/null
+++ b/test/test-execute/exec-privatetmp-yes.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for PrivateTmp=yes
+
+[Service]
+ExecStart=/bin/sh -x -c 'test ! -f /tmp/test-exec_privatetmp'
+Type=oneshot
+PrivateTmp=yes
diff --git a/test/test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service b/test/test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service
new file mode 100644
index 0000000..1522ff8
--- /dev/null
+++ b/test/test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test ProtectHome=tmpfs vs ProtectSystem=strict
+# Test for #11276
+
+[Service]
+ProtectHome=tmpfs
+ProtectSystem=strict
+Type=oneshot
+ExecStart=/bin/sh -x -c 'test "$$(stat -fc %%T /home)" = "tmpfs"'
diff --git a/test/test-execute/exec-protectkernellogs-no-capabilities.service b/test/test-execute/exec-protectkernellogs-no-capabilities.service
new file mode 100644
index 0000000..36aae7c
--- /dev/null
+++ b/test/test-execute/exec-protectkernellogs-no-capabilities.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test CAP_SYSLOG for ProtectKernelLogs=no
+
+[Service]
+ProtectKernelLogs=no
+# sed: remove dropped (cap_xxx-[epi]) and IAB capabilities from the output
+ExecStart=/bin/sh -x -c 'capsh --print | sed -re "s/[^ ]+?\-[epi]+//g" -e '/IAB/d' | grep cap_syslog'
+Type=oneshot
diff --git a/test/test-execute/exec-protectkernellogs-yes-capabilities.service b/test/test-execute/exec-protectkernellogs-yes-capabilities.service
new file mode 100644
index 0000000..4a5f1a0
--- /dev/null
+++ b/test/test-execute/exec-protectkernellogs-yes-capabilities.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test CAP_SYSLOG for ProtectKernelLogs=yes
+
+[Service]
+ProtectKernelLogs=yes
+# sed: remove dropped (cap_xxx-[epi]) and IAB capabilities from the output
+ExecStart=/bin/sh -x -c '! capsh --print | sed -re "s/[^ ]+?\-[epi]+//g" -e '/IAB/d' | grep cap_syslog'
+Type=oneshot
diff --git a/test/test-execute/exec-protectkernelmodules-no-capabilities.service b/test/test-execute/exec-protectkernelmodules-no-capabilities.service
new file mode 100644
index 0000000..1b73656
--- /dev/null
+++ b/test/test-execute/exec-protectkernelmodules-no-capabilities.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test CAP_SYS_MODULE ProtectKernelModules=no
+
+[Service]
+ProtectKernelModules=no
+# sed: remove dropped (cap_xxx-[epi]) and IAB capabilities from the output
+ExecStart=/bin/sh -x -c 'capsh --print | sed -re "s/[^ ]+?\-[epi]+//g" -e '/IAB/d' | grep cap_sys_module'
+Type=oneshot
diff --git a/test/test-execute/exec-protectkernelmodules-yes-capabilities.service b/test/test-execute/exec-protectkernelmodules-yes-capabilities.service
new file mode 100644
index 0000000..e43e727
--- /dev/null
+++ b/test/test-execute/exec-protectkernelmodules-yes-capabilities.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test CAP_SYS_MODULE for ProtectKernelModules=yes
+
+[Service]
+ProtectKernelModules=yes
+# sed: remove dropped (cap_xxx-[epi]) and IAB capabilities from the output
+ExecStart=/bin/sh -x -c '! capsh --print | sed -re "s/[^ ]+?\-[epi]+//g" -e '/IAB/d' | grep cap_sys_module'
+Type=oneshot
diff --git a/test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service b/test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service
new file mode 100644
index 0000000..0775812
--- /dev/null
+++ b/test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test to make sure that passing ProtectKernelModules=yes disconnect mount propagation
+
+[Service]
+ProtectKernelModules=yes
+ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo'
+Type=oneshot
diff --git a/test/test-execute/exec-readonlypaths-mount-propagation.service b/test/test-execute/exec-readonlypaths-mount-propagation.service
new file mode 100644
index 0000000..7edb0da
--- /dev/null
+++ b/test/test-execute/exec-readonlypaths-mount-propagation.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test to make sure that passing ReadOnlyPaths= disconnect mount propagation
+
+[Service]
+ReadOnlyPaths=-/i-dont-exist
+ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo'
+Type=oneshot
diff --git a/test/test-execute/exec-readonlypaths-simple.service b/test/test-execute/exec-readonlypaths-simple.service
new file mode 100644
index 0000000..a9a7159
--- /dev/null
+++ b/test/test-execute/exec-readonlypaths-simple.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for ReadOnlyPaths=
+
+[Service]
+Type=oneshot
+# This should work, as we explicitly disable the effect of ReadOnlyPaths=
+ExecStart=+/bin/sh -c 'touch /tmp/thisisasimpletest'
+# This should also work, as we do not disable the effect of ReadOnlyPaths= but invert the exit code
+ExecStart=/bin/sh -x -c '! touch /tmp/thisisasimpletest'
+ExecStart=+/bin/sh -c 'rm /tmp/thisisasimpletest'
+ReadOnlyPaths=/tmp
diff --git a/test/test-execute/exec-readonlypaths-with-bindpaths.service b/test/test-execute/exec-readonlypaths-with-bindpaths.service
new file mode 100644
index 0000000..438c7de
--- /dev/null
+++ b/test/test-execute/exec-readonlypaths-with-bindpaths.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for ReadOnlyPaths=
+
+[Service]
+ReadOnlyPaths=/etc -/i-dont-exist /usr
+BindPaths=/etc:/tmp/etc2
+ExecStart=/bin/sh -x -c 'test ! -w /etc && test ! -w /usr && test ! -e /i-dont-exist && test -w /var'
+Type=oneshot
diff --git a/test/test-execute/exec-readonlypaths.service b/test/test-execute/exec-readonlypaths.service
new file mode 100644
index 0000000..a0ca68f
--- /dev/null
+++ b/test/test-execute/exec-readonlypaths.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for ReadOnlyPaths=
+
+[Service]
+ReadOnlyPaths=/usr /etc /sys /dev -/i-dont-exist
+PrivateDevices=yes
+ExecStart=/bin/sh -x -c 'test ! -w /usr && test ! -w /etc && test ! -w /sys && test ! -w /sys/fs/cgroup'
+ExecStart=/bin/sh -x -c 'test ! -w /dev && test ! -w /dev/shm && test ! -e /i-dont-exist && test -w /var'
+Type=oneshot
diff --git a/test/test-execute/exec-readwritepaths-mount-propagation.service b/test/test-execute/exec-readwritepaths-mount-propagation.service
new file mode 100644
index 0000000..b38978d
--- /dev/null
+++ b/test/test-execute/exec-readwritepaths-mount-propagation.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test to make sure that passing ReadWritePaths= disconnect mount propagation
+
+[Service]
+ReadWritePaths=-/i-dont-exist
+ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo'
+Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-merge-all.service b/test/test-execute/exec-restrictnamespaces-merge-all.service
new file mode 100644
index 0000000..de98cd0
--- /dev/null
+++ b/test/test-execute/exec-restrictnamespaces-merge-all.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test merging RestrictNamespaces= with all flags
+
+[Service]
+RestrictNamespaces=mnt pid cgroup net uts ipc user
+RestrictNamespaces=net
+ExecStart=unshare -m -u -i -n -p -f
+Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-merge-and.service b/test/test-execute/exec-restrictnamespaces-merge-and.service
new file mode 100644
index 0000000..6702e6a
--- /dev/null
+++ b/test/test-execute/exec-restrictnamespaces-merge-and.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test merging RestrictNamespaces= with AND
+
+[Service]
+RestrictNamespaces=mnt pid
+RestrictNamespaces=~mnt usr
+ExecStart=unshare -p -f
+ExecStart=sh -c '! unshare -m -u -i -n'
+Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-merge-or.service b/test/test-execute/exec-restrictnamespaces-merge-or.service
new file mode 100644
index 0000000..a524552
--- /dev/null
+++ b/test/test-execute/exec-restrictnamespaces-merge-or.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test merging RestrictNamespaces= with OR
+
+[Service]
+RestrictNamespaces=mnt pid
+RestrictNamespaces=mnt uts
+ExecStart=unshare -m -u -p -f
+ExecStart=sh -c '! unshare -u -i -n'
+Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-mnt-deny-list.service b/test/test-execute/exec-restrictnamespaces-mnt-deny-list.service
new file mode 100644
index 0000000..7756a25
--- /dev/null
+++ b/test/test-execute/exec-restrictnamespaces-mnt-deny-list.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test RestrictNamespaces=~mnt
+
+[Service]
+RestrictNamespaces=~mnt
+ExecStart=unshare -m
+Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-mnt.service b/test/test-execute/exec-restrictnamespaces-mnt.service
new file mode 100644
index 0000000..2c5b942
--- /dev/null
+++ b/test/test-execute/exec-restrictnamespaces-mnt.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test RestrictNamespaces=mnt
+
+[Service]
+RestrictNamespaces=mnt
+ExecStart=unshare -m
+Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-no.service b/test/test-execute/exec-restrictnamespaces-no.service
new file mode 100644
index 0000000..5ffe081
--- /dev/null
+++ b/test/test-execute/exec-restrictnamespaces-no.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test RestrictNamespaces=no
+
+[Service]
+RestrictNamespaces=no
+ExecStart=unshare -m -u -i -n -p -f
+Type=oneshot
diff --git a/test/test-execute/exec-restrictnamespaces-yes.service b/test/test-execute/exec-restrictnamespaces-yes.service
new file mode 100644
index 0000000..8e077ed
--- /dev/null
+++ b/test/test-execute/exec-restrictnamespaces-yes.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test RestrictNamespaces=yes
+
+[Service]
+RestrictNamespaces=yes
+ExecStart=unshare -m
+Type=oneshot
diff --git a/test/test-execute/exec-runtimedirectory-mode.service b/test/test-execute/exec-runtimedirectory-mode.service
new file mode 100644
index 0000000..85ae516
--- /dev/null
+++ b/test/test-execute/exec-runtimedirectory-mode.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for RuntimeDirectoryMode
+
+[Service]
+ExecStart=/bin/sh -x -c 'mode=$$(stat -c %%a %t/test-exec_runtimedirectory-mode); test "$$mode" = "750"'
+ExecStart=/bin/sh -x -c 'test "$$RUNTIME_DIRECTORY" = "%t/test-exec_runtimedirectory-mode"'
+Type=oneshot
+RuntimeDirectory=test-exec_runtimedirectory-mode
+RuntimeDirectoryMode=0750
diff --git a/test/test-execute/exec-runtimedirectory-owner-nfsnobody.service b/test/test-execute/exec-runtimedirectory-owner-nfsnobody.service
new file mode 100644
index 0000000..1e3b6b4
--- /dev/null
+++ b/test/test-execute/exec-runtimedirectory-owner-nfsnobody.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set)
+
+[Service]
+ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G %t/test-exec_runtimedirectory-owner); test "$$group" = "nfsnobody"'
+Type=oneshot
+Group=nfsnobody
+User=root
+RuntimeDirectory=test-exec_runtimedirectory-owner
diff --git a/test/test-execute/exec-runtimedirectory-owner-nobody.service b/test/test-execute/exec-runtimedirectory-owner-nobody.service
new file mode 100644
index 0000000..54782f9
--- /dev/null
+++ b/test/test-execute/exec-runtimedirectory-owner-nobody.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set)
+
+[Service]
+ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G %t/test-exec_runtimedirectory-owner); test "$$group" = "nobody"'
+Type=oneshot
+Group=nobody
+User=root
+RuntimeDirectory=test-exec_runtimedirectory-owner
diff --git a/test/test-execute/exec-runtimedirectory-owner-nogroup.service b/test/test-execute/exec-runtimedirectory-owner-nogroup.service
new file mode 100644
index 0000000..663afe1
--- /dev/null
+++ b/test/test-execute/exec-runtimedirectory-owner-nogroup.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set)
+
+[Service]
+ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G %t/test-exec_runtimedirectory-owner); test "$$group" = "nogroup"'
+Type=oneshot
+Group=nogroup
+User=root
+RuntimeDirectory=test-exec_runtimedirectory-owner
diff --git a/test/test-execute/exec-runtimedirectory-owner.service b/test/test-execute/exec-runtimedirectory-owner.service
new file mode 100644
index 0000000..07dd7ca
--- /dev/null
+++ b/test/test-execute/exec-runtimedirectory-owner.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set)
+
+[Service]
+ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G %t/test-exec_runtimedirectory-owner-daemon); test "$$group" = "daemon"'
+Type=oneshot
+Group=daemon
+User=root
+RuntimeDirectory=test-exec_runtimedirectory-owner-daemon
diff --git a/test/test-execute/exec-runtimedirectory.service b/test/test-execute/exec-runtimedirectory.service
new file mode 100644
index 0000000..a33044d
--- /dev/null
+++ b/test/test-execute/exec-runtimedirectory.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Test for RuntimeDirectory
+
+[Service]
+ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectory'
+ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectory2/hogehoge'
+ExecStart=/bin/sh -x -c 'test "$$RUNTIME_DIRECTORY" = "%t/test-exec_runtimedirectory:%t/test-exec_runtimedirectory2/hogehoge"'
+Type=oneshot
+RuntimeDirectory=test-exec_runtimedirectory
+RuntimeDirectory=./test-exec_runtimedirectory2///./hogehoge/.
diff --git a/test/test-execute/exec-specifier-interpolation.service b/test/test-execute/exec-specifier-interpolation.service
new file mode 100644
index 0000000..f128e3c
--- /dev/null
+++ b/test/test-execute/exec-specifier-interpolation.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=https://github.com/systemd/systemd/issues/2637
+
+[Service]
+Type=oneshot
+ExecStart=/bin/sh -x -c "! test -x perl || perl -e 'exit(!(qq{%%U} eq qq{\\x25U}))'"
diff --git a/test/test-execute/exec-specifier.service b/test/test-execute/exec-specifier.service
new file mode 100644
index 0000000..a58abc6
--- /dev/null
+++ b/test/test-execute/exec-specifier.service
@@ -0,0 +1,31 @@
+[Unit]
+Description=Test for specifiers
+
+[Service]
+Type=oneshot
+ExecStart=test %n = exec-specifier.service
+ExecStart=test %N = exec-specifier
+ExecStart=test %p = exec-specifier
+ExecStart=test %P = exec/specifier
+ExecStart=test %i = ""
+ExecStart=test %I = ""
+ExecStart=test %j = specifier
+ExecStart=test %J = specifier
+ExecStart=test %f = /exec/specifier
+ExecStart=test %t = /run
+ExecStart=test %S = /var/lib
+ExecStart=test %C = /var/cache
+ExecStart=test %L = /var/log
+ExecStart=test %E = /etc
+ExecStart=test %T = /tmp
+ExecStart=test %V = /var/tmp
+ExecStart=sh -c 'test %u = $$(id -un)'
+ExecStart=sh -c 'test %U = $$(id -u)'
+ExecStart=sh -c 'test %g = $$(id -gn)'
+ExecStart=sh -c 'test %G = $$(id -g)'
+ExecStart=test %h = /root
+ExecStart=sh -c 'test %s = /bin/sh'
+ExecStart=sh -c 'test %m = $$(cat /etc/machine-id)'
+ExecStart=sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
+ExecStart=sh -c 'test %H = $$(uname -n)'
+ExecStart=sh -c 'test %v = $$(uname -r)'
diff --git a/test/test-execute/exec-specifier@.service b/test/test-execute/exec-specifier@.service
new file mode 100644
index 0000000..faecbf3
--- /dev/null
+++ b/test/test-execute/exec-specifier@.service
@@ -0,0 +1,29 @@
+[Unit]
+Description=Test for specifiers (template unit)
+
+[Service]
+Type=oneshot
+ExecStart=test %n = exec-specifier@foo-bar.service
+ExecStart=test %N = exec-specifier@foo-bar
+ExecStart=test %p = exec-specifier
+ExecStart=test %P = exec/specifier
+ExecStart=test %i = foo-bar
+ExecStart=test %I = foo/bar
+ExecStart=test %j = specifier
+ExecStart=test %J = specifier
+ExecStart=test %f = /foo/bar
+ExecStart=test %t = /run
+ExecStart=test %S = /var/lib
+ExecStart=test %C = /var/cache
+ExecStart=test %L = /var/log
+ExecStart=test %E = /etc
+ExecStart=sh -c 'test %u = $$(id -un)'
+ExecStart=sh -c 'test %U = $$(id -u)'
+ExecStart=sh -c 'test %g = $$(id -gn)'
+ExecStart=sh -c 'test %G = $$(id -g)'
+ExecStart=test %h = /root
+ExecStart=sh -c 'test %s = /bin/sh'
+ExecStart=sh -c 'test %m = $$(cat /etc/machine-id)'
+ExecStart=sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')'
+ExecStart=sh -c 'test %H = $$(uname -n)'
+ExecStart=sh -c 'test %v = $$(uname -r)'
diff --git a/test/test-execute/exec-standardinput-data.service b/test/test-execute/exec-standardinput-data.service
new file mode 100644
index 0000000..1ca536f
--- /dev/null
+++ b/test/test-execute/exec-standardinput-data.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=Test for StandardInputText= and StandardInputData=
+
+[Service]
+ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); echo -e "this is a test\nand this is more\nsomething encoded!\nsomething in multiple lines\nand some more\nand a more bas64 data\nsomething with strange\nembedded\tcharacters\nand something with a exec-stdin-data.service specifier" > $d/text ; cmp $d/text ; rm -rf $d'
+Type=oneshot
+StandardInput=data
+StandardInputText=this is a test
+StandardInputText=and this is more
+StandardInputData=c29tZXRoaW5nIGVuY29kZWQhCg==
+StandardInputText=something \
+ in multiple lines
+StandardInputText=\
+and some more
+StandardInputData=YW5kIGEgbW9y \
+ ZSBiYXM2NCBk\
+YXRhCg==
+StandardInputText=something with strange\nembedded\tcharacters
+StandardInputText=and something with a %n specifier
diff --git a/test/test-execute/exec-standardinput-file-cat.service b/test/test-execute/exec-standardinput-file-cat.service
new file mode 100644
index 0000000..a0c786c
--- /dev/null
+++ b/test/test-execute/exec-standardinput-file-cat.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for StandardInput=file:
+
+[Service]
+ExecStart=cat
+Type=oneshot
+StandardInput=file:/etc/os-release
+# We leave StandardOutput= unset here, to verify https://github.com/systemd/systemd/issues/14560 works
+# The "cat" tool is going to write to stdout, which fails if we dup() stdin to stdout
diff --git a/test/test-execute/exec-standardinput-file.service b/test/test-execute/exec-standardinput-file.service
new file mode 100644
index 0000000..8fd11ca
--- /dev/null
+++ b/test/test-execute/exec-standardinput-file.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for StandardInput=file:
+
+[Service]
+ExecStart=/usr/bin/cmp /usr/bin/cmp
+Type=oneshot
+StandardInput=file:/usr/bin/cmp
diff --git a/test/test-execute/exec-standardoutput-append.service b/test/test-execute/exec-standardoutput-append.service
new file mode 100644
index 0000000..8983bb0
--- /dev/null
+++ b/test/test-execute/exec-standardoutput-append.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Test for StandardOutput=append:
+
+[Service]
+ExecStartPre=sh -c 'printf "hello\n" > /tmp/test-exec-standardoutput-output'
+ExecStartPre=sh -c 'printf "hello\nhello\n" > /tmp/test-exec-standardoutput-expected'
+StandardInput=data
+StandardInputText=hello
+StandardOutput=append:/tmp/test-exec-standardoutput-output
+StandardError=null
+ExecStart=cat
+ExecStart=cmp /tmp/test-exec-standardoutput-output /tmp/test-exec-standardoutput-expected
+Type=oneshot
diff --git a/test/test-execute/exec-standardoutput-file.service b/test/test-execute/exec-standardoutput-file.service
new file mode 100644
index 0000000..71e2604
--- /dev/null
+++ b/test/test-execute/exec-standardoutput-file.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Test for StandardOutput=file:
+
+[Service]
+ExecStartPre=sh -c 'printf "nooo\nhello\n" > /tmp/test-exec-standardoutput-output'
+ExecStartPre=sh -c 'printf "hello\nello\n" > /tmp/test-exec-standardoutput-expected'
+StandardInput=data
+StandardInputText=hello
+StandardOutput=file:/tmp/test-exec-standardoutput-output
+StandardError=null
+ExecStart=cat
+ExecStart=cmp /tmp/test-exec-standardoutput-expected /tmp/test-exec-standardoutput-output
+Type=oneshot
diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service b/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service
new file mode 100644
index 0000000..2a7ce87
--- /dev/null
+++ b/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for Supplementary Group with multiple groups without Group and User
+
+[Service]
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "%G" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "%G" && test "$$(id -u)" = "%U"'
+Type=oneshot
+SupplementaryGroups=1 2 3
diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service b/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service
new file mode 100644
index 0000000..aae20fb
--- /dev/null
+++ b/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for Supplementary Group with multiple groups and Group=1
+
+[Service]
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "%U"'
+Type=oneshot
+Group=1
+SupplementaryGroups=1 2 3
diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service b/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service
new file mode 100644
index 0000000..2714235
--- /dev/null
+++ b/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Test for Supplementary Group with multiple groups and Uid=1
+
+[Service]
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1'
+Type=oneshot
+User=1
+SupplementaryGroups=1 2 3
diff --git a/test/test-execute/exec-supplementarygroups-single-group-user.service b/test/test-execute/exec-supplementarygroups-single-group-user.service
new file mode 100644
index 0000000..405c5f9
--- /dev/null
+++ b/test/test-execute/exec-supplementarygroups-single-group-user.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Test for Supplementary Group with only one group and uid 1
+
+[Service]
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "1"'
+Type=oneshot
+User=1
+Group=1
+SupplementaryGroups=1
diff --git a/test/test-execute/exec-supplementarygroups-single-group.service b/test/test-execute/exec-supplementarygroups-single-group.service
new file mode 100644
index 0000000..f9b7216
--- /dev/null
+++ b/test/test-execute/exec-supplementarygroups-single-group.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for Supplementary Group with only one group
+
+[Service]
+ExecStart=/bin/sh -x -c 'HAVE=; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "0"'
+Type=oneshot
+Group=1
+SupplementaryGroups=1
diff --git a/test/test-execute/exec-supplementarygroups.service b/test/test-execute/exec-supplementarygroups.service
new file mode 100644
index 0000000..6f6e2ba
--- /dev/null
+++ b/test/test-execute/exec-supplementarygroups.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for Supplementary Group
+
+[Service]
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "%G" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+Type=oneshot
+SupplementaryGroups=1
diff --git a/test/test-execute/exec-systemcallerrornumber-name.service b/test/test-execute/exec-systemcallerrornumber-name.service
new file mode 100644
index 0000000..e167d27
--- /dev/null
+++ b/test/test-execute/exec-systemcallerrornumber-name.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for SystemCallErrorNumber
+
+[Service]
+ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
+Type=oneshot
+SystemCallFilter=~uname
+SystemCallErrorNumber=EACCES
diff --git a/test/test-execute/exec-systemcallerrornumber-number.service b/test/test-execute/exec-systemcallerrornumber-number.service
new file mode 100644
index 0000000..2032156
--- /dev/null
+++ b/test/test-execute/exec-systemcallerrornumber-number.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for SystemCallErrorNumber
+
+[Service]
+ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
+Type=oneshot
+SystemCallFilter=~uname
+SystemCallErrorNumber=255
diff --git a/test/test-execute/exec-systemcallfilter-failing.service b/test/test-execute/exec-systemcallfilter-failing.service
new file mode 100644
index 0000000..996f859
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-failing.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Test for SystemCallFilter
+
+[Service]
+ExecStart=/bin/sh -c 'echo "This should not be seen"'
+Type=oneshot
+LimitCORE=0
+SystemCallFilter=ioperm
+SystemCallFilter=~ioperm
+SystemCallFilter=ioperm
diff --git a/test/test-execute/exec-systemcallfilter-failing2.service b/test/test-execute/exec-systemcallfilter-failing2.service
new file mode 100644
index 0000000..c74f422
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-failing2.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for SystemCallFilter
+
+[Service]
+ExecStart=/bin/sh -c 'echo "This should not be seen"'
+Type=oneshot
+LimitCORE=0
+SystemCallFilter=~write open execve exit_group close mmap munmap fstat DONOTEXIST
diff --git a/test/test-execute/exec-systemcallfilter-not-failing.service b/test/test-execute/exec-systemcallfilter-not-failing.service
new file mode 100644
index 0000000..f3a752b
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-not-failing.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Test for SystemCallFilter
+
+[Service]
+ExecStart=/bin/sh -c 'echo "Foo bar"'
+Type=oneshot
+SystemCallFilter=~read write open execve ioperm
+SystemCallFilter=ioctl
+SystemCallFilter=read write open execve
+SystemCallFilter=~ioperm
diff --git a/test/test-execute/exec-systemcallfilter-not-failing2.service b/test/test-execute/exec-systemcallfilter-not-failing2.service
new file mode 100644
index 0000000..1df076a
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-not-failing2.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for SystemCallFilter
+
+[Service]
+ExecStart=/bin/sh -c 'echo "Foo bar"'
+Type=oneshot
+SystemCallFilter=
diff --git a/test/test-execute/exec-systemcallfilter-override-error-action.service b/test/test-execute/exec-systemcallfilter-override-error-action.service
new file mode 100644
index 0000000..3569b45
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-override-error-action.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for SystemCallFilter with specific kill action overriding default errno action
+
+[Service]
+ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
+Type=oneshot
+SystemCallFilter=~uname:kill
+SystemCallErrorNumber=EILSEQ
diff --git a/test/test-execute/exec-systemcallfilter-override-error-action2.service b/test/test-execute/exec-systemcallfilter-override-error-action2.service
new file mode 100644
index 0000000..04bfd6b
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-override-error-action2.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for SystemCallFilter with specific errno action overriding default kill action
+
+[Service]
+ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
+Type=oneshot
+SystemCallFilter=~uname:EILSEQ
+SystemCallErrorNumber=kill
diff --git a/test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service b/test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service
new file mode 100644
index 0000000..b1195d0
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for SystemCallFilter in system mode with User set
+
+[Service]
+ExecStart=/bin/sh -c 'echo "Foo bar"'
+Type=oneshot
+User=nfsnobody
+SystemCallFilter=~read write open execve ioperm
+SystemCallFilter=ioctl
+SystemCallFilter=read write open execve
+SystemCallFilter=~ioperm
diff --git a/test/test-execute/exec-systemcallfilter-system-user-nobody.service b/test/test-execute/exec-systemcallfilter-system-user-nobody.service
new file mode 100644
index 0000000..da129a3
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-system-user-nobody.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for SystemCallFilter in system mode with User set
+
+[Service]
+ExecStart=/bin/sh -c 'echo "Foo bar"'
+Type=oneshot
+User=nobody
+SystemCallFilter=~read write open execve ioperm
+SystemCallFilter=ioctl
+SystemCallFilter=read write open execve
+SystemCallFilter=~ioperm
diff --git a/test/test-execute/exec-systemcallfilter-system-user.service b/test/test-execute/exec-systemcallfilter-system-user.service
new file mode 100644
index 0000000..488a3bb
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-system-user.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Test for SystemCallFilter in system mode with User set (daemon)
+
+[Service]
+ExecStart=/bin/sh -c 'echo "Foo bar"'
+Type=oneshot
+User=daemon
+SystemCallFilter=~read write open execve ioperm
+SystemCallFilter=ioctl
+SystemCallFilter=read write open execve
+SystemCallFilter=~ioperm
diff --git a/test/test-execute/exec-systemcallfilter-with-errno-multi.service b/test/test-execute/exec-systemcallfilter-with-errno-multi.service
new file mode 100644
index 0000000..951e7ac
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-with-errno-multi.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Test for SystemCallFilter updating errno
+# test for issue #9939 which is fixed by a5404992cc7724ebf7572a0aa89d9fdb26ce0b62 (#9942)
+
+[Service]
+ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
+Type=oneshot
+SystemCallFilter=~uname:ENOENT uname:EILSEQ
+SystemCallErrorNumber=EACCES
diff --git a/test/test-execute/exec-systemcallfilter-with-errno-name.service b/test/test-execute/exec-systemcallfilter-with-errno-name.service
new file mode 100644
index 0000000..8380d5a
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-with-errno-name.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for SystemCallFilter with errno name
+
+[Service]
+ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
+Type=oneshot
+SystemCallFilter=~uname:EILSEQ
+SystemCallErrorNumber=EACCES
diff --git a/test/test-execute/exec-systemcallfilter-with-errno-number.service b/test/test-execute/exec-systemcallfilter-with-errno-number.service
new file mode 100644
index 0000000..dbb9540
--- /dev/null
+++ b/test/test-execute/exec-systemcallfilter-with-errno-number.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for SystemCallFilter with errno number
+
+[Service]
+ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)'
+Type=oneshot
+SystemCallFilter=~uname:255
+SystemCallErrorNumber=EACCES
diff --git a/test/test-execute/exec-temporaryfilesystem-options.service b/test/test-execute/exec-temporaryfilesystem-options.service
new file mode 100644
index 0000000..371e567
--- /dev/null
+++ b/test/test-execute/exec-temporaryfilesystem-options.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Test for TemporaryFileSystem with mount options
+
+[Service]
+Type=oneshot
+
+# The mount options default to "mode=0755,nodev,strictatime".
+# Let's override some of them, and test "ro".
+TemporaryFileSystem=/var:ro,mode=0700,nostrictatime
+
+# Check /proc/self/mountinfo
+ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$11 !~ /(^|,)mode=700(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""'
+
+ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$6 !~ /(^|,)ro(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""'
+ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$6 !~ /(^|,)nodev(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""'
+ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$6 ~ /(^|,)strictatime(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""'
diff --git a/test/test-execute/exec-temporaryfilesystem-ro.service b/test/test-execute/exec-temporaryfilesystem-ro.service
new file mode 100644
index 0000000..c161aec
--- /dev/null
+++ b/test/test-execute/exec-temporaryfilesystem-ro.service
@@ -0,0 +1,36 @@
+[Unit]
+Description=Test for TemporaryFileSystem with read-only mode
+
+[Service]
+Type=oneshot
+
+# Check directories exist
+ExecStart=/bin/sh -c 'test -d /var/test-exec-temporaryfilesystem/rw && test -d /var/test-exec-temporaryfilesystem/ro'
+
+# Check TemporaryFileSystem= are empty
+ExecStart=/bin/sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
+
+# Check default mode
+ExecStart=sh -x -c 'test "$$(stat -c %%a /var)" = "755"'
+
+# Cannot create a file in /var
+ExecStart=/bin/sh -c '! touch /var/hoge'
+
+# Create a file in /var/test-exec-temporaryfilesystem/rw
+ExecStart=/bin/sh -c 'touch /var/test-exec-temporaryfilesystem/rw/thisisasimpletest-temporaryfilesystem'
+
+# Then, the file can be access through /tmp
+ExecStart=/bin/sh -c 'test -f /tmp/thisisasimpletest-temporaryfilesystem'
+
+# Also, through /var/test-exec-temporaryfilesystem/ro
+ExecStart=/bin/sh -c 'test -f /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem'
+
+# The file cannot modify through /var/test-exec-temporaryfilesystem/ro
+ExecStart=/bin/sh -c '! touch /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem'
+
+# Cleanup
+ExecStart=/bin/sh -c 'rm /tmp/thisisasimpletest-temporaryfilesystem'
+
+TemporaryFileSystem=/var:ro
+BindPaths=/tmp:/var/test-exec-temporaryfilesystem/rw
+BindReadOnlyPaths=/tmp:/var/test-exec-temporaryfilesystem/ro
diff --git a/test/test-execute/exec-temporaryfilesystem-rw.service b/test/test-execute/exec-temporaryfilesystem-rw.service
new file mode 100644
index 0000000..bb83059
--- /dev/null
+++ b/test/test-execute/exec-temporaryfilesystem-rw.service
@@ -0,0 +1,36 @@
+[Unit]
+Description=Test for TemporaryFileSystem
+
+[Service]
+Type=oneshot
+
+# Check directories exist
+ExecStart=test -d /var/test-exec-temporaryfilesystem/rw -a -d /var/test-exec-temporaryfilesystem/ro
+
+# Check TemporaryFileSystem= are empty
+ExecStart=sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done'
+
+# Check default mode
+ExecStart=sh -x -c 'test "$$(stat -c %%a /var)" = "755"'
+
+# Create a file in /var
+ExecStart=touch /var/hoge
+
+# Create a file in /var/test-exec-temporaryfilesystem/rw
+ExecStart=touch /var/test-exec-temporaryfilesystem/rw/thisisasimpletest-temporaryfilesystem
+
+# Then, the file can be access through /tmp
+ExecStart=test -f /tmp/thisisasimpletest-temporaryfilesystem
+
+# Also, through /var/test-exec-temporaryfilesystem/ro
+ExecStart=test -f /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem
+
+# The file cannot modify through /var/test-exec-temporaryfilesystem/ro
+ExecStart=sh -c '! touch /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem'
+
+# Cleanup
+ExecStart=rm /tmp/thisisasimpletest-temporaryfilesystem
+
+TemporaryFileSystem=/var
+BindPaths=/tmp:/var/test-exec-temporaryfilesystem/rw
+BindReadOnlyPaths=/tmp:/var/test-exec-temporaryfilesystem/ro
diff --git a/test/test-execute/exec-temporaryfilesystem-usr.service b/test/test-execute/exec-temporaryfilesystem-usr.service
new file mode 100644
index 0000000..05c1ec0
--- /dev/null
+++ b/test/test-execute/exec-temporaryfilesystem-usr.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Test for TemporaryFileSystem on /usr
+
+[Service]
+Type=oneshot
+
+# Check TemporaryFileSystem= are empty
+ExecStart=/bin/sh -c 'for i in $$(ls -A /usr); do test $$i = lib -o $$i = lib64 -o $$i = bin -o $$i = sbin || false; done'
+
+# Cannot create files under /usr
+ExecStart=/bin/sh -c '! touch /usr/hoge'
+ExecStart=/bin/sh -c '! touch /usr/bin/hoge'
+
+TemporaryFileSystem=/usr:ro
+BindReadOnlyPaths=-/usr/lib -/usr/lib64 /usr/bin /usr/sbin
diff --git a/test/test-execute/exec-umask-0177.service b/test/test-execute/exec-umask-0177.service
new file mode 100644
index 0000000..c18293e
--- /dev/null
+++ b/test/test-execute/exec-umask-0177.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for UMask
+
+[Service]
+ExecStart=/bin/sh -x -c 'rm /tmp/test-exec-umask; touch /tmp/test-exec-umask; mode=$$(stat -c %%a /tmp/test-exec-umask); test "$$mode" = "600"'
+Type=oneshot
+UMask=0177
+PrivateTmp=yes
diff --git a/test/test-execute/exec-umask-default.service b/test/test-execute/exec-umask-default.service
new file mode 100644
index 0000000..bf0573d
--- /dev/null
+++ b/test/test-execute/exec-umask-default.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for UMask default
+
+[Service]
+ExecStart=/bin/sh -x -c 'rm /tmp/test-exec-umask; touch /tmp/test-exec-umask; mode=$$(stat -c %%a /tmp/test-exec-umask); test "$$mode" = "644"'
+Type=oneshot
+PrivateTmp=yes
diff --git a/test/test-execute/exec-unsetenvironment.service b/test/test-execute/exec-unsetenvironment.service
new file mode 100644
index 0000000..5b0123b
--- /dev/null
+++ b/test/test-execute/exec-unsetenvironment.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for UnsetEnvironment
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$FOO" = "bar" && test "$${QUUX-X}" = "X" && test "$$VAR3" = "value3" && test "$${VAR4-X}" = "X" && test "$$VAR5" = "value5" && test "$${X%b-X}" = "X"'
+Type=oneshot
+Environment=FOO=bar QUUX=waldo VAR3=value3 VAR4=value4 VAR5=value5 X%b=%U
+UnsetEnvironment=QUUX=waldo VAR3=somethingelse VAR4 X%b=%U
diff --git a/test/test-execute/exec-user-nfsnobody.service b/test/test-execute/exec-user-nfsnobody.service
new file mode 100644
index 0000000..aafda3a
--- /dev/null
+++ b/test/test-execute/exec-user-nfsnobody.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for User
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$USER" = "nfsnobody"'
+Type=oneshot
+User=nfsnobody
diff --git a/test/test-execute/exec-user-nobody.service b/test/test-execute/exec-user-nobody.service
new file mode 100644
index 0000000..0a00c1a
--- /dev/null
+++ b/test/test-execute/exec-user-nobody.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for User
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$USER" = "nobody"'
+Type=oneshot
+User=nobody
diff --git a/test/test-execute/exec-user.service b/test/test-execute/exec-user.service
new file mode 100644
index 0000000..d315a82
--- /dev/null
+++ b/test/test-execute/exec-user.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for User (daemon)
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$USER" = "daemon"'
+Type=oneshot
+User=daemon
diff --git a/test/test-execute/exec-workingdirectory-trailing-dot.service b/test/test-execute/exec-workingdirectory-trailing-dot.service
new file mode 100644
index 0000000..5c807b3
--- /dev/null
+++ b/test/test-execute/exec-workingdirectory-trailing-dot.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for WorkingDirectory with trailing dot
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$PWD" = "/tmp/test-exec_workingdirectory"'
+Type=oneshot
+WorkingDirectory=/tmp///./test-exec_workingdirectory/.
diff --git a/test/test-execute/exec-workingdirectory.service b/test/test-execute/exec-workingdirectory.service
new file mode 100644
index 0000000..fe3c420
--- /dev/null
+++ b/test/test-execute/exec-workingdirectory.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for WorkingDirectory
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$PWD" = "/tmp/test-exec_workingdirectory"'
+Type=oneshot
+WorkingDirectory=/tmp/test-exec_workingdirectory