Merge remote-tracking branch 'origin/pr/259'
[grml-debootstrap.git] / tests / test-vm.sh
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0-or-later
3 #
4 # Run previously built VM image in qemu and check if it boots.
5 # Requires virtiofs support in VM.
6
7 set -eu -o pipefail
8
9 if [ "$#" -ne 2 ]; then
10   echo "$0: Invalid arguments" >&2
11   echo "Expect: $0 VM_IMAGE VM_HOSTNAME" >&2
12   exit 1
13 fi
14 set -x
15
16 VM_IMAGE="$1"
17 VM_HOSTNAME="$2"
18
19 TEST_PWD="$PWD"
20 TEST_TMPDIR=$(mktemp -d)
21 TESTS_RESULTSDIR="$PWD/tests/results"
22 echo "Working in $TEST_TMPDIR, writing results to $TESTS_RESULTSDIR"
23 mkdir -p "$TESTS_RESULTSDIR"
24
25 bailout() {
26   if [ -n "${QEMU_PID:-}" ] ; then
27     # shellcheck disable=SC2009
28     ps --pid="${QEMU_PID}" -o pid= | grep -q '.' && kill "${QEMU_PID:-}"
29   fi
30
31   rm -rf "${TEST_TMPDIR}"
32
33   [ -n "${1:-}" ] && EXIT_CODE="$1" || EXIT_CODE=1
34   exit "$EXIT_CODE"
35 }
36 trap bailout 1 2 3 6 14 15
37
38 # Setup test runner
39 cp ./tests/goss "$TEST_TMPDIR"/
40 cp ./tests/goss.yaml "$TEST_TMPDIR"/
41 cat <<EOT > "$TEST_TMPDIR"/testrunner
42 #!/bin/bash
43 # Do not set -eu, we want to continue even if individual commands fail.
44 set -x
45 echo "INSIDE_VM $0 running"
46 mkdir results
47
48 # Collect information from VM first
49 lsb_release -a > results/lsb_release.txt
50 uname -a > results/uname-a.txt
51 systemctl list-units > results/systemctl_list-units.txt
52 systemctl status > results/systemctl_status.txt
53 fdisk -l > results/fdisk-l.txt
54 hostname -f > results/hostname-f.txt 2>&1
55 journalctl -b > results/journalctl-b.txt
56 dpkg -l > results/dpkg-l.txt
57
58 # Run tests
59 ./goss --gossfile goss.yaml validate --format tap > results/goss.tap
60 # Detection of testrunner success hinges on goss.exitcode file.
61 echo \$? > results/goss.exitcode
62
63 echo "INSIDE_VM $0 finished"
64 EOT
65 chmod a+rx "$TEST_TMPDIR"/testrunner
66
67 cd "$TEST_TMPDIR"
68
69 MOUNT_TAG=host0
70 qemu-system-x86_64 -hda "${VM_IMAGE}" -m 2048 \
71                    -display none -vnc :0 \
72                    -virtfs local,path="$TEST_TMPDIR",mount_tag="$MOUNT_TAG",security_model=none,id=host0 \
73                    -serial pty &>qemu.log &
74 QEMU_PID="$!"
75
76 timeout=30
77 success=0
78 while [ "$timeout" -gt 0 ] ; do
79   ((timeout--))
80   if grep -q 'char device redirected to ' qemu.log ; then
81     success=1
82     sleep 1
83     break
84   else
85     echo "No serial console from Qemu found yet [$timeout retries left]"
86     sleep 1
87   fi
88 done
89
90 if [ "$success" = "1" ] ; then
91   serial_port=$(awk '/char device redirected/ {print $5}' qemu.log)
92 else
93   echo "Error: Failed to identify serial console port." >&2
94   cat qemu.log
95   exit 1
96 fi
97
98 timeout=30
99 success=0
100 while [ "$timeout" -gt 0 ] ; do
101   ((timeout--))
102   if [ -c "$serial_port" ] ; then
103     success=1
104     sleep 1
105     break
106   else
107     echo "No block device for serial console found yet [$timeout retries left]"
108     sleep 1
109   fi
110 done
111
112 if [ "$success" = "0" ] ; then
113   echo "Error: can't access serial console block device." >&2
114   exit 1
115 fi
116
117 "$TEST_PWD"/tests/serial-console-connection \
118   --tries 180 \
119   --port "$serial_port" \
120   --hostname "$VM_HOSTNAME" \
121   --poweroff \
122   "mount -t 9p -o trans=virtio,version=9p2000.L,rw $MOUNT_TAG /mnt && cd /mnt && ./testrunner"
123
124 if [ ! -d results ] || [ ! -f ./results/goss.tap ] || [ ! -f ./results/goss.exitcode ]; then
125   echo "Running tests inside VM failed for unknown reason" >&2
126   RC=1
127 else
128   RC=$(cat results/goss.exitcode)
129   echo "goss exitcode: $RC"
130
131   cat results/goss.tap
132 fi
133
134 echo "Finished serial console connection [timeout=${timeout}]."
135
136 mv results/* "$TESTS_RESULTSDIR/"
137
138 bailout $RC
139
140 # EOF