]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - test/test-functions
Merge pull request #17085 from yuwata/network-configure-mdb-entries-on-bridge-master
[thirdparty/systemd.git] / test / test-functions
index fbdc92c96eeeb33c857b6c7b8fdf13871566f06f..9893864bcd197f0e4b031ddd51dfd0dd93123525 100644 (file)
@@ -4,9 +4,10 @@
 PATH=/sbin:/bin:/usr/sbin:/usr/bin
 export PATH
 
-LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || " $ID_LIKE " = *" debian "* ]] && echo yes || :)
-LOOKS_LIKE_ARCH=$(source /etc/os-release && [[ "$ID" = "arch" || " $ID_LIKE " = *" arch "* ]] && echo yes || :)
-LOOKS_LIKE_SUSE=$(source /etc/os-release && [[ " $ID_LIKE " = *" suse "* ]] && echo yes || :)
+os_release=$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release)
+LOOKS_LIKE_DEBIAN=$(source $os_release && [[ "$ID" = "debian" || " $ID_LIKE " = *" debian "* ]] && echo yes || :)
+LOOKS_LIKE_ARCH=$(source $os_release && [[ "$ID" = "arch" || " $ID_LIKE " = *" arch "* ]] && echo yes || :)
+LOOKS_LIKE_SUSE=$(source $os_release && [[ " $ID_LIKE " = *" suse "* ]] && echo yes || :)
 KERNEL_VER=${KERNEL_VER-$(uname -r)}
 KERNEL_MODS="/lib/modules/$KERNEL_VER/"
 QEMU_TIMEOUT="${QEMU_TIMEOUT:-infinity}"
@@ -18,6 +19,7 @@ EFI_MOUNT="${EFI_MOUNT:-$(bootctl -x 2>/dev/null || echo /boot)}"
 QEMU_MEM="${QEMU_MEM:-512M}"
 IMAGE_NAME=${IMAGE_NAME:-default}
 TEST_REQUIRE_INSTALL_TESTS="${TEST_REQUIRE_INSTALL_TESTS:-1}"
+TEST_PARALLELIZE="${TEST_PARALLELIZE:-0}"
 LOOPDEV=
 
 # Decide if we can (and want to) run QEMU with KVM acceleration.
@@ -38,6 +40,7 @@ fi
 
 PATH_TO_INIT=$ROOTLIBDIR/systemd
 [ "$SYSTEMD_JOURNALD" ] || SYSTEMD_JOURNALD=$(which -a $BUILD_DIR/systemd-journald $ROOTLIBDIR/systemd-journald 2>/dev/null | grep '^/' -m1)
+[ "$SYSTEMD_JOURNAL_REMOTE" ] || SYSTEMD_JOURNAL_REMOTE=$(which -a $BUILD_DIR/systemd-journal-remote $ROOTLIBDIR/systemd-journal-remote 2>/dev/null | grep '^/' -m1)
 [ "$SYSTEMD" ] || SYSTEMD=$(which -a $BUILD_DIR/systemd $ROOTLIBDIR/systemd 2>/dev/null | grep '^/' -m1)
 [ "$SYSTEMD_NSPAWN" ] || SYSTEMD_NSPAWN=$(which -a $BUILD_DIR/systemd-nspawn systemd-nspawn 2>/dev/null | grep '^/' -m1)
 [ "$JOURNALCTL" ] || JOURNALCTL=$(which -a $BUILD_DIR/journalctl journalctl 2>/dev/null | grep '^/' -m1)
@@ -78,6 +81,7 @@ BASICTOOLS=(
     mktemp
     modprobe
     mount
+    mountpoint
     mv
     nc
     nproc
@@ -101,6 +105,7 @@ BASICTOOLS=(
     tar
     tee
     test
+    timeout
     touch
     tr
     true
@@ -234,6 +239,7 @@ run_qemu() {
 
     CONSOLE=ttyS0
 
+    rm -f "$initdir"/{testok,failed,skipped}
     # make sure the initdir is not mounted to avoid concurrent access
     cleanup_initdir
     umount_loopback
@@ -326,12 +332,13 @@ systemd.wants=testsuite-$1.service ${_end} \
 $KERNEL_APPEND \
 "
 
+    [ -e "$IMAGE_PRIVATE" ] && image="$IMAGE_PRIVATE" || image="$IMAGE_PUBLIC"
     QEMU_OPTIONS="-smp $QEMU_SMP \
 -net none \
 -m $QEMU_MEM \
 -nographic \
 -kernel $KERNEL_BIN \
--drive format=raw,cache=unsafe,file=${IMAGESTATEDIR}/${IMAGE_NAME}.img \
+-drive format=raw,cache=unsafe,file=$image \
 $QEMU_OPTIONS \
 "
 
@@ -362,6 +369,7 @@ $QEMU_OPTIONS \
 # success), or 1 if nspawn is not available.
 run_nspawn() {
     [[ -d /run/systemd/system ]] || return 1
+    rm -f "$initdir"/{testok,failed,skipped}
 
     local _nspawn_cmd=(
         --register=no
@@ -389,9 +397,9 @@ run_nspawn() {
         dwarn "nspawn doesn't support SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=hybrid, skipping"
         exit
     elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "yes" || "$UNIFIED_CGROUP_HIERARCHY" = "no" ]]; then
-        _nspawn_pre=("${nspawn_pre[@]}" env SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=$UNIFIED_CGROUP_HIERARCHY)
+        _nspawn_pre=("${_nspawn_pre[@]}" env SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=$UNIFIED_CGROUP_HIERARCHY)
     elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "default" ]]; then
-        _nspawn_pre=("${nspawn_pre[@]}" env --unset=UNIFIED_CGROUP_HIERARCHY --unset=SYSTEMD_NSPAWN_UNIFIED_HIERARCHY)
+        _nspawn_pre=("${_nspawn_pre[@]}" env --unset=UNIFIED_CGROUP_HIERARCHY --unset=SYSTEMD_NSPAWN_UNIFIED_HIERARCHY)
     else
         dfatal "Unknown UNIFIED_CGROUP_HIERARCHY. Got $UNIFIED_CGROUP_HIERARCHY, expected [yes|no|hybrid|default]"
         exit 1
@@ -566,7 +574,7 @@ printf "[Service]\nStandardOutput=file:/systemd-journald.out\n" >"\$JOURNALD_CON
 # under ASan+UBSan in containers, which, in turn, are run in VMs.
 # Let's limit which environments such services should be executed in.
 mkdir -p /etc/systemd/system/systemd-hwdb-update.service.d
-printf "[Unit]\nConditionVirtualization=container\n\n[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-hwdb-update.service.d/env-override.conf
+printf "[Unit]\nConditionVirtualization=container\n\n[Service]\nTimeoutSec=240s\n" >/etc/systemd/system/systemd-hwdb-update.service.d/env-override.conf
 
 # Let's override another hard-coded timeout that kicks in too early
 mkdir -p /etc/systemd/system/systemd-journal-flush.service.d
@@ -626,10 +634,14 @@ install_dmevent() {
     else
         inst_rules 10-dm.rules 13-dm-disk.rules 95-dm-notify.rules
     fi
+    if [[ "$LOOKS_LIKE_SUSE" ]]; then
+        inst_rules 60-persistent-storage.rules 61-persistent-storage-compat.rules 99-systemd.rules
+    fi
 }
 
 install_systemd() {
-    # install compiled files
+    ddebug "Install compiled systemd"
+
     local _ninja_bin=$(type -P ninja || type -P ninja-build)
     if [[ -z "$_ninja_bin" ]]; then
         dfatal "ninja was not found"
@@ -638,9 +650,6 @@ install_systemd() {
     (set -x; DESTDIR=$initdir "$_ninja_bin" -C $BUILD_DIR install)
     # remove unneeded documentation
     rm -fr $initdir/usr/share/{man,doc}
-    # we strip binaries since debug symbols increase binaries size a lot
-    # and it could fill the available space
-    strip_binaries
 
     [[ "$LOOKS_LIKE_SUSE" ]] && setup_suse
 
@@ -664,7 +673,7 @@ get_ldpath() {
 install_missing_libraries() {
     # install possible missing libraries
     for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/{,tests/{,manual/,unsafe/}}*; do
-        LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath $i)" inst_libs $i
+        LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath $i):$(get_ldpath $i)/src/udev" inst_libs $i
     done
 }
 
@@ -672,10 +681,11 @@ cleanup_loopdev() {
     if [ -n "${LOOPDEV}" ]; then
         ddebug "losetup -d $LOOPDEV"
         losetup -d "${LOOPDEV}"
+        unset LOOPDEV
     fi
 }
 
-trap cleanup_loopdev EXIT
+trap cleanup_loopdev EXIT INT QUIT PIPE
 
 create_empty_image() {
     if [ -z "$IMAGE_NAME" ]; then
@@ -688,16 +698,13 @@ create_empty_image() {
         _size=$((4*_size))
     fi
 
-    image="${TESTDIR}/${IMAGE_NAME}.img"
-    public="$IMAGESTATEDIR/${IMAGE_NAME}.img"
-    echo "Setting up $public (${_size} MB)"
-    rm -f "$image" "$public"
+    echo "Setting up $IMAGE_PUBLIC (${_size} MB)"
+    rm -f "$IMAGE_PRIVATE" "$IMAGE_PUBLIC"
 
     # Create the blank file to use as a root filesystem
-    truncate -s "${_size}M" "$image"
-    ln -vs "$(realpath $image)" "$public"
+    truncate -s "${_size}M" "$IMAGE_PUBLIC"
 
-    LOOPDEV=$(losetup --show -P -f "$public")
+    LOOPDEV=$(losetup --show -P -f "$IMAGE_PUBLIC")
     [ -b "$LOOPDEV" ] || return 1
     sfdisk "$LOOPDEV" <<EOF
 ,$((_size-50))M
@@ -718,7 +725,7 @@ EOF
 
 mount_initdir() {
     if [ -z "${LOOPDEV}" ]; then
-        image="${IMAGESTATEDIR}/${IMAGE_NAME}.img"
+        [ -e "$IMAGE_PRIVATE" ] && image="$IMAGE_PRIVATE" || image="$IMAGE_PUBLIC"
         LOOPDEV=$(losetup --show -P -f "$image")
         [ -b "$LOOPDEV" ] || return 1
 
@@ -740,8 +747,7 @@ cleanup_initdir() {
 umount_loopback() {
     # unmount the loopback device from all places. Otherwise we risk file
     # system corruption.
-    image="${IMAGESTATEDIR}/${IMAGE_NAME}.img"
-    for device in $(losetup -l | awk '$6=="'"$image"'" {print $1}'); do
+    for device in $(losetup -l | awk '$6=="'"$IMAGE_PUBLIC"'" {print $1}'); do
         ddebug "Unmounting all uses of $device"
         mount | awk '/^'"${device}"'p/{print $1}' | xargs --no-run-if-empty umount -v
     done
@@ -790,16 +796,39 @@ check_asan_reports() {
     return $ret
 }
 
+save_journal() {
+    if [ -n "${ARTIFACT_DIRECTORY}" ]; then
+        dest="${ARTIFACT_DIRECTORY}/${testname}.journal"
+    else
+        dest="$TESTDIR/system.journal"
+    fi
+
+    for j in $1/*; do
+        $SYSTEMD_JOURNAL_REMOTE \
+            -o $dest \
+            --getter="$JOURNALCTL -o export -D $j"
+
+        if [ -n "${TEST_SHOW_JOURNAL}" ]; then
+            echo "---- $j ----"
+            $JOURNALCTL --no-pager -o short-monotonic --no-hostname --priority=${TEST_SHOW_JOURNAL} -D $j
+        fi
+
+        rm -r $j
+    done
+
+    # we want to print this sometime later, so save this in a variable
+    JOURNAL_LIST="$(ls -l $dest*)"
+}
+
 check_result_nspawn() {
     local ret=1
     local journald_report=""
     local pids=""
     [[ -e $1/testok ]] && ret=0
     [[ -f $1/failed ]] && cp -a $1/failed $TESTDIR
-    cp -a $1/var/log/journal $TESTDIR
-    rm -r $1/var/log/journal/*
+    save_journal $1/var/log/journal
     [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
-    ls -l $TESTDIR/journal/*/*.journal
+    echo $JOURNAL_LIST
     test -s $TESTDIR/failed && ret=$(($ret+1))
     [ -n "$TIMED_OUT" ] && ret=$(($ret+1))
     check_asan_reports "$1" || ret=$(($ret+1))
@@ -813,12 +842,11 @@ check_result_qemu() {
     mount_initdir
     [[ -e $initdir/testok ]] && ret=0
     [[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR
-    cp -a $initdir/var/log/journal $TESTDIR
-    rm -r $initdir/var/log/journal/*
+    save_journal $initdir/var/log/journal
     check_asan_reports "$initdir" || ret=$(($ret+1))
     _umount_dir $initdir
     [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
-    ls -l $TESTDIR/journal/*/*.journal
+    echo $JOURNAL_LIST
     test -s $TESTDIR/failed && ret=$(($ret+1))
     [ -n "$TIMED_OUT" ] && ret=$(($ret+1))
     return $ret
@@ -857,7 +885,7 @@ install_execs() {
          # also, plymouth is pulled in by rescue.service, but even there the exit code
          # is ignored; as it's not present on some distros, don't fail if it doesn't exist
          dinfo "Attempting to install $i"
-         inst $i || [ "${i%.local}" != "$i" ] || [ "${i%systemd-update-done}" != "$i" ] || [ "/bin/plymouth" == "$i" ]
+         inst $i || [ "${i%.local}" != "$i" ] || [ "${i%systemd-update-done}" != "$i" ] || [ "${i##*/}" == "plymouth" ]
      done
     )
 }
@@ -882,7 +910,7 @@ install_plymouth() {
     #         /usr/libexec/plymouth/plymouth-populate-initrd -t $initdir
     #         dracut_install plymouth plymouthd
     # else
-        rm -f $initdir/{usr/lib,etc}/systemd/system/plymouth* $initdir/{usr/lib,etc}/systemd/system/*/plymouth*
+        rm -f $initdir/{usr/lib,lib,etc}/systemd/system/plymouth* $initdir/{usr/lib,lib,etc}/systemd/system/*/plymouth*
     # fi
 }
 
@@ -906,12 +934,12 @@ install_config_files() {
     inst /etc/sysconfig/init || :
     inst /etc/passwd
     inst /etc/shadow
-    inst /etc/login.defs
+    inst_any /etc/login.defs /usr/etc/login.defs
     inst /etc/group
     inst /etc/shells
-    inst /etc/nsswitch.conf
+    inst_any /etc/nsswitch.conf /usr/etc/nsswitch.conf
     inst /etc/pam.conf || :
-    inst /etc/os-release
+    inst_any /etc/os-release /usr/lib/os-release
     inst /etc/localtime
     # we want an empty environment
     > $initdir/etc/environment
@@ -919,6 +947,12 @@ install_config_files() {
 
     # set the hostname
     echo systemd-testsuite > $initdir/etc/hostname
+
+    # let's set up just one image with the traditional verbose output
+    if [ ${IMAGE_NAME} != "basic" ]; then
+        mkdir -p $initdir/etc/systemd/system.conf.d
+        echo -e '[Manager]\nStatusUnitFormat=name' >$initdir/etc/systemd/system.conf.d/status.conf
+    fi
 }
 
 install_basic_tools() {
@@ -1183,6 +1217,9 @@ TESTDIR="$TESTDIR"
 EOF
         export TESTDIR
     fi
+
+    IMAGE_PRIVATE="${TESTDIR}/${IMAGE_NAME}.img"
+    IMAGE_PUBLIC="${IMAGESTATEDIR}/${IMAGE_NAME}.img"
 }
 
 import_initdir() {
@@ -1913,6 +1950,7 @@ setup_suse() {
     ln -fs ../usr/bin/systemctl $initdir/bin/
     ln -fs ../usr/lib/systemd $initdir/lib/
     inst_simple "/usr/lib/systemd/system/haveged.service"
+    instmods ext4
 }
 
 _umount_dir() {
@@ -1932,7 +1970,7 @@ _test_cleanup() {
     (
         set +e
         _umount_dir $initdir
-        rm -vf "${IMAGESTATEDIR}/${IMAGE_NAME}.img"
+        rm -vf "$IMAGE_PUBLIC"
         rm -vfr "$TESTDIR"
         rm -vf "$STATEFILE"
     ) || :
@@ -1968,17 +2006,29 @@ test_setup() {
         exit 1
     fi
 
-    image="${TESTDIR}/${IMAGE_NAME}.img"
-    public="${IMAGESTATEDIR}/${IMAGE_NAME}.img"
-    if [ -e "$image" ]; then
-        echo "Reusing existing image $PWD/$image → $(realpath $image)"
-        mount_initdir
-    elif [ -e "$public" ]; then
-        echo "Reusing existing cached image $PWD/$public → $(realpath $public)"
-        ln -s "$(realpath $public)" "$image"
+    if [ -e "$IMAGE_PRIVATE" ]; then
+        echo "Reusing existing image $IMAGE_PRIVATE → $(realpath $IMAGE_PRIVATE)"
         mount_initdir
     else
-        test_create_image
+        if [ ! -e "$IMAGE_PUBLIC" ]; then
+            # Create the backing public image, but then completely unmount
+            # it and drop the loopback device responsible for it, since we're
+            # going to symlink/copy the image and mount it again from
+            # elsewhere.
+            test_create_image
+            test_setup_cleanup
+            umount_loopback
+            cleanup_loopdev
+        fi
+
+        echo "Reusing existing cached image $IMAGE_PUBLIC → $(realpath $IMAGE_PUBLIC)"
+        if [ ${TEST_PARALLELIZE} -ne 0 ]; then
+            cp -v "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
+        else
+            ln -sv "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
+        fi
+
+        mount_initdir
     fi
 
     setup_nspawn_root
@@ -1986,7 +2036,6 @@ test_setup() {
 
 test_run() {
     mount_initdir
-    rm -f "$initdir"/{testok,failed,skipped}
 
     if [ -z "$TEST_NO_QEMU" ]; then
         if run_qemu "$1"; then