1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
#!/bin/bash
function die() {
echo "Error: ${*}" 1>&2
exit 1
}
error() { echo "$@" 1>&2; }
get_snap_version_info() {
# get_snap_version_info(snap)
# set SNAP_VERSION and SNAP_REVISION to the installed 'version' and 'rev'
# of the provided 'snap'. The caller must export or scope (using local) if
# desired.
local name="${1:-git-ubuntu}" out=""
command -v snap >/dev/null 2>&1 || {
error "no 'snap' command available."
return 1
}
out=$(snap list "$name") || {
error "failed 'snap list $name'. Is snap '$name' installed?"
return 1;
}
set -- $(echo "$out" |
while read curname ver rev track pub notes other; do
[ "$curname" = "$name" ] && echo "$rev" "$ver" && exit 0
done
exit 1)
[ -n "$1" -a -n "$2" ] || {
error "Failed reading output of 'snap list $name'"
return 1
}
SNAP_REVISION="$1" SNAP_VERSION="$2"
}
snap_run() {
# snap_run([--exec,] snap, cmd, args...)
# execute the provided command in the snap environment.
# if '--exec' is provided, then use 'exec' (do not return).
#
# executing 'snap run --shell <snap> cmd arg1 arg2...'
# results in snap changing the environment and then executing:
# /bin/sh cmd arg1 arg2 ...
# (with cmd, arg1, arg2 as separate argv)
#
# It was probably only ever intended to be used to invoke an interactive
# shell. But we use it here to invoke arbitrary commands while keeping
# positional parameters correct and avoiding any shell interpretation
# of cmd or args. We invoke:
# /bin/sh -c 'exec "$0" "$@"' cmd arg1 arg2...
#
# The end result is that 'cmd' is correctly invoked with exactly the args
# provided and no need to worry about shell interpretation.
local exec="" snap=""
[ "$1" = "--exec" ] && { exec="exec"; shift; }
snap="$1"
shift
$exec snap run --shell "$snap" -c 'exec "$0" "$@"' "$@"
}
if [ -n "$TEST_SYSTEM_TREE" ]; then
pkg_dir=$(dirname $(python3 -c 'import gitubuntu; print(gitubuntu.__path__[0])'))
snap_bin_glob=/usr/bin/git-ubuntu.*
pylintrc_path=/usr/share/git-ubuntu/pylintrc
elif [ -n "$SNAP" -a -z "$TEST_TREE" ]; then
pkg_dir=${SNAP}/usr/lib/python3/dist-packages
snap_bin_glob="${SNAP}/usr/bin/git-ubuntu.*"
pylintrc_path="${SNAP}/usr/share/git-ubuntu/pylintrc"
[ -d "$pkg_dir" ] ||
{ error "$pkg_dir is not a directory"; exit 1; }
else
if [ -z "$TEST_TREE" ]; then
if [ -d "./gitubuntu" ]; then
export TEST_TREE="."
else
error "ERROR: Neither SNAP nor TEST_TREE set in environment."
error "And no 'gitubuntu' dir in $PWD" 1>&2
exit 3
fi
fi
if [ ! -d "$TEST_TREE/gitubuntu" ]; then
error "ERROR: TEST_TREE=$TEST_TREE but no $TEST_TREE/gitubuntu"
exit 3
fi
if [ -z "$SNAP" ]; then
if ! get_snap_version_info git-ubuntu; then
error "Must have git-ubuntu snap installed to test tree."
exit 3
fi
export SNAP_REVISION SNAP_VERSION
snap_run --exec git-ubuntu "$0" "$@"
fi
pkg_dir=$( cd "${TEST_TREE%/}" && pwd )
snap_bin_glob="${pkg_dir}/bin/*.py"
pylintrc_path="$TEST_TREE/.pylintrc"
fi
retval=0
# Create temporary directory for test artifacts
tmp_dir=$(mktemp -d -t "ci-$(date +%Y%m%d)-XXXXXXXXXX")
[ -d "${tmp_dir}" ] \
|| die "Could not create ${tmp_dir}"
cd "${pkg_dir}" \
|| die "Could not chdir to ${pkg_dir}"
ln -s "${pkg_dir}/gitubuntu" "${tmp_dir}" \
|| die "Could not create link to gitubuntu module in ${tmp_dir}"
if [ -n "$TEST_SYSTEM_TREE" ]; then
error "Testing git-ubuntu system installation."
else
error "Inside git-ubuntu snap $SNAP_REVISION/$SNAP_VERSION."
fi
error "Testing tree in $pkg_dir/gitubuntu"
error "Working dir $PWD"
function cleanup() {
rm "${tmp_dir}/gitubuntu"
rm -rf "${tmp_dir}"
}
trap cleanup EXIT
if [ -z "$TEST_SYSTEM_TREE" ]; then
# Check dependencies are installed
if python3 -m pip check
then
echo "pip3 found all required dependencies"
else
echo "pip check failed; self test will fail"
retval=1
fi
fi
# Style check python modules
# For some reason, pylint hangs indefinitely if used without a -j option (the
# default is two) in the multiprocessing module. As a workaround for now, we
# specify -j1, which seems to work.
if python3 -m pylint --rcfile "$pylintrc_path" -E gitubuntu/ -j1
then
echo "pylint passed!"
else
echo "pylint failed; self test will fail"
retval=1
fi
# Check python scripts in ${SNAP}/bin
while IFS= read -r -d '' script_source; do
# py_compile will be writing .pyc to a __pycache__ directory adjacent to
# the script. Since we may be testing the script at a read-only location
# (as will happen when jenkins tests the snap), we need to move the script
# to a read-write location temporarily.
#
# Note that starting in python 3.8, there is a -B flag which
# suppresses the creation of .pyc files; so, once this version of python
# can be assumed, this logic can be simplified by avoiding the copying.
cp "${script_source}" "${tmp_dir}/"
script=$(basename "${script_source}")
# Python version 3 basic syntax check. Also catches code that is
# valid for python2 but not python3.
if python3 -m py_compile "${tmp_dir}/${script}"
then
echo "PASS (syntax) ${script}"
else
echo "FAIL (syntax) ${script}"
continue
fi
# Smoke test compilation by attempting to import the script as if it
# were a module, but only if the script handles __main__. This catches
# errors due to attempted imports of python module dependencies, and may
# catch other coding errors not detected by pycompile3.
if grep "if __name__ == '__main__':" "${tmp_dir}/${script}" > /dev/null
then
cd "${tmp_dir}" \
|| die "Could not chdir to ${tmp_dir}"
if python3 -m "${script%.py}" --help > /dev/null 2>&1
then
echo "PASS (compilation) ${script}"
else
echo "FAIL (compilation) ${script}; self test will fail"
retval=1
fi
else
echo "SKIP (compilation) ${script}"
fi
done < <(compgen -G "$snap_bin_glob")
# Run the unit testsuite
if COVERAGE_FILE="${tmp_dir}/coverage.txt" python3 -m pytest -p no:cacheprovider --cov=gitubuntu gitubuntu/*
then
echo "pytest passed!"
else
echo "pytest failed; self test will fail"
retval=1
fi
exit ${retval}
|