[lxc-devel] [lxd/master] Test helpers split

albertodonato on Github lxc-bot at linuxcontainers.org
Thu Aug 17 13:53:32 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 504 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170817/1d90b11d/attachment.bin>
-------------- next part --------------
From 9db33d031fdf350c62030d26ee019c37f2d98b5a Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Thu, 17 Aug 2017 11:48:29 +0200
Subject: [PATCH 1/8] tests: split out storage-related helper functions

Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
 test/includes/storage.sh | 41 +++++++++++++++++++++++++++++++++++++++++
 test/main.sh             | 45 +++++----------------------------------------
 2 files changed, 46 insertions(+), 40 deletions(-)
 create mode 100644 test/includes/storage.sh

diff --git a/test/includes/storage.sh b/test/includes/storage.sh
new file mode 100644
index 000000000..63e4802d8
--- /dev/null
+++ b/test/includes/storage.sh
@@ -0,0 +1,41 @@
+# Helper functions related to storage backends.
+
+# Whether a storage backend is available
+storage_backend_available() {
+    # shellcheck disable=2039
+    local backends
+    backends="$(available_storage_backends)"
+    [ "${backends#*$1}" != "$backends" ]
+}
+
+# Choose a random available backend, excluding LXD_BACKEND
+random_storage_backend() {
+    # shellcheck disable=2046
+    shuf -e $(available_storage_backends) | head -n 1
+}
+
+# Return the storage backend being used by a LXD instance
+storage_backend() {
+    cat "$1/lxd.backend"
+}
+
+# Return a list of available storage backends
+available_storage_backends() {
+    # shellcheck disable=2039
+    local backend backends storage_backends
+
+    backends="dir" # always available
+
+    storage_backends="btrfs lvm zfs"
+    if [ -n "${LXD_CEPH_CLUSTER:-}" ]; then
+        storage_backends="${storage_backends} ceph"
+    fi
+
+    for backend in $storage_backends; do
+        if which "$backend" >/dev/null 2>&1; then
+            backends="$backends $backend"
+        fi
+    done
+
+    echo "$backends"
+}
diff --git a/test/main.sh b/test/main.sh
index 5667a75b9..6b0ad1553 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -36,6 +36,11 @@ if [ -n "${LXD_LOGS:-}" ] && [ ! -d "${LXD_LOGS}" ]; then
 fi
 
 # Helper functions
+for include in includes/*.sh; do
+    # shellcheck disable=SC1090
+    . "$include"
+done
+
 local_tcp_port() {
   while :; do
     port=$(shuf -i 10000-32768 -n 1)
@@ -48,46 +53,6 @@ local_tcp_port() {
   done
 }
 
-# return a list of available storage backends
-available_storage_backends() {
-  # shellcheck disable=2039
-  local backend backends
-
-  backends="dir"
-
-  storage_backends="btrfs lvm zfs"
-  if [ -n "${LXD_CEPH_CLUSTER:-}" ]; then
-    storage_backends="${storage_backends} ceph"
-  fi
-
-  for backend in $storage_backends; do
-    if which "$backend" >/dev/null 2>&1; then
-      backends="$backends $backend"
-    fi
-  done
-
-  echo "$backends"
-}
-
-# whether a storage backend is available
-storage_backend_available() {
-  # shellcheck disable=2039
-  local backends
-  backends="$(available_storage_backends)"
-  [ "${backends#*$1}" != "$backends" ]
-}
-
-# choose a random available backend, excluding LXD_BACKEND
-random_storage_backend() {
-    # shellcheck disable=2046
-    shuf -e $(available_storage_backends) | head -n 1
-}
-
-# return the storage backend being used by a LXD instance
-storage_backend() {
-    cat "$1/lxd.backend"
-}
-
 
 if [ -z "${LXD_BACKEND:-}" ]; then
   LXD_BACKEND=dir

From e9add472478bc33f405f2ba8193b9bdfa048df4a Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Thu, 17 Aug 2017 11:58:27 +0200
Subject: [PATCH 2/8] tests: split out network-related helper functions

Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
 test/includes/net.sh | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/main.sh         | 70 --------------------------------------------
 2 files changed, 83 insertions(+), 70 deletions(-)
 create mode 100644 test/includes/net.sh

diff --git a/test/includes/net.sh b/test/includes/net.sh
new file mode 100644
index 000000000..47a9aa330
--- /dev/null
+++ b/test/includes/net.sh
@@ -0,0 +1,83 @@
+# Network-related helper functions.
+
+# Return an available random local port
+local_tcp_port() {
+    # shellcheck disable=SC2039
+    local port pid
+
+    while true; do
+        port=$(shuf -i 10000-32768 -n 1)
+        nc -l 127.0.0.1 "${port}" >/dev/null 2>&1 &
+        pid=$!
+        kill "${pid}" >/dev/null 2>&1 || continue
+        wait "${pid}" || true
+        echo "${port}"
+        return
+    done
+}
+
+# Certificate-aware curl wrapper
+my_curl() {
+    curl -k -s --cert "${LXD_CONF}/client.crt" --key "${LXD_CONF}/client.key" "$@"
+}
+
+
+# set up a loopback device
+configure_loop_device() {
+    # shellcheck disable=SC2039
+    local lv_loop_file pvloopdev
+
+    lv_loop_file=$(mktemp -p "${TEST_DIR}" XXXX.img)
+    truncate -s 10G "${lv_loop_file}"
+    pvloopdev=$(losetup --show -f "${lv_loop_file}")
+    if [ ! -e "${pvloopdev}" ]; then
+        echo "failed to setup loop"
+        false
+    fi
+    echo "${pvloopdev}" >> "${TEST_DIR}/loops"
+
+    # The following code enables to return a value from a shell function by
+    # calling the function as: fun VAR1
+
+    # shellcheck disable=2039
+    local __tmp1="${1}"
+    # shellcheck disable=2039
+    local res1="${lv_loop_file}"
+    if [ "${__tmp1}" ]; then
+        eval "${__tmp1}='${res1}'"
+    fi
+
+    # shellcheck disable=2039
+    local __tmp2="${2}"
+    # shellcheck disable=2039
+    local res2="${pvloopdev}"
+    if [ "${__tmp2}" ]; then
+        eval "${__tmp2}='${res2}'"
+    fi
+}
+
+deconfigure_loop_device() {
+    # shellcheck disable=SC2039
+    local lv_loop_file loopdev success
+
+    lv_loop_file="${1}"
+    loopdev="${2}"
+    success=0
+    # shellcheck disable=SC2034
+    for i in $(seq 10); do
+        if losetup -d "${loopdev}"; then
+            success=1
+            break
+        fi
+
+        sleep 0.5
+    done
+
+    if [ "$success" = "0" ]; then
+        echo "Failed to tear down loop device"
+        false
+    fi
+
+    rm -f "${lv_loop_file}"
+    sed -i "\|^${loopdev}|d" "${TEST_DIR}/loops"
+}
diff --git a/test/main.sh b/test/main.sh
index 6b0ad1553..c127cbd2d 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -41,19 +41,6 @@ for include in includes/*.sh; do
     . "$include"
 done
 
-local_tcp_port() {
-  while :; do
-    port=$(shuf -i 10000-32768 -n 1)
-    nc -l 127.0.0.1 "${port}" >/dev/null 2>&1 &
-    pid=$!
-    kill "${pid}" >/dev/null 2>&1 || continue
-    wait "${pid}" || true
-    echo "${port}"
-    return
-  done
-}
-
-
 if [ -z "${LXD_BACKEND:-}" ]; then
   LXD_BACKEND=dir
 fi
@@ -219,10 +206,6 @@ gen_cert() {
   mv "${LXD_CONF}/client.key.bak" "${LXD_CONF}/client.key"
 }
 
-my_curl() {
-  curl -k -s --cert "${LXD_CONF}/client.crt" --key "${LXD_CONF}/client.key" "$@"
-}
-
 wait_for() {
   addr=${1}
   shift
@@ -474,59 +457,6 @@ wipe() {
   rm -Rf "${1}"
 }
 
-configure_loop_device() {
-  lv_loop_file=$(mktemp -p "${TEST_DIR}" XXXX.img)
-  truncate -s 10G "${lv_loop_file}"
-  pvloopdev=$(losetup --show -f "${lv_loop_file}")
-  if [ ! -e "${pvloopdev}" ]; then
-    echo "failed to setup loop"
-    false
-  fi
-  echo "${pvloopdev}" >> "${TEST_DIR}/loops"
-
-  # The following code enables to return a value from a shell function by
-  # calling the function as: fun VAR1
-
-  # shellcheck disable=2039
-  local  __tmp1="${1}"
-  # shellcheck disable=2039
-  local  res1="${lv_loop_file}"
-  if [ "${__tmp1}" ]; then
-      eval "${__tmp1}='${res1}'"
-  fi
-
-  # shellcheck disable=2039
-  local  __tmp2="${2}"
-  # shellcheck disable=2039
-  local  res2="${pvloopdev}"
-  if [ "${__tmp2}" ]; then
-      eval "${__tmp2}='${res2}'"
-  fi
-}
-
-deconfigure_loop_device() {
-  lv_loop_file="${1}"
-  loopdev="${2}"
-
-  SUCCESS=0
-  # shellcheck disable=SC2034
-  for i in $(seq 10); do
-    if losetup -d "${loopdev}"; then
-      SUCCESS=1
-      break
-    fi
-
-    sleep 0.5
-  done
-
-  if [ "${SUCCESS}" = "0" ]; then
-    echo "Failed to tear down loop device"
-    false
-  fi
-
-  rm -f "${lv_loop_file}"
-  sed -i "\|^${loopdev}|d" "${TEST_DIR}/loops"
-}
 
 # Must be set before cleanup()
 TEST_CURRENT=setup

From 12381381069fcfc426868f8cd4193fd0040d3532 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Thu, 17 Aug 2017 12:40:39 +0200
Subject: [PATCH 3/8] tests: split out lxc and lxd related helper functions

Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
 test/includes/lxc.sh |  52 ++++++++
 test/includes/lxd.sh | 307 ++++++++++++++++++++++++++++++++++++++++++++
 test/main.sh         | 352 ---------------------------------------------------
 3 files changed, 359 insertions(+), 352 deletions(-)
 create mode 100644 test/includes/lxc.sh
 create mode 100644 test/includes/lxd.sh

diff --git a/test/includes/lxc.sh b/test/includes/lxc.sh
new file mode 100644
index 000000000..74b45cde6
--- /dev/null
+++ b/test/includes/lxc.sh
@@ -0,0 +1,52 @@
+# lxc CLI related test helpers.
+
+lxc() {
+    LXC_LOCAL=1 lxc_remote "$@"
+}
+
+lxc_remote() {
+    set +x
+    # shellcheck disable=SC2039
+    local injected cmd arg
+
+    injected=0
+    cmd=$(which lxc)
+
+    # shellcheck disable=SC2048,SC2068
+    for arg in $@; do
+        if [ "${arg}" = "--" ]; then
+            injected=1
+            cmd="${cmd} ${DEBUG:-}"
+            [ -n "${LXC_LOCAL}" ] && cmd="${cmd} --force-local"
+            cmd="${cmd} --"
+        elif [ "${arg}" = "--force-local" ]; then
+            continue
+        else
+            cmd="${cmd} \"${arg}\""
+        fi
+    done
+
+    if [ "${injected}" = "0" ]; then
+        cmd="${cmd} ${DEBUG-}"
+    fi
+    if [ -n "${DEBUG:-}" ]; then
+        set -x
+    fi
+    eval "${cmd}"
+}
+
+gen_cert() {
+    # Temporarily move the existing cert to trick LXC into generating a
+    # second cert.  LXC will only generate a cert when adding a remote
+    # server with a HTTPS scheme.  The remote server URL just needs to
+    # be syntactically correct to get past initial checks; in fact, we
+    # don't want it to succeed, that way we don't have to delete it later.
+    [ -f "${LXD_CONF}/${1}.crt" ] && return
+    mv "${LXD_CONF}/client.crt" "${LXD_CONF}/client.crt.bak"
+    mv "${LXD_CONF}/client.key" "${LXD_CONF}/client.key.bak"
+    echo y | lxc_remote remote add "$(uuidgen)" https://0.0.0.0 || true
+    mv "${LXD_CONF}/client.crt" "${LXD_CONF}/${1}.crt"
+    mv "${LXD_CONF}/client.key" "${LXD_CONF}/${1}.key"
+    mv "${LXD_CONF}/client.crt.bak" "${LXD_CONF}/client.crt"
+    mv "${LXD_CONF}/client.key.bak" "${LXD_CONF}/client.key"
+}
diff --git a/test/includes/lxd.sh b/test/includes/lxd.sh
new file mode 100644
index 000000000..a8e2f561b
--- /dev/null
+++ b/test/includes/lxd.sh
@@ -0,0 +1,307 @@
+# LXD-related test helpers.
+
+spawn_lxd() {
+    set +x
+    # LXD_DIR is local here because since $(lxc) is actually a function, it
+    # overwrites the environment and we would lose LXD_DIR's value otherwise.
+
+    # shellcheck disable=2039
+    local LXD_DIR lxddir lxd_backend
+
+    lxddir=${1}
+    shift
+
+    storage=${1}
+    shift
+
+    if [ "$LXD_BACKEND" = "random" ]; then
+        lxd_backend="$(random_storage_backend)"
+    else
+        lxd_backend="$LXD_BACKEND"
+    fi
+
+    if [ "${LXD_BACKEND}" = "ceph" ] && [ -z "${LXD_CEPH_CLUSTER:-}" ]; then
+        echo "A cluster name must be specified when using the CEPH driver." >&2
+        exit 1
+    fi
+
+    # Copy pre generated Certs
+    cp deps/server.crt "${lxddir}"
+    cp deps/server.key "${lxddir}"
+
+    # setup storage
+    "$lxd_backend"_setup "${lxddir}"
+    echo "$lxd_backend" > "${lxddir}/lxd.backend"
+
+    echo "==> Spawning lxd in ${lxddir}"
+    # shellcheck disable=SC2086
+    LXD_DIR="${lxddir}" lxd --logfile "${lxddir}/lxd.log" ${DEBUG-} "$@" 2>&1 &
+    LXD_PID=$!
+    echo "${LXD_PID}" > "${lxddir}/lxd.pid"
+    echo "${lxddir}" >> "${TEST_DIR}/daemons"
+    echo "==> Spawned LXD (PID is ${LXD_PID})"
+
+    echo "==> Confirming lxd is responsive"
+    LXD_DIR="${lxddir}" lxd waitready --timeout=300
+
+    echo "==> Binding to network"
+    # shellcheck disable=SC2034
+    for i in $(seq 10); do
+        addr="127.0.0.1:$(local_tcp_port)"
+        LXD_DIR="${lxddir}" lxc config set core.https_address "${addr}" || continue
+        echo "${addr}" > "${lxddir}/lxd.addr"
+        echo "==> Bound to ${addr}"
+        break
+    done
+
+    echo "==> Setting trust password"
+    LXD_DIR="${lxddir}" lxc config set core.trust_password foo
+    if [ -n "${DEBUG:-}" ]; then
+        set -x
+    fi
+
+    echo "==> Setting up networking"
+    LXD_DIR="${lxddir}" lxc profile device add default eth0 nic nictype=p2p name=eth0
+
+    if [ "${storage}" = true ]; then
+        echo "==> Configuring storage backend"
+        "$lxd_backend"_configure "${lxddir}"
+    fi
+}
+
+respawn_lxd() {
+    set +x
+    # LXD_DIR is local here because since $(lxc) is actually a function, it
+    # overwrites the environment and we would lose LXD_DIR's value otherwise.
+
+    # shellcheck disable=2039
+    local LXD_DIR
+
+    lxddir=${1}
+    shift
+
+    echo "==> Spawning lxd in ${lxddir}"
+    # shellcheck disable=SC2086
+    LXD_DIR="${lxddir}" lxd --logfile "${lxddir}/lxd.log" ${DEBUG-} "$@" 2>&1 &
+    LXD_PID=$!
+    echo "${LXD_PID}" > "${lxddir}/lxd.pid"
+    echo "==> Spawned LXD (PID is ${LXD_PID})"
+
+    echo "==> Confirming lxd is responsive"
+    LXD_DIR="${lxddir}" lxd waitready --timeout=300
+}
+
+kill_lxd() {
+    # LXD_DIR is local here because since $(lxc) is actually a function, it
+    # overwrites the environment and we would lose LXD_DIR's value otherwise.
+
+    # shellcheck disable=2039
+    local LXD_DIR daemon_dir daemon_pid check_leftovers lxd_backend
+
+    daemon_dir=${1}
+    LXD_DIR=${daemon_dir}
+    daemon_pid=$(cat "${daemon_dir}/lxd.pid")
+    check_leftovers="false"
+    lxd_backend=$(storage_backend "$daemon_dir")
+    echo "==> Killing LXD at ${daemon_dir}"
+
+    if [ -e "${daemon_dir}/unix.socket" ]; then
+        # Delete all containers
+        echo "==> Deleting all containers"
+        for container in $(lxc list --fast --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do
+            lxc delete "${container}" --force-local -f || true
+        done
+
+        # Delete all images
+        echo "==> Deleting all images"
+        for image in $(lxc image list --force-local | tail -n+3 | grep "^| " | cut -d'|' -f3 | sed "s/^ //g"); do
+            lxc image delete "${image}" --force-local || true
+        done
+
+        # Delete all networks
+        echo "==> Deleting all networks"
+        for network in $(lxc network list --force-local | grep YES | grep "^| " | cut -d' ' -f2); do
+            lxc network delete "${network}" --force-local || true
+        done
+
+        # Delete all profiles
+        echo "==> Deleting all profiles"
+        for profile in $(lxc profile list --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do
+            lxc profile delete "${profile}" --force-local || true
+        done
+
+        echo "==> Deleting all storage pools"
+        for storage in $(lxc storage list --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do
+            lxc storage delete "${storage}" --force-local || true
+        done
+
+        echo "==> Checking for locked DB tables"
+        for table in $(echo .tables | sqlite3 "${daemon_dir}/lxd.db"); do
+            echo "SELECT * FROM ${table};" | sqlite3 "${daemon_dir}/lxd.db" >/dev/null
+        done
+
+        # Kill the daemon
+        lxd shutdown || kill -9 "${daemon_pid}" 2>/dev/null || true
+
+        # Cleanup shmounts (needed due to the forceful kill)
+        find "${daemon_dir}" -name shmounts -exec "umount" "-l" "{}" \; >/dev/null 2>&1 || true
+        find "${daemon_dir}" -name devlxd -exec "umount" "-l" "{}" \; >/dev/null 2>&1 || true
+
+        check_leftovers="true"
+    fi
+
+    if [ -n "${LXD_LOGS:-}" ]; then
+        echo "==> Copying the logs"
+        mkdir -p "${LXD_LOGS}/${daemon_pid}"
+        cp -R "${daemon_dir}/logs/" "${LXD_LOGS}/${daemon_pid}/"
+        cp "${daemon_dir}/lxd.log" "${LXD_LOGS}/${daemon_pid}/"
+    fi
+
+    if [ "${check_leftovers}" = "true" ]; then
+        echo "==> Checking for leftover files"
+        rm -f "${daemon_dir}/containers/lxc-monitord.log"
+        rm -f "${daemon_dir}/security/apparmor/cache/.features"
+        check_empty "${daemon_dir}/containers/"
+        check_empty "${daemon_dir}/devices/"
+        check_empty "${daemon_dir}/images/"
+        # FIXME: Once container logging rework is done, uncomment
+        # check_empty "${daemon_dir}/logs/"
+        check_empty "${daemon_dir}/security/apparmor/cache/"
+        check_empty "${daemon_dir}/security/apparmor/profiles/"
+        check_empty "${daemon_dir}/security/seccomp/"
+        check_empty "${daemon_dir}/shmounts/"
+        check_empty "${daemon_dir}/snapshots/"
+
+        echo "==> Checking for leftover DB entries"
+        check_empty_table "${daemon_dir}/lxd.db" "containers"
+        check_empty_table "${daemon_dir}/lxd.db" "containers_config"
+        check_empty_table "${daemon_dir}/lxd.db" "containers_devices"
+        check_empty_table "${daemon_dir}/lxd.db" "containers_devices_config"
+        check_empty_table "${daemon_dir}/lxd.db" "containers_profiles"
+        check_empty_table "${daemon_dir}/lxd.db" "networks"
+        check_empty_table "${daemon_dir}/lxd.db" "networks_config"
+        check_empty_table "${daemon_dir}/lxd.db" "images"
+        check_empty_table "${daemon_dir}/lxd.db" "images_aliases"
+        check_empty_table "${daemon_dir}/lxd.db" "images_properties"
+        check_empty_table "${daemon_dir}/lxd.db" "images_source"
+        check_empty_table "${daemon_dir}/lxd.db" "profiles"
+        check_empty_table "${daemon_dir}/lxd.db" "profiles_config"
+        check_empty_table "${daemon_dir}/lxd.db" "profiles_devices"
+        check_empty_table "${daemon_dir}/lxd.db" "profiles_devices_config"
+        check_empty_table "${daemon_dir}/lxd.db" "storage_pools"
+        check_empty_table "${daemon_dir}/lxd.db" "storage_pools_config"
+        check_empty_table "${daemon_dir}/lxd.db" "storage_volumes"
+        check_empty_table "${daemon_dir}/lxd.db" "storage_volumes_config"
+    fi
+
+    # teardown storage
+    "$lxd_backend"_teardown "${daemon_dir}"
+
+    # Wipe the daemon directory
+    wipe "${daemon_dir}"
+
+    # Remove the daemon from the list
+    sed "\|^${daemon_dir}|d" -i "${TEST_DIR}/daemons"
+}
+
+shutdown_lxd() {
+    # LXD_DIR is local here because since $(lxc) is actually a function, it
+    # overwrites the environment and we would lose LXD_DIR's value otherwise.
+
+    # shellcheck disable=2039
+    local LXD_DIR
+
+    daemon_dir=${1}
+    LXD_DIR=${daemon_dir}
+    daemon_pid=$(cat "${daemon_dir}/lxd.pid")
+    echo "==> Killing LXD at ${daemon_dir}"
+
+    # Kill the daemon
+    lxd shutdown || kill -9 "${daemon_pid}" 2>/dev/null || true
+}
+
+cleanup() {
+    # Allow for failures and stop tracing everything
+    set +ex
+    DEBUG=
+
+    # Allow for inspection
+    if [ -n "${LXD_INSPECT:-}" ]; then
+        if [ "${TEST_RESULT}" != "success" ]; then
+            echo "==> TEST DONE: ${TEST_CURRENT_DESCRIPTION}"
+        fi
+        echo "==> Test result: ${TEST_RESULT}"
+
+        # shellcheck disable=SC2086
+        printf "To poke around, use:\n LXD_DIR=%s LXD_CONF=%s sudo -E %s/bin/lxc COMMAND\n" "${LXD_DIR}" "${LXD_CONF}" ${GOPATH:-}
+        echo "Tests Completed (${TEST_RESULT}): hit enter to continue"
+
+        # shellcheck disable=SC2034
+        read -r nothing
+    fi
+
+    echo "==> Cleaning up"
+
+    # Kill all the LXD instances
+    # shellcheck disable=SC2039
+    local daemon_dir
+    while read -r daemon_dir; do
+        kill_lxd "${daemon_dir}"
+    done < "${TEST_DIR}/daemons"
+
+    # Cleanup leftover networks
+    # shellcheck disable=SC2009
+    ps aux | grep "interface=lxdt$$ " | grep -v grep | awk '{print $2}' | while read -r line; do
+        kill -9 "${line}"
+    done
+    if [ -e "/sys/class/net/lxdt$$" ]; then
+        ip link del lxdt$$
+    fi
+
+    # Wipe the test environment
+    wipe "${TEST_DIR}"
+
+    echo ""
+    echo ""
+    if [ "${TEST_RESULT}" != "success" ]; then
+        echo "==> TEST DONE: ${TEST_CURRENT_DESCRIPTION}"
+    fi
+    echo "==> Test result: ${TEST_RESULT}"
+}
+
+wait_for() {
+    # shellcheck disable=SC2039
+    local addr op
+
+    addr=${1}
+    shift
+    op=$("$@" | jq -r .operation)
+    my_curl "https://${addr}${op}/wait"
+}
+
+wipe() {
+    if which btrfs >/dev/null 2>&1; then
+        rm -Rf "${1}" 2>/dev/null || true
+        if [ -d "${1}" ]; then
+            find "${1}" | tac | xargs btrfs subvolume delete >/dev/null 2>&1 || true
+        fi
+    fi
+
+    # shellcheck disable=SC2039
+    local pid
+    # shellcheck disable=SC2009
+    ps aux | grep lxc-monitord | grep "${1}" | awk '{print $2}' | while read -r pid; do
+        kill -9 "${pid}" || true
+    done
+
+    if [ -f "${TEST_DIR}/loops" ]; then
+        while read -r line; do
+            losetup -d "${line}" || true
+        done < "${TEST_DIR}/loops"
+    fi
+    if mountpoint -q "${1}"; then
+        umount "${1}"
+    fi
+
+    rm -Rf "${1}"
+}
diff --git a/test/main.sh b/test/main.sh
index c127cbd2d..7d060ae5a 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -62,157 +62,6 @@ for backend in $(available_storage_backends); do
   . "backends/${backend}.sh"
 done
 
-
-spawn_lxd() {
-  set +x
-  # LXD_DIR is local here because since $(lxc) is actually a function, it
-  # overwrites the environment and we would lose LXD_DIR's value otherwise.
-
-  # shellcheck disable=2039
-  local LXD_DIR lxddir lxd_backend
-
-  lxddir=${1}
-  shift
-
-  storage=${1}
-  shift
-
-  if [ "$LXD_BACKEND" = "random" ]; then
-    lxd_backend="$(random_storage_backend)"
-  else
-    lxd_backend="$LXD_BACKEND"
-  fi
-
-  if [ "${LXD_BACKEND}" = "ceph" ] && [ -z "${LXD_CEPH_CLUSTER:-}" ]; then
-    echo "A cluster name must be specified when using the CEPH driver." >&2
-    exit 1
-  fi
-
-  # Copy pre generated Certs
-  cp deps/server.crt "${lxddir}"
-  cp deps/server.key "${lxddir}"
-
-  # setup storage
-  "$lxd_backend"_setup "${lxddir}"
-  echo "$lxd_backend" > "${lxddir}/lxd.backend"
-
-  echo "==> Spawning lxd in ${lxddir}"
-  # shellcheck disable=SC2086
-  LXD_DIR="${lxddir}" lxd --logfile "${lxddir}/lxd.log" ${DEBUG-} "$@" 2>&1 &
-  LXD_PID=$!
-  echo "${LXD_PID}" > "${lxddir}/lxd.pid"
-  echo "${lxddir}" >> "${TEST_DIR}/daemons"
-  echo "==> Spawned LXD (PID is ${LXD_PID})"
-
-  echo "==> Confirming lxd is responsive"
-  LXD_DIR="${lxddir}" lxd waitready --timeout=300
-
-  echo "==> Binding to network"
-  # shellcheck disable=SC2034
-  for i in $(seq 10); do
-    addr="127.0.0.1:$(local_tcp_port)"
-    LXD_DIR="${lxddir}" lxc config set core.https_address "${addr}" || continue
-    echo "${addr}" > "${lxddir}/lxd.addr"
-    echo "==> Bound to ${addr}"
-    break
-  done
-
-  echo "==> Setting trust password"
-  LXD_DIR="${lxddir}" lxc config set core.trust_password foo
-  if [ -n "${DEBUG:-}" ]; then
-    set -x
-  fi
-
-  echo "==> Setting up networking"
-  LXD_DIR="${lxddir}" lxc profile device add default eth0 nic nictype=p2p name=eth0
-
-  if [ "${storage}" = true ]; then
-    echo "==> Configuring storage backend"
-    "$lxd_backend"_configure "${lxddir}"
-  fi
-}
-
-respawn_lxd() {
-  set +x
-  # LXD_DIR is local here because since $(lxc) is actually a function, it
-  # overwrites the environment and we would lose LXD_DIR's value otherwise.
-
-  # shellcheck disable=2039
-  local LXD_DIR
-
-  lxddir=${1}
-  shift
-
-  echo "==> Spawning lxd in ${lxddir}"
-  # shellcheck disable=SC2086
-  LXD_DIR="${lxddir}" lxd --logfile "${lxddir}/lxd.log" ${DEBUG-} "$@" 2>&1 &
-  LXD_PID=$!
-  echo "${LXD_PID}" > "${lxddir}/lxd.pid"
-  echo "==> Spawned LXD (PID is ${LXD_PID})"
-
-  echo "==> Confirming lxd is responsive"
-  LXD_DIR="${lxddir}" lxd waitready --timeout=300
-}
-
-lxc() {
-  LXC_LOCAL=1
-  lxc_remote "$@"
-  RET=$?
-  unset LXC_LOCAL
-  return ${RET}
-}
-
-lxc_remote() {
-  set +x
-  injected=0
-  cmd=$(which lxc)
-
-  # shellcheck disable=SC2048,SC2068
-  for arg in $@; do
-    if [ "${arg}" = "--" ]; then
-      injected=1
-      cmd="${cmd} ${DEBUG:-}"
-      [ -n "${LXC_LOCAL}" ] && cmd="${cmd} --force-local"
-      cmd="${cmd} --"
-    elif [ "${arg}" = "--force-local" ]; then
-      continue
-    else
-      cmd="${cmd} \"${arg}\""
-    fi
-  done
-
-  if [ "${injected}" = "0" ]; then
-    cmd="${cmd} ${DEBUG-}"
-  fi
-  if [ -n "${DEBUG:-}" ]; then
-    set -x
-  fi
-  eval "${cmd}"
-}
-
-gen_cert() {
-  # Temporarily move the existing cert to trick LXC into generating a
-  # second cert.  LXC will only generate a cert when adding a remote
-  # server with a HTTPS scheme.  The remote server URL just needs to
-  # be syntactically correct to get past initial checks; in fact, we
-  # don't want it to succeed, that way we don't have to delete it later.
-  [ -f "${LXD_CONF}/${1}.crt" ] && return
-  mv "${LXD_CONF}/client.crt" "${LXD_CONF}/client.crt.bak"
-  mv "${LXD_CONF}/client.key" "${LXD_CONF}/client.key.bak"
-  echo y | lxc_remote remote add "$(uuidgen)" https://0.0.0.0 || true
-  mv "${LXD_CONF}/client.crt" "${LXD_CONF}/${1}.crt"
-  mv "${LXD_CONF}/client.key" "${LXD_CONF}/${1}.key"
-  mv "${LXD_CONF}/client.crt.bak" "${LXD_CONF}/client.crt"
-  mv "${LXD_CONF}/client.key.bak" "${LXD_CONF}/client.key"
-}
-
-wait_for() {
-  addr=${1}
-  shift
-  op=$("$@" | jq -r .operation)
-  my_curl "https://${addr}${op}/wait"
-}
-
 ensure_has_localhost_remote() {
   addr=${1}
   if ! lxc remote list | grep -q "localhost"; then
@@ -256,207 +105,6 @@ check_empty_table() {
   fi
 }
 
-kill_lxd() {
-  # LXD_DIR is local here because since $(lxc) is actually a function, it
-  # overwrites the environment and we would lose LXD_DIR's value otherwise.
-
-  # shellcheck disable=2039
-  local LXD_DIR daemon_dir daemon_pid check_leftovers lxd_backend
-
-  daemon_dir=${1}
-  LXD_DIR=${daemon_dir}
-  daemon_pid=$(cat "${daemon_dir}/lxd.pid")
-  check_leftovers="false"
-  lxd_backend=$(storage_backend "$daemon_dir")
-  echo "==> Killing LXD at ${daemon_dir}"
-
-  if [ -e "${daemon_dir}/unix.socket" ]; then
-    # Delete all containers
-    echo "==> Deleting all containers"
-    for container in $(lxc list --fast --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do
-      lxc delete "${container}" --force-local -f || true
-    done
-
-    # Delete all images
-    echo "==> Deleting all images"
-    for image in $(lxc image list --force-local | tail -n+3 | grep "^| " | cut -d'|' -f3 | sed "s/^ //g"); do
-      lxc image delete "${image}" --force-local || true
-    done
-
-    # Delete all networks
-    echo "==> Deleting all networks"
-    for network in $(lxc network list --force-local | grep YES | grep "^| " | cut -d' ' -f2); do
-      lxc network delete "${network}" --force-local || true
-    done
-
-    # Delete all profiles
-    echo "==> Deleting all profiles"
-    for profile in $(lxc profile list --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do
-      lxc profile delete "${profile}" --force-local || true
-    done
-
-    echo "==> Deleting all storage pools"
-    for storage in $(lxc storage list --force-local | tail -n+3 | grep "^| " | cut -d' ' -f2); do
-      lxc storage delete "${storage}" --force-local || true
-    done
-
-    echo "==> Checking for locked DB tables"
-    for table in $(echo .tables | sqlite3 "${daemon_dir}/lxd.db"); do
-      echo "SELECT * FROM ${table};" | sqlite3 "${daemon_dir}/lxd.db" >/dev/null
-    done
-
-    # Kill the daemon
-    lxd shutdown || kill -9 "${daemon_pid}" 2>/dev/null || true
-
-    # Cleanup shmounts (needed due to the forceful kill)
-    find "${daemon_dir}" -name shmounts -exec "umount" "-l" "{}" \; >/dev/null 2>&1 || true
-    find "${daemon_dir}" -name devlxd -exec "umount" "-l" "{}" \; >/dev/null 2>&1 || true
-
-    check_leftovers="true"
-  fi
-
-  if [ -n "${LXD_LOGS:-}" ]; then
-    echo "==> Copying the logs"
-    mkdir -p "${LXD_LOGS}/${daemon_pid}"
-    cp -R "${daemon_dir}/logs/" "${LXD_LOGS}/${daemon_pid}/"
-    cp "${daemon_dir}/lxd.log" "${LXD_LOGS}/${daemon_pid}/"
-  fi
-
-  if [ "${check_leftovers}" = "true" ]; then
-    echo "==> Checking for leftover files"
-    rm -f "${daemon_dir}/containers/lxc-monitord.log"
-    rm -f "${daemon_dir}/security/apparmor/cache/.features"
-    check_empty "${daemon_dir}/containers/"
-    check_empty "${daemon_dir}/devices/"
-    check_empty "${daemon_dir}/images/"
-    # FIXME: Once container logging rework is done, uncomment
-    # check_empty "${daemon_dir}/logs/"
-    check_empty "${daemon_dir}/security/apparmor/cache/"
-    check_empty "${daemon_dir}/security/apparmor/profiles/"
-    check_empty "${daemon_dir}/security/seccomp/"
-    check_empty "${daemon_dir}/shmounts/"
-    check_empty "${daemon_dir}/snapshots/"
-
-    echo "==> Checking for leftover DB entries"
-    check_empty_table "${daemon_dir}/lxd.db" "containers"
-    check_empty_table "${daemon_dir}/lxd.db" "containers_config"
-    check_empty_table "${daemon_dir}/lxd.db" "containers_devices"
-    check_empty_table "${daemon_dir}/lxd.db" "containers_devices_config"
-    check_empty_table "${daemon_dir}/lxd.db" "containers_profiles"
-    check_empty_table "${daemon_dir}/lxd.db" "networks"
-    check_empty_table "${daemon_dir}/lxd.db" "networks_config"
-    check_empty_table "${daemon_dir}/lxd.db" "images"
-    check_empty_table "${daemon_dir}/lxd.db" "images_aliases"
-    check_empty_table "${daemon_dir}/lxd.db" "images_properties"
-    check_empty_table "${daemon_dir}/lxd.db" "images_source"
-    check_empty_table "${daemon_dir}/lxd.db" "profiles"
-    check_empty_table "${daemon_dir}/lxd.db" "profiles_config"
-    check_empty_table "${daemon_dir}/lxd.db" "profiles_devices"
-    check_empty_table "${daemon_dir}/lxd.db" "profiles_devices_config"
-    check_empty_table "${daemon_dir}/lxd.db" "storage_pools"
-    check_empty_table "${daemon_dir}/lxd.db" "storage_pools_config"
-    check_empty_table "${daemon_dir}/lxd.db" "storage_volumes"
-    check_empty_table "${daemon_dir}/lxd.db" "storage_volumes_config"
-  fi
-
-  # teardown storage
-  "$lxd_backend"_teardown "${daemon_dir}"
-
-  # Wipe the daemon directory
-  wipe "${daemon_dir}"
-
-  # Remove the daemon from the list
-  sed "\|^${daemon_dir}|d" -i "${TEST_DIR}/daemons"
-}
-
-shutdown_lxd() {
-  # LXD_DIR is local here because since $(lxc) is actually a function, it
-  # overwrites the environment and we would lose LXD_DIR's value otherwise.
-
-  # shellcheck disable=2039
-  local LXD_DIR
-
-  daemon_dir=${1}
-  LXD_DIR=${daemon_dir}
-  daemon_pid=$(cat "${daemon_dir}/lxd.pid")
-  echo "==> Killing LXD at ${daemon_dir}"
-
-  # Kill the daemon
-  lxd shutdown || kill -9 "${daemon_pid}" 2>/dev/null || true
-}
-
-cleanup() {
-  # Allow for failures and stop tracing everything
-  set +ex
-  DEBUG=
-
-  # Allow for inspection
-  if [ -n "${LXD_INSPECT:-}" ]; then
-    if [ "${TEST_RESULT}" != "success" ]; then
-      echo "==> TEST DONE: ${TEST_CURRENT_DESCRIPTION}"
-    fi
-    echo "==> Test result: ${TEST_RESULT}"
-
-    # shellcheck disable=SC2086
-    printf "To poke around, use:\n LXD_DIR=%s LXD_CONF=%s sudo -E %s/bin/lxc COMMAND\n" "${LXD_DIR}" "${LXD_CONF}" ${GOPATH:-}
-    echo "Tests Completed (${TEST_RESULT}): hit enter to continue"
-
-    # shellcheck disable=SC2034
-    read -r nothing
-  fi
-
-  echo "==> Cleaning up"
-
-  # Kill all the LXD instances
-  while read -r daemon_dir; do
-    kill_lxd "${daemon_dir}"
-  done < "${TEST_DIR}/daemons"
-
-  # Cleanup leftover networks
-  # shellcheck disable=SC2009
-  ps aux | grep "interface=lxdt$$ " | grep -v grep | awk '{print $2}' | while read -r line; do
-    kill -9 "${line}"
-  done
-  if [ -e "/sys/class/net/lxdt$$" ]; then
-    ip link del lxdt$$
-  fi
-
-  # Wipe the test environment
-  wipe "${TEST_DIR}"
-
-  echo ""
-  echo ""
-  if [ "${TEST_RESULT}" != "success" ]; then
-    echo "==> TEST DONE: ${TEST_CURRENT_DESCRIPTION}"
-  fi
-  echo "==> Test result: ${TEST_RESULT}"
-}
-
-wipe() {
-  if which btrfs >/dev/null 2>&1; then
-    rm -Rf "${1}" 2>/dev/null || true
-    if [ -d "${1}" ]; then
-      find "${1}" | tac | xargs btrfs subvolume delete >/dev/null 2>&1 || true
-    fi
-  fi
-
-  # shellcheck disable=SC2009
-  ps aux | grep lxc-monitord | grep "${1}" | awk '{print $2}' | while read -r pid; do
-    kill -9 "${pid}" || true
-  done
-
-  if [ -f "${TEST_DIR}/loops" ]; then
-    while read -r line; do
-      losetup -d "${line}" || true
-    done < "${TEST_DIR}/loops"
-  fi
-  if mountpoint -q "${1}"; then
-    umount "${1}"
-  fi
-
-  rm -Rf "${1}"
-}
-
 
 # Must be set before cleanup()
 TEST_CURRENT=setup

From 076103ad539aec71e12df6bfcda66eefb93f8888 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Thu, 17 Aug 2017 13:50:40 +0200
Subject: [PATCH 4/8] tests: split out test setup related helper functions

Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
 test/includes/setup.sh | 29 +++++++++++++++++++++++++++++
 test/main.sh           | 26 --------------------------
 2 files changed, 29 insertions(+), 26 deletions(-)
 create mode 100644 test/includes/setup.sh

diff --git a/test/includes/setup.sh b/test/includes/setup.sh
new file mode 100644
index 000000000..1ecbc5cbe
--- /dev/null
+++ b/test/includes/setup.sh
@@ -0,0 +1,29 @@
+# Test setup helper functions.
+
+ensure_has_localhost_remote() {
+    # shellcheck disable=SC2039
+    local addr=${1}
+    if ! lxc remote list | grep -q "localhost"; then
+        lxc remote add localhost "https://${addr}" --accept-certificate --password foo
+    fi
+}
+
+ensure_import_testimage() {
+    if ! lxc image alias list | grep -q "^| testimage\s*|.*$"; then
+        if [ -e "${LXD_TEST_IMAGE:-}" ]; then
+            lxc image import "${LXD_TEST_IMAGE}" --alias testimage
+        else
+            if [ ! -e "/bin/busybox" ]; then
+                echo "Please install busybox (busybox-static) or set LXD_TEST_IMAGE"
+                exit 1
+            fi
+
+            if ldd /bin/busybox >/dev/null 2>&1; then
+                echo "The testsuite requires /bin/busybox to be a static binary"
+                exit 1
+            fi
+
+            deps/import-busybox --alias testimage
+        fi
+    fi
+}
diff --git a/test/main.sh b/test/main.sh
index 7d060ae5a..8797c10b1 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -62,32 +62,6 @@ for backend in $(available_storage_backends); do
   . "backends/${backend}.sh"
 done
 
-ensure_has_localhost_remote() {
-  addr=${1}
-  if ! lxc remote list | grep -q "localhost"; then
-    lxc remote add localhost "https://${addr}" --accept-certificate --password foo
-  fi
-}
-
-ensure_import_testimage() {
-  if ! lxc image alias list | grep -q "^| testimage\s*|.*$"; then
-    if [ -e "${LXD_TEST_IMAGE:-}" ]; then
-      lxc image import "${LXD_TEST_IMAGE}" --alias testimage
-    else
-      if [ ! -e "/bin/busybox" ]; then
-        echo "Please install busybox (busybox-static) or set LXD_TEST_IMAGE"
-        exit 1
-      fi
-
-      if ldd /bin/busybox >/dev/null 2>&1; then
-        echo "The testsuite requires /bin/busybox to be a static binary"
-        exit 1
-      fi
-
-      deps/import-busybox --alias testimage
-    fi
-  fi
-}
 
 check_empty() {
   if [ "$(find "${1}" 2> /dev/null | wc -l)" -gt "1" ]; then

From 152691cac7f987fe5736352a9e852db0faea0bdf Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Thu, 17 Aug 2017 15:20:11 +0200
Subject: [PATCH 5/8] tests: split out checks helper functions

Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
 test/includes/check.sh | 17 +++++++++++++++++
 test/main.sh           | 17 -----------------
 2 files changed, 17 insertions(+), 17 deletions(-)
 create mode 100644 test/includes/check.sh

diff --git a/test/includes/check.sh b/test/includes/check.sh
new file mode 100644
index 000000000..0447402c5
--- /dev/null
+++ b/test/includes/check.sh
@@ -0,0 +1,17 @@
+# Miscellanous test checks.
+
+check_empty() {
+    if [ "$(find "${1}" 2> /dev/null | wc -l)" -gt "1" ]; then
+        echo "${1} is not empty, content:"
+        find "${1}"
+        false
+    fi
+}
+
+check_empty_table() {
+    if [ -n "$(sqlite3 "${1}" "SELECT * FROM ${2};")" ]; then
+        echo "DB table ${2} is not empty, content:"
+        sqlite3 "${1}" "SELECT * FROM ${2};"
+        false
+    fi
+}
diff --git a/test/main.sh b/test/main.sh
index 8797c10b1..8075861e2 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -63,23 +63,6 @@ for backend in $(available_storage_backends); do
 done
 
 
-check_empty() {
-  if [ "$(find "${1}" 2> /dev/null | wc -l)" -gt "1" ]; then
-    echo "${1} is not empty, content:"
-    find "${1}"
-    false
-  fi
-}
-
-check_empty_table() {
-  if [ -n "$(sqlite3 "${1}" "SELECT * FROM ${2};")" ]; then
-    echo "DB table ${2} is not empty, content:"
-    sqlite3 "${1}" "SELECT * FROM ${2};"
-    false
-  fi
-}
-
-
 # Must be set before cleanup()
 TEST_CURRENT=setup
 TEST_RESULT=failure

From d818291e4ac6ae171d9ee714bce9de0e7885a3f0 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Thu, 17 Aug 2017 12:57:12 +0200
Subject: [PATCH 6/8] tests: add helper for importing shell files

Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
 test/main.sh | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/test/main.sh b/test/main.sh
index 8075861e2..5a2402350 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -36,10 +36,17 @@ if [ -n "${LXD_LOGS:-}" ] && [ ! -d "${LXD_LOGS}" ]; then
 fi
 
 # Helper functions
-for include in includes/*.sh; do
-    # shellcheck disable=SC1090
-    . "$include"
-done
+import_subdir_files() {
+    test  "$1"
+    # shellcheck disable=SC2039
+    local file
+    for file in "$1"/*.sh; do
+        # shellcheck disable=SC1090
+        . "$file"
+    done
+}
+
+import_subdir_files includes
 
 if [ -z "${LXD_BACKEND:-}" ]; then
   LXD_BACKEND=dir
@@ -70,10 +77,7 @@ TEST_RESULT=failure
 trap cleanup EXIT HUP INT TERM
 
 # Import all the testsuites
-for suite in suites/*.sh; do
-  # shellcheck disable=SC1090
- . "${suite}"
-done
+import_subdir_files suites
 
 # Setup test directory
 TEST_DIR=$(mktemp -d -p "$(pwd)" tmp.XXX)

From 74a471ffd391d56815f6b8830ffd864485db8654 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Thu, 17 Aug 2017 13:28:37 +0200
Subject: [PATCH 7/8] tests: lints

Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
 test/includes/lxd.sh           | 1 +
 test/main.sh                   | 3 ++-
 test/suites/static_analysis.sh | 2 +-
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/test/includes/lxd.sh b/test/includes/lxd.sh
index a8e2f561b..baa64cbe3 100644
--- a/test/includes/lxd.sh
+++ b/test/includes/lxd.sh
@@ -14,6 +14,7 @@ spawn_lxd() {
     storage=${1}
     shift
 
+    # shellcheck disable=SC2153
     if [ "$LXD_BACKEND" = "random" ]; then
         lxd_backend="$(random_storage_backend)"
     else
diff --git a/test/main.sh b/test/main.sh
index 5a2402350..ec4ce774c 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -11,6 +11,7 @@ if [ -n "${LXD_VERBOSE:-}" ] || [ -n "${LXD_DEBUG:-}" ]; then
   set -x
 fi
 
+export DEBUG
 if [ -n "${LXD_VERBOSE:-}" ]; then
   DEBUG="--verbose"
 fi
@@ -72,7 +73,7 @@ done
 
 # Must be set before cleanup()
 TEST_CURRENT=setup
-TEST_RESULT=failure
+export TEST_RESULT=failure
 
 trap cleanup EXIT HUP INT TERM
 
diff --git a/test/suites/static_analysis.sh b/test/suites/static_analysis.sh
index a87ef9cc6..f831d22aa 100644
--- a/test/suites/static_analysis.sh
+++ b/test/suites/static_analysis.sh
@@ -16,7 +16,7 @@ test_static_analysis() {
 
     # Shell static analysis
     if which shellcheck >/dev/null 2>&1; then
-      shellcheck --shell sh test/main.sh test/suites/* test/backends/*
+      shellcheck --shell sh test/*.sh test/includes/*.sh test/suites/*.sh test/backends/*.sh
     else
       echo "shellcheck not found, shell static analysis disabled"
     fi

From 6e915ed3c14323a8a2685e81c51d3a3816c3e388 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Thu, 17 Aug 2017 15:51:57 +0200
Subject: [PATCH 8/8] Add dependencies check helper.

Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
 test/includes/check.sh | 17 +++++++++++++++++
 test/main.sh           | 13 +++++--------
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/test/includes/check.sh b/test/includes/check.sh
index 0447402c5..421225083 100644
--- a/test/includes/check.sh
+++ b/test/includes/check.sh
@@ -1,5 +1,22 @@
 # Miscellanous test checks.
 
+
+check_dependencies() {
+    # shellcheck disable=SC2039
+    local dep missing
+
+    for dep in "$@"; do
+        if ! which "$dep" >/dev/null 2>&1; then
+            [ "$missing" ] && missing="$missing $dep" || missing="$dep"
+        fi
+    done
+
+    if [ "$missing" ]; then
+       echo "Missing dependencies: $missing" >&2
+       exit 1
+    fi
+}
+
 check_empty() {
     if [ "$(find "${1}" 2> /dev/null | wc -l)" -gt "1" ]; then
         echo "${1} is not empty, content:"
diff --git a/test/main.sh b/test/main.sh
index ec4ce774c..69630b074 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -20,11 +20,12 @@ if [ -n "${LXD_DEBUG:-}" ]; then
   DEBUG="--debug"
 fi
 
+if [ -z "${LXD_BACKEND:-}" ]; then
+    LXD_BACKEND="dir"
+fi
+
 echo "==> Checking for dependencies"
-deps="lxd lxc curl jq git xgettext sqlite3 msgmerge msgfmt shuf setfacl uuidgen"
-for dep in $deps; do
-  which "${dep}" >/dev/null 2>&1 || (echo "Missing dependency: ${dep}" >&2 && exit 1)
-done
+check_dependencies lxd lxc curl jq git xgettext sqlite3 msgmerge msgfmt shuf setfacl uuidgen
 
 if [ "${USER:-'root'}" != "root" ]; then
   echo "The testsuite must be run as root." >&2
@@ -49,10 +50,6 @@ import_subdir_files() {
 
 import_subdir_files includes
 
-if [ -z "${LXD_BACKEND:-}" ]; then
-  LXD_BACKEND=dir
-fi
-
 echo "==> Available storage backends: $(available_storage_backends | sort)"
 if [ "$LXD_BACKEND" != "random" ] && ! storage_backend_available "$LXD_BACKEND"; then
   if [ "${LXD_BACKEND}" = "ceph" ] && [ -z "${LXD_CEPH_CLUSTER:-}" ]; then


More information about the lxc-devel mailing list