TEST-67-INTEGRITY: modernize test code
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 26 Nov 2024 15:06:39 +0000 (00:06 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 27 Nov 2024 15:56:23 +0000 (00:56 +0900)
- make udevd generate debugging logs for loopback and DM devices,
- insert 'udevadm wait' at several places to make the device processed
  by udevd,
- cleanup generated integritysetup service before moving to next
  algorithm,
- drop unnecessary exit on command failure,
- also test data splitting mode for all algorithms.

test/units/TEST-67-INTEGRITY.sh

index eb3082d1320ba5895e8ebb148c61269a25e66217..d13f9071ac96dd01f594361770b9b784a438497f 100755 (executable)
 # SPDX-License-Identifier: LGPL-2.1-or-later
 set -euxo pipefail
 
-export DM_NAME="integrity_test"
-export FULL_DM_DEV_NAME="/dev/mapper/${DM_NAME}"
-export FS_UUID="01234567-ffff-eeee-eeee-0123456789ab"
-export GEN="/var/run/systemd/generator"
+DM_NAME="integrity_test"
+DM_NODE="/dev/mapper/${DM_NAME}"
+DM_SERVICE="systemd-integritysetup@${DM_NAME}.service"
+FS_UUID="01234567-ffff-eeee-eeee-0123456789ab"
 
-image_dir=""
+TMP_DIR=
+LOOP=
 
-cleanup()
-{
-    if [ -z "${image_dir}" ]; then
-        return
+cleanup() (
+    set +e
+
+    if [[ -n "${LOOP}" ]]; then
+        losetup -d "${LOOP}"
     fi
 
-    if [ -f "${image_dir}/image" ]; then
-        if [ -e "${FULL_DM_DEV_NAME}" ]; then
-            integritysetup close "${DM_NAME}"
-        fi
-        losetup -d "${loop}"
+    if [[ -n "${TMP_DIR}" ]]; then
+        rm -rf "${TMP_DIR}"
     fi
 
-    rm -rf "${image_dir}"
-}
+    rm -rf /run/udev/rules.d/
+    udevadm control --reload
+)
 
 trap cleanup EXIT
 
-build_integrity_tab()
-{
-cat <<EOF >"/etc/integritytab"
-${DM_NAME} ${loop} - integrity-algorithm=$1
+udevadm settle
+
+# Enable debugging logs for loop and dm block devices.
+mkdir -p /run/udev/rules.d/
+cat >/run/udev/rules.d/00-integrity-test.rules <<EOF
+SUBSYSTEM=="block", KERNEL=="loop*|dm-*", OPTIONS="log_level=debug"
 EOF
-}
 
-image_dir="$(mktemp -d -t -p / integrity.tmp.XXXXXX)"
-if [ -z "${image_dir}" ] || [ ! -d "${image_dir}" ]; then
-    echo "mktemp under / failed"
-    exit 1
-fi
+udevadm control --reload
+
+TMP_DIR="$(mktemp -d -t -p / integrity.tmp.XXXXXX)"
+dd if=/dev/zero of="${TMP_DIR}/image" bs=1048576 count=64
+dd if=/dev/zero of="${TMP_DIR}/data" bs=1048576 count=64
+LOOP="$(losetup --show -f "${TMP_DIR}/image")"
+udevadm wait --timeout=30 --settle "${LOOP}"
+
+test_cleanup() (
+    set +e
+
+    if [[ -e "/run/systemd/generator/${DM_SERVICE}" ]]; then
+        systemctl stop "${DM_SERVICE}"
+    elif [[ -e "${DM_NODE}" ]]; then
+        integritysetup close "${DM_NAME}"
+    fi
+
+    udevadm wait --timeout=30 --settle --removed "${DM_NODE}"
 
-dd if=/dev/zero of="${image_dir}/image" bs=1048576 count=64 || exit 1
-dd if=/dev/zero of="${image_dir}/data" bs=1048576 count=64 || exit 1
-loop="$(losetup --show -f "${image_dir}/image")"
+    # Clear integritytab.
+    rm -f /etc/integritytab
 
-if [[ ! -e ${loop} ]]; then
-    echo "Loopback device created not found!"
-    exit 1
-fi
+    # Make the generator to re-run.
+    systemctl daemon-reload
+)
 
-# Do one iteration with a separate data device, to test those branches
-separate_data=1
+test_one() {
+    local algorithm="${1?}"
+    local separate_data="${2?}"
+    local data_option dev_name
 
-for algorithm in crc32c crc32 xxhash64 sha1 sha256
-do
-    if [ "${separate_data}" -eq 1 ]; then
-        data_option="--data-device=${image_dir}/data"
+    trap test_cleanup RETURN
+
+    if [[ "${separate_data}" == 1 ]]; then
+        data_option="--data-device=${TMP_DIR}/data"
     else
         data_option=""
     fi
-    integritysetup format "${loop}" --batch-mode -I "${algorithm}" "${data_option}" || exit 1
-    integritysetup open -I "${algorithm}" "${loop}" "${DM_NAME}" "${data_option}" || exit 1
-    mkfs.ext4 -U "${FS_UUID}" "${FULL_DM_DEV_NAME}" || exit 1
 
-    # Give userspace time to handle udev events for new FS showing up ...
+    integritysetup format "${LOOP}" --batch-mode -I "${algorithm}" "${data_option}"
+    integritysetup open -I "${algorithm}" "${LOOP}" "${DM_NAME}" "${data_option}"
+    udevadm wait --timeout=30 --settle "${DM_NODE}"
+    mkfs.ext4 -U "${FS_UUID}" "${DM_NODE}"
+    # Wait for synthetic events being processed.
     udevadm settle
+    integritysetup close "${DM_NAME}"
+    udevadm wait --timeout=30 --settle --removed "${DM_NODE}"
 
-    integritysetup close "${DM_NAME}" || exit 1
-
-    # create integritytab, generate units, start service
-    if [ "${separate_data}" -eq 1 ]; then
-        data_option=",data-device=${image_dir}/data"
+    # Create integritytab.
+    if [[ "${separate_data}" == 1 ]]; then
+        data_option=",data-device=${TMP_DIR}/data"
     else
         data_option=""
     fi
-    build_integrity_tab "${algorithm}${data_option}"
+    cat >"/etc/integritytab" <<EOF
+${DM_NAME} ${LOOP} - integrity-algorithm=${algorithm}${data_option}
+EOF
 
-    # Cause the generator to re-run
-    systemctl daemon-reload || exit 1
+    # Make the generator to re-run.
+    systemctl daemon-reload
 
-    # Check for existence of unit files...
-    if [[ ! -e "/run/systemd/generator/systemd-integritysetup@${DM_NAME}.service" ]]; then
-        echo "Service file does not exist!"
-        exit 1
-    fi
+    # Check for existence of the unit file.
+    [[ -e "/run/systemd/generator/${DM_SERVICE}" ]]
 
-    # Make sure we are in a consistent state, e.g. not already active before we start
-    systemctl stop systemd-integritysetup@"${DM_NAME}".service || exit 1
-    systemctl start systemd-integritysetup@"${DM_NAME}".service || exit 1
-    # Reset the start-limit counters, as we're going to restart the service a couple of times
-    systemctl reset-failed systemd-integritysetup@"${DM_NAME}".service
-
-    # Check the signature on the FS to ensure we can retrieve it and that is matches
-    if [ -e "${FULL_DM_DEV_NAME}" ]; then
-        # If a separate device is used for the metadata storage, then blkid will return one of the loop devices
-        if [ "${separate_data}" -eq 1 ]; then
-            dev_name="$(integritysetup status ${DM_NAME} | grep '^\s*device:' | awk '{print $2}')"
-        else
-            dev_name="${FULL_DM_DEV_NAME}"
-        fi
-        if [ "${dev_name}" != "$(blkid -U "${FS_UUID}")" ]; then
-            echo "Failed to locate FS with matching UUID!"
-            exit 1
-        fi
-    else
-        echo "Failed to bring up integrity device!"
-        exit 1
-    fi
-
-    systemctl stop systemd-integritysetup@"${DM_NAME}".service || exit 1
+    # Make sure we are in a consistent state, e.g. not already active before we start.
+    [[ "$(systemctl is-active "${DM_SERVICE}")" == inactive ]]
+    systemctl start "${DM_SERVICE}"
+    udevadm wait --timeout=30 --settle "${DM_NODE}"
 
-    if [ -e "${FULL_DM_DEV_NAME}" ]; then
-        echo "Expecting ${FULL_DM_DEV_NAME} to not exist after stopping unit!"
-        exit 1
+    # Check the signature on the FS to ensure we can retrieve it and that is matches.
+    # If a separate device is used for the metadata storage, then blkid will return one of the loop devices.
+    if [[ "${separate_data}" == 1 ]]; then
+        dev_name="$(integritysetup status ${DM_NAME} | grep '^\s*device:' | awk '{print $2}')"
+    else
+        dev_name="${DM_NODE}"
     fi
+    [[ "$(blkid -U "${FS_UUID}")" == "${dev_name}" ]]
+}
 
-    separate_data=0
+for a in crc32c crc32 xxhash64 sha1 sha256; do
+    test_one "$a" 0
+    test_one "$a" 1
 done
 
 touch /testok