123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- #!/bin/bash
- set -e
- set -u
- set -o pipefail
- NAME=$(basename ${0})
- GENERAL_DEPENDENCIES="
- cucumber
- devscripts
- dnsmasq-base
- gawk
- git
- i18nspector
- libav-tools
- libcap2-bin
- libsikuli-script-java
- libvirt-clients
- libvirt-daemon-system
- libvirt-dev
- libvirt0
- obfs4proxy
- openssh-server
- ovmf
- pry
- python-jabberbot
- python-potr
- qemu-kvm
- qemu-system-x86
- ruby-guestfs
- ruby-json
- ruby-libvirt
- ruby-net-irc
- ruby-packetfu
- ruby-rb-inotify
- ruby-rjb
- ruby-rspec
- ruby-test-unit
- seabios
- tcpdump
- tor
- unclutter
- virt-viewer
- xvfb
- "
- usage() {
- echo "Usage: $NAME [OPTION]... [--] [CUCUMBER_ARGS]...
- Sets up an appropriate environment and invokes cucumber. Note that this script
- must be run from the Tails source directory root.
- Options for '@product' features:
- --artifacts-base-uri URI
- Pretend that the artifact is located at URI when printing
- its location during a scenario failure. This is useful if
- you intend to serve the artifacts via the web, for
- instance.
- --capture Captures failed scenarios into videos stored in the
- temporary directory (see --tmpdir below) using x264
- encoding. Requires x264.
- --capture-all Keep videos for all scenarios, including those that
- succeed (implies --capture).
- --interactive-debugging
- On failure, pause test suite until pressing Enter. Also
- offer the option to open an interactive Ruby shell (pry)
- in the Cucumber world's context.
- --keep-snapshots Don't ever delete any snapshots (including ones marked as
- temporary). This can be a big time saver when debugging new
- features.
- --retry-find Print a warning whenever Sikuli fails to find an image
- and allow *one* retry after pressing ENTER. This is useful
- for updating outdated images.
- --tmpdir Directory where various temporary files are written
- during a test, e.g. VM snapshots and memory dumps,
- failure screenshots, pcap files and disk images
- (default is TMPDIR in the environment, and if unset,
- /tmp/TailsToaster).
- --view Shows the test session in a windows. Requires x11vnc
- and xtightvncviewer.
- --vnc-server-only Starts a VNC server for the test session. Requires x11vnc.
- --iso IMAGE Test '@product' features using IMAGE.
- --old-iso IMAGE For some '@product' features (e.g. usb_install) we need
- an older version of Tails, which this options sets to
- IMAGE. If none is given, it defaults to the same IMAGE
- given by --iso, which will be good enough for most testing
- purposes.
- Note that '@source' features has no relevant options.
- CUCUMBER_ARGS can be used to specify which features to be run, but also any
- cucumber option, although then you must pass \`--\` first to let this wrapper
- script know that we're done with *its* options. For debugging purposes, a
- 'debug' formatter has been added so pretty debugging can be enabled with
- \`--format debug\`. You could even combine the default (pretty) formatter with
- pretty debugging printed to a file with \`--format pretty --format debug
- --out debug.log\`.
- "
- }
- error() {
- echo "${NAME}: error: ${*}" >&2
- usage
- exit 1
- }
- package_installed() {
- local ret
- set +o pipefail
- if dpkg -s "${1}" 2>/dev/null | grep -q "^Status:.*installed"; then
- ret=0
- else
- ret=1
- fi
- set -o pipefail
- return ${ret}
- }
- check_dependencies() {
- while [ -n "${1:-}" ]; do
- if ! which "${1}" >/dev/null && ! package_installed "${1}" ; then
- error "'${1}' is missing, please install it and run again."
- fi
- shift
- done
- }
- display_in_use() {
- [ -e "/tmp/.X${1#:}-lock" ] || [ -e "/tmp/.X11-unix/X${1#:}" ]
- }
- next_free_display() {
- display_nr=0
- while display_in_use ":${display_nr}"; do
- display_nr=$((display_nr+1))
- done
- echo ":${display_nr}"
- }
- test_suite_cleanup() {
- (kill -0 ${XVFB_PID} 2>/dev/null && kill ${XVFB_PID}) || /bin/true
- }
- start_xvfb() {
- Xvfb $TARGET_DISPLAY -screen 0 1024x768x24+32 >/dev/null 2>&1 &
- XVFB_PID=$!
- # Wait for Xvfb to run on TARGET_DISPLAY
- until display_in_use $TARGET_DISPLAY; do
- sleep 1
- done
- echo "Virtual X framebuffer started on display ${TARGET_DISPLAY}"
- # Hide the mouse cursor so it won't mess up Sikuli's screen scanning
- unclutter -display $TARGET_DISPLAY -root -idle 0 >/dev/null 2>&1 &
- }
- start_vnc_server() {
- check_dependencies x11vnc
- VNC_SERVER_PORT="$(x11vnc -listen localhost -display ${TARGET_DISPLAY} \
- -bg -nopw -forever 2>&1 | \
- grep -m 1 "^PORT=[0-9]\+" | sed 's/^PORT=//')"
- echo "VNC server running on: localhost:${VNC_SERVER_PORT}"
- }
- start_vnc_viewer() {
- check_dependencies xtightvncviewer
- xtightvncviewer -viewonly localhost:${VNC_SERVER_PORT} 1>/dev/null 2>&1 &
- }
- capture_session() {
- check_dependencies libvpx1
- echo "Capturing guest display into ${CAPTURE_FILE}"
- avconv -f x11grab -s 1024x768 -r 15 -i ${TARGET_DISPLAY}.0 -an \
- -vcodec libvpx -y "${CAPTURE_FILE}" >/dev/null 2>&1 &
- }
- # main script
- # Unset all environment variables used by this script to pass options
- # to cucumber, except TMPDIR since we explicitly want to support
- # setting it that way.
- ARTIFACTS_BASE_URI=
- CAPTURE=
- CAPTURE_ALL=
- LOG_FILE=
- VNC_VIEWER=
- VNC_SERVER=
- INTERACTIVE_DEBUGGING=
- KEEP_SNAPSHOTS=
- SIKULI_RETRY_FINDFAILED=
- TAILS_ISO=
- OLD_TAILS_ISO=
- LONGOPTS="artifacts-base-uri:,view,vnc-server-only,capture,capture-all,help,tmpdir:,keep-snapshots,retry-find,iso:,old-iso:,interactive-debugging"
- OPTS=$(getopt -o "" --longoptions $LONGOPTS -n "${NAME}" -- "$@")
- eval set -- "$OPTS"
- while [ $# -gt 0 ]; do
- case $1 in
- --artifacts-base-uri)
- shift
- export ARTIFACTS_BASE_URI="${1}"
- ;;
- --view)
- VNC_VIEWER=yes
- VNC_SERVER=yes
- ;;
- --vnc-server-only)
- VNC_VIEWER=
- VNC_SERVER=yes
- ;;
- --capture)
- check_dependencies x264
- export CAPTURE="yes"
- ;;
- --capture-all)
- check_dependencies x264
- export CAPTURE="yes"
- export CAPTURE_ALL="yes"
- ;;
- --interactive-debugging)
- export INTERACTIVE_DEBUGGING="yes"
- ;;
- --keep-snapshots)
- export KEEP_SNAPSHOTS="yes"
- ;;
- --retry-find)
- export SIKULI_RETRY_FINDFAILED="yes"
- ;;
- --tmpdir)
- shift
- export TMPDIR="$(readlink -f $1)"
- ;;
- --iso)
- shift
- export TAILS_ISO="$(readlink -f $1)"
- ;;
- --old-iso)
- shift
- export OLD_TAILS_ISO="$(readlink -f $1)"
- ;;
- --help)
- usage
- exit 0
- ;;
- --)
- shift
- break
- ;;
- esac
- shift
- done
- trap "test_suite_cleanup" EXIT HUP INT QUIT TERM
- check_dependencies ${GENERAL_DEPENDENCIES}
- TARGET_DISPLAY=$(next_free_display)
- start_xvfb
- if [ -n "${VNC_SERVER:-}" ]; then
- start_vnc_server
- fi
- if [ -n "${VNC_VIEWER:-}" ]; then
- start_vnc_viewer
- fi
- export SIKULI_HOME="/usr/share/java"
- export DISPLAY=${TARGET_DISPLAY}
- cucumber ${@}
|