1#!/bin/bash 2# Copyright (c) 2021, Google Inc. All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: 7# 8# * Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 11# * Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in 13# the documentation and/or other materials provided with the 14# distribution. 15# 16# * Neither the name of Google nor the names of its contributors may 17# be used to endorse or promote products derived from this software 18# without specific prior written permission. 19# 20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32set -xeo pipefail 33shopt -s inherit_errexit 34 35readonly GOOGLETEST_REPO="https://github.com/google/googletest.git" 36LIBWEBM_ROOT="$(realpath "$(dirname "$0")/..")" 37readonly LIBWEBM_ROOT 38readonly WORKSPACE=${WORKSPACE:-"$(mktemp -d -t webm.XXX)"} 39 40# shellcheck source=infra/common.sh 41source "${LIBWEBM_ROOT}/infra/common.sh" 42 43usage() { 44 cat << EOF 45Usage: $(basename "$0") TARGET 46Options: 47TARGET supported targets: (x86-asan, x86-ubsan, x86_64-asan, x86_64-ubsan, 48 x86_64-valgrind) 49Global variables: 50WORKSPACE directory where the build is done 51EOF 52} 53 54####################################### 55# Run valgrind 56####################################### 57run_valgrind() { 58 valgrind \ 59 --leak-check=full \ 60 --show-reachable=yes \ 61 --track-origins=yes \ 62 --error-exitcode=1 \ 63 "$@" 64} 65 66####################################### 67# Ensure GoogleTest repository is setup 68# 69# Globals: 70# GOOGLETEST_REPO googletest repository url 71# WORKSPACE directory where the build is done 72####################################### 73ensure_googletest() { 74 local googletest_dir 75 googletest_dir="${WORKSPACE}/googletest" 76 77 if [[ ! -d "${googletest_dir}" ]] || ! git -C "${googletest_dir}" pull; then 78 rm -rf "${googletest_dir}" 79 git clone --depth 1 "${GOOGLETEST_REPO}" "${googletest_dir}" 80 fi 81 82 opts+=("-DGTEST_SRC_DIR=${googletest_dir}") 83} 84 85####################################### 86# Symbolizes and dumps warnings in the address sanitizer log 87# Globals: 88# BUILD_DIR directory where the build is done 89# SANITIZER_LOG path to sanitizer log file 90####################################### 91dump_sanitizer_log() { 92 if [[ "$#" -ne 1 ]]; then 93 return 1 94 fi 95 96 if command -v asan_symbolize; then 97 asan_symbolize_tool="asan_symbolize" 98 else 99 asan_symbolize_tool="asan_symbolize.py" 100 fi 101 102 local target 103 target="$1" 104 case "${target}" in 105 *-asan) 106 asanlog_symbolized="${BUILD_DIR}/asan_log.asanlog_symbolized" 107 grep -v 'Invalid VP9' "${SANITIZER_LOG}" > "${SANITIZER_LOG}.2" || true 108 "${asan_symbolize_tool}" "${BUILD_DIR}" < "${SANITIZER_LOG}.2" \ 109 | c++filt > "${asanlog_symbolized}" 110 if [[ -s "${asanlog_symbolized}" ]]; then 111 cat "${asanlog_symbolized}" 112 return 1 113 fi 114 ;; 115 *) ;; # No other sanitizer options are required 116 # TODO(b/185520494): Handle ubsan warning output inspection 117 esac 118} 119 120################################################################################ 121echo "Unit testing libwebm in ${WORKSPACE}" 122 123if [[ ! -d "${WORKSPACE}" ]]; then 124 log_err "${WORKSPACE} directory does not exist" 125 exit 1 126fi 127 128TARGET=${1:? "$( 129 echo 130 usage 131)"} 132readonly BUILD_DIR="${WORKSPACE}/tests-${TARGET}" 133readonly SANITIZER_LOG="${BUILD_DIR}/sanitizer_log" 134 135# Create a fresh build directory. 136trap 'dump_sanitizer_log ${TARGET}; cleanup' EXIT 137make_build_dir "${BUILD_DIR}" 138 139case "${TARGET}" in 140 x86-*) CXX='clang++ -m32' ;; 141 x86_64-*) CXX=clang++ ;; 142 *) 143 log_err "${TARGET} should have x86 or x86_64 prefix." 144 usage 145 exit 1 146 ;; 147esac 148# cmake (3.4.3) will only accept the -m32 variants when used via the CXX env 149# var. 150export CXX 151opts+=("-DCMAKE_BUILD_TYPE=Debug" "-DENABLE_TESTS=ON") 152case "${TARGET}" in 153 *-asan) opts+=("-DCMAKE_CXX_FLAGS=-fsanitize=address") ;; 154 *-ubsan) 155 opts+=("-DCMAKE_CXX_FLAGS=-fsanitize=integer") 156 if [[ "${TARGET}" == "x86-ubsan" ]]; then 157 # clang fails to find symbols when -fsanitize=integer is set in x86 arch. 158 # https://bugs.llvm.org/show_bug.cgi?id=17693 159 opts+=("-DCMAKE_CXX_FLAGS=-rtlib=compiler-rt") 160 opts+=("-DCMAKE_EXE_LINKER_FLAGS=-lgcc_s") 161 fi 162 ;; 163 *) ;; # No additional flags needed. 164esac 165 166ensure_googletest 167# Using pushd instead of -S/-B for backward compatibility with CMake < 3.13.x 168pushd "${BUILD_DIR}" 169cmake "${LIBWEBM_ROOT}" "${opts[@]}" 170make -j 4 171popd 172 173find_tests="$(find "${BUILD_DIR}" -name '*_tests')" 174UNIT_TESTS=() 175while IFS='' read -r line; do 176 UNIT_TESTS+=("${line}") 177done < <(echo "${find_tests}") 178 179export LIBWEBM_TEST_DATA_PATH="${LIBWEBM_ROOT}/testing/testdata" 180case "${TARGET}" in 181 *-asan | *-ubsan) 182 rm -f "${SANITIZER_LOG}" 183 for test in "${UNIT_TESTS[@]}"; do 184 "${test}" \ 185 --gtest_output="xml:${BUILD_DIR}/$(basename "${test}")_detail.xml" \ 186 3<&1 1>&2 2>&3 | tee -a "${SANITIZER_LOG}" 187 done 188 ;; 189 *-valgrind) 190 for test in "${UNIT_TESTS[@]}"; do 191 run_valgrind --error-exitcode=1 "${test}" \ 192 --gtest_output="xml:${BUILD_DIR}/$(basename "${test}")_detail.xml" 193 done 194 ;; 195 *) 196 log_err "Unrecognized TARGET:${TARGET}." 197 usage 198 exit 1 199 ;; 200esac 201