tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

ci-driver.sh (13819B)


      1 #!/bin/bash
      2 
      3 ####
      4 # DO NOT EDIT THIS FILE IN MASTER.  ONLY EDIT IT IN THE OLDEST SUPPORTED
      5 # BRANCH, THEN MERGE FORWARD.
      6 ####
      7 
      8 # This script is used to build Tor for continuous integration.  It should
      9 # be kept the same for all supported Tor versions.
     10 #
     11 # It's subject to the regular Tor license; see LICENSE for copying
     12 # information.
     13 
     14 set -o errexit
     15 set -o nounset
     16 
     17 # Options for this script.
     18 DEBUG_CI="${DEBUG_CI:-no}"
     19 COLOR_CI="${COLOR_CI:-yes}"
     20 
     21 # Options for which CI system this is.
     22 ON_GITLAB="${ON_GITLAB:-yes}"
     23 
     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}"
     28 
     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}"
     41 
     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}"
     47 
     48 # Options for where the Tor source is.
     49 CI_SRCDIR="${CI_SRCDIR:-.}"
     50 
     51 # Options for where to build.
     52 CI_BUILDDIR="${CI_BUILDDIR:-./build}"
     53 
     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}"
     58 
     59 # What make target should we use for chutney?
     60 CHUTNEY_MAKE_TARGET="${CHUTNEY_MAKE_TARGET:-test-network}"
     61 
     62 # Where do we find our additional testing tools?
     63 CHUTNEY_PATH="${CHUTNEY_PATH:-}"
     64 STEM_PATH="${STEM_PATH:-}"
     65 
     66 #############################################################################
     67 # Preliminary functions.
     68 
     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=
     84 fi
     85 
     86 function error()
     87 {
     88    echo "${T_BOLD}${T_RED}ERROR:${T_RESET} $*" 1>&2
     89 }
     90 
     91 function die()
     92 {
     93    echo "${T_BOLD}${T_RED}FATAL ERROR:${T_RESET} $*" 1>&2
     94    exit 1
     95 }
     96 
     97 function skipping()
     98 {
     99    echo "${T_BOLD}${T_YELLOW}Skipping $*${T_RESET}"
    100 }
    101 
    102 function hooray()
    103 {
    104    echo "${T_BOLD}${T_GREEN}$*${T_RESET}"
    105 }
    106 
    107 if [[ "${DEBUG_CI}" == "yes" ]]; then
    108    function debug()
    109    {
    110        echo "${T_DIM}(debug): $*${T_RESET}"
    111    }
    112 else
    113    function debug()
    114    {
    115        :
    116    }
    117 fi
    118 
    119 function yes_or_no()
    120 {
    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}".
    126    fi
    127 }
    128 
    129 function incompatible()
    130 {
    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."
    137    fi
    138 }
    139 
    140 function runcmd()
    141 {
    142    echo "${T_BOLD}\$ $*${T_RESET}"
    143    if ! "$@" ; then
    144        error "command '$*' has failed."
    145        return 1
    146    fi
    147 }
    148 
    149 function show_git_version()
    150 {
    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)
    156    fi
    157    echo "${T_BOLD}$tool:${T_RESET} $version"
    158 }
    159 
    160 if [[ "${ON_GITLAB}" == "yes" ]]; then
    161    function start_section()
    162    {
    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}"
    168    }
    169    function end_section()
    170    {
    171        local label="$1"
    172        local stamp
    173        stamp=$(date +%s)
    174        printf "section_end:%s:%s\r\e[0K" "$stamp" "$label"
    175    }
    176 else
    177    function start_section()
    178    {
    179        true
    180    }
    181    function end_section()
    182    {
    183        true
    184    }
    185 fi
    186 
    187 #############################################################################
    188 # Validate inputs.
    189 
    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
    205 
    206 yes_or_no RUN_STAGE_CONFIGURE
    207 yes_or_no RUN_STAGE_BUILD
    208 yes_or_no RUN_STAGE_TEST
    209 
    210 yes_or_no CHECK
    211 yes_or_no STEM
    212 yes_or_no DISTCHECK
    213 
    214 incompatible DISTCHECK CHECK
    215 incompatible DISTCHECK CHUTNEY
    216 incompatible DISTCHECK STEM
    217 incompatible DISTCHECK COVERAGE
    218 incompatible DISTCHECK DOXYGEN
    219 
    220 if [[ "${CHUTNEY}" = yes && "${CHUTNEY_PATH}" = '' ]] ; then
    221    die "CHUTNEY is set to 'yes', but CHUTNEY_PATH was not specified."
    222 fi
    223 
    224 if [[ "${STEM}" = yes && "${STEM_PATH}" = '' ]] ; then
    225    die "STEM is set to 'yes', but STEM_PATH was not specified."
    226 fi
    227 
    228 #############################################################################
    229 # Set up options for make and configure.
    230 
    231 make_options=()
    232 if [[ "$MAKE_J_OPT" != "" ]]; then
    233    make_options+=("$MAKE_J_OPT")
    234 fi
    235 if [[ "$MAKE_K_OPT" != "" ]]; then
    236    make_options+=("$MAKE_K_OPT")
    237 fi
    238 
    239 configure_options=()
    240 if [[ "$FATAL_WARNINGS" == "yes" ]]; then
    241    configure_options+=("--enable-fatal-warnings")
    242 fi
    243 if [[ "$HARDENING" == "yes" ]]; then
    244    configure_options+=("--enable-fragile-hardening")
    245 fi
    246 if [[ "$COVERAGE" == "yes" ]]; then
    247    configure_options+=("--enable-coverage")
    248 fi
    249 if [[ "$ASCIIDOC" != "yes" ]]; then
    250    configure_options+=("--disable-asciidoc")
    251 fi
    252 if [[ "$TRACING" == "yes" ]]; then
    253    configure_options+=("--enable-tracing-instrumentation-lttng")
    254 fi
    255 if [[ "$ALL_BUGS_ARE_FATAL" == "yes" ]]; then
    256    configure_options+=("--enable-all-bugs-are-fatal")
    257 fi
    258 if [[ "$DISABLE_DIRAUTH" == "yes" ]]; then
    259    configure_options+=("--disable-module-dirauth")
    260 fi
    261 if [[ "$DISABLE_RELAY" == "yes" ]]; then
    262    configure_options+=("--disable-module-relay")
    263 fi
    264 if [[ "$NSS" == "yes" ]]; then
    265    configure_options+=("--enable-nss")
    266 fi
    267 if [[ "$GPL" == "yes" ]]; then
    268    configure_options+=("--enable-gpl")
    269 fi
    270 
    271 #############################################################################
    272 # Tell the user about our versions of different tools and packages.
    273 
    274 uname -a
    275 printf "python: "
    276 python -V || echo "no 'python' binary."
    277 printf "python3: "
    278 python3 -V || echo "no 'python3' binary."
    279 
    280 show_git_version Tor "${CI_SRCDIR}"
    281 if [[ "${STEM}" = "yes" ]]; then
    282    show_git_version Stem "${STEM_PATH}"
    283 fi
    284 if [[ "${CHUTNEY}" = "yes" ]]; then
    285    show_git_version Chutney "${CHUTNEY_PATH}"
    286 fi
    287 
    288 #############################################################################
    289 # Determine the version of Tor.
    290 
    291 TOR_VERSION=$(grep -m 1 AC_INIT "${CI_SRCDIR}"/configure.ac | sed -e 's/.*\[//; s/\].*//;')
    292 
    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
    297 
    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.8.*)
    302        TOR_VER_AT_LEAST_043=yes
    303        TOR_VER_AT_LEAST_044=yes
    304        ;;
    305    0.4.9.*)
    306        TOR_VER_AT_LEAST_043=yes
    307        TOR_VER_AT_LEAST_044=yes
    308        ;;
    309    0.5.0.*)
    310        TOR_VER_AT_LEAST_043=yes
    311        TOR_VER_AT_LEAST_044=yes
    312        ;;
    313 esac
    314 
    315 #############################################################################
    316 # Make sure the directories are all there.
    317 
    318 # Make sure CI_SRCDIR exists and has a file we expect.
    319 if [[ ! -d "$CI_SRCDIR" ]] ; then
    320    die "CI_SRCDIR=${CI_SRCDIR} is not a directory"
    321 fi
    322 if [[ ! -f "$CI_SRCDIR/src/core/or/or.h" ]] ; then
    323    die "CI_SRCDIR=${CI_SRCDIR} does not look like a Tor directory."
    324 fi
    325 
    326 # Make CI_SRCDIR absolute.
    327 CI_SRCDIR=$(cd "$CI_SRCDIR" && pwd)
    328 
    329 # Create an "artifacts" directory to copy artifacts into.
    330 mkdir -p ./artifacts
    331 
    332 if [[ "$RUN_STAGE_CONFIGURE" = "yes" ]]; then
    333 
    334    start_section "Autogen"
    335    runcmd cd "${CI_SRCDIR}"
    336    runcmd ./autogen.sh
    337    runcmd mkdir -p "${CI_BUILDDIR}"
    338    runcmd cd "${CI_BUILDDIR}"
    339    end_section "Autogen"
    340 
    341    # make the builddir absolute too.
    342    CI_BUILDDIR=$(pwd)
    343 
    344    start_section "Configure"
    345    if ! runcmd "${CI_SRCDIR}"/configure "${configure_options[@]}" ; then
    346        error "Here is the end of config.log:"
    347        runcmd tail config.log
    348        die "Unable to continue"
    349    fi
    350    end_section "Configure"
    351 else
    352    debug "Skipping configure stage. Making sure that ${CI_BUILDDIR}/config.log exists."
    353    if [[ ! -d "${CI_BUILDDIR}" ]]; then
    354        die "Build directory ${CI_BUILDDIR} did not exist!"
    355    fi
    356    if [[ ! -f "${CI_BUILDDIR}/config.log" ]]; then
    357        die "Tor was not configured in ${CI_BUILDDIR}!"
    358    fi
    359 
    360    cp config.log "${CI_SRCDIR}"/artifacts
    361 
    362    runcmd cd "${CI_BUILDDIR}"
    363    CI_BUILDDIR=$(pwd)
    364 fi
    365 
    366 ###############################
    367 # Build Tor.
    368 
    369 if [[ "$RUN_STAGE_BUILD" = "yes" ]] ; then
    370    if [[ "$DISTCHECK" = "no" ]]; then
    371        start_section "Build"
    372        runcmd make "${make_options[@]}" all
    373        cp src/app/tor "${CI_SRCDIR}"/artifacts
    374        end_section "Build"
    375    else
    376        export DISTCHECK_CONFIGURE_FLAGS="${configure_options[*]}"
    377        # XXXX Set make options?
    378        start_section Distcheck
    379        if runcmd make "${make_options[@]}" distcheck ; then
    380            hooray "Distcheck was successful. Nothing further will be done."
    381            # We have to exit early here, since we can't do any other tests.
    382            cp tor-*.tar.gz "${CI_SRCDIR}"/artifacts
    383        else
    384            error "Diagnostics:"
    385            runcmd make show-distdir-testlog || true
    386            runcmd make show-distdir-core || true
    387            die "Unable to continue."
    388        fi
    389        end_section Distcheck
    390        exit 0
    391    fi
    392 fi
    393 
    394 ##############################
    395 # Run tests.
    396 
    397 if [[ "$RUN_STAGE_TEST" == "no" ]]; then
    398    echo "Skipping tests. Exiting now."
    399    exit 0
    400 fi
    401 
    402 FAILED_TESTS=""
    403 
    404 if [[ "${DOXYGEN}" = 'yes' ]]; then
    405    start_section Doxygen
    406    if [[ "${TOR_VER_AT_LEAST_043}" = 'yes' ]]; then
    407        if runcmd make doxygen; then
    408            hooray "make doxygen has succeeded."
    409        else
    410            FAILED_TESTS="${FAILED_TESTS} doxygen"
    411        fi
    412    else
    413        skipping "make doxygen: doxygen is broken for Tor < 0.4.3"
    414    fi
    415    end_section Doxygen
    416 fi
    417 
    418 if [[ "${ASCIIDOC}" = 'yes' ]]; then
    419    start_section Asciidoc
    420    if runcmd make manpages; then
    421        hooray "make manpages has succeeded."
    422    else
    423        FAILED_TESTS="${FAILED_TESTS} asciidoc"
    424    fi
    425    end_section Asciidoc
    426 fi
    427 
    428 if [[ "${CHECK}" = "yes" ]]; then
    429    start_section "Check"
    430    if runcmd make "${make_options[@]}" check; then
    431        hooray "make check has succeeded."
    432    else
    433        error "Here are the contents of the test suite output:"
    434        runcmd cat test-suite.log || true
    435        FAILED_TESTS="${FAILED_TESTS} check"
    436    fi
    437    end_section "Check"
    438 fi
    439 
    440 if [[ "${CHUTNEY}" = "yes" ]]; then
    441    start_section "Chutney"
    442    export CHUTNEY_TOR_SANDBOX=0
    443    export CHUTNEY_ALLOW_FAILURES=2
    444    # Send 5MB for every verify check.
    445    export CHUTNEY_DATA_BYTES=5000000
    446    if runcmd make "${CHUTNEY_MAKE_TARGET}"; then
    447        hooray "Chutney tests have succeeded"
    448    else
    449        error "Chutney says:"
    450        export CHUTNEY_DATA_DIR="${CHUTNEY_PATH}/net"
    451        runcmd "${CHUTNEY_PATH}"/tools/diagnostics.sh || true
    452        # XXXX These next two should be part of a make target.
    453        runcmd ls test_network_log || true
    454        runcmd head -n -0 test_network_log/* || true
    455        FAILED_TESTS="${FAILED_TESTS} chutney"
    456    fi
    457    end_section "Chutney"
    458 fi
    459 
    460 if [[ "${STEM}" = "yes" ]]; then
    461    start_section "Stem"
    462    # 0.3.5 and onward have now disabled onion service v2 so we need to exclude
    463    # these Stem tests from now on.
    464    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 --exclude-test control.controller.test_with_detached_ephemeral_hidden_services --exclude-test control.controller.test_with_invalid_ephemeral_hidden_service_port --exclude-test control.controller.test_ephemeral_hidden_services_v3"
    465    if [[ "${TOR_VER_AT_LEAST_044}" = 'yes' ]]; then
    466        # XXXX This should probably be part of some test-stem make target.
    467 
    468        # Disable the check around EXCLUDE_TESTS that requires double quote. We
    469        # need it to be expanded.
    470        # shellcheck disable=SC2086
    471        if runcmd timelimit -p -t 520 -s USR1 -T 30 -S ABRT \
    472            python3 "${STEM_PATH}/run_tests.py" \
    473            --tor src/app/tor \
    474            --integ --test control.controller \
    475            $EXCLUDE_TESTS \
    476            --test control.base_controller \
    477            --test process \
    478            --log TRACE \
    479            --log-file stem.log ; then
    480            hooray "Stem tests have succeeded"
    481        else
    482            error "Stem output:"
    483            runcmd tail -1000 "${STEM_PATH}"/test/data/tor_log
    484            runcmd grep -v "SocketClosed" stem.log | tail -1000
    485            FAILED_TESTS="${FAILED_TESTS} stem"
    486        fi
    487    else
    488        skipping "Stem: broken with <= 0.4.3. See bug tor#40077"
    489    fi
    490    end_section "Stem"
    491 fi
    492 
    493 # TODO: Coverage
    494 
    495 if [[ "${FAILED_TESTS}" != "" ]]; then
    496    die "Failed tests: ${FAILED_TESTS}"
    497 fi
    498 
    499 hooray "Everything seems fine."