]> granicus.if.org Git - libvpx/blob - test/tools_common.sh
45b77717861b82ede51229ca07d997866fb2a4ad
[libvpx] / test / tools_common.sh
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   local tool_name="$1"
134   local tool="${LIBVPX_BIN_PATH}/${tool_name}${VPX_TEST_EXE_SUFFIX}"
135   [ -x "${tool}" ] && echo yes
136 }
137
138 # Echoes yes to stdout when vpx_config_option_enabled() reports yes for
139 # CONFIG_VP8_DECODER.
140 vp8_decode_available() {
141   [ "$(vpx_config_option_enabled CONFIG_VP8_DECODER)" = "yes" ] && echo yes
142 }
143
144 # Echoes yes to stdout when vpx_config_option_enabled() reports yes for
145 # CONFIG_VP8_ENCODER.
146 vp8_encode_available() {
147   [ "$(vpx_config_option_enabled CONFIG_VP8_ENCODER)" = "yes" ] && echo yes
148 }
149
150 # Echoes yes to stdout when vpx_config_option_enabled() reports yes for
151 # CONFIG_VP9_DECODER.
152 vp9_decode_available() {
153   [ "$(vpx_config_option_enabled CONFIG_VP9_DECODER)" = "yes" ] && echo yes
154 }
155
156 # Echoes yes to stdout when vpx_config_option_enabled() reports yes for
157 # CONFIG_VP9_ENCODER.
158 vp9_encode_available() {
159   [ "$(vpx_config_option_enabled CONFIG_VP9_ENCODER)" = "yes" ] && echo yes
160 }
161
162 # Echoes yes to stdout when vpx_config_option_enabled() reports yes for
163 # CONFIG_WEBM_IO.
164 webm_io_available() {
165   [ "$(vpx_config_option_enabled CONFIG_WEBM_IO)" = "yes" ] && echo yes
166 }
167
168 # Echoes yes to stdout when vpxdec exists according to vpx_tool_available().
169 vpxdec_available() {
170   [ -n $(vpx_tool_available vpxdec) ] && echo yes
171 }
172
173 # Wrapper function for running vpxdec in noblit mode. Requires that
174 # LIBVPX_BIN_PATH points to the directory containing vpxdec. Positional
175 # parameter one is used as the input file path. Positional parameter two, when
176 # present, is interpreted as a boolean flag that means the input should be sent
177 # to vpxdec via pipe from cat instead of directly.
178 vpxdec() {
179   local input="${1}"
180   local pipe_input=${2}
181
182   if [ $# -gt 2 ]; then
183     # shift away $1 and $2 so the remaining arguments can be passed to vpxdec
184     # via $@.
185     shift 2
186   fi
187
188   local decoder="${LIBVPX_BIN_PATH}/vpxdec${VPX_TEST_EXE_SUFFIX}"
189
190   if [ -z "${pipe_input}" ]; then
191     "${decoder}" "$input" --summary --noblit "$@" > /dev/null 2>&1
192   else
193     cat "${input}" | "${decoder}" - --summary --noblit "$@" > /dev/null 2>&1
194   fi
195 }
196
197 # Echoes yes to stdout when vpxenc exists according to vpx_tool_available().
198 vpxenc_available() {
199   [ -n $(vpx_tool_available vpxenc) ] && echo yes
200 }
201
202 # Wrapper function for running vpxenc. Positional parameters are interpreted as
203 # follows:
204 #   1 - codec name
205 #   2 - input width
206 #   3 - input height
207 #   4 - number of frames to encode
208 #   5 - path to input file
209 #   6 - path to output file
210 #       Note: The output file path must end in .ivf to output an IVF file.
211 #   7 - extra flags
212 #       Note: Extra flags currently supports a special case: when set to "-"
213 #             input is piped to vpxenc via cat.
214 vpxenc() {
215   local encoder="${LIBVPX_BIN_PATH}/vpxenc${VPX_TEST_EXE_SUFFIX}"
216   local codec="${1}"
217   local width=${2}
218   local height=${3}
219   local frames=${4}
220   local input=${5}
221   local output="${VPX_TEST_OUTPUT_DIR}/${6}"
222   local extra_flags=${7}
223
224   # Because --ivf must be within the command line to get IVF from vpxenc.
225   if echo "${output}" | egrep -q 'ivf$'; then
226     use_ivf=--ivf
227   else
228     unset use_ivf
229   fi
230
231   if [ "${extra_flags}" = "-" ]; then
232     pipe_input=yes
233     extra_flags=${8}
234   else
235     unset pipe_input
236   fi
237
238   if [ -z "${pipe_input}" ]; then
239     "${encoder}" --codec=${codec} --width=${width} --height=${height} \
240         --limit=${frames} ${use_ivf} ${extra_flags} --output="${output}" \
241         "${input}" > /dev/null 2>&1
242   else
243     cat "${input}" \
244         | "${encoder}" --codec=${codec} --width=${width} --height=${height} \
245             --limit=${frames} ${use_ivf} ${extra_flags} --output="${output}" - \
246             > /dev/null 2>&1
247   fi
248
249   if [ ! -e "${output}" ]; then
250     # Return non-zero exit status: output file doesn't exist, so something
251     # definitely went wrong.
252     return 1
253   fi
254 }
255
256 # Filters strings from positional parameter one using the filter specified by
257 # positional parameter two. Filter behavior depends on the presence of a third
258 # positional parameter. When parameter three is present, strings that match the
259 # filter are excluded. When omitted, strings matching the filter are included.
260 # The filtered string is echoed to stdout.
261 filter_strings() {
262   strings=${1}
263   filter=${2}
264   exclude=${3}
265
266   if [ -n "${exclude}" ]; then
267     # When positional parameter three exists the caller wants to remove strings.
268     # Tell grep to invert matches using the -v argument.
269     exclude='-v'
270   else
271     unset exclude
272   fi
273
274   if [ -n "${filter}" ]; then
275     for s in ${strings}; do
276       if echo "${s}" | egrep -q ${exclude} "${filter}" > /dev/null 2>&1; then
277         filtered_strings="${filtered_strings} ${s}"
278       fi
279     done
280   else
281     filtered_strings="${strings}"
282   fi
283   echo "${filtered_strings}"
284 }
285
286 # Runs user test functions passed via positional parameters one and two.
287 # Functions in positional parameter one are treated as environment verification
288 # functions and are run unconditionally. Functions in positional parameter two
289 # are run according to the rules specified in vpx_test_usage().
290 run_tests() {
291   env_tests="verify_vpx_test_environment ${1}"
292   tests_to_filter="${2}"
293
294   if [ "${VPX_TEST_RUN_DISABLED_TESTS}" != "yes" ]; then
295     # Filter out DISABLED tests.
296     tests_to_filter=$(filter_strings "${tests_to_filter}" ^DISABLED exclude)
297   fi
298
299   if [ -n "${VPX_TEST_FILTER}" ]; then
300     # Remove tests not matching the user's filter.
301     tests_to_filter=$(filter_strings "${tests_to_filter}" ${VPX_TEST_FILTER})
302   fi
303
304   tests_to_run="${env_tests} ${tests_to_filter}"
305
306   check_git_hashes
307
308   # Run tests.
309   for test in ${tests_to_run}; do
310     test_begin "${test}"
311     [ "${VPX_TEST_VERBOSE_OUTPUT}" = "yes" ] && echo "  RUN  ${test}"
312     "${test}"
313     [ "${VPX_TEST_VERBOSE_OUTPUT}" = "yes" ] && echo "  PASS ${test}"
314     test_end "${test}"
315   done
316
317   tested_config="$(test_configuration_target) @ $(current_hash)"
318   echo $(basename "${0%.*}"): Done, all tests pass for ${tested_config}.
319 }
320
321 vpx_test_usage() {
322 cat << EOF
323   Usage: ${0##*/} [arguments]
324     --bin-path <path to libvpx binaries directory>
325     --config-path <path to libvpx config directory>
326     --filter <filter>: User test filter. Only tests matching filter are run.
327     --run-disabled-tests: Run disabled tests.
328     --help: Display this message and exit.
329     --test-data-path <path to libvpx test data directory>
330     --verbose: Verbose output.
331
332     When the --bin-path option is not specified the script attempts to use
333     \$LIBVPX_BIN_PATH and then the current directory.
334
335     When the --config-path option is not specified the script attempts to use
336     \$LIBVPX_CONFIG_PATH and then the current directory.
337
338     When the -test-data-path option is not specified the script attempts to use
339     \$LIBVPX_TEST_DATA_PATH and then the current directory.
340 EOF
341 }
342
343 # Returns non-zero (failure) when required environment variables are empty
344 # strings.
345 vpx_test_check_environment() {
346   if [ -z "${LIBVPX_BIN_PATH}" ] || \
347      [ -z "${LIBVPX_CONFIG_PATH}" ] || \
348      [ -z "${LIBVPX_TEST_DATA_PATH}" ]; then
349     return 1
350   fi
351 }
352
353 # Parse the command line.
354 while [ -n "$1" ]; do
355   case "$1" in
356     --bin-path)
357       LIBVPX_BIN_PATH="$2"
358       shift
359       ;;
360     --config-path)
361       LIBVPX_CONFIG_PATH="$2"
362       shift
363       ;;
364     --filter)
365       VPX_TEST_FILTER="$2"
366       shift
367       ;;
368     --run-disabled-tests)
369       VPX_TEST_RUN_DISABLED_TESTS=yes
370       ;;
371     --help)
372       vpx_test_usage
373       exit
374       ;;
375     --test-data-path)
376       LIBVPX_TEST_DATA_PATH="$2"
377       shift
378       ;;
379     --verbose)
380       VPX_TEST_VERBOSE_OUTPUT=yes
381       ;;
382     *)
383       vpx_test_usage
384       exit 1
385       ;;
386   esac
387   shift
388 done
389
390 # Handle running the tests from a build directory without arguments when running
391 # the tests on *nix/macosx.
392 LIBVPX_BIN_PATH="${LIBVPX_BIN_PATH:-.}"
393 LIBVPX_CONFIG_PATH="${LIBVPX_CONFIG_PATH:-.}"
394 LIBVPX_TEST_DATA_PATH="${LIBVPX_TEST_DATA_PATH:-.}"
395
396 # Create a temporary directory for output files, and a trap to clean it up.
397 if [ -n "${TMPDIR}" ]; then
398   VPX_TEST_TEMP_ROOT="${TMPDIR}"
399 elif [ -n "${TEMPDIR}" ]; then
400   VPX_TEST_TEMP_ROOT="${TEMPDIR}"
401 else
402   VPX_TEST_TEMP_ROOT=/tmp
403 fi
404
405 VPX_TEST_RAND=$(awk 'BEGIN { srand(); printf "%d\n",(rand() * 32768)}')
406 VPX_TEST_OUTPUT_DIR="${VPX_TEST_TEMP_ROOT}/vpx_test_${VPX_TEST_RAND}"
407
408 if ! mkdir -p "${VPX_TEST_OUTPUT_DIR}" || \
409    [ ! -d "${VPX_TEST_OUTPUT_DIR}" ]; then
410   echo "${0##*/}: Cannot create output directory, giving up."
411   echo "${0##*/}:   VPX_TEST_OUTPUT_DIR=${VPX_TEST_OUTPUT_DIR}"
412   exit 1
413 fi
414
415 if [ "$(is_windows_target)" = "yes" ]; then
416   VPX_TEST_EXE_SUFFIX=".exe"
417 fi
418
419 # Variables shared by tests.
420 VP8_IVF_FILE="${LIBVPX_TEST_DATA_PATH}/vp80-00-comprehensive-001.ivf"
421 VP9_IVF_FILE="${LIBVPX_TEST_DATA_PATH}/vp90-2-09-subpixel-00.ivf"
422
423 VP9_WEBM_FILE="${LIBVPX_TEST_DATA_PATH}/vp90-2-00-quantizer-00.webm"
424
425 YUV_RAW_INPUT="${LIBVPX_TEST_DATA_PATH}/hantro_collage_w352h288.yuv"
426 YUV_RAW_INPUT_WIDTH=352
427 YUV_RAW_INPUT_HEIGHT=288
428
429 # Setup a trap function to clean up after tests complete.
430 trap cleanup EXIT
431
432 if [ "${VPX_TEST_VERBOSE_OUTPUT}" = "yes" ]; then
433 cat << EOF
434 $(basename "${0%.*}") test configuration:
435   LIBVPX_BIN_PATH=${LIBVPX_BIN_PATH}
436   LIBVPX_CONFIG_PATH=${LIBVPX_CONFIG_PATH}
437   LIBVPX_TEST_DATA_PATH=${LIBVPX_TEST_DATA_PATH}
438   VPX_TEST_OUTPUT_DIR=${VPX_TEST_OUTPUT_DIR}
439   VPX_TEST_VERBOSE_OUTPUT=${VPX_TEST_VERBOSE_OUTPUT}
440   VPX_TEST_FILTER=${VPX_TEST_FILTER}
441   VPX_TEST_RUN_DISABLED_TESTS=${VPX_TEST_RUN_DISABLED_TESTS}
442 EOF
443 fi