ci: Exclude broken Stem tests
[tor.git] / scripts / ci / ci-driver.sh
blob2cbded0dc949c0d93c1301758963207db46f8925
1 #!/bin/bash
3 ####
4 # DO NOT EDIT THIS FILE IN MASTER. ONLY EDIT IT IN THE OLDEST SUPPORTED
5 # BRANCH, THEN MERGE FORWARD.
6 ####
8 # This script is used to build Tor for continuous integration. It should
9 # be kept the same for all supported Tor versions.
11 # It's subject to the regular Tor license; see LICENSE for copying
12 # information.
14 set -o errexit
15 set -o nounset
17 # Options for this script.
18 DEBUG_CI="${DEBUG_CI:-no}"
19 COLOR_CI="${COLOR_CI:-yes}"
21 # Options for which CI system this is.
22 ON_GITLAB="${ON_GITLAB:-yes}"
24 # Options for things we usually won't want to skip.
25 RUN_STAGE_CONFIGURE="${RUN_STAGE_CONFIGURE:-yes}"
26 RUN_STAGE_BUILD="${RUN_STAGE_BUILD:-yes}"
27 RUN_STAGE_TEST="${RUN_STAGE_TEST:-yes}"
29 # Options for how to build Tor. All should be yes/no.
30 FATAL_WARNINGS="${FATAL_WARNINGS:-yes}"
31 HARDENING="${HARDENING:-no}"
32 COVERAGE="${COVERAGE:-no}"
33 DOXYGEN="${DOXYGEN:-no}"
34 ASCIIDOC="${ASCIIDOC:-no}"
35 TRACING="${TRACING:-no}"
36 ALL_BUGS_ARE_FATAL="${ALL_BUGS_ARE_FATAL:-no}"
37 DISABLE_DIRAUTH="${DISABLE_DIRAUTH:-no}"
38 DISABLE_RELAY="${DISABLE_RELAY:-no}"
39 NSS="${NSS:-no}"
40 GPL="${GPL:-no}"
42 # Options for which tests to run. All should be yes/no.
43 CHECK="${CHECK:-yes}"
44 STEM="${STEM:-no}"
45 CHUTNEY="${CHUTNEY:-no}"
46 DISTCHECK="${DISTCHECK:-no}"
48 # Options for where the Tor source is.
49 CI_SRCDIR="${CI_SRCDIR:-.}"
51 # Options for where to build.
52 CI_BUILDDIR="${CI_BUILDDIR:-./build}"
54 # How parallel should we run make?
55 MAKE_J_OPT="${MAKE_J_OPT:--j4}"
56 # Should we stop after make finds an error?
57 MAKE_K_OPT="${MAKE_K_OPT:--k}"
59 # What make target should we use for chutney?
60 CHUTNEY_MAKE_TARGET="${CHUTNEY_MAKE_TARGET:-test-network}"
62 # Where do we find our additional testing tools?
63 CHUTNEY_PATH="${CHUTNEY_PATH:-}"
64 STEM_PATH="${STEM_PATH:-}"
66 #############################################################################
67 # Preliminary functions.
69 # Terminal coloring/emphasis stuff.
70 if [[ "${COLOR_CI}" == "yes" ]]; then
71 T_RED=$(tput setaf 1 || true)
72 T_GREEN=$(tput setaf 2 || true)
73 T_YELLOW=$(tput setaf 3 || true)
74 T_DIM=$(tput dim || true)
75 T_BOLD=$(tput bold || true)
76 T_RESET=$(tput sgr0 || true)
77 else
78 T_RED=
79 T_GREEN=
80 T_YELLOW=
81 T_DIM=
82 T_BOLD=
83 T_RESET=
86 function error()
88 echo "${T_BOLD}${T_RED}ERROR:${T_RESET} $*" 1>&2
91 function die()
93 echo "${T_BOLD}${T_RED}FATAL ERROR:${T_RESET} $*" 1>&2
94 exit 1
97 function skipping()
99 echo "${T_BOLD}${T_YELLOW}Skipping $*${T_RESET}"
102 function hooray()
104 echo "${T_BOLD}${T_GREEN}$*${T_RESET}"
107 if [[ "${DEBUG_CI}" == "yes" ]]; then
108 function debug()
110 echo "${T_DIM}(debug): $*${T_RESET}"
112 else
113 function debug()
119 function yes_or_no()
121 local varname="$1"
122 local value="${!varname}"
123 debug "${varname} is ${value}"
124 if [[ "${value}" != 'yes' && "${value}" != 'no' ]]; then
125 die "${varname} must be 'yes' or 'no'. Got unexpected value ${value}".
129 function incompatible()
131 local varname1="$1"
132 local varname2="$2"
133 local val1="${!varname1}"
134 local val2="${!varname2}"
135 if [[ "${val1}" = 'yes' && "${val2}" = 'yes' ]]; then
136 die "Cannot set both ${varname1} and ${varname2}: they are incompatible."
140 function runcmd()
142 echo "${T_BOLD}\$ $*${T_RESET}"
143 if ! "$@" ; then
144 error "command '$*' has failed."
145 return 1
149 function show_git_version()
151 local tool="$1"
152 local dir="$2"
153 local version="?????"
154 if [[ -e "$dir/.git" ]] ; then
155 version=$(cd "$dir"; git rev-parse HEAD)
157 echo "${T_BOLD}$tool:${T_RESET} $version"
160 if [[ "${ON_GITLAB}" == "yes" ]]; then
161 function start_section()
163 local label="$1"
164 local stamp
165 stamp=$(date +%s)
166 printf "section_start:%s:%s\r\e[0K" "$stamp" "$label"
167 echo "${T_BOLD}${T_GREEN}========= $label${T_RESET}"
169 function end_section()
171 local label="$1"
172 local stamp
173 stamp=$(date +%s)
174 printf "section_end:%s:%s\r\e[0K" "$stamp" "$label"
176 else
177 function start_section()
179 true
181 function end_section()
183 true
187 #############################################################################
188 # Validate inputs.
190 debug Validating inputs
191 yes_or_no DEBUG_CI
192 yes_or_no COLOR_CI
193 yes_or_no ON_GITLAB
194 yes_or_no FATAL_WARNINGS
195 yes_or_no HARDENING
196 yes_or_no COVERAGE
197 yes_or_no DOXYGEN
198 yes_or_no ASCIIDOC
199 yes_or_no TRACING
200 yes_or_no ALL_BUGS_ARE_FATAL
201 yes_or_no DISABLE_DIRAUTH
202 yes_or_no DISABLE_RELAY
203 yes_or_no NSS
204 yes_or_no GPL
206 yes_or_no RUN_STAGE_CONFIGURE
207 yes_or_no RUN_STAGE_BUILD
208 yes_or_no RUN_STAGE_TEST
210 yes_or_no CHECK
211 yes_or_no STEM
212 yes_or_no DISTCHECK
214 incompatible DISTCHECK CHECK
215 incompatible DISTCHECK CHUTNEY
216 incompatible DISTCHECK STEM
217 incompatible DISTCHECK COVERAGE
218 incompatible DISTCHECK DOXYGEN
220 if [[ "${CHUTNEY}" = yes && "${CHUTNEY_PATH}" = '' ]] ; then
221 die "CHUTNEY is set to 'yes', but CHUTNEY_PATH was not specified."
224 if [[ "${STEM}" = yes && "${STEM_PATH}" = '' ]] ; then
225 die "STEM is set to 'yes', but STEM_PATH was not specified."
228 #############################################################################
229 # Set up options for make and configure.
231 make_options=()
232 if [[ "$MAKE_J_OPT" != "" ]]; then
233 make_options+=("$MAKE_J_OPT")
235 if [[ "$MAKE_K_OPT" != "" ]]; then
236 make_options+=("$MAKE_K_OPT")
239 configure_options=()
240 if [[ "$FATAL_WARNINGS" == "yes" ]]; then
241 configure_options+=("--enable-fatal-warnings")
243 if [[ "$HARDENING" == "yes" ]]; then
244 configure_options+=("--enable-fragile-hardening")
246 if [[ "$COVERAGE" == "yes" ]]; then
247 configure_options+=("--enable-coverage")
249 if [[ "$ASCIIDOC" != "yes" ]]; then
250 configure_options+=("--disable-asciidoc")
252 if [[ "$TRACING" == "yes" ]]; then
253 configure_options+=("--enable-tracing-instrumentation-lttng")
255 if [[ "$ALL_BUGS_ARE_FATAL" == "yes" ]]; then
256 configure_options+=("--enable-all-bugs-are-fatal")
258 if [[ "$DISABLE_DIRAUTH" == "yes" ]]; then
259 configure_options+=("--disable-module-dirauth")
261 if [[ "$DISABLE_RELAY" == "yes" ]]; then
262 configure_options+=("--disable-module-relay")
264 if [[ "$NSS" == "yes" ]]; then
265 configure_options+=("--enable-nss")
267 if [[ "$GPL" == "yes" ]]; then
268 configure_options+=("--enable-gpl")
271 #############################################################################
272 # Tell the user about our versions of different tools and packages.
274 uname -a
275 printf "python: "
276 python -V || echo "no 'python' binary."
277 printf "python3: "
278 python3 -V || echo "no 'python3' binary."
280 show_git_version Tor "${CI_SRCDIR}"
281 if [[ "${STEM}" = "yes" ]]; then
282 show_git_version Stem "${STEM_PATH}"
284 if [[ "${CHUTNEY}" = "yes" ]]; then
285 show_git_version Chutney "${CHUTNEY_PATH}"
288 #############################################################################
289 # Determine the version of Tor.
291 TOR_VERSION=$(grep -m 1 AC_INIT "${CI_SRCDIR}"/configure.ac | sed -e 's/.*\[//; s/\].*//;')
293 # Use variables like these when we need to behave differently depending on
294 # Tor version. Only create the variables we need.
295 TOR_VER_AT_LEAST_043=no
296 TOR_VER_AT_LEAST_044=no
298 # These are the currently supported Tor versions; no need to work with anything
299 # ancient in this script.
300 case "$TOR_VERSION" in
301 0.4.7.*)
302 TOR_VER_AT_LEAST_043=yes
303 TOR_VER_AT_LEAST_044=yes
305 0.4.8.*)
306 TOR_VER_AT_LEAST_043=yes
307 TOR_VER_AT_LEAST_044=yes
309 esac
311 #############################################################################
312 # Make sure the directories are all there.
314 # Make sure CI_SRCDIR exists and has a file we expect.
315 if [[ ! -d "$CI_SRCDIR" ]] ; then
316 die "CI_SRCDIR=${CI_SRCDIR} is not a directory"
318 if [[ ! -f "$CI_SRCDIR/src/core/or/or.h" ]] ; then
319 die "CI_SRCDIR=${CI_SRCDIR} does not look like a Tor directory."
322 # Make CI_SRCDIR absolute.
323 CI_SRCDIR=$(cd "$CI_SRCDIR" && pwd)
325 # Create an "artifacts" directory to copy artifacts into.
326 mkdir -p ./artifacts
328 if [[ "$RUN_STAGE_CONFIGURE" = "yes" ]]; then
330 start_section "Autogen"
331 runcmd cd "${CI_SRCDIR}"
332 runcmd ./autogen.sh
333 runcmd mkdir -p "${CI_BUILDDIR}"
334 runcmd cd "${CI_BUILDDIR}"
335 end_section "Autogen"
337 # make the builddir absolute too.
338 CI_BUILDDIR=$(pwd)
340 start_section "Configure"
341 if ! runcmd "${CI_SRCDIR}"/configure "${configure_options[@]}" ; then
342 error "Here is the end of config.log:"
343 runcmd tail config.log
344 die "Unable to continue"
346 end_section "Configure"
347 else
348 debug "Skipping configure stage. Making sure that ${CI_BUILDDIR}/config.log exists."
349 if [[ ! -d "${CI_BUILDDIR}" ]]; then
350 die "Build directory ${CI_BUILDDIR} did not exist!"
352 if [[ ! -f "${CI_BUILDDIR}/config.log" ]]; then
353 die "Tor was not configured in ${CI_BUILDDIR}!"
356 cp config.log "${CI_SRCDIR}"/artifacts
358 runcmd cd "${CI_BUILDDIR}"
359 CI_BUILDDIR=$(pwd)
362 ###############################
363 # Build Tor.
365 if [[ "$RUN_STAGE_BUILD" = "yes" ]] ; then
366 if [[ "$DISTCHECK" = "no" ]]; then
367 start_section "Build"
368 runcmd make "${make_options[@]}" all
369 cp src/app/tor "${CI_SRCDIR}"/artifacts
370 end_section "Build"
371 else
372 export DISTCHECK_CONFIGURE_FLAGS="${configure_options[*]}"
373 # XXXX Set make options?
374 start_section Distcheck
375 if runcmd make "${make_options[@]}" distcheck ; then
376 hooray "Distcheck was successful. Nothing further will be done."
377 # We have to exit early here, since we can't do any other tests.
378 cp tor-*.tar.gz "${CI_SRCDIR}"/artifacts
379 else
380 error "Diagnostics:"
381 runcmd make show-distdir-testlog || true
382 runcmd make show-distdir-core || true
383 die "Unable to continue."
385 end_section Distcheck
386 exit 0
390 ##############################
391 # Run tests.
393 if [[ "$RUN_STAGE_TEST" == "no" ]]; then
394 echo "Skipping tests. Exiting now."
395 exit 0
398 FAILED_TESTS=""
400 if [[ "${DOXYGEN}" = 'yes' ]]; then
401 start_section Doxygen
402 if [[ "${TOR_VER_AT_LEAST_043}" = 'yes' ]]; then
403 if runcmd make doxygen; then
404 hooray "make doxygen has succeeded."
405 else
406 FAILED_TESTS="${FAILED_TESTS} doxygen"
408 else
409 skipping "make doxygen: doxygen is broken for Tor < 0.4.3"
411 end_section Doxygen
414 if [[ "${ASCIIDOC}" = 'yes' ]]; then
415 start_section Asciidoc
416 if runcmd make manpages; then
417 hooray "make manpages has succeeded."
418 else
419 FAILED_TESTS="${FAILED_TESTS} asciidoc"
421 end_section Asciidoc
424 if [[ "${CHECK}" = "yes" ]]; then
425 start_section "Check"
426 if runcmd make "${make_options[@]}" check; then
427 hooray "make check has succeeded."
428 else
429 error "Here are the contents of the test suite output:"
430 runcmd cat test-suite.log || true
431 FAILED_TESTS="${FAILED_TESTS} check"
433 end_section "Check"
436 if [[ "${CHUTNEY}" = "yes" ]]; then
437 start_section "Chutney"
438 export CHUTNEY_TOR_SANDBOX=0
439 export CHUTNEY_ALLOW_FAILURES=2
440 # Send 5MB for every verify check.
441 export CHUTNEY_DATA_BYTES=5000000
442 if runcmd make "${CHUTNEY_MAKE_TARGET}"; then
443 hooray "Chutney tests have succeeded"
444 else
445 error "Chutney says:"
446 export CHUTNEY_DATA_DIR="${CHUTNEY_PATH}/net"
447 runcmd "${CHUTNEY_PATH}"/tools/diagnostics.sh || true
448 # XXXX These next two should be part of a make target.
449 runcmd ls test_network_log || true
450 runcmd head -n -0 test_network_log/* || true
451 FAILED_TESTS="${FAILED_TESTS} chutney"
453 end_section "Chutney"
456 if [[ "${STEM}" = "yes" ]]; then
457 start_section "Stem"
458 # 0.3.5 and onward have now disabled onion service v2 so we need to exclude
459 # these Stem tests from now on.
460 EXCLUDE_TESTS="--exclude-test control.controller.test_ephemeral_hidden_services_v2 --exclude-test control.controller.test_hidden_services_conf --exclude-test control.controller.test_with_ephemeral_hidden_services_basic_auth --exclude-test control.controller.test_without_ephemeral_hidden_services --exclude-test control.controller.test_with_ephemeral_hidden_services_basic_auth_no_credentials control.controller.test_with_detached_ephemeral_hidden_services control.controller.test_with_invalid_ephemeral_hidden_service_port"
461 if [[ "${TOR_VER_AT_LEAST_044}" = 'yes' ]]; then
462 # XXXX This should probably be part of some test-stem make target.
464 # Disable the check around EXCLUDE_TESTS that requires double quote. We
465 # need it to be expanded.
466 # shellcheck disable=SC2086
467 if runcmd timelimit -p -t 520 -s USR1 -T 30 -S ABRT \
468 python3 "${STEM_PATH}/run_tests.py" \
469 --tor src/app/tor \
470 --integ --test control.controller \
471 $EXCLUDE_TESTS \
472 --test control.base_controller \
473 --test process \
474 --log TRACE \
475 --log-file stem.log ; then
476 hooray "Stem tests have succeeded"
477 else
478 error "Stem output:"
479 runcmd tail -1000 "${STEM_PATH}"/test/data/tor_log
480 runcmd grep -v "SocketClosed" stem.log | tail -1000
481 FAILED_TESTS="${FAILED_TESTS} stem"
483 else
484 skipping "Stem: broken with <= 0.4.3. See bug tor#40077"
486 end_section "Stem"
489 # TODO: Coverage
491 if [[ "${FAILED_TESTS}" != "" ]]; then
492 die "Failed tests: ${FAILED_TESTS}"
495 hooray "Everything seems fine."