1 #!/bin/sh 2 ## 3 ## Copyright (c) 2014 The WebM project authors. All Rights Reserved. 4 ## 5 ## Use of this source code is governed by a BSD-style license 6 ## that can be found in the LICENSE file in the root of the source 7 ## tree. An additional intellectual property rights grant can be found 8 ## in the file PATENTS. All contributing project authors may 9 ## be found in the AUTHORS file in the root of the source tree. 10 ## 11 ## This file contains shell code shared by test scripts for libvpx tools. 12 set -e 13 14 # Sets $VPX_TOOL_TEST to the name specified by positional parameter one. 15 test_begin() { 16 VPX_TOOL_TEST="${1}" 17 } 18 19 # Clears the VPX_TOOL_TEST variable after confirming that $VPX_TOOL_TEST matches 20 # positional parameter one. 21 test_end() { 22 if [ "$1" != "${VPX_TOOL_TEST}" ]; then 23 echo "FAIL completed test mismatch!." 24 echo " completed test: ${1}" 25 echo " active test: ${VPX_TOOL_TEST}." 26 return 1 27 fi 28 VPX_TOOL_TEST='<unset>' 29 } 30 31 # Echoes the target configuration being tested. 32 test_configuration_target() { 33 vpx_config_mk="${LIBVPX_CONFIG_PATH}/config.mk" 34 # Find the TOOLCHAIN line, split it using ':=' as the field separator, and 35 # print the last field to get the value. Then pipe the value to tr to consume 36 # any leading/trailing spaces while allowing tr to echo the output to stdout. 37 awk -F ':=' '/TOOLCHAIN/ { print $NF }' "${vpx_config_mk}" | tr -d ' ' 38 } 39 40 # Trap function used for failure reports and tool output directory removal. 41 # When the contents of $VPX_TOOL_TEST do not match the string '<unset>', reports 42 # failure of test stored in $VPX_TOOL_TEST. 43 cleanup() { 44 if [ -n "${VPX_TOOL_TEST}" ] && [ "${VPX_TOOL_TEST}" != '<unset>' ]; then 45 echo "FAIL: $VPX_TOOL_TEST" 46 fi 47 if [ -n "${VPX_TEST_OUTPUT_DIR}" ] && [ -d "${VPX_TEST_OUTPUT_DIR}" ]; then 48 rm -rf "${VPX_TEST_OUTPUT_DIR}" 49 fi 50 } 51 52 # Echoes the git hash portion of the VERSION_STRING variable defined in 53 # $LIBVPX_CONFIG_PATH/config.mk to stdout, or the version number string when 54 # no git hash is contained in VERSION_STRING. 55 config_hash() { 56 vpx_config_mk="${LIBVPX_CONFIG_PATH}/config.mk" 57 # Find VERSION_STRING line, split it with "-g" and print the last field to 58 # output the git hash to stdout. 59 vpx_version=$(awk -F -g '/VERSION_STRING/ {print $NF}' "${vpx_config_mk}") 60 # Handle two situations here: 61 # 1. The default case: $vpx_version is a git hash, so echo it unchanged. 62 # 2. When being run a non-dev tree, the -g portion is not present in the 63 # version string: It's only the version number. 64 # In this case $vpx_version is something like 'VERSION_STRING=v1.3.0', so 65 # we echo only what is after the '='. 66 echo "${vpx_version##*=}" 67 } 68 69 # Echoes the short form of the current git hash. 70 current_hash() { 71 if git --version > /dev/null 2>&1; then 72 (cd "$(dirname "${0}")" 73 git rev-parse --short HEAD) 74 else 75 # Return the config hash if git is unavailable: Fail silently, git hashes 76 # are used only for warnings. 77 config_hash 78 fi 79 } 80 81 # Echoes warnings to stdout when git hash in vpx_config.h does not match the 82 # current git hash. 83 check_git_hashes() { 84 hash_at_configure_time=$(config_hash) 85 hash_now=$(current_hash) 86 87 if [ "${hash_at_configure_time}" != "${hash_now}" ]; then 88 echo "Warning: git hash has changed since last configure." 89 fi 90 } 91 92 # This script requires that the LIBVPX_BIN_PATH, LIBVPX_CONFIG_PATH, and 93 # LIBVPX_TEST_DATA_PATH variables are in the environment: Confirm that 94 # the variables are set and that they all evaluate to directory paths. 95 verify_vpx_test_environment() { 96 if [ ! -d "${LIBVPX_BIN_PATH}" ]; then 97 echo "The LIBVPX_BIN_PATH environment variable must be set." 98 return 1 99 fi 100 if [ ! -d "${LIBVPX_CONFIG_PATH}" ]; then 101 echo "The LIBVPX_CONFIG_PATH environment variable must be set." 102 return 1 103 fi 104 if [ ! -d "${LIBVPX_TEST_DATA_PATH}" ]; then 105 echo "The LIBVPX_TEST_DATA_PATH environment variable must be set." 106 return 1 107 fi 108 } 109 110 # Greps vpx_config.h in LIBVPX_CONFIG_PATH for positional parameter one, which 111 # should be a LIBVPX preprocessor flag. Echoes yes to stdout when the feature 112 # is available. 113 vpx_config_option_enabled() { 114 vpx_config_option="${1}" 115 vpx_config_file="${LIBVPX_CONFIG_PATH}/vpx_config.h" 116 config_line=$(grep "${vpx_config_option}" "${vpx_config_file}") 117 if echo "${config_line}" | egrep -q '1$'; then 118 echo yes 119 fi 120 } 121 122 # Echoes yes when output of test_configuration_target() contains win32 or win64. 123 is_windows_target() { 124 if test_configuration_target \ 125 | grep -q -e win32 -e win64 > /dev/null 2>&1; then 126 echo yes 127 fi 128 } 129 130 # Echoes yes to stdout when the file named by positional parameter one exists 131 # in LIBVPX_BIN_PATH, and is executable. 132 vpx_tool_available() { 133 tool_name="${1}" 134 if [ "$(is_windows_target)" = "yes" ]; then 135 tool_name="${tool_name}.exe" 136 fi 137 [ -x "${LIBVPX_BIN_PATH}/${1}" ] && echo yes 138 } 139 140 # Echoes yes to stdout when vpx_config_option_enabled() reports yes for 141 # CONFIG_VP8_DECODER. 142 vp8_decode_available() { 143 [ "$(vpx_config_option_enabled CONFIG_VP8_DECODER)" = "yes" ] && echo yes 144 } 145 146 # Echoes yes to stdout when vpx_config_option_enabled() reports yes for 147 # CONFIG_VP8_ENCODER. 148 vp8_encode_available() { 149 [ "$(vpx_config_option_enabled CONFIG_VP8_ENCODER)" = "yes" ] && echo yes 150 } 151 152 # Echoes yes to stdout when vpx_config_option_enabled() reports yes for 153 # CONFIG_VP9_DECODER. 154 vp9_decode_available() { 155 [ "$(vpx_config_option_enabled CONFIG_VP9_DECODER)" = "yes" ] && echo yes 156 } 157 158 # Echoes yes to stdout when vpx_config_option_enabled() reports yes for 159 # CONFIG_VP9_ENCODER. 160 vp9_encode_available() { 161 [ "$(vpx_config_option_enabled CONFIG_VP9_ENCODER)" = "yes" ] && echo yes 162 } 163 164 # Echoes yes to stdout when vpx_config_option_enabled() reports yes for 165 # CONFIG_WEBM_IO. 166 webm_io_available() { 167 [ "$(vpx_config_option_enabled CONFIG_WEBM_IO)" = "yes" ] && echo yes 168 } 169 170 # Echoes yes to stdout when vpxdec exists according to vpx_tool_available(). 171 vpxdec_available() { 172 [ -n $(vpx_tool_available vpxdec) ] && echo yes 173 } 174 175 # Wrapper function for running vpxdec in noblit mode. Requires that 176 # LIBVPX_BIN_PATH points to the directory containing vpxdec. Positional 177 # parameter one is used as the input file path. Positional parameter two, when 178 # present, is interpreted as a boolean flag that means the input should be sent 179 # to vpxdec via pipe from cat instead of directly. 180 vpxdec() { 181 input="${1}" 182 pipe_input=${2} 183 184 if [ $# -gt 2 ]; then 185 # shift away $1 and $2 so the remaining arguments can be passed to vpxdec 186 # via $@. 187 shift 2 188 fi 189 190 decoder="${LIBVPX_BIN_PATH}/vpxdec" 191 192 if [ "$(is_windows_target)" = "yes" ]; then 193 decoder="${decoder}.exe" 194 fi 195 196 if [ -z "${pipe_input}" ]; then 197 "${decoder}" "$input" --summary --noblit "$@" > /dev/null 2>&1 198 else 199 cat "${input}" | "${decoder}" - --summary --noblit "$@" > /dev/null 2>&1 200 fi 201 } 202 203 # Echoes yes to stdout when vpxenc exists according to vpx_tool_available(). 204 vpxenc_available() { 205 [ -n $(vpx_tool_available vpxenc) ] && echo yes 206 } 207 208 # Wrapper function for running vpxenc. Positional parameters are interpreted as 209 # follows: 210 # 1 - codec name 211 # 2 - input width 212 # 3 - input height 213 # 4 - number of frames to encode 214 # 5 - path to input file 215 # 6 - path to output file 216 # Note: The output file path must end in .ivf to output an IVF file. 217 # 7 - extra flags 218 # Note: Extra flags currently supports a special case: when set to "-" 219 # input is piped to vpxenc via cat. 220 vpxenc() { 221 encoder="${LIBVPX_BIN_PATH}/vpxenc" 222 codec="${1}" 223 width=${2} 224 height=${3} 225 frames=${4} 226 input=${5} 227 output="${VPX_TEST_OUTPUT_DIR}/${6}" 228 extra_flags=${7} 229 230 if [ "$(is_windows_target)" = "yes" ]; then 231 encoder="${encoder}.exe" 232 fi 233 234 # Because --ivf must be within the command line to get IVF from vpxenc. 235 if echo "${output}" | egrep -q 'ivf$'; then 236 use_ivf=--ivf 237 else 238 unset use_ivf 239 fi 240 241 if [ "${extra_flags}" = "-" ]; then 242 pipe_input=yes 243 extra_flags=${8} 244 else 245 unset pipe_input 246 fi 247 248 if [ -z "${pipe_input}" ]; then 249 "${encoder}" --codec=${codec} --width=${width} --height=${height} \ 250 --limit=${frames} ${use_ivf} ${extra_flags} --output="${output}" \ 251 "${input}" > /dev/null 2>&1 252 else 253 cat "${input}" \ 254 | "${encoder}" --codec=${codec} --width=${width} --height=${height} \ 255 --limit=${frames} ${use_ivf} ${extra_flags} --output="${output}" - \ 256 > /dev/null 2>&1 257 fi 258 259 if [ ! -e "${output}" ]; then 260 # Return non-zero exit status: output file doesn't exist, so something 261 # definitely went wrong. 262 return 1 263 fi 264 } 265 266 # Filters strings from positional parameter one using the filter specified by 267 # positional parameter two. Filter behavior depends on the presence of a third 268 # positional parameter. When parameter three is present, strings that match the 269 # filter are excluded. When omitted, strings matching the filter are included. 270 # The filtered string is echoed to stdout. 271 filter_strings() { 272 strings=${1} 273 filter=${2} 274 exclude=${3} 275 276 if [ -n "${exclude}" ]; then 277 # When positional parameter three exists the caller wants to remove strings. 278 # Tell grep to invert matches using the -v argument. 279 exclude='-v' 280 else 281 unset exclude 282 fi 283 284 if [ -n "${filter}" ]; then 285 for s in ${strings}; do 286 if echo "${s}" | egrep -q ${exclude} "${filter}" > /dev/null 2>&1; then 287 filtered_strings="${filtered_strings} ${s}" 288 fi 289 done 290 else 291 filtered_strings="${strings}" 292 fi 293 echo "${filtered_strings}" 294 } 295 296 # Runs user test functions passed via positional parameters one and two. 297 # Functions in positional parameter one are treated as environment verification 298 # functions and are run unconditionally. Functions in positional parameter two 299 # are run according to the rules specified in vpx_test_usage(). 300 run_tests() { 301 env_tests="verify_vpx_test_environment ${1}" 302 tests_to_filter="${2}" 303 304 if [ "${VPX_TEST_RUN_DISABLED_TESTS}" != "yes" ]; then 305 # Filter out DISABLED tests. 306 tests_to_filter=$(filter_strings "${tests_to_filter}" ^DISABLED exclude) 307 fi 308 309 if [ -n "${VPX_TEST_FILTER}" ]; then 310 # Remove tests not matching the user's filter. 311 tests_to_filter=$(filter_strings "${tests_to_filter}" ${VPX_TEST_FILTER}) 312 fi 313 314 tests_to_run="${env_tests} ${tests_to_filter}" 315 316 check_git_hashes 317 318 # Run tests. 319 for test in ${tests_to_run}; do 320 test_begin "${test}" 321 "${test}" 322 [ "${VPX_TEST_VERBOSE_OUTPUT}" = "yes" ] && echo " PASS ${test}" 323 test_end "${test}" 324 done 325 326 tested_config="$(test_configuration_target) @ $(current_hash)" 327 echo $(basename "${0%.*}"): Done, all tests pass for ${tested_config}. 328 } 329 330 vpx_test_usage() { 331 cat << EOF 332 Usage: ${0##*/} [arguments] 333 --bin-path <path to libvpx binaries directory> 334 --config-path <path to libvpx config directory> 335 --filter <filter>: User test filter. Only tests matching filter are run. 336 --run-disabled-tests: Run disabled tests. 337 --help: Display this message and exit. 338 --test-data-path <path to libvpx test data directory> 339 --verbose: Verbose output. 340 341 When the --bin-path option is not specified the script attempts to use 342 \$LIBVPX_BIN_PATH and then the current directory. 343 344 When the --config-path option is not specified the script attempts to use 345 \$LIBVPX_CONFIG_PATH and then the current directory. 346 347 When the -test-data-path option is not specified the script attempts to use 348 \$LIBVPX_TEST_DATA_PATH and then the current directory. 349 EOF 350 } 351 352 # Returns non-zero (failure) when required environment variables are empty 353 # strings. 354 vpx_test_check_environment() { 355 if [ -z "${LIBVPX_BIN_PATH}" ] || \ 356 [ -z "${LIBVPX_CONFIG_PATH}" ] || \ 357 [ -z "${LIBVPX_TEST_DATA_PATH}" ]; then 358 return 1 359 fi 360 } 361 362 # Parse the command line. 363 while [ -n "$1" ]; do 364 case "$1" in 365 --bin-path) 366 LIBVPX_BIN_PATH="$2" 367 shift 368 ;; 369 --config-path) 370 LIBVPX_CONFIG_PATH="$2" 371 shift 372 ;; 373 --filter) 374 VPX_TEST_FILTER="$2" 375 shift 376 ;; 377 --run-disabled-tests) 378 VPX_TEST_RUN_DISABLED_TESTS=yes 379 ;; 380 --help) 381 vpx_test_usage 382 exit 383 ;; 384 --test-data-path) 385 LIBVPX_TEST_DATA_PATH="$2" 386 shift 387 ;; 388 --verbose) 389 VPX_TEST_VERBOSE_OUTPUT=yes 390 ;; 391 *) 392 vpx_test_usage 393 exit 1 394 ;; 395 esac 396 shift 397 done 398 399 # Handle running the tests from a build directory without arguments when running 400 # the tests on *nix/macosx. 401 LIBVPX_BIN_PATH="${LIBVPX_BIN_PATH:-.}" 402 LIBVPX_CONFIG_PATH="${LIBVPX_CONFIG_PATH:-.}" 403 LIBVPX_TEST_DATA_PATH="${LIBVPX_TEST_DATA_PATH:-.}" 404 405 # Create a temporary directory for output files, and a trap to clean it up. 406 if [ -n "${TMPDIR}" ]; then 407 VPX_TEST_TEMP_ROOT="${TMPDIR}" 408 elif [ -n "${TEMPDIR}" ]; then 409 VPX_TEST_TEMP_ROOT="${TEMPDIR}" 410 else 411 VPX_TEST_TEMP_ROOT=/tmp 412 fi 413 414 VPX_TEST_RAND=$(awk 'BEGIN { srand(); printf "%d\n",(rand() * 32768)}') 415 VPX_TEST_OUTPUT_DIR="${VPX_TEST_TEMP_ROOT}/vpx_test_${VPX_TEST_RAND}" 416 417 if ! mkdir -p "${VPX_TEST_OUTPUT_DIR}" || \ 418 [ ! -d "${VPX_TEST_OUTPUT_DIR}" ]; then 419 echo "${0##*/}: Cannot create output directory, giving up." 420 echo "${0##*/}: VPX_TEST_OUTPUT_DIR=${VPX_TEST_OUTPUT_DIR}" 421 exit 1 422 fi 423 424 trap cleanup EXIT 425 426 if [ "${VPX_TEST_VERBOSE_OUTPUT}" = "yes" ]; then 427 cat << EOF 428 $(basename "${0%.*}") test configuration: 429 LIBVPX_BIN_PATH=${LIBVPX_BIN_PATH} 430 LIBVPX_CONFIG_PATH=${LIBVPX_CONFIG_PATH} 431 LIBVPX_TEST_DATA_PATH=${LIBVPX_TEST_DATA_PATH} 432 VPX_TEST_OUTPUT_DIR=${VPX_TEST_OUTPUT_DIR} 433 VPX_TEST_VERBOSE_OUTPUT=${VPX_TEST_VERBOSE_OUTPUT} 434 VPX_TEST_FILTER=${VPX_TEST_FILTER} 435 VPX_TEST_RUN_DISABLED_TESTS=${VPX_TEST_RUN_DISABLED_TESTS} 436 EOF 437 fi 438