test: verify bootctl link-auto and io.systemd.BootControl.LinkAuto
Add a TEST-87 testcase exercising "bootctl link-auto" and the equivalent io.systemd.BootControl.LinkAuto() Varlink method: a UKI plus extras are staged below the search directories and we assert the kernel and sidecar resources are linked into $BOOT. Covered: plain kernel.efi + extras.d/, versioned kernel.efi.v/ and extras .v/ resolved via vpick, directory priority (/etc wins over /run), the no-op case when nothing is staged, and the Varlink method including its empty reply when there is nothing to link.
This commit is contained in:
@@ -710,4 +710,162 @@ EOF
|
||||
'{"id":"foo*.conf"}')
|
||||
}
|
||||
|
||||
cleanup_link_auto() {
|
||||
rm -rf /run/systemd/uki /etc/systemd/uki
|
||||
if [[ -n "${LINK_WORKDIR:-}" ]]; then
|
||||
rm -rf "$LINK_WORKDIR"
|
||||
unset LINK_WORKDIR
|
||||
fi
|
||||
restore_esp
|
||||
}
|
||||
|
||||
testcase_bootctl_link_auto() {
|
||||
if ! command -v ukify >/dev/null; then
|
||||
echo "ukify not found, skipping."
|
||||
return 0
|
||||
fi
|
||||
|
||||
backup_esp
|
||||
LINK_WORKDIR="$(mktemp --directory /tmp/test-bootctl-link-auto.XXXXXXXXXX)"
|
||||
trap cleanup_link_auto RETURN ERR
|
||||
|
||||
# Ensure loader/entries directory is present
|
||||
bootctl install --make-entry-directory=yes
|
||||
|
||||
local ESP
|
||||
ESP="$(bootctl --print-esp-path)"
|
||||
|
||||
cat >"$LINK_WORKDIR/os-release" <<'EOF'
|
||||
ID=testos
|
||||
NAME="Test OS"
|
||||
PRETTY_NAME="Test OS"
|
||||
EOF
|
||||
echo "fake-kernel" >"$LINK_WORKDIR/vmlinuz"
|
||||
echo "fake-initrd" >"$LINK_WORKDIR/initrd"
|
||||
|
||||
# Two distinct UKIs, so we can tell which one was picked up.
|
||||
ukify build \
|
||||
--linux "$LINK_WORKDIR/vmlinuz" \
|
||||
--initrd "$LINK_WORKDIR/initrd" \
|
||||
--os-release "@$LINK_WORKDIR/os-release" \
|
||||
--uname "1.2.3-testkernel" \
|
||||
--cmdline "quiet uki=a" \
|
||||
--output "$LINK_WORKDIR/uki_a.efi"
|
||||
ukify build \
|
||||
--linux "$LINK_WORKDIR/vmlinuz" \
|
||||
--initrd "$LINK_WORKDIR/initrd" \
|
||||
--os-release "@$LINK_WORKDIR/os-release" \
|
||||
--uname "1.2.3-testkernel" \
|
||||
--cmdline "quiet uki=b" \
|
||||
--output "$LINK_WORKDIR/uki_b.efi"
|
||||
|
||||
local TOKEN="systemdtest"
|
||||
local BOOTCTL=(bootctl "--entry-token=literal:$TOKEN")
|
||||
local ENTRY="$ESP/loader/entries/${TOKEN}-commit_1.conf"
|
||||
|
||||
# --- Test 1: link-auto picks up kernel.efi + extras.d/ from /run/systemd/uki/ ---
|
||||
rm -rf /run/systemd/uki
|
||||
mkdir -p /run/systemd/uki/extras.d
|
||||
cp "$LINK_WORKDIR/uki_a.efi" /run/systemd/uki/kernel.efi
|
||||
echo "sysext-data" >/run/systemd/uki/extras.d/hello.sysext.raw
|
||||
echo "confext-data" >/run/systemd/uki/extras.d/hello.confext.raw
|
||||
echo "cred-data" >/run/systemd/uki/extras.d/hello.cred
|
||||
|
||||
"${BOOTCTL[@]}" link-auto
|
||||
|
||||
test -f "$ENTRY"
|
||||
test -f "$ESP/$TOKEN/kernel.efi"
|
||||
cmp "$LINK_WORKDIR/uki_a.efi" "$ESP/$TOKEN/kernel.efi"
|
||||
test -f "$ESP/$TOKEN/hello.sysext.raw"
|
||||
test -f "$ESP/$TOKEN/hello.confext.raw"
|
||||
test -f "$ESP/$TOKEN/hello.cred"
|
||||
grep "^uki /${TOKEN}/kernel.efi\$" "$ENTRY" >/dev/null
|
||||
grep "^extra /${TOKEN}/hello.sysext.raw\$" "$ENTRY" >/dev/null
|
||||
grep "^extra /${TOKEN}/hello.confext.raw\$" "$ENTRY" >/dev/null
|
||||
grep "^extra /${TOKEN}/hello.cred\$" "$ENTRY" >/dev/null
|
||||
|
||||
"${BOOTCTL[@]}" unlink "${TOKEN}-commit_1.conf"
|
||||
test ! -e "$ENTRY"
|
||||
test ! -e "$ESP/$TOKEN/kernel.efi"
|
||||
|
||||
# --- Test 2: versioned kernel.efi.v/ and extras .v/ are resolved via vpick ---
|
||||
rm -rf /run/systemd/uki
|
||||
mkdir -p /run/systemd/uki/kernel.efi.v /run/systemd/uki/extras.d/hello.sysext.raw.v
|
||||
cp "$LINK_WORKDIR/uki_a.efi" /run/systemd/uki/kernel.efi.v/kernel_1.0.efi
|
||||
cp "$LINK_WORKDIR/uki_a.efi" /run/systemd/uki/kernel.efi.v/kernel_2.0.efi
|
||||
echo "sysext-1" >/run/systemd/uki/extras.d/hello.sysext.raw.v/hello_1.0.sysext.raw
|
||||
echo "sysext-2" >/run/systemd/uki/extras.d/hello.sysext.raw.v/hello_2.0.sysext.raw
|
||||
|
||||
"${BOOTCTL[@]}" link-auto
|
||||
|
||||
test -f "$ENTRY"
|
||||
# vpick must select the newest version
|
||||
test -f "$ESP/$TOKEN/kernel_2.0.efi"
|
||||
test ! -e "$ESP/$TOKEN/kernel_1.0.efi"
|
||||
test -f "$ESP/$TOKEN/hello_2.0.sysext.raw"
|
||||
test ! -e "$ESP/$TOKEN/hello_1.0.sysext.raw"
|
||||
grep "^uki /${TOKEN}/kernel_2.0.efi\$" "$ENTRY" >/dev/null
|
||||
grep "^extra /${TOKEN}/hello_2.0.sysext.raw\$" "$ENTRY" >/dev/null
|
||||
|
||||
"${BOOTCTL[@]}" unlink "${TOKEN}-commit_1.conf"
|
||||
|
||||
# --- Test 3: priority — /etc/systemd/uki/ wins over /run/systemd/uki/ ---
|
||||
rm -rf /run/systemd/uki /etc/systemd/uki
|
||||
mkdir -p /run/systemd/uki/extras.d /etc/systemd/uki/extras.d
|
||||
cp "$LINK_WORKDIR/uki_b.efi" /run/systemd/uki/kernel.efi
|
||||
cp "$LINK_WORKDIR/uki_a.efi" /etc/systemd/uki/kernel.efi
|
||||
echo "run-cred" >/run/systemd/uki/extras.d/hello.cred
|
||||
echo "etc-cred" >/etc/systemd/uki/extras.d/hello.cred
|
||||
|
||||
"${BOOTCTL[@]}" link-auto
|
||||
|
||||
test -f "$ESP/$TOKEN/kernel.efi"
|
||||
# The /etc copy (uki_a) must win over the /run copy (uki_b)
|
||||
cmp "$LINK_WORKDIR/uki_a.efi" "$ESP/$TOKEN/kernel.efi"
|
||||
cmp <(echo "etc-cred") "$ESP/$TOKEN/hello.cred"
|
||||
|
||||
"${BOOTCTL[@]}" unlink "${TOKEN}-commit_1.conf"
|
||||
rm -rf /etc/systemd/uki
|
||||
|
||||
# --- Test 4: with nothing staged, link-auto is a successful no-op ---
|
||||
rm -rf /run/systemd/uki
|
||||
"${BOOTCTL[@]}" link-auto
|
||||
# No entries referencing our token should remain.
|
||||
local leftover
|
||||
leftover="$(find "$ESP/loader/entries/" -name "*$TOKEN*" -print -quit 2>/dev/null)"
|
||||
test -z "$leftover"
|
||||
|
||||
# === Varlink coverage: io.systemd.BootControl.LinkAuto ===
|
||||
local BOOTCTL_BIN vreply vid vtoken
|
||||
BOOTCTL_BIN="$(type -p bootctl)"
|
||||
|
||||
# --- Test 5: LinkAuto discovers kernel.efi + extras ---
|
||||
rm -rf /run/systemd/uki
|
||||
mkdir -p /run/systemd/uki/extras.d
|
||||
cp "$LINK_WORKDIR/uki_a.efi" /run/systemd/uki/kernel.efi
|
||||
echo "cred-data" >/run/systemd/uki/extras.d/hello.cred
|
||||
|
||||
vreply="$(varlinkctl call --json=short "$BOOTCTL_BIN" io.systemd.BootControl.LinkAuto '{}')"
|
||||
vid="$(echo "$vreply" | jq -r '.ids[0]')"
|
||||
test -n "$vid"
|
||||
test "$vid" != "null"
|
||||
vtoken="${vid%%-commit_*}"
|
||||
test -n "$vtoken"
|
||||
|
||||
test -f "$ESP/loader/entries/$vid"
|
||||
test -f "$ESP/$vtoken/kernel.efi"
|
||||
test -f "$ESP/$vtoken/hello.cred"
|
||||
grep "^uki /$vtoken/kernel.efi\$" "$ESP/loader/entries/$vid" >/dev/null
|
||||
|
||||
varlinkctl call --quiet "$BOOTCTL_BIN" io.systemd.BootControl.Unlink "{\"id\":\"$vid\"}"
|
||||
test ! -e "$ESP/loader/entries/$vid"
|
||||
test ! -e "$ESP/$vtoken/kernel.efi"
|
||||
test ! -e "$ESP/$vtoken/hello.cred"
|
||||
|
||||
# --- Test 6: LinkAuto with nothing staged returns an empty id list ---
|
||||
rm -rf /run/systemd/uki
|
||||
vreply="$(varlinkctl call --json=short "$BOOTCTL_BIN" io.systemd.BootControl.LinkAuto '{}')"
|
||||
assert_eq "$(echo "$vreply" | jq -r '.ids | length')" "0"
|
||||
}
|
||||
|
||||
run_testcases
|
||||
|
||||
Reference in New Issue
Block a user