updated PO files
[tails.git] / run_test_suite
blob4437bc30245de6b6333990d148f58b3cb5fae1d9
1 #!/bin/bash
3 set -e
4 set -u
5 set -o pipefail
7 NAME=$(basename "${0}")
9 GENERAL_DEPENDENCIES="
10 cucumber
11 devscripts
12 dnsmasq-base
13 ffmpeg
14 gawk
15 git
16 imagemagick
17 libcap2-bin
18 libvirt-clients
19 libvirt-daemon-system
20 libvirt-dev
21 libvirt0
22 obfs4proxy
23 openssh-server
24 ovmf
25 pry
26 python3-opencv
27 python3-pil
28 python3-slixmpp
29 qemu-system-x86
30 qrencode
31 ruby-guestfs
32 ruby-json
33 ruby-libvirt
34 ruby-net-dns
35 ruby-packetfu
36 ruby-rb-inotify
37 ruby-rspec
38 ruby-test-unit
39 seabios
40 tcpdump
41 tcplay
42 tor
43 unclutter
44 virt-viewer
45 xdotool
46 xvfb
49 # Recent tor client require a Chutney network with tor >= 0.4.4.6 (#18190)
50 MINIMUM_TOR_VERSION=0.4.4.6
52 usage() {
53 echo "Usage: $NAME [OPTION]... [--] [CUCUMBER_ARGS]...
54 Sets up an appropriate environment and invokes cucumber. Note that this script
55 must be run from the Tails source directory root.
57 Options for '@product' features:
58 --allow-non-root Normally the test suite must be run as root, but if you
59 really know what you are doing this option allows any
60 user to run it.
61 --artifacts-base-uri URI
62 Pretend that the artifact is located at URI when printing
63 its location during a scenario failure. This is useful if
64 you intend to serve the artifacts via the web, for
65 instance.
66 --capture Captures failed scenarios into videos stored in the
67 temporary directory (see --tmpdir below) using x264
68 encoding. Requires x264.
69 --capture-all Keep videos for all scenarios, including those that
70 succeed (implies --capture).
71 --interactive-debugging
72 On failure, pause test suite until pressing Enter. Also
73 offer the option to open an interactive Ruby shell (pry)
74 in the Cucumber world's context.
75 --image-bumping-mode
76 When any image matching fails, enter an interactive mode
77 that allows to update the image. If run from a graphical
78 environment, any found candidate image will be displayed
79 in a pop-up.
80 --keep-chutney Don't ever clean Chutney data directory.
81 This can be a big time saver when debugging steps
82 when --keep-snapshots is not an option.
83 --keep-snapshots Don't ever delete any snapshots (including ones marked as
84 temporary). This can be a big time saver when debugging new
85 features. Implies --keep-chutney.
86 --disable-chutney EXPERIMENTAL: All tests will be run using the real Tor
87 network, not a simulated one.
88 Expect this to break many test cases.
89 --late-patch FILE Copies files into the VM before running the test suite.
90 This often can avoid a rebuild.
91 FILE is a text file where each line contains tab-separated
92 source and destination.
93 lines without a tab are ignored.
94 lines with a leading \"#\" are ignored.
95 --early-patch Boots the system with the \"early_patch=umount\" cmdline option.
96 See wiki/src/contribute/build/early-patch.mdwn for details
97 This is useful when you need something to be patched early
98 in the boot process; or if you need to run arbitrary
99 commands, not just copying files
100 --all-tests Don't skip tests which have a @fragile or @skip_by_default tag.
101 --tmpdir Directory where various temporary files are written
102 during a test, e.g. VM snapshots and memory dumps,
103 failure screenshots, pcap files and disk images
104 (default is TMPDIR in the environment, and if unset,
105 /tmp/TailsToaster).
106 --view Shows the test session in a windows. Requires x11vnc
107 and tigervnc-viewer.
108 --view-interact The test session can be \"touched\". For debugging purposes
109 only.
110 --vnc-server-only Starts a VNC server for the test session. Requires x11vnc.
111 --iso IMAGE Test '@product' features using IMAGE.
112 --old-iso IMAGE For some '@product' features (e.g. usb_install) we need
113 an older version of Tails, which this options sets to
114 IMAGE. If none is given, it defaults to the same IMAGE
115 given by --iso, which will be good enough for most testing
116 purposes.
118 Note that '@source' features has no relevant options.
120 CUCUMBER_ARGS can be used to specify which features to be run, but also any
121 cucumber option, although then you must pass \`--\` first to let this wrapper
122 script know that we're done with *its* options. For debugging purposes, a
123 'debug' formatter has been added so pretty debugging can be enabled with
124 \`--format debug\`. You could even combine the default (pretty) formatter with
125 pretty debugging printed to a file with \`--format pretty --format debug
126 --out debug.log\`.
130 error() {
131 echo "${NAME}: error: ${*}" >&2
132 exit 1
135 package_installed() {
136 local ret
137 set +o pipefail
138 if dpkg -s "${1}" 2>/dev/null | grep -q "^Status:.*installed"; then
139 ret=0
140 else
141 ret=1
143 set -o pipefail
144 return ${ret}
147 check_dependencies() {
148 while [ -n "${1:-}" ]; do
149 if ! command -v "${1}" >/dev/null && ! package_installed "${1}" ; then
150 error "'${1}' is missing, please install it and run again."
152 shift
153 done
156 check_tor_version() {
157 local tor_version
158 tor_version=$(tor --version | grep -Po '^Tor version \K.*' | sed --regexp-extended 's,[.]$,,')
159 echo "tor version: $tor_version"
160 if dpkg --compare-versions "$tor_version" lt "$MINIMUM_TOR_VERSION"; then
161 error "Please upgrade to tor ${MINIMUM_TOR_VERSION} or newer."
165 check_virt_viewer_version() {
166 local version
167 version="$(dpkg-query --show --showformat='${VERSION}' virt-viewer)"
168 if dpkg --compare-versions "${version}" ge 10.0; then
169 if ! echo "${version}" | grep -q 'tails$'; then
170 error 'Please install virt-viewer from the isotester-bookworm APT suite' \
171 '(instructions: https://tails.net/contribute/release_process/test/setup/' \
172 'details: https://gitlab.tails.boum.org/tails/tails/-/issues/19064)'
177 display_in_use() {
178 [ -e "/tmp/.X${1#:}-lock" ] || [ -e "/tmp/.X11-unix/X${1#:}" ]
181 next_free_display() {
182 display_nr=0
183 while display_in_use ":${display_nr}"; do
184 display_nr=$((display_nr+1))
185 done
186 echo ":${display_nr}"
189 test_suite_cleanup() {
190 if [ -n "${XVFB_PID:-}" ]; then
191 (kill -0 "${XVFB_PID}" 2>/dev/null && kill "${XVFB_PID}") || /bin/true
193 return $?
196 start_xvfb() {
197 Xvfb "$TARGET_DISPLAY" -screen 0 1024x768x24+32 -noreset >/dev/null 2>&1 &
198 XVFB_PID=$!
199 # Wait for Xvfb to run on TARGET_DISPLAY
200 until display_in_use "$TARGET_DISPLAY"; do
201 sleep 1
202 done
203 echo "Virtual X framebuffer started on display ${TARGET_DISPLAY}"
204 # Hide the mouse cursor so it won't be in the way when we are
205 # trying to match images.
206 unclutter -display "$TARGET_DISPLAY" -root -idle 0.1 >/dev/null 2>&1 &
209 start_vnc_server() {
210 check_dependencies x11vnc
211 # shellcheck disable=SC2086
212 VNC_SERVER_PORT="$(env -u WAYLAND_DISPLAY x11vnc \
213 -listen localhost -display "${TARGET_DISPLAY}" \
214 -bg -nopw -forever ${TAILS_X11VNC_OPTS:-} 2>&1 | \
215 grep -m 1 "^PORT=[0-9]\+" | sed 's/^PORT=//')"
216 echo "VNC server running on: localhost:${VNC_SERVER_PORT}"
219 start_vnc_viewer() {
220 opts=
221 if [[ "${VNC_VIEWER_VIEWONLY}" = yes ]]; then
222 opts=-viewonly
224 check_dependencies tigervnc-viewer
225 xtigervncviewer \
226 -nojpeg $opts \
227 -RemoteResize=0 \
228 -AcceptClipboard=0 \
229 -SendClipboard=0 \
230 -SetPrimary=0 \
231 -SendPrimary=0 \
232 "localhost:${VNC_SERVER_PORT}" 1>/dev/null 2>&1 &
235 # main script
237 # Set default values of environment variables used by this script to
238 # pass options to cucumber (unless they are already set).
239 ALLOW_NON_ROOT=${ALLOW_NON_ROOT-}
240 ARTIFACTS_BASE_URI=${ARTIFACTS_BASE_URI-}
241 CAPTURE=${CAPTURE-}
242 CAPTURE_ALL=${CAPTURE_ALL-}
243 VNC_VIEWER=${VNC_VIEWER-}
244 VNC_VIEWER_VIEWONLY=${VNC_VIEWER_VIEWONLY-yes}
245 VNC_SERVER=${VNC_SERVER-}
246 INTERACTIVE_DEBUGGING=${INTERACTIVE_DEBUGGING-}
247 IMAGE_BUMPING_MODE=${IMAGE_BUMPING_MODE-}
248 KEEP_CHUTNEY=${KEEP_CHUTNEY-}
249 KEEP_SNAPSHOTS=${KEEP_SNAPSHOTS-}
250 TAILS_ISO=${TAILS_ISO-}
251 OLD_TAILS_ISO=${OLD_TAILS_ISO-}
252 EARLY_PATCH=${EARLY_PATCH-}
253 EXTRA_BOOT_OPTIONS=${EXTRA_BOOT_OPTIONS-}
254 ALL_TESTS=${ALL_TESTS-}
256 LONGOPTS="allow-non-root,artifacts-base-uri:,view,view-interact,vnc-server-only,capture,capture-all,help,tmpdir:,keep-chutney,keep-snapshots,disable-chutney,late-patch:,early-patch,extra-boot-options:,all-tests,iso:,old-iso:,interactive-debugging,image-bumping-mode"
257 OPTS=$(getopt -o "" --longoptions $LONGOPTS -n "${NAME}" -- "$@")
258 eval set -- "$OPTS"
259 while [ $# -gt 0 ]; do
260 case $1 in
261 --allow-non-root)
262 if ! /sbin/getcap /usr/bin/tcpdump | grep -q 'cap_net_raw=eip'; then
263 error "/usr/bin/tcpdump lacks cap_net_raw=eip"
265 ALLOW_NON_ROOT="yes"
267 --artifacts-base-uri)
268 shift
269 export ARTIFACTS_BASE_URI="${1}"
271 --view)
272 VNC_VIEWER=yes
273 VNC_VIEWER_VIEWONLY=yes
274 VNC_SERVER=yes
276 --view-interact)
277 VNC_VIEWER=yes
278 VNC_VIEWER_VIEWONLY=
279 VNC_SERVER=yes
281 --vnc-server-only)
282 VNC_VIEWER=
283 VNC_SERVER=yes
285 --capture)
286 check_dependencies x264
287 export CAPTURE="yes"
289 --capture-all)
290 check_dependencies x264
291 export CAPTURE="yes"
292 export CAPTURE_ALL="yes"
294 --interactive-debugging)
295 export INTERACTIVE_DEBUGGING="yes"
297 --image-bumping-mode)
298 export IMAGE_BUMPING_MODE="yes"
300 --keep-chutney)
301 export KEEP_CHUTNEY="yes"
303 --keep-snapshots)
304 export KEEP_CHUTNEY="yes"
305 export KEEP_SNAPSHOTS="yes"
307 --disable-chutney)
308 export DISABLE_CHUTNEY="yes"
310 --late-patch)
311 shift
312 LATE_PATCH="$(realpath -s "$1")"
313 if ! [[ -f "$LATE_PATCH" ]]; then
314 echo "--late-patch requires a valid FILE as argument"
315 exit 2
317 export LATE_PATCH
319 --early-patch)
320 export EARLY_PATCH="yes"
322 --extra-boot-options)
323 shift
324 export EXTRA_BOOT_OPTIONS="$1"
326 --all-tests)
327 ALL_TESTS="yes"
329 --tmpdir)
330 shift
331 TMPDIR="$(readlink -f "$1")"
332 export TMPDIR
334 --iso)
335 shift
336 TAILS_ISO="$(realpath -s "$1")"
337 export TAILS_ISO
339 --old-iso)
340 shift
341 OLD_TAILS_ISO="$(realpath -s "$1")"
342 export OLD_TAILS_ISO
344 --help)
345 usage
346 exit 0
349 shift
350 break
352 esac
353 shift
354 done
356 trap "test_suite_cleanup" EXIT HUP INT QUIT TERM
358 if [ "${EUID}" -ne 0 ] && [ -z "${ALLOW_NON_ROOT}" ]; then
359 error "you are not running as root; if you really know what you are" \
360 "doing, see the --allow-non-root option"
363 # shellcheck disable=SC2086
364 check_dependencies ${GENERAL_DEPENDENCIES}
365 check_tor_version
366 check_virt_viewer_version
368 TARGET_DISPLAY=$(next_free_display)
370 start_xvfb
372 if [ -n "${VNC_SERVER:-}" ]; then
373 start_vnc_server
375 if [ -n "${VNC_VIEWER:-}" ]; then
376 start_vnc_viewer
379 TAGS_ARGS=""
380 if [ -n "${JENKINS_URL:-}" ]; then
381 . auto/scripts/utils.sh
383 if echo "${GIT_BRANCH}" | grep -q -E '[+-]real-Tor$'; then
384 export DISABLE_CHUTNEY="yes"
385 TAGS_ARGS="--tag @supports_real_tor"
386 # The current Git state may not reflect the state at the time the
387 # upstream job was started (e.g. since then we git fetch + git
388 # reset --hard) so we trust the Git state described in Jenkins'
389 # environment variables instead.
390 elif echo "${GIT_BRANCH}" | grep -q -E '[+-]force-all-tests$' \
391 || git_on_a_tag \
392 || [ "${GIT_BRANCH#origin/}" = feature/bullseye ] \
393 || [ "${GIT_BRANCH#origin/}" = testing ] \
394 || [ "${GIT_BRANCH#origin/}" = devel ] \
395 || [ -n "${ALL_TESTS:-}" ]; then
396 TAGS_ARGS=""
397 else
398 TAGS_ARGS="${TAGS_ARGS} --tag ~@fragile --tag ~@skip_by_default"
400 if [ "${UPSTREAMJOB_GIT_COMMIT}" != "${UPSTREAMJOB_GIT_BASE_BRANCH_HEAD}" ] && \
401 git_only_doc_changes_since "${UPSTREAMJOB_GIT_BASE_BRANCH_HEAD}"; then
402 TAGS_ARGS="${TAGS_ARGS} --tag @doc"
406 export USER_DISPLAY="${DISPLAY:-}"
407 export DISPLAY=${TARGET_DISPLAY}
409 # shellcheck disable=SC2086
410 cucumber --expand ${TAGS_ARGS} "${@}"