blob: 26861c765eff3439d43ae9d3bf35adbba4d15da7 [file] [log] [blame]
#!/bin/bash
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
CHROMITE_PATH=$(realpath "$(dirname "$0")/..")
IN_CHROOT="cros_sdk"
CHROOT_CHROMITE=../../chromite
set -eu
LOGFILE="$(mktemp)"
# Helper function to add failed logs/tests to be printed out later.
# $1 test that failed.
# $2 log file where we stored the output of the failed test.
append_failed_test() {
echo "ERROR: Unittest $1 failed. Log will be output at end of run!!!"
cat << EOF >> "${LOGFILE}.$$"
FAIL: Unittest $1 failed output:
$(<"$2")
EOF
rm -f "$2"
}
# Wrapper to run unittest. Hides output unless test fails.
# $1 test to run. Must be in chromite/buildbot.
# $2 If set, run inside the chroot.
run_test() {
local log_file="$(mktemp)"
local special="${special_tests[$1]:-}"
local starttime="$(date +%s%N)"
if [[ "${special}" == "skip" ]]; then
echo "Skipping unittest $1"
rm "${log_file}"
return
elif [[ "${special}" == "outside" && -f /etc/debian_chroot ]]; then
echo "Skipping unittest $1 because it must run outside the chroot."
rm "${log_file}"
return
elif [[ "${special}" == "inside" && ! -f /etc/debian_chroot ]]; then
if ${SKIP_CHROOT_TESTS}; then
echo "Skipping unittest $1 because it must run inside the chroot"
rm "${log_file}"
return
else
echo "Starting unittest $1 inside the chroot"
${IN_CHROOT} python "${CHROOT_CHROMITE}/$1" &> "${log_file}" ||
append_failed_test "$1" "${log_file}"
fi
else
echo "Starting unittest $1"
python "${CHROMITE_PATH}/$1" &> "${log_file}" ||
append_failed_test "$1" "${log_file}"
fi
local endtime="$(date +%s%N)"
local duration=$(( (endtime - starttime) / 1000000 ))
echo "Finished unittest $1 (${duration} ms)"
rm -f "${log_file}"
}
# For some versions of 'sudo' (notably, the 'sudo' in the chroot at
# the time of this writing), sudo -v will ask for a password whether
# or not it's needed. 'sudo true' will do what we want.
sudo true
# List all exceptions, with a token describing what's odd here.
# inside - inside the chroot
# skip - don't run this test (please comment on why)
declare -A special_tests
special_tests=(
# Tests that need to run inside the chroot.
['cros/commands/cros_build_unittest.py']=inside
['lib/upgrade_table_unittest.py']=inside
['scripts/cros_mark_as_stable_unittest.py']=inside
['scripts/cros_mark_chrome_as_stable_unittest.py']=inside
['scripts/sync_package_status_unittest.py']=inside
['scripts/cros_portage_upgrade_unittest.py']=inside
['scripts/upload_package_status_unittest.py']=inside
# Tests that need to run outside the chroot.
['lib/cgroups_unittest.py']=outside
# gerrit_unittest is bound to be a little flaky because it depends on gerrit
# itself. Do not run it on the bots.
['lib/gerrit_unittest.py']=outside
# Tests that are presently broken.
['lib/gdata_lib_unittest.py']=skip
['scripts/chrome_set_ver_unittest.py']=skip
['scripts/check_gdata_token_unittest.py']=skip
['scripts/merge_package_status_unittest.py']=skip
['scripts/upload_package_status_unittest.py']=skip
# Tests that take >2 minutes to run.
['scripts/cros_portage_upgrade_unittest.py']=skip
)
if [[ $# -ne 0 && $1 == "--quick" ]]; then
shift
# Tests that require network can be really slow.
special_tests['buildbot/manifest_version_unittest.py']=skip
special_tests['buildbot/repository_unittest.py']=skip
special_tests['buildbot/remote_try_unittest.py']=skip
special_tests['lib/cros_build_lib_unittest.py']=skip
special_tests['lib/gerrit_unittest.py']=skip
special_tests['lib/patch_unittest.py']=skip
# cgroups_unittest runs cros_sdk a lot, so is slow.
special_tests['lib/cgroups_unittest.py']=skip
fi
SKIP_CHROOT_TESTS=false
if ! repo list | grep -q chromiumos-overlay; then
echo "chromiumos-overlay is not present. Skipping chroot tests..."
SKIP_CHROOT_TESTS=true
# cgroups_unittest requires cros_sdk, so it doesn't work.
special_tests['lib/cgroups_unittest.py']=skip
fi
if [[ $# -eq 0 ]]; then
# List all unit test scripts that match the given pattern.
all_tests=(
$(find "${CHROMITE_PATH}" -name '*_unittest.py' -printf '%P ')
)
set -- "${all_tests[@]}"
fi
declare -a children
cleanup() {
delayed_kill() {
sleep 5
kill -9 ${children[*]} &> /dev/null
}
echo "Cleaning up backgrounded jobs."
# Graceful exit.
kill -INT ${children[*]} &> /dev/null
# Set of a hard kill timer after a while.
delayed_kill &
wait ${children[*]}
}
trap cleanup INT TERM
for test in "$@"; do
run_test ${test} &
children+=( $! )
done
wait ${children[*]}
trap - INT TERM
cat "${LOGFILE}".* > "${LOGFILE}" 2>/dev/null || :
rm -f "${LOGFILE}".*
if [[ $(wc -c "${LOGFILE}" |cut -f1 -d' ') -gt 0 ]]; then
cat "${LOGFILE}"
echo
echo
echo "FAIL: The following tests failed:"
sed -nre '/^FAIL:/s/^FAIL: Unittest (.*) failed output:/\1/p' "${LOGFILE}"
rm -f "${LOGFILE}"
exit 1
fi
rm -f "${LOGFILE}"
echo "All tests succeeded!"