3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 CHROMITE_PATH=$(realpath "$(dirname "$0")/..")
9 TIMEOUT="timeout -k 5m 20m"
10 CHROOT_CHROMITE=../../chromite
14 # List all exceptions, with a token describing what's odd here.
15 # inside - inside the chroot
16 # skip - don't run this test (please comment on why)
17 declare -A special_tests
19 # Tests that need to run inside the chroot.
20 ['cbuildbot/stages/test_stages_unittest.py']=inside
21 ['cros/commands/cros_build_unittest.py']=inside
22 ['cros/commands/lint_unittest.py']=inside
23 ['lib/filetype_unittest.py']=inside
24 ['lib/upgrade_table_unittest.py']=inside
25 ['scripts/cros_list_modified_packages_unittest.py']=inside
26 ['scripts/cros_mark_as_stable_unittest.py']=inside
27 ['scripts/cros_mark_chrome_as_stable_unittest.py']=inside
28 ['scripts/sync_package_status_unittest.py']=inside
29 ['scripts/cros_portage_upgrade_unittest.py']=inside
30 ['scripts/dep_tracker_unittest.py']=inside
31 ['scripts/test_image_unittest.py']=inside
32 ['scripts/upload_package_status_unittest.py']=inside
34 # Tests that need to run outside the chroot.
35 ['lib/cgroups_unittest.py']=outside
37 # Tests that are presently broken.
38 ['lib/gdata_lib_unittest.py']=skip
39 ['scripts/chrome_set_ver_unittest.py']=skip
40 ['scripts/check_gdata_token_unittest.py']=skip
41 ['scripts/merge_package_status_unittest.py']=skip
42 ['scripts/upload_package_status_unittest.py']=skip
44 # Tests that take >2 minutes to run. All the slow tests are
45 # disabled atm though ...
46 #['scripts/cros_portage_upgrade_unittest.py']=skip
50 # Tests that require network can be really slow.
51 special_tests['cbuildbot/manifest_version_unittest.py']=skip
52 special_tests['cbuildbot/repository_unittest.py']=skip
53 special_tests['cbuildbot/remote_try_unittest.py']=skip
54 special_tests['lib/cros_build_lib_unittest.py']=skip
55 special_tests['lib/gerrit_unittest.py']=skip
56 special_tests['lib/patch_unittest.py']=skip
58 # cgroups_unittest runs cros_sdk a lot, so is slow.
59 special_tests['lib/cgroups_unittest.py']=skip
62 # Helper function to add failed logs/tests to be printed out later.
63 # $1 test that failed.
64 # $2 log file where we stored the output of the failed test.
65 append_failed_test() {
66 echo "ERROR: Unittest $1 failed. Log will be output at end of run!!!"
68 cat - "$2" <<EOF >>"${LOGFILE}.err.${BASHPID}"
70 FAIL: Unittest $1 failed output:
75 # Wrapper to run unittest. Hides output unless test fails.
76 # $1 test to run. Must be in chromite/cbuildbot.
77 # $2 Is this a dry run?
78 # $3 Do we run network tests?
80 local test=$1 dryrun=$2 network_tests=$3
81 local log_file="${LOGFILE}.tmp.${BASHPID}"
82 local special="${special_tests[${test}]:-}"
83 local starttime="$(date +%s%N)"
86 if ${network_tests}; then
87 network_flag="--network"
90 if [[ "${special}" == "skip" ]]; then
91 echo "Skipping unittest ${test}"
93 elif [[ "${special}" == "outside" && -f /etc/cros_chroot_version ]]; then
94 echo "Skipping unittest ${test} because it must run outside the chroot"
96 elif [[ "${special}" == "inside" && ! -f /etc/cros_chroot_version ]]; then
97 if ${SKIP_CHROOT_TESTS}; then
98 echo "Skipping unittest ${test} because it must run inside the chroot"
101 echo "Starting unittest ${test} inside the chroot"
103 ${TIMEOUT} ${IN_CHROOT} -- python "${CHROOT_CHROMITE}/${test}" -v \
104 ${network_flag} &> "${log_file}" \
105 || append_failed_test "${test}" "${log_file}"
109 echo "Starting unittest ${test}"
111 ${TIMEOUT} python "${CHROMITE_PATH}/${test}" -v ${network_flag} \
112 &> "${log_file}" || append_failed_test "${test}" "${log_file}"
117 local endtime="$(date +%s%N)"
118 local duration=$(( (endtime - starttime) / 1000000 ))
120 echo "Finished unittest ${test} (${duration} ms)"
128 kill -9 ${children[*]} &> /dev/null
131 echo "Cleaning up backgrounded jobs."
133 kill -INT ${children[*]} &> /dev/null
134 # Set of a hard kill timer after a while.
141 cat "${LOGFILE}".err.* > "${LOGFILE}" 2>/dev/null || :
144 if [[ -s ${LOGFILE} ]]; then
148 echo "FAIL: The following tests failed:"
149 sed -nre '/^FAIL:/s/^FAIL: Unittest (.*) failed output:/\1/p' "${LOGFILE}"
159 Usage: run_tests [options] [tests]
161 Run the specified tests. If none are specified, we'll scan the
162 tree looking for tests to run and then only run the semi-fast ones.
164 You can add a .testignore file to a dir to disable scanning it.
167 -q, --quick Only run the really quick tests
168 -n, --dry-run Do everything but actually run the test
169 --network Run tests that depend on good network connectivity
170 -l, --list List all the available tests
171 -h, --help This screen
174 if [[ $# -gt 0 ]]; then
175 printf '\nerror: %s\n' "$*" >&2
183 # Parse args from the user first.
187 local network_tests=false
188 while [[ $# -gt 0 ]]; do
191 -q|--quick) skip_quick_tests;;
192 -n|--dry-run) dryrun=true;;
193 -l|--list) list=true;;
194 --network) network_tests=true;;
195 -*) usage "unknown option $1";;
196 *) user_tests+=( "$1" );;
200 if [[ ${#user_tests[@]} -gt 0 ]]; then
201 set -- "${user_tests[@]}"
204 # For some versions of 'sudo' (notably, the 'sudo' in the chroot at
205 # the time of this writing), sudo -v will ask for a password whether
206 # or not it's needed. 'sudo true' will do what we want.
209 # Switch to CHROMITE_PATH, in case cwd is outside of the repo. This ensures
210 # that "repo list" looks at the right repo, and sets up a consistent test
212 cd "${CHROMITE_PATH}"
214 SKIP_CHROOT_TESTS=false
215 if ! repo list 2>/dev/null | grep -q chromiumos-overlay; then
216 echo "chromiumos-overlay is not present. Skipping chroot tests..."
217 SKIP_CHROOT_TESTS=true
219 # cgroups_unittest requires cros_sdk, so it doesn't work.
220 special_tests['lib/cgroups_unittest.py']=skip
223 # Default to running all tests.
224 if [[ $# -eq 0 ]]; then
225 # List all unit test scripts that match the given pattern.
227 $(find "${CHROMITE_PATH}" -name .testignore \
228 -printf '-path %h -prune -o ')
231 $(find "${CHROMITE_PATH}" \
233 -name '*_unittest.py' -printf '%P ')
235 set -- "${all_tests[@]}"
239 printf '%s\n' "$@" | sort
243 # Now do the real code.
244 LOGFILE="$(mktemp -t cbuildbot.run_tests.XXXXXX)"
245 trap cleanup INT TERM
249 run_test ${test} ${dryrun} ${network_tests} &
258 echo "All tests succeeded!"
259 if ! ${network_tests}; then
260 echo "Note: Network tests skipped; use --network to run them."