]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - test/test-functions
update TODO
[thirdparty/systemd.git] / test / test-functions
index ead815f2fab148e6d932eb4a9d3fd5c458ae9c65..863cc18aeff0d29cbe9e801b7f72c70f5604768e 100644 (file)
@@ -18,6 +18,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 +39,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 +80,7 @@ BASICTOOLS=(
     mktemp
     modprobe
     mount
+    mountpoint
     mv
     nc
     nproc
@@ -101,6 +104,7 @@ BASICTOOLS=(
     tar
     tee
     test
+    timeout
     touch
     tr
     true
@@ -234,6 +238,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 +331,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 +368,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 +396,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 +573,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,6 +633,9 @@ 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() {
@@ -672,10 +682,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 +699,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 +726,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 +748,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 +797,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 +843,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 +886,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 +911,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,10 +935,10 @@ 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 /etc/localtime
@@ -919,6 +948,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 +1218,9 @@ TESTDIR="$TESTDIR"
 EOF
         export TESTDIR
     fi
+
+    IMAGE_PRIVATE="${TESTDIR}/${IMAGE_NAME}.img"
+    IMAGE_PUBLIC="${IMAGESTATEDIR}/${IMAGE_NAME}.img"
 }
 
 import_initdir() {
@@ -1913,6 +1951,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 +1971,7 @@ _test_cleanup() {
     (
         set +e
         _umount_dir $initdir
-        rm -vf "${IMAGESTATEDIR}/${IMAGE_NAME}.img"
+        rm -vf "$IMAGE_PUBLIC"
         rm -vfr "$TESTDIR"
         rm -vf "$STATEFILE"
     ) || :
@@ -1964,21 +2003,33 @@ test_setup() {
     if [ ${TEST_REQUIRE_INSTALL_TESTS} -ne 0 ] && \
             type -P meson >/dev/null && \
             [[ "$(meson configure $BUILD_DIR | grep install-tests | awk '{ print $2 }')" != "true" ]]; then
-        dfatal "Needs to be built with -Dinstall-tests=true"
+        dfatal "$BUILD_DIR needs to be built with -Dinstall-tests=true"
         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 +2037,6 @@ test_setup() {
 
 test_run() {
     mount_initdir
-    rm -f "$initdir"/{testok,failed,skipped}
 
     if [ -z "$TEST_NO_QEMU" ]; then
         if run_qemu "$1"; then