run revision 3e2f89726a90dfe091d7d7d3b558d97469e5d3af
327N/A#!/bin/bash
327N/A#
327N/A# Run continuous integration tests.
327N/A#
327N/A# Copyright (C) 2014 Red Hat
327N/A#
327N/A# This program is free software; you can redistribute it and/or modify
327N/A# it under the terms of the GNU General Public License as published by
327N/A# the Free Software Foundation; either version 3 of the License, or
327N/A# (at your option) any later version.
327N/A#
327N/A# This program is distributed in the hope that it will be useful,
327N/A# but WITHOUT ANY WARRANTY; without even the implied warranty of
327N/A# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
327N/A# GNU General Public License for more details.
327N/A#
327N/A# You should have received a copy of the GNU General Public License
327N/A# along with this program. If not, see <http://www.gnu.org/licenses/>.
327N/A
327N/Aset -o nounset -o pipefail -o errexit
327N/Adeclare -r CI_DIR=`dirname "\`readlink -f \"\$0\"\`"`
327N/Aexport PATH=$CI_DIR:$PATH
5636N/Aexport LC_ALL=C
327N/A
5680N/A. deps.sh
327N/A. distro.sh
327N/A. configure.sh
5680N/A. misc.sh
864N/A
327N/Adeclare -r DEBUG_CFLAGS="-g3 -O2"
3888N/Adeclare -r COVERAGE_CFLAGS="-g3 -O0 --coverage"
618N/Adeclare -r ARCH=`uname -m`
844N/Adeclare -r CPU_NUM=`getconf _NPROCESSORS_ONLN`
3888N/Adeclare -r TITLE_WIDTH=24
327N/Adeclare -r RESULT_WIDTH=18
327N/A
3888N/A# Minimum percentage of code lines covered by tests
2899N/Adeclare -r COVERAGE_MIN_LINES=15
5680N/A# Minimum percentage of code functions covered by tests
5680N/Adeclare -r COVERAGE_MIN_FUNCS=0
327N/A
327N/Adeclare BASE_PFX=""
327N/Adeclare DEPS=true
327N/Adeclare BASE_DIR=`pwd`
327N/Adeclare MODERATE=false
327N/Adeclare RIGOROUS=false
327N/A
327N/A# Output program usage information.
327N/Afunction usage()
327N/A{
327N/A cat <<EOF
327N/AUsage: `basename "$0"` [OPTION...]
327N/ARun continuous integration tests.
5680N/A
327N/AOptions:
5680N/A -h, --help Output this help message and exit.
5680N/A -p, --prefix=STRING Use STRING as the prefix to prepend to file and
5680N/A directory paths in output.
5680N/A -n, --no-deps Don't attempt to install dependencies.
5680N/A -e, --essential Run the essential subset of tests.
5680N/A -m, --moderate Run the moderate subset of tests.
5680N/A -r, --rigorous,
5680N/A -f, --full Run the rigorous (full) set of tests.
5680N/A
5680N/ADefault options: --essential
5680N/AEOF
5680N/A}
5680N/A
5680N/A# Output a file display path: a path relocated from base directory (BASE_DIR)
5680N/A# to base prefix (BASE_PFX).
327N/A# Args: path
327N/Afunction disppath()
327N/A{
4571N/A declare -r path=`readlink -f "$1"`
4571N/A printf "%s" "$BASE_PFX${path:${#BASE_DIR}+1}"
4571N/A}
4571N/A
4571N/A# Run a stage.
4571N/A# Args: id cmd [arg...]
4571N/Afunction stage()
1938N/A{
327N/A declare -r id="$1"; shift
3817N/A declare -r log="ci-$id.log"
3817N/A declare status
3817N/A declare start
5636N/A declare end
3817N/A declare duration
3817N/A
4878N/A printf "%-${TITLE_WIDTH}s" "$id:"
3817N/A
3817N/A {
3817N/A printf "Start: "
3817N/A start=`date +%s`
3817N/A date --date="@$start"
4878N/A set +o errexit
(
set -o errexit -o xtrace
"$@"
)
status=$?
set -o errexit
printf "End: "
end=`date +%s`
date --date="@$end"
} &> "$log"
duration=$((end - start))
if [ "$status" == 0 ]; then
printf 'success '
else
printf 'failure '
fi
printf "%02u:%02u:%02u " \
$((duration / (60 * 60))) \
$((duration / 60 % 60)) \
$((duration % 60))
disppath "$log"
printf "\n"
return "$status"
}
# Execute mock as is, or, if the user is not in the "mock" group, under sudo,
# which has password prompt/input on the console, instead of stderr/stdin.
# Args: [mock_arg...]
function mock_privileged()
{
if memberof mock; then
mock "$@"
else
declare prompt=$'Not a "mock" group member.\n'
prompt+="To run mock enter sudo password for $USER: "
sudo -p "$prompt" mock "$@"
fi
}
# Execute mock_privileged with extra chroot configuration added.
# Args: chroot [mock_arg...]
# Input: extra configuration
function mock_privileged_conf()
{
declare -r chroot="$1"; shift
declare conf_dir
conf_dir=`mktemp --tmpdir --directory mock-config.XXXXXXXX`
trap 'trap - RETURN; rm -R "$conf_dir";' RETURN
# Preserve timestamps to avoid unnecessary cache rebuilds
cp -r --preserve=timestamps /etc/mock/* "$conf_dir"/
cat >> "${conf_dir}/${chroot}.cfg"
touch --reference="/etc/mock/${chroot}.cfg" "${conf_dir}/${chroot}.cfg"
mock_privileged --configdir="$conf_dir" --root="$chroot" "$@"
}
# Execute mock_privileged with dependency package source configuration added.
# Args: chroot [mock_arg...]
function mock_privileged_deps()
{
declare -r chroot_name="$1"; shift
declare -r config=$(basename $(readlink -f "/etc/mock/${chroot_name}.cfg"))
declare -r chroot="${config%.cfg}"
declare repo
if [[ "$chroot" == fedora-* ]]; then
repo='fedora-$releasever-$basearch'
elif [[ "$chroot" =~ epel-([0-9]+) ]]; then
repo="epel-${BASH_REMATCH[1]}-\$basearch"
else
echo "Unknown chroot config: $chroot" >&2
exit 1
fi
mock_privileged_conf "$chroot" "$@" <<<"
config_opts['yum.conf'] += '''
[sssd-deps]
name=Extra SSSD dependencies
baseurl=http://copr-be.cloud.fedoraproject.org/results/lslebodn/sssd-deps/$repo/
skip_if_unavailable=true
gpgcheck=0
enabled=1
'''
"
}
# Run debug build checks.
function build_debug()
{
export CFLAGS="$DEBUG_CFLAGS"
declare test_dir
declare test_dir_distcheck
declare distcheck_configure_args
declare status
test_dir=`mktemp --directory /dev/shm/ci-test-dir.XXXXXXXX`
stage configure "$BASE_DIR/configure" \
"${CONFIGURE_ARG_LIST[@]}" \
--with-test-dir="$test_dir"
# Not building "tests" due to https://fedorahosted.org/sssd/ticket/2350
stage make-tests make-check-wrap -j $CPU_NUM check -- true
status=0
CK_FORK=no \
stage make-check-valgrind \
make-check-wrap -j $CPU_NUM check -- \
libtool --mode=execute \
valgrind-condense 99 \
'!(*.py|*dlopen-tests)' -- \
--trace-children=yes \
--trace-children-skip='*/bin/*,*/sbin/*' \
--leak-check=full \
--gen-suppressions=all \
--suppressions="$CI_DIR/sssd.supp" \
--verbose ||
status=$?
mv "$test_dir" ci-test-dir
((status == 0))
if "$MODERATE"; then
test_dir_distcheck=`mktemp --directory /dev/shm/ci-test-dir.XXXXXXXX`
# Single thread due to https://fedorahosted.org/sssd/ticket/2354
status=0
printf -v distcheck_configure_args " %q" \
"${CONFIGURE_ARG_LIST[@]}" \
"--with-test-dir=$test_dir_distcheck"
stage make-distcheck make distcheck \
AUX_DISTCHECK_CONFIGURE_FLAGS=" \
$distcheck_configure_args" ||
status=$?
mv "$test_dir_distcheck" ci-test-dir-distcheck
((status == 0))
if [[ "$DISTRO_BRANCH" == -redhat-* ]]; then
stage make-srpm env -u CFLAGS -- make srpm
stage mock-build mock_privileged_deps "default" \
--resultdir ci-mock-result \
rpmbuild/SRPMS/*.src.rpm
fi
fi
unset CFLAGS
}
# Run coverage build checks.
function build_coverage()
{
declare -r scan_report_dir="ci-report-scan"
declare -r coverage_report_dir="ci-report-coverage"
declare test_dir
export CFLAGS="$COVERAGE_CFLAGS"
test_dir=`mktemp --directory /dev/shm/ci-test-dir.XXXXXXXX`
stage configure scan-build "$BASE_DIR/configure" \
"${CONFIGURE_ARG_LIST[@]}" \
--with-test-dir="$test_dir"
# Build everything, including tests
# Not building "tests" due to https://fedorahosted.org/sssd/ticket/2350
stage scan-make-tests scan_build_single \
"$scan_report_dir" \
-plist-html \
--html-title="sssd - scan-build report" \
make-check-wrap -j $CPU_NUM check -- true
printf "%-$((TITLE_WIDTH + RESULT_WIDTH))s%s\n" \
"scan report:" \
"`disppath \"\$scan_report_dir/index.html\"`"
# Ignored until issues found by the scanner are fixed
stage scan-check scan_check "$scan_report_dir" ||
true
stage lcov-pre lcov --capture --initial --directory . \
--base-directory "$BASE_DIR" \
--output-file ci-base.info
# Run tests
stage make-check scan-build make -j $CPU_NUM check || true
mv "$test_dir" ci-test-dir
stage lcov-post lcov --capture --directory . \
--base-directory "$BASE_DIR" \
--output-file ci-check.info
stage lcov-merge lcov --add-tracefile ci-base.info \
--add-tracefile ci-check.info \
--output-file ci-dirty.info
stage lcov-clean lcov --remove ci-dirty.info \
"/usr/*" "src/tests/*" \
--output-file ci.info
stage genhtml eval 'genhtml --output-directory \
"$coverage_report_dir" \
--title "sssd" --show-details \
--legend --prefix "$BASE_DIR" \
ci.info |& tee ci-genhtml.out'
printf "%-$((TITLE_WIDTH + RESULT_WIDTH))s%s\n" \
"coverage report:" \
"`disppath \"\$coverage_report_dir/index.html\"`"
stage lcov-check eval 'lcov_check "$COVERAGE_MIN_LINES" \
"$COVERAGE_MIN_FUNCS" \
< ci-genhtml.out'
unset CFLAGS
}
# Run a build inside a sub-directory.
# Args: id cmd [arg...]
function run_build()
{
declare -r id="$1"; shift
declare -r dir="ci-build-$id"
mkdir "$dir"
printf "%-$((TITLE_WIDTH + RESULT_WIDTH))s%s\n" \
"${id^^} BUILD:" "`disppath \"\$dir\"`"
cd "$dir"
"$@"
cd ..
}
#
# Main routine
#
declare args_expr
args_expr=`getopt --name \`basename "\$0"\` \
--options hp:nemrf \
--longoptions help,prefix:,no-deps \
--longoptions essential,moderate,rigorous,full \
-- "$@"`
eval set -- "$args_expr"
while true; do
case "$1" in
-h|--help)
usage; exit 0;;
-p|--prefix)
BASE_PFX="$2"; shift 2;;
-n|--no-deps)
DEPS=false; shift;;
-e|--essential)
MODERATE=false; RIGOROUS=false; shift;;
-m|--moderate)
MODERATE=true; RIGOROUS=false; shift;;
-r|--rigorous|-f|--full)
MODERATE=true; RIGOROUS=true; shift;;
--)
shift; break;;
*)
echo "Unknown option: $1" >&2
exit 1;;
esac
done
if [ $# != 0 ]; then
echo "Positional arguments are not accepted." >&2
usage >&2
exit 1
fi
trap 'echo FAILURE' EXIT
rm_rf_ro ci-*
export V=1
if "$DEPS"; then
stage install-deps deps_install
fi
stage autoreconf autoreconf --install --force
run_build debug build_debug
if "$RIGOROUS"; then
run_build coverage build_coverage
fi
unset V
trap - EXIT
echo SUCCESS