mirror of
https://github.com/troglobit/finit.git
synced 2026-09-30 21:13:01 +07:00
A daemon known under more than one name had to be declared once per
name, each stanza carrying nowarn so the ones that were not installed
were skipped quietly. That leaned on the line-based format having no
titles. With a title as the service identity the repetition is no
longer available, so the candidates move inside the block:
command = { "/lib/systemd/systemd-udevd", "-udevd" }
Finit starts the first one whose binary resolves. A candidate that is
not installed is expected here, so nothing is logged for the ones that
lose, and only the winner is looked up again by service_register().
The leading '-' keeps its meaning and is read from the candidate that
wins, or from the last one when none resolve.
libconfuse accepts a bare string for a list option, so the common
`command = "prog args"` is unchanged, and whichp() already skips any
arguments to the command, so the candidate goes to it as written.
tty blocks take the same list. Their command is the getty to run, and
it has the same reason to name alternatives. Both block types now
share svc_command(), which also puts the leading '-' rule back in one
place: tty_translate() had its own copy. A tty needs no command at
all, it may name a device or notty instead, so svc_command() returns
NULL for an empty section and each caller decides whether that is an
error.
system/10-hotplug.conf.in returns to one udevd block, which is what it
meant all along.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
101 lines
4.0 KiB
Bash
Executable File
101 lines
4.0 KiB
Bash
Executable File
#!/bin/sh
|
|
# Verify a command list. The entries are candidates for the same
|
|
# service and the first one whose binary resolves wins, which the
|
|
# line-based format could only express as one stanza per candidate.
|
|
set -eu
|
|
|
|
TEST_DIR=$(dirname "$0")
|
|
|
|
# shellcheck disable=SC2034
|
|
# The first candidate is not installed, so the second one runs. This
|
|
# is the udevd case from system/10-hotplug.conf, where the systemd
|
|
# build of the daemon is tried before the standalone one.
|
|
BOOTSTRAP="service pick {
|
|
runlevel = \"S12345\"
|
|
command = { \"/no/such/binary --daemon\", \"serv -np -i pick\" }
|
|
}"
|
|
|
|
# The chosen candidate is what Finit runs, so assert on that rather
|
|
# than on process names: pgrep matches a substring, and 'serv' is one
|
|
# of 'service.sh'.
|
|
assert_cmd()
|
|
{
|
|
assert "Service $1 command == $2" \
|
|
"$(texec initctl status "$1" | grep 'Command' | sed 's/.*Command : //')" = "$2"
|
|
}
|
|
|
|
test_teardown()
|
|
{
|
|
say "Running test teardown."
|
|
run "rm -f $FINIT_CONF"
|
|
}
|
|
|
|
# shellcheck source=/dev/null
|
|
. "$TEST_DIR/lib/setup.sh"
|
|
|
|
say 'A missing first candidate hands the service to the next one'
|
|
retry 'assert_num_children 1 serv'
|
|
assert_cmd pick "serv -np -i pick"
|
|
|
|
# With a BOOTSTRAP the test is released in runlevel S, where a reload
|
|
# is ignored, and the rewritten file would then be picked up by the
|
|
# runlevel change instead of the reload under test.
|
|
say 'Waiting for bootstrap to finish before rewriting the configuration'
|
|
retry "test \"\$(texec sh -c \"initctl runlevel | awk '{print \\\$2;}'\")\" = 2" 20 1
|
|
|
|
# Both binaries exist here, so a plain "does it resolve" check would
|
|
# be satisfied by either. Only order decides.
|
|
say 'When several candidates resolve, the first one wins'
|
|
run "echo 'service pick {' > $FINIT_CONF"
|
|
run "echo ' command = { \"serv -np -i pick\", \"service.sh\" }' >> $FINIT_CONF"
|
|
run "echo '}' >> $FINIT_CONF"
|
|
run "initctl reload"
|
|
|
|
retry 'assert_cmd pick "serv -np -i pick"'
|
|
assert_num_children 1 serv
|
|
|
|
say 'The order is honoured the other way around too'
|
|
run "echo 'service pick {' > $FINIT_CONF"
|
|
run "echo ' command = { \"service.sh\", \"serv -np -i pick\" }' >> $FINIT_CONF"
|
|
run "echo '}' >> $FINIT_CONF"
|
|
run "initctl reload"
|
|
|
|
retry 'assert_cmd pick "service.sh"'
|
|
assert_num_children 1 service.sh
|
|
|
|
# libconfuse takes a bare string for a list option, so the spelling
|
|
# every other .conf uses has to keep working after command became one.
|
|
say 'A single command needs no braces'
|
|
run "echo 'service pick {' > $FINIT_CONF"
|
|
run "echo ' description = \"Single command\"' >> $FINIT_CONF"
|
|
run "echo ' command = \"serv -np -i pick\"' >> $FINIT_CONF"
|
|
run "echo '}' >> $FINIT_CONF"
|
|
run "initctl reload"
|
|
|
|
retry 'assert_cmd pick "serv -np -i pick"'
|
|
assert_desc "Single command" pick
|
|
assert_num_children 1 serv
|
|
|
|
# A tty block takes the same list, its command is the getty to run.
|
|
# Asserting it is loaded is enough here, a getty in the test namespace
|
|
# has no terminal to attach to.
|
|
say 'A tty block takes candidates too'
|
|
run "echo 'tty console {' > $FINIT_CONF"
|
|
run "echo ' runlevel = \"12345\"' >> $FINIT_CONF"
|
|
run "echo ' command = { \"/no/such/getty\", \"serv -np -i ttypick\" }' >> $FINIT_CONF"
|
|
run "echo '}' >> $FINIT_CONF"
|
|
run "initctl reload"
|
|
|
|
retry 'assert_cmd tty "serv -np -i ttypick"'
|
|
|
|
# Nothing resolves, so the block is skipped the same way a single
|
|
# missing command is. The leading - only decides whether that is
|
|
# quiet, service_register() bails before svc_new() either way.
|
|
say 'A block whose candidates are all missing is skipped'
|
|
run "echo 'service ghost {' > $FINIT_CONF"
|
|
run "echo ' command = { \"-/no/such/one\", \"-/no/such/two\" }' >> $FINIT_CONF"
|
|
run "echo '}' >> $FINIT_CONF"
|
|
run "initctl reload"
|
|
|
|
assert_num_services 0 ghost
|