xref: /Universal-ctags/misc/units (revision aba929e40409f1000e07a83f8abfdb4501eabda4)
12b81e1e7SMasatake YAMATO#!/bin/sh
22b81e1e7SMasatake YAMATO#
32b81e1e7SMasatake YAMATO# units - Units test harness for ctags
42b81e1e7SMasatake YAMATO#
52b81e1e7SMasatake YAMATO# Copyright (C) 2014 Masatake YAMATO
62b81e1e7SMasatake YAMATO#
72b81e1e7SMasatake YAMATO# This program is free software; you can redistribute it and/or modify
82b81e1e7SMasatake YAMATO# it under the terms of the GNU General Public License as published by
97963e4b9Sviccuad# the Free Software Foundation; either version 2 of the License, or
102b81e1e7SMasatake YAMATO# (at your option) any later version.
112b81e1e7SMasatake YAMATO#
122b81e1e7SMasatake YAMATO# This program is distributed in the hope that it will be useful,
132b81e1e7SMasatake YAMATO# but WITHOUT ANY WARRANTY; without even the implied warranty of
142b81e1e7SMasatake YAMATO# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
152b81e1e7SMasatake YAMATO# GNU General Public License for more details.
162b81e1e7SMasatake YAMATO#
172b81e1e7SMasatake YAMATO# You should have received a copy of the GNU General Public License
182b81e1e7SMasatake YAMATO# along with this program.  If not, see <http://www.gnu.org/licenses/>.
192b81e1e7SMasatake YAMATO#
2072c31db2SMasatake YAMATOif test -n "${ZSH_VERSION+set}"; then
2172c31db2SMasatake YAMATO    set -o SH_WORD_SPLIT
2272c31db2SMasatake YAMATO    set +o NOMATCH
2372c31db2SMasatake YAMATOfi
242b81e1e7SMasatake YAMATO
252b81e1e7SMasatake YAMATO#
262b81e1e7SMasatake YAMATO# Global Parameters
272b81e1e7SMasatake YAMATO#
283d7a2de7SVitor AntunesSHELL=/bin/sh
292b81e1e7SMasatake YAMATOCTAGS=./ctags
305b9e0eddSMasatake YAMATOREADTAGS=./readtags
316eb4d4b5SMasatake YAMATOWITH_TIMEOUT=
32e50035ffSMasatake YAMATOWITH_VALGRIND=
33c2c83b6dSMasatake YAMATOCOLORIZED_OUTPUT=yes
34c2c83b6dSMasatake YAMATO[ -f /dev/stdout ] && COLORIZED_OUTPUT=no
359f3d1f0eSMasatake YAMATOCATEGORIES=
3636fdd421SMasatake YAMATOUNITS=
379619b798SMasatake YAMATOLANGUAGES=
38a3f9ddccSMasatake YAMATOPRETENSE_OPTS=
39c556017aSMasatake YAMATORUN_SHRINK=
409c9fadebSMasatake YAMATOQUIET=
41b8a26e30SMasatake YAMATOSHOW_DIFF_OUTPUT=
42e5399325SMasatake YAMATOVALIDATORS=
432b81e1e7SMasatake YAMATO
442b81e1e7SMasatake YAMATO#
452b81e1e7SMasatake YAMATO# Internal variables and constants
462b81e1e7SMasatake YAMATO#
472b81e1e7SMasatake YAMATO_CMDLINE=
48796e3610SMasatake YAMATO_CMDLINE_FOR_SHRINKING=
499bca788aSK.Takata_PREPERE_ENV=
50f00bd6f0SK.Takata_FEATURE_LIST=
512b81e1e7SMasatake YAMATOreadonly _DEFAULT_CATEGORY=ROOT
522b81e1e7SMasatake YAMATOreadonly _TIMEOUT_EXIT=124
532b81e1e7SMasatake YAMATOreadonly _VG_TIMEOUT_FACTOR=10
548540b3e7SMasatake YAMATOreadonly _VALGRIND_EXIT=58
55a67f3c01SMasatake YAMATOreadonly _BASH_INTERRUPT_EXIT=59
5690521286SMasatake YAMATOreadonly _LINE_SPLITTER=$(if type dos2unix > /dev/null 2>&1; then echo "dos2unix"; else echo "cat"; fi)
57db1337eaSMasatake YAMATOreadonly _STDERR_OUTPUT_NAME="STDERR.tmp"
58b8a26e30SMasatake YAMATOreadonly _DIFF_OUTPUT_NAME="DIFF.tmp"
59796e3610SMasatake YAMATOreadonly _NOISE_REPORT_MAX_COLUMN=50
608cee4794SMasatake YAMATOreadonly _VALIDATION_EXIT_INVALID=2
61e5399325SMasatake YAMATOreadonly _NOOP_VALIDATOR="NONE"
62e5399325SMasatake YAMATOreadonly _KNOWN_INVALIDATION_VALIDATOR="KNOWN-INVALIDATION"
632004d7e3SHiroo HAYASHIif stat --help >/dev/null 2>&1; then
642004d7e3SHiroo HAYASHI    readonly _FSIZE="stat -c %s" # GNU coreutils
652004d7e3SHiroo HAYASHIelse
662004d7e3SHiroo HAYASHI    readonly _FSIZE="stat -f %z" # BSD based OSes including macOS
672004d7e3SHiroo HAYASHIfi
688cee4794SMasatake YAMATO
69e5399325SMasatake YAMATO_RUNNABLE_VALIDATORS=
70e5399325SMasatake YAMATO_UNAVAILABLE_VALIDATORS=
712b81e1e7SMasatake YAMATO
722b81e1e7SMasatake YAMATO#
737d081696SK.Takata# Result files and results
742b81e1e7SMasatake YAMATO#
757d081696SK.Takatareadonly R_PASSED="_PASSED.result"
767d081696SK.Takatareadonly R_FIXED="_FIXED.result"
777d081696SK.Takatareadonly R_FAILED_BY_STATUS="_FAILED_BY_STATUS.result"
787d081696SK.Takatareadonly R_FAILED_BY_DIFF="_FAILED_BY_DIFF.result"
797d081696SK.Takatareadonly R_SKIPPED_BY_FEATURES="_SKIPPED_BY_FEATURES.result"
807d081696SK.Takatareadonly R_SKIPPED_BY_LANGUAGES="_SKIPPED_BY_LANGUAGES.result"
817d081696SK.Takatareadonly R_SKIPPED_BY_ILOOP="_SKIPPED_BY_ILOOP.result"
827d081696SK.Takatareadonly R_KNOWN_BUGS="_KNOWN_BUGS.result"
837d081696SK.Takatareadonly R_FAILED_BY_TIMEED_OUT="_FAILED_BY_TIMEED_OUT.result"
847d081696SK.Takatareadonly R_BROKEN_ARGS_CTAGS="_BROKEN_ARGS_CTAGS.result"
857d081696SK.Takatareadonly R_VALGRIND="_VALGRIND.result"
862b81e1e7SMasatake YAMATOL_PASSED=
872b81e1e7SMasatake YAMATOL_FIXED=
882b81e1e7SMasatake YAMATOL_FAILED_BY_STATUS=
892b81e1e7SMasatake YAMATOL_FAILED_BY_DIFF=
902b81e1e7SMasatake YAMATOL_SKIPPED_BY_FEATURES=
912b81e1e7SMasatake YAMATOL_SKIPPED_BY_LANGUAGES=
922b81e1e7SMasatake YAMATOL_SKIPPED_BY_ILOOP=
932b81e1e7SMasatake YAMATOL_KNOWN_BUGS=
942b81e1e7SMasatake YAMATOL_FAILED_BY_TIMEED_OUT=
9594d30755SMasatake YAMATOL_BROKEN_ARGS_CTAGS=
967d081696SK.TakataL_VALGRIND=
972b81e1e7SMasatake YAMATO
988cee4794SMasatake YAMATOV_VALID=0
998cee4794SMasatake YAMATOV_INVALID=0
100e5399325SMasatake YAMATOV_SKIP_VALIDATOR_UNAVAILABLE=0
1018cee4794SMasatake YAMATOV_SKIP_KNOWN_INVALIDATION=0
1028cee4794SMasatake YAMATO
1032b81e1e7SMasatake YAMATO#
1042b81e1e7SMasatake YAMATO# TODO
1052b81e1e7SMasatake YAMATO#
1063dce721eSMarkus Heidelberg#  * write new class 'r' (category directory) to units.rst.
10742067cf8SK.Takata#  * write new class 'v' (skip the checking by valgrind) to units.rst.
1082b81e1e7SMasatake YAMATO#
1092b81e1e7SMasatake YAMATOaction_help ()
1102b81e1e7SMasatake YAMATO{
1112b81e1e7SMasatake YAMATO    cat <<EOF
1122b81e1e7SMasatake YAMATOUsage:
1135cc6fe77SMasatake YAMATO	$(help_help)
114470fca09SMasatake YAMATO
1155cc6fe77SMasatake YAMATO	$(help_run)
116470fca09SMasatake YAMATO
1175cc6fe77SMasatake YAMATO	$(help_clean)
118470fca09SMasatake YAMATO
1196eb4d4b5SMasatake YAMATO	$(help_fuzz)
1206eb4d4b5SMasatake YAMATO
121470fca09SMasatake YAMATO	$(help_shrink)
122796e3610SMasatake YAMATO
123796e3610SMasatake YAMATO	$(help_noise)
124ec63b4a8SMasatake YAMATO
125ec63b4a8SMasatake YAMATO	$(help_tmain)
126be317af6SMasatake YAMATO
12730bea0aeSMasatake YAMATO	$(help_chop)
12830bea0aeSMasatake YAMATO
129e5399325SMasatake YAMATO	$(help_validate_input)
1308cee4794SMasatake YAMATO
131be317af6SMasatake YAMATO	$(help_clean_tmain)
1322b81e1e7SMasatake YAMATOEOF
1332b81e1e7SMasatake YAMATO}
1342b81e1e7SMasatake YAMATO
1355cc6fe77SMasatake YAMATOhelp_help()
1365cc6fe77SMasatake YAMATO{
1375cc6fe77SMasatake YAMATO    echo "$0 help|--help"
1385cc6fe77SMasatake YAMATO}
1392b81e1e7SMasatake YAMATO
1402b81e1e7SMasatake YAMATOERROR ()
1412b81e1e7SMasatake YAMATO{
14272c31db2SMasatake YAMATO    local status_="$1"
1432b81e1e7SMasatake YAMATO    local msg="$2"
1442b81e1e7SMasatake YAMATO    shift 2
1452b81e1e7SMasatake YAMATO    echo "$msg" 1>&2
14672c31db2SMasatake YAMATO    exit $status_
1472b81e1e7SMasatake YAMATO}
1482b81e1e7SMasatake YAMATO
1492b81e1e7SMasatake YAMATOline()
1502b81e1e7SMasatake YAMATO{
151c556017aSMasatake YAMATO    local c=${1:--}
152796e3610SMasatake YAMATO    local no_newline="${2}"
1532b81e1e7SMasatake YAMATO    local i=0
1542b81e1e7SMasatake YAMATO    while [ $i -lt 60 ]; do
155c556017aSMasatake YAMATO	printf "%c" "$c"
1562b81e1e7SMasatake YAMATO	i=$(( i + 1 ))
1572b81e1e7SMasatake YAMATO    done
158796e3610SMasatake YAMATO
159796e3610SMasatake YAMATO    if ! [ "${no_newline}" = "--no-newline" ]; then
1602b81e1e7SMasatake YAMATO	echo
161796e3610SMasatake YAMATO    fi
1622b81e1e7SMasatake YAMATO}
1632b81e1e7SMasatake YAMATO
1642b81e1e7SMasatake YAMATOcount_list ()
1652b81e1e7SMasatake YAMATO{
1665c9f1670SMasatake YAMATO    echo $#
1672b81e1e7SMasatake YAMATO}
1682b81e1e7SMasatake YAMATO
1699619b798SMasatake YAMATOmember_p ()
1709619b798SMasatake YAMATO{
1719619b798SMasatake YAMATO    local elt="$1"
1729619b798SMasatake YAMATO    shift
1739619b798SMasatake YAMATO    local x
1749619b798SMasatake YAMATO
1759619b798SMasatake YAMATO    for x in "$@"; do
1769619b798SMasatake YAMATO	if [ "$x" = "$elt" ]; then
1779619b798SMasatake YAMATO	    return 0
1789619b798SMasatake YAMATO	fi
1799619b798SMasatake YAMATO    done
1809619b798SMasatake YAMATO
1819619b798SMasatake YAMATO    return 1
1829619b798SMasatake YAMATO}
1839619b798SMasatake YAMATO
1842b81e1e7SMasatake YAMATOclean_tcase ()
1852b81e1e7SMasatake YAMATO{
1862b81e1e7SMasatake YAMATO    local d="$1"
1875617e54aSMasatake YAMATO    local bundles="$2"
1885617e54aSMasatake YAMATO    local b
1892b81e1e7SMasatake YAMATO
19034ff9001SMasatake YAMATO    if [ -d "$d" ]; then
1915617e54aSMasatake YAMATO	if [ -f "${bundles}" ]; then
1925617e54aSMasatake YAMATO	    while read b; do
1935617e54aSMasatake YAMATO		rm -rf "${b}"
1945617e54aSMasatake YAMATO	    done < "${bundles}"
1955617e54aSMasatake YAMATO	    rm ${bundles}
1965617e54aSMasatake YAMATO	fi
19734ff9001SMasatake YAMATO	rm -f "$d"/*.tmp "$d"/*.TMP
1982b81e1e7SMasatake YAMATO    fi
1992b81e1e7SMasatake YAMATO}
2002b81e1e7SMasatake YAMATO
2012b81e1e7SMasatake YAMATOcheck_availability()
2022b81e1e7SMasatake YAMATO{
2032b81e1e7SMasatake YAMATO    local cmd="$1"
2042b81e1e7SMasatake YAMATO    shift
2052b81e1e7SMasatake YAMATO    type "${cmd}" > /dev/null 2>&1 || ERROR 1 "${cmd} command is not available"
2062b81e1e7SMasatake YAMATO}
2072b81e1e7SMasatake YAMATO
20836fdd421SMasatake YAMATOcheck_units ()
20936fdd421SMasatake YAMATO{
21036fdd421SMasatake YAMATO    local name="$1"
21136fdd421SMasatake YAMATO    local category="$2"
21236fdd421SMasatake YAMATO    shift 2
21336fdd421SMasatake YAMATO    local u
21436fdd421SMasatake YAMATO
21536fdd421SMasatake YAMATO    for u in "$@"; do
21636fdd421SMasatake YAMATO	if echo "${u}" | grep -q /; then
21736fdd421SMasatake YAMATO	    if [ "${u%/*}" = "${category}" ] && [ "${u#*/}" = "${name}" ]; then
21836fdd421SMasatake YAMATO		return 0
21936fdd421SMasatake YAMATO	    fi
22036fdd421SMasatake YAMATO	elif [ "${u}" = "${name}" ]; then
22136fdd421SMasatake YAMATO	    return 0
22236fdd421SMasatake YAMATO	fi
22336fdd421SMasatake YAMATO    done
22436fdd421SMasatake YAMATO    return 1
22536fdd421SMasatake YAMATO}
22636fdd421SMasatake YAMATO
227f00bd6f0SK.Takatainit_features()
228f00bd6f0SK.Takata{
229f00bd6f0SK.Takata    _FEATURE_LIST=$( ${CTAGS} --quiet --options=NONE \
230f00bd6f0SK.Takata			      --list-features --with-list-header=no \
231f00bd6f0SK.Takata			      2> /dev/null \
232f00bd6f0SK.Takata		| "${_LINE_SPLITTER}" \
233f00bd6f0SK.Takata		| cut -f 1 -d ' ')
234f00bd6f0SK.Takata}
235f00bd6f0SK.Takata
2362b81e1e7SMasatake YAMATOcheck_features()
2372b81e1e7SMasatake YAMATO{
23895ac772eSMasatake YAMATO    local flag="$1"
23995ac772eSMasatake YAMATO    local ffile
24095ac772eSMasatake YAMATO    local feature
24195ac772eSMasatake YAMATO
24295ac772eSMasatake YAMATO    if [ "${flag}" = "-f" ]; then
24395ac772eSMasatake YAMATO	ffile="$2"
24495ac772eSMasatake YAMATO    elif [ "${flag}" = "-e" ]; then
24595ac772eSMasatake YAMATO	feature="$2"
24695ac772eSMasatake YAMATO    fi
24795ac772eSMasatake YAMATO    shift 2
2482b81e1e7SMasatake YAMATO
2492b81e1e7SMasatake YAMATO    local f
2502b81e1e7SMasatake YAMATO    local found
2511e019631SMasatake YAMATO    local found_unexpectedly
2522b81e1e7SMasatake YAMATO    local expected;
2532b81e1e7SMasatake YAMATO
2542b81e1e7SMasatake YAMATO
25595ac772eSMasatake YAMATO    for expected in $([ -f "$ffile" ] && cat "$ffile") ${feature}; do
2562b81e1e7SMasatake YAMATO	    found=no
2571e019631SMasatake YAMATO	    found_unexpectedly=no
258f00bd6f0SK.Takata	    for f in ${_FEATURE_LIST} ; do
2591e019631SMasatake YAMATO		[ "$expected" = "$f" ] && found=yes
2601e019631SMasatake YAMATO		[ "$expected" = '!'"$f" ] && found_unexpectedly=yes
2612b81e1e7SMasatake YAMATO	    done
2621e019631SMasatake YAMATO	    if [ "${found_unexpectedly}" = yes ]; then
2631e019631SMasatake YAMATO		echo "$expected"
2641e019631SMasatake YAMATO		return 1
2651e019631SMasatake YAMATO	    elif ! [ "$found" = yes ]; then
2662b81e1e7SMasatake YAMATO		echo "$expected"
2672b81e1e7SMasatake YAMATO		return 1
2682b81e1e7SMasatake YAMATO	    fi
26995ac772eSMasatake YAMATO    done
2702b81e1e7SMasatake YAMATO
2712b81e1e7SMasatake YAMATO    return 0
2722b81e1e7SMasatake YAMATO}
2732b81e1e7SMasatake YAMATO
2742b81e1e7SMasatake YAMATOcheck_languages()
2752b81e1e7SMasatake YAMATO{
2762b81e1e7SMasatake YAMATO    local lfile="$1"
2772b81e1e7SMasatake YAMATO    shift
2782b81e1e7SMasatake YAMATO
2792b81e1e7SMasatake YAMATO    local l
2802b81e1e7SMasatake YAMATO    local found
2812b81e1e7SMasatake YAMATO    local expected;
2822b81e1e7SMasatake YAMATO
2832b81e1e7SMasatake YAMATO
2842b81e1e7SMasatake YAMATO    #
2859619b798SMasatake YAMATO    # TODO: consider the value of LANGUAGES
2862b81e1e7SMasatake YAMATO    #
2872b81e1e7SMasatake YAMATO    while read expected; do
2882b81e1e7SMasatake YAMATO	    found=no
28990521286SMasatake YAMATO	    for l in $( ${_CMDLINE} --list-languages 2>/dev/null | "${_LINE_SPLITTER}" |sed -e 's/ //' ); do
2902b81e1e7SMasatake YAMATO		[ "$expected" = "$l" ] && found=yes
2912b81e1e7SMasatake YAMATO	    done
2922b81e1e7SMasatake YAMATO	    if ! [ "$found" = yes ]; then
2932b81e1e7SMasatake YAMATO		echo "$expected"
2942b81e1e7SMasatake YAMATO		return 1
2952b81e1e7SMasatake YAMATO	    fi
2962b81e1e7SMasatake YAMATO    done < "$lfile"
2972b81e1e7SMasatake YAMATO
2982b81e1e7SMasatake YAMATO    return 0
2992b81e1e7SMasatake YAMATO}
3002b81e1e7SMasatake YAMATO
301c6f0c07dSMasatake YAMATOdecorate ()
302c6f0c07dSMasatake YAMATO{
303c6f0c07dSMasatake YAMATO    local decorator="$1"
304c6f0c07dSMasatake YAMATO    local msg="$2"
305c6f0c07dSMasatake YAMATO
3063bdc8165SMasatake YAMATO    case "$decorator" in
3073bdc8165SMasatake YAMATO	red)    decorator=31 ;;
3083bdc8165SMasatake YAMATO	green)  decorator=32 ;;
3093bdc8165SMasatake YAMATO	yellow) decorator=33 ;;
3103bdc8165SMasatake YAMATO	*) ERROR 1 "INTERNAL ERROR: wrong run_result function: $f"
3113bdc8165SMasatake YAMATO    esac
3123bdc8165SMasatake YAMATO
313c2c83b6dSMasatake YAMATO    if [ "${COLORIZED_OUTPUT}" = 'yes' ]; then
314c6f0c07dSMasatake YAMATO	printf '%b\n' "\033[${decorator}m${msg}\033[39m"
315c6f0c07dSMasatake YAMATO    else
316c6f0c07dSMasatake YAMATO	printf '%b\n' "${msg}"
317c6f0c07dSMasatake YAMATO    fi
318c6f0c07dSMasatake YAMATO}
319c6f0c07dSMasatake YAMATO
32034ff9001SMasatake YAMATOrun_result ()
32134ff9001SMasatake YAMATO{
32234ff9001SMasatake YAMATO    local result_type="$1"
3237d081696SK.Takata    local msg="$2"
3247d081696SK.Takata    local output="$3"
3257d081696SK.Takata    shift 3
32634ff9001SMasatake YAMATO    local f="run_result_${result_type}"
32734ff9001SMasatake YAMATO    local tmp
32834ff9001SMasatake YAMATO
32934ff9001SMasatake YAMATO    type "$f" > /dev/null 2>&1 || ERROR 1 \
3307d081696SK.Takata	"${msg}INTERNAL ERROR: wrong run_result function: $f"
33134ff9001SMasatake YAMATO
3327d081696SK.Takata    "$f" "${msg}" "$@"
33334ff9001SMasatake YAMATO
33434ff9001SMasatake YAMATO    tmp="${COLORIZED_OUTPUT}"
33534ff9001SMasatake YAMATO    COLORIZED_OUTPUT=no
3367d081696SK.Takata    "$f" "${msg}" "$@" > "${output}"
33734ff9001SMasatake YAMATO    COLORIZED_OUTPUT="${tmp}"
33834ff9001SMasatake YAMATO}
33934ff9001SMasatake YAMATO
340e3d1af7eSVitor Antunesrun_result_skip ()
3412b81e1e7SMasatake YAMATO{
3427d081696SK.Takata    local msg="$1"
3437d081696SK.Takata    shift 1
3447d081696SK.Takata
345e3d1af7eSVitor Antunes    if [ -n "$1" ]; then
3467d081696SK.Takata	printf '%b%b\n' "${msg}" $(decorate yellow "skipped")" ($1)"
34748a6af74SMasatake YAMATO    else
3487d081696SK.Takata	printf '%b%b\n' "${msg}" $(decorate yellow "skipped")
349e3d1af7eSVitor Antunes    fi
350e3d1af7eSVitor Antunes}
351e3d1af7eSVitor Antunes
352e3d1af7eSVitor Antunesrun_result_error ()
353e3d1af7eSVitor Antunes{
3547d081696SK.Takata    local msg="$1"
3557d081696SK.Takata    shift 1
3567d081696SK.Takata
357e3d1af7eSVitor Antunes    if [ ! -n "$1" ]; then
3587d081696SK.Takata	printf '%b%b\n' "${msg}" $(decorate red "failed")
359e3d1af7eSVitor Antunes    else
3607d081696SK.Takata	printf '%b%b\n' "${msg}" $(decorate red "failed")" ($1)"
361e3d1af7eSVitor Antunes    fi
362e3d1af7eSVitor Antunes}
363e3d1af7eSVitor Antunes
364e3d1af7eSVitor Antunesrun_result_ok ()
365e3d1af7eSVitor Antunes{
3667d081696SK.Takata    local msg="$1"
3677d081696SK.Takata    shift 1
3687d081696SK.Takata
36959c6aafcSMasatake YAMATO    if [ ! -n "$1" ]; then
3707d081696SK.Takata	printf '%b%b\n' "${msg}" $(decorate green "passed")
37159c6aafcSMasatake YAMATO    else
3727d081696SK.Takata	printf '%b%b\n' "${msg}" $(decorate green "passed")" ($1)"
37359c6aafcSMasatake YAMATO    fi
374e3d1af7eSVitor Antunes}
375e3d1af7eSVitor Antunes
376e3d1af7eSVitor Antunesrun_result_known_error ()
377e3d1af7eSVitor Antunes{
3787d081696SK.Takata    local msg="$1"
3797d081696SK.Takata    shift 1
3807d081696SK.Takata
3817d081696SK.Takata    printf '%b%b\n' "${msg}" $(decorate yellow "failed")" (KNOWN bug)"
3822b81e1e7SMasatake YAMATO}
3832b81e1e7SMasatake YAMATO
384c556017aSMasatake YAMATOrun_shrink ()
385c556017aSMasatake YAMATO{
386c556017aSMasatake YAMATO    local cmdline_template="$1"
387c556017aSMasatake YAMATO    local input="$2"
388c556017aSMasatake YAMATO    local output="$3"
389c556017aSMasatake YAMATO    local lang="$4"
390796e3610SMasatake YAMATO    shift 4
391c556017aSMasatake YAMATO
392796e3610SMasatake YAMATO    echo "Shrinking ${input} as ${lang}"
393c556017aSMasatake YAMATO    shrink_main "${cmdline_template}" "${input}" "${output}"  1 yes
394b7dcf4feSMasatake YAMATO}
39531d9b760SMasatake YAMATO
3962f04e152SColomban Wendling# filters out the directory prefix in a ctags input
397c5eccb42SMasatake YAMATOctags_basename_filter_regex='s%\(^[^	]\{1,\}	\)\(/\{0,1\}\([^/	]\{1,\}/\)*\)%\1%'
398c77cd950SMasatake YAMATOctags_basename_filter()
3992f04e152SColomban Wendling{
400c77cd950SMasatake YAMATO    sed "${ctags_basename_filter_regex}"
401c77cd950SMasatake YAMATO}
402c77cd950SMasatake YAMATO
40365349126SMasatake YAMATO# About "input" in the expression, see units.py.
40465349126SMasatake YAMATOetags_basename_filter_regex='s%.*\/\(input[-._][[:print:]]\{1,\}\),\([0-9]\{1,\}$\)%\1,\2%'
405c77cd950SMasatake YAMATOetags_basename_filter()
406c77cd950SMasatake YAMATO{
407c77cd950SMasatake YAMATO    sed "${etags_basename_filter_regex}"
408c77cd950SMasatake YAMATO}
409c77cd950SMasatake YAMATO
4102eece520SMasatake YAMATOxref_basename_filter_regex='s%\(.*[[:digit:]]\{1,\} \)\([^ ]\{1,\}[^ ]\{1,\}\)/\([^ ].\{1,\}.\{1,\}$\)%\1\3%'
411c77cd950SMasatake YAMATOxref_basename_filter()
412c77cd950SMasatake YAMATO{
413c77cd950SMasatake YAMATO    sed "${xref_basename_filter_regex}"
4147398f54aSMasatake YAMATO}
4157398f54aSMasatake YAMATO
41627a090dfSMasatake YAMATOjson_basename_filter_regex='s%\("path": \)"[^"]\{1,\}/\([^/"]\{1,\}\)"%\1"\2"%'
41727a090dfSMasatake YAMATOjson_basename_filter()
41827a090dfSMasatake YAMATO{
41927a090dfSMasatake YAMATO    sed "${json_basename_filter_regex}"
42027a090dfSMasatake YAMATO}
42127a090dfSMasatake YAMATO
4227398f54aSMasatake YAMATOrun_record_cmdline ()
4237398f54aSMasatake YAMATO{
4247398f54aSMasatake YAMATO    local ffilter="$1"
4257398f54aSMasatake YAMATO    local ocmdline="$2"
4267398f54aSMasatake YAMATO
4279bca788aSK.Takata    printf "%s\n%s \\\\\n| %s \\\\\n| %s\n"  \
4289bca788aSK.Takata	"${_PREPERE_ENV}" \
4297398f54aSMasatake YAMATO	"${_CMDLINE}" \
430e4b28d8bSVitor Antunes	"sed '${tags_basename_filter_regex}'" \
4317398f54aSMasatake YAMATO	"${ffilter}" \
4327398f54aSMasatake YAMATO	> "${ocmdline}"
433c556017aSMasatake YAMATO}
434c556017aSMasatake YAMATO
4355617e54aSMasatake YAMATO#
4365617e54aSMasatake YAMATO# All files and directories other than input.*, expected.tags,
4375617e54aSMasatake YAMATO# args.ctags, README*, features, languages, and filters under srcdir
4385617e54aSMasatake YAMATO# are copied to builddir. These copied files are called bundles.
4395617e54aSMasatake YAMATO#
4405617e54aSMasatake YAMATOprepare_bundles ()
4415617e54aSMasatake YAMATO{
4425617e54aSMasatake YAMATO    local from=$1
4435617e54aSMasatake YAMATO    local to=$2
4445617e54aSMasatake YAMATO    local obundles=$3
4455617e54aSMasatake YAMATO    local src
4465617e54aSMasatake YAMATO    local dist
4475617e54aSMasatake YAMATO
4485617e54aSMasatake YAMATO    for src in ${from}/*; do
4495617e54aSMasatake YAMATO	if [ "${from}"'/*' = "${src}" ]; then
4505617e54aSMasatake YAMATO	    break
4515617e54aSMasatake YAMATO	fi
452cac91c56SK.Takata	case "${src##*/}" in
4535617e54aSMasatake YAMATO	    input.*)
4545617e54aSMasatake YAMATO		continue
4555617e54aSMasatake YAMATO		;;
4565617e54aSMasatake YAMATO	    expected.tags*)
4575617e54aSMasatake YAMATO		continue
4585617e54aSMasatake YAMATO		;;
4595617e54aSMasatake YAMATO	    README*)
4605617e54aSMasatake YAMATO		continue
4615617e54aSMasatake YAMATO		;;
4625617e54aSMasatake YAMATO	    features|languages|filters)
4635617e54aSMasatake YAMATO		continue
4645617e54aSMasatake YAMATO		;;
4655617e54aSMasatake YAMATO	    args.ctags)
4665617e54aSMasatake YAMATO		continue
4675617e54aSMasatake YAMATO		;;
4685617e54aSMasatake YAMATO	    *)
469cac91c56SK.Takata		dist="${to}/${src##*/}"
4703d686140SMasatake YAMATO		if ! cp -a "${src}" "${to}"; then
4715617e54aSMasatake YAMATO		    ERROR 1 "failure in copying bundle file \"${src}\" to \"${to}\""
4725617e54aSMasatake YAMATO		else
4735617e54aSMasatake YAMATO		    echo ${dist} >> ${obundles}
4745617e54aSMasatake YAMATO		fi
4755617e54aSMasatake YAMATO		;;
4765617e54aSMasatake YAMATO	esac
4775617e54aSMasatake YAMATO    done
4785617e54aSMasatake YAMATO}
4795617e54aSMasatake YAMATO
4805617e54aSMasatake YAMATOdireq ()
4815617e54aSMasatake YAMATO{
4825617e54aSMasatake YAMATO    [ "$(cd ${1} && pwd)" = "$(cd ${2} && pwd)" ]
4835617e54aSMasatake YAMATO    return $?
4845617e54aSMasatake YAMATO}
4855617e54aSMasatake YAMATO
486ddd5229aSMasatake YAMATOanon_normalize ()
487ddd5229aSMasatake YAMATO{
488ddd5229aSMasatake YAMATO    local ctags=$1
489d0ca9858SMasatake YAMATO    local input_actual
490d0ca9858SMasatake YAMATO
491d0ca9858SMasatake YAMATO    if [ -n "$2" ]; then
492d0ca9858SMasatake YAMATO	input_actual=$2
493d0ca9858SMasatake YAMATO	shift 2
494ddd5229aSMasatake YAMATO
495ddd5229aSMasatake YAMATO	# TODO: "Units" should not be hardcoded.
496ddd5229aSMasatake YAMATO	local input_expected="./Units${input_actual#*/Units}"
497ddd5229aSMasatake YAMATO
498ddd5229aSMasatake YAMATO	local actual=$(${CTAGS} --quiet --options=NONE --_anonhash="${input_actual}")
499ddd5229aSMasatake YAMATO	local expected=$(${CTAGS} --quiet --options=NONE --_anonhash="${input_expected}")
500ddd5229aSMasatake YAMATO
501d0ca9858SMasatake YAMATO	sed -e s/${actual}/${expected}/g | anon_normalize "${ctags}" "$@"
502d0ca9858SMasatake YAMATO    else
503d0ca9858SMasatake YAMATO	cat
504d0ca9858SMasatake YAMATO    fi
505ddd5229aSMasatake YAMATO}
506ddd5229aSMasatake YAMATO
5072b81e1e7SMasatake YAMATOrun_tcase ()
5082b81e1e7SMasatake YAMATO{
5092b81e1e7SMasatake YAMATO    local input="$1"
5102b81e1e7SMasatake YAMATO    local t="$2"
5112b81e1e7SMasatake YAMATO    local name="$3"
5122b81e1e7SMasatake YAMATO    local class="$4"
5132b81e1e7SMasatake YAMATO    local category="$5"
5145617e54aSMasatake YAMATO    local build_t="$6"
5155617e54aSMasatake YAMATO    shift 6
516d0ca9858SMasatake YAMATO    # The rest of arguments ($@) are extra inputs
5172b81e1e7SMasatake YAMATO
5185617e54aSMasatake YAMATO    # I violate the naming convention of build_* to reduce typing
5195617e54aSMasatake YAMATO    local o=${build_t}
5202b81e1e7SMasatake YAMATO
5212b81e1e7SMasatake YAMATO    local fargs="$t/args.ctags"
5222b81e1e7SMasatake YAMATO    local ffeatures="$t/features"
5232b81e1e7SMasatake YAMATO    local flanguages="$t/languages"
5242b81e1e7SMasatake YAMATO    local ffilter="$t/filter"
525c77cd950SMasatake YAMATO
526c77cd950SMasatake YAMATO    #
527c77cd950SMasatake YAMATO    # tags-e if for etags output(-e). TAGS is good
528c77cd950SMasatake YAMATO    # suffix but foo.tags and foo.TAGS may be the same on Windows.
52942067cf8SK.Takata    # tags-x is for cross reference output(-x).
53027a090dfSMasatake YAMATO    # tags-json is for json output.
531c77cd950SMasatake YAMATO    #
532c77cd950SMasatake YAMATO    # fexpected must be set even if none of
53327a090dfSMasatake YAMATO    # expected.{tags,tags-e,tags-x,tags-json} exits.
534c77cd950SMasatake YAMATO    #
5352b81e1e7SMasatake YAMATO    local fexpected="$t/expected.tags"
536c77cd950SMasatake YAMATO    local output_type=ctags
537c77cd950SMasatake YAMATO    local output_label=
538c77cd950SMasatake YAMATO    local output_tflag=
53995ac772eSMasatake YAMATO    local output_feature=
540d0ca9858SMasatake YAMATO    local output_lang_extras=
541d0ca9858SMasatake YAMATO
542c77cd950SMasatake YAMATO    if [ -f "$t/expected.tags" ]; then
543c77cd950SMasatake YAMATO	:
544c77cd950SMasatake YAMATO    elif [ -f "$t/expected.tags-e" ]; then
545c77cd950SMasatake YAMATO	fexpected=$t/expected.tags-e
546c77cd950SMasatake YAMATO	output_type=etags
547c77cd950SMasatake YAMATO	output_label=/${output_type}
54816322568SMasatake YAMATO	output_tflag="-e  --tag-relative=no"
549c77cd950SMasatake YAMATO    elif [ -f "$t/expected.tags-x" ]; then
550c77cd950SMasatake YAMATO	fexpected=$t/expected.tags-x
551c77cd950SMasatake YAMATO	output_type=xref
552c77cd950SMasatake YAMATO	output_label=/${output_type}
553c77cd950SMasatake YAMATO	output_tflag=-x
55427a090dfSMasatake YAMATO    elif [ -f "$t/expected.tags-json" ]; then
55527a090dfSMasatake YAMATO	fexpected=$t/expected.tags-json
55627a090dfSMasatake YAMATO	output_type=json
55727a090dfSMasatake YAMATO	output_label=/${output_type}
55827a090dfSMasatake YAMATO	output_tflag="--output-format=json"
55995ac772eSMasatake YAMATO	output_feature=json
560c77cd950SMasatake YAMATO    fi
5612b81e1e7SMasatake YAMATO
562d0ca9858SMasatake YAMATO    if [ $# -gt 0 ]; then
563d0ca9858SMasatake YAMATO	output_lang_extras=" (multi inputs)"
564d0ca9858SMasatake YAMATO    fi
565d0ca9858SMasatake YAMATO
5667398f54aSMasatake YAMATO    [ -x "$ffilter" ] || ffilter=cat
5677398f54aSMasatake YAMATO
5682b81e1e7SMasatake YAMATO    #
5692b81e1e7SMasatake YAMATO    # All generated file must have suffix ".tmp".
5702b81e1e7SMasatake YAMATO    #
571db1337eaSMasatake YAMATO    local ostderr="$o/${_STDERR_OUTPUT_NAME}"
5725617e54aSMasatake YAMATO    local orawout="$o/RAWOUT.tmp"
5735617e54aSMasatake YAMATO    local ofiltered="$o/FILTERED.tmp"
5745617e54aSMasatake YAMATO    local odiff="$o/${_DIFF_OUTPUT_NAME}"
5755617e54aSMasatake YAMATO    local ocmdline="$o/CMDLINE.tmp"
5765617e54aSMasatake YAMATO    local ovalgrind="$o/VALGRIND.tmp"
5775617e54aSMasatake YAMATO    local oresult="$o/RESULT.tmp"
5785617e54aSMasatake YAMATO    local oshrink_template="$o/SHRINK-%s.tmp"
5795617e54aSMasatake YAMATO    local obundles="$o/BUNDLES"
580c556017aSMasatake YAMATO    local oshrink
581ce426075SMasatake YAMATO
582ce426075SMasatake YAMATO    local guessed_lang
583c556017aSMasatake YAMATO    local guessed_lang_no_slash
584c556017aSMasatake YAMATO    local cmdline_template
58563d8a751SVitor Antunes    local timeout_value
5862b81e1e7SMasatake YAMATO    local tmp
5877d081696SK.Takata    local msg
5882b81e1e7SMasatake YAMATO
589dc0a530cSMasatake YAMATO    local broke_args_ctags
5902b81e1e7SMasatake YAMATO
5912b81e1e7SMasatake YAMATO    #
5922b81e1e7SMasatake YAMATO    # Filtered by UNIT
5932b81e1e7SMasatake YAMATO    #
59436fdd421SMasatake YAMATO    if [ -n "${UNITS}" ]; then
59536fdd421SMasatake YAMATO	check_units "${name}" "${category}" ${UNITS} || return 1
5962b81e1e7SMasatake YAMATO    fi
5972b81e1e7SMasatake YAMATO
5982b81e1e7SMasatake YAMATO    #
5992b81e1e7SMasatake YAMATO    # Build _CMDLINE
6002b81e1e7SMasatake YAMATO    #
601c8565aa9SMasatake YAMATO    _CMDLINE="${CTAGS} --verbose --options=NONE --fields=-T $PRETENSE_OPTS --optlib-dir=+$t/optlib -o -"
6022b81e1e7SMasatake YAMATO    [ -f "${fargs}" ] && _CMDLINE="${_CMDLINE} --options=${fargs}"
6032b81e1e7SMasatake YAMATO
60494d30755SMasatake YAMATO    if [ -f "${fargs}" ] && ! ${_CMDLINE} --_force-quit=0 > /dev/null 2>&1; then
605dc0a530cSMasatake YAMATO	broke_args_ctags=1
60694d30755SMasatake YAMATO    fi
60794d30755SMasatake YAMATO
6082b81e1e7SMasatake YAMATO    #
6099619b798SMasatake YAMATO    # Filtered by LANGUAGES
6102b81e1e7SMasatake YAMATO    #
611e4b28d8bSVitor Antunes    guessed_lang=$( ${_CMDLINE} --print-language "$input" 2>/dev/null | sed -n 's/^.*: //p')
6129619b798SMasatake YAMATO    if [ -n "${LANGUAGES}" ]; then
613ce426075SMasatake YAMATO	member_p "${guessed_lang}" ${LANGUAGES} || return 1
6142b81e1e7SMasatake YAMATO    fi
615c556017aSMasatake YAMATO    guessed_lang_no_slash=$(echo "${guessed_lang}" | tr '/' '-')
616c556017aSMasatake YAMATO    oshrink=$(printf "${oshrink_template}" "${guessed_lang_no_slash}")
6172b81e1e7SMasatake YAMATO
6185617e54aSMasatake YAMATO    clean_tcase "${o}" "${obundles}"
6195617e54aSMasatake YAMATO    mkdir -p "${o}"
6205617e54aSMasatake YAMATO    if ! direq "${o}" "${t}"; then
6215617e54aSMasatake YAMATO	prepare_bundles ${t} ${o} "${obundles}"
6225617e54aSMasatake YAMATO    fi
6235617e54aSMasatake YAMATO
6242b81e1e7SMasatake YAMATO
6257d081696SK.Takata    msg=$(printf '%-60s' "Testing ${name} as ${guessed_lang}${output_lang_extras}${output_label}")
6262b81e1e7SMasatake YAMATO
62795ac772eSMasatake YAMATO    if tmp=$( ( [ -n "${output_feature}" ] && ! check_features -e "${output_feature}" ) ||
62895ac772eSMasatake YAMATO	      ( [ -f "${ffeatures}" ] && ! check_features -f "${ffeatures}" ) ); then
6297d081696SK.Takata	echo "${category}/${name}" >> ${R_SKIPPED_BY_FEATURES}
6308de58d7aSMasatake YAMATO	case "${tmp}" in
6317d081696SK.Takata	    !*) run_result skip "${msg}" "${oresult}" "unwanted feature \"${tmp#?}\" is available";;
6327d081696SK.Takata	    *)  run_result skip "${msg}" "${oresult}" "required feature \"${tmp}\" is not available";;
6338de58d7aSMasatake YAMATO	esac
6342b81e1e7SMasatake YAMATO	return 1
6352b81e1e7SMasatake YAMATO    elif [ -f "${flanguages}" ] && ! tmp=$(check_languages "${flanguages}"); then
6367d081696SK.Takata	echo "${category}/${name}" >> ${R_SKIPPED_BY_LANGUAGES}
6377d081696SK.Takata	run_result skip "${msg}" "${oresult}" "required language parser \"$tmp\" is not available"
6382b81e1e7SMasatake YAMATO	return 1
6392b81e1e7SMasatake YAMATO    elif [ "$WITH_TIMEOUT" = 0 ] && [ "${class}" = 'i' ]; then
6407d081696SK.Takata	echo "${category}/${name}" >> ${R_SKIPPED_BY_ILOOP}
6417d081696SK.Takata	run_result skip "${msg}" "${oresult}" "may cause an infinite loop"
6422b81e1e7SMasatake YAMATO	return 1
643dc0a530cSMasatake YAMATO    elif [ "$broke_args_ctags" = 1 ]; then
6447d081696SK.Takata	run_result error "${msg}" '/dev/null' "broken args.ctags?"
6457d081696SK.Takata	echo "${category}/${name}/" >> ${R_BROKEN_ARGS_CTAGS}
646dc0a530cSMasatake YAMATO	return 1
6472b81e1e7SMasatake YAMATO    fi
6482b81e1e7SMasatake YAMATO
649c556017aSMasatake YAMATO    cmdline_template="${_CMDLINE} --language-force=${guessed_lang} %s > /dev/null 2>&1"
650d0ca9858SMasatake YAMATO    _CMDLINE="${_CMDLINE} ${output_tflag} ${input} $@"
6512b81e1e7SMasatake YAMATO
65263d8a751SVitor Antunes    timeout_value=$WITH_TIMEOUT
6532b81e1e7SMasatake YAMATO    if [ "$WITH_VALGRIND" = yes ]; then
6542335fe25SMasatake YAMATO	_CMDLINE="valgrind --leak-check=full --error-exitcode=${_VALGRIND_EXIT} --log-file=${ovalgrind} ${_CMDLINE}"
65563d8a751SVitor Antunes	timeout_value=$(( timeout_value * ${_VG_TIMEOUT_FACTOR} ))
6562b81e1e7SMasatake YAMATO    fi
6572b81e1e7SMasatake YAMATO
65863d8a751SVitor Antunes    if ! [ "$timeout_value" = 0 ]; then
65963d8a751SVitor Antunes	_CMDLINE="timeout $timeout_value ${_CMDLINE}"
6602b81e1e7SMasatake YAMATO    fi
6612b81e1e7SMasatake YAMATO
6622b81e1e7SMasatake YAMATO    {
663a67f3c01SMasatake YAMATO	(
664ed45c132SMasatake YAMATO	    #
66542067cf8SK.Takata	    # When a launched process is exited abnormally, the parent shell reports it
666ed45c132SMasatake YAMATO	    # to stderr: See j_strsignal function call in wait_for in bash-4.2/nojobs.c.
667ed45c132SMasatake YAMATO	    # This becomes noise; close the stderr of subshell.
668ed45c132SMasatake YAMATO	    #
669a67f3c01SMasatake YAMATO	    exec  2>&-;
670a67f3c01SMasatake YAMATO	    #
671a67f3c01SMasatake YAMATO	    # The original bug report(#1100 by @techee):
672a67f3c01SMasatake YAMATO	    # --------------------------------------------------------------------------
673a67f3c01SMasatake YAMATO	    # When running
674a67f3c01SMasatake YAMATO	    #
675a67f3c01SMasatake YAMATO	    #     make units VG=1
676a67f3c01SMasatake YAMATO	    #
677a67f3c01SMasatake YAMATO	    # one cannot stop its execution by pressing Ctrl+C and
678a67f3c01SMasatake YAMATO	    # there doesn't seem to be any way (except for looking at
679a67f3c01SMasatake YAMATO	    # processes which run and killing them) to stop its
680a67f3c01SMasatake YAMATO	    # execution.
681a67f3c01SMasatake YAMATO	    #
682a67f3c01SMasatake YAMATO	    trap "exit ${_BASH_INTERRUPT_EXIT}" INT;
683a67f3c01SMasatake YAMATO	    ${_CMDLINE} 2> "${ostderr}" > "${orawout}"
684a67f3c01SMasatake YAMATO	)
6852b81e1e7SMasatake YAMATO	tmp="$?"
6867398f54aSMasatake YAMATO	run_record_cmdline "${ffilter}" "${ocmdline}"
6872b81e1e7SMasatake YAMATO    }
6882b81e1e7SMasatake YAMATO    if [ "$tmp" != 0 ]; then
689a67f3c01SMasatake YAMATO	if [ "${tmp}" = "${_BASH_INTERRUPT_EXIT}" ]; then
690a67f3c01SMasatake YAMATO	    ERROR 1 "The execution is interrupted"
691a67f3c01SMasatake YAMATO	elif ! [ "$WITH_TIMEOUT" = 0 ] && [ "${tmp}" = "${_TIMEOUT_EXIT}" ]; then
6927d081696SK.Takata	    echo "${category}/${name}" >> ${R_FAILED_BY_TIMEED_OUT}
6937d081696SK.Takata	    run_result error "${msg}" "${oresult}" "TIMED OUT"
6947398f54aSMasatake YAMATO	    run_record_cmdline "${ffilter}" "${ocmdline}"
695d0ca9858SMasatake YAMATO	    [ "${RUN_SHRINK}" = 'yes' ] \
696d0ca9858SMasatake YAMATO		&& [ $# -eq 0 ] \
697d0ca9858SMasatake YAMATO		&& run_shrink "${cmdline_template}" "${input}" "${oshrink}" "${guessed_lang}"
6982b81e1e7SMasatake YAMATO	    return 1
6992b81e1e7SMasatake YAMATO	elif [ "$WITH_VALGRIND" = 'yes' ] && [ "${tmp}" = "${_VALGRIND_EXIT}" ] && ! [ "${class}" = v ]; then
7007d081696SK.Takata	    echo "${category}/${name}" >> ${R_VALGRIND}
7017d081696SK.Takata	    run_result error "${msg}" "${oresult}" "valgrind-error"
7027398f54aSMasatake YAMATO	    run_record_cmdline "${ffilter}" "${ocmdline}"
7032b81e1e7SMasatake YAMATO	    return 1
70478bec692SMasatake YAMATO	elif [ "$class" = 'b' ]; then
7057d081696SK.Takata	    echo "${category}/${name}" >> ${R_KNOWN_BUGS}
7067d081696SK.Takata	    run_result known_error "${msg}" "${oresult}"
7077398f54aSMasatake YAMATO	    run_record_cmdline "${ffilter}" "${ocmdline}"
708d0ca9858SMasatake YAMATO	    [ "${RUN_SHRINK}" = 'yes' ] \
709d0ca9858SMasatake YAMATO		&& [ $# -eq 0 ] \
710d0ca9858SMasatake YAMATO		&& run_shrink "${cmdline_template}" "${input}" "${oshrink}" "${guessed_lang}"
71178bec692SMasatake YAMATO	    return 0
7122b81e1e7SMasatake YAMATO	else
7137d081696SK.Takata	    echo "${category}/${name}" >> ${R_FAILED_BY_STATUS}
7147d081696SK.Takata	    run_result error "${msg}" "${oresult}" "unexpected exit status: $tmp"
7157398f54aSMasatake YAMATO	    run_record_cmdline "${ffilter}" "${ocmdline}"
716d0ca9858SMasatake YAMATO	    [ "${RUN_SHRINK}" = 'yes' ] \
717d0ca9858SMasatake YAMATO		&& [ $# -eq 0 ] \
718d0ca9858SMasatake YAMATO		&& run_shrink "${cmdline_template}" "${input}" "${oshrink}" "${guessed_lang}"
7192b81e1e7SMasatake YAMATO	    return 1
7202b81e1e7SMasatake YAMATO	fi
7212b81e1e7SMasatake YAMATO    elif [ "$WITH_VALGRIND" = 'yes' ] && [ "$class" = 'v' ]; then
7227d081696SK.Takata	echo "${category}/${name}" >> ${R_FIXED}
7232b81e1e7SMasatake YAMATO    fi
7242b81e1e7SMasatake YAMATO
7252b81e1e7SMasatake YAMATO    if ! [ -f "${fexpected}" ]; then
7265617e54aSMasatake YAMATO	clean_tcase "${o}" "${obundles}"
7275b6bbb48SMasatake YAMATO	if [ "$class" = 'b' ]; then
7287d081696SK.Takata	    echo "${category}/${name}" >> ${R_FIXED}
729b656f2adSMasatake YAMATO	elif [ "$class" = 'i' ]; then
7307d081696SK.Takata	    echo "${category}/${name}" >> ${R_FIXED}
7315b6bbb48SMasatake YAMATO	fi
7327d081696SK.Takata	echo "${category}/${name}" >> ${R_PASSED}
7337d081696SK.Takata	run_result ok "${msg}" '/dev/null' "\"expected.tags*\" not found"
7342b81e1e7SMasatake YAMATO	return 0
7352b81e1e7SMasatake YAMATO    fi
7362b81e1e7SMasatake YAMATO
737ddd5229aSMasatake YAMATO    ${output_type}_basename_filter < "${orawout}" | \
738d0ca9858SMasatake YAMATO	anon_normalize "${CTAGS}" "${input}" "$@" | \
739ddd5229aSMasatake YAMATO	$ffilter > "${ofiltered}"
7402b81e1e7SMasatake YAMATO
7412b81e1e7SMasatake YAMATO    {
7422b81e1e7SMasatake YAMATO	diff -U 0 -I '^!_TAG' --strip-trailing-cr "${fexpected}" "${ofiltered}" > "${odiff}"
7432b81e1e7SMasatake YAMATO	tmp="$?"
7442b81e1e7SMasatake YAMATO    }
7452b81e1e7SMasatake YAMATO    if [ "${tmp}" = 0 ]; then
7465617e54aSMasatake YAMATO	clean_tcase "${o}" "${obundles}"
7472b81e1e7SMasatake YAMATO	if [ "${class}" = 'b' ]; then
7487d081696SK.Takata	    echo "${category}/${name}" >> ${R_FIXED}
7492b81e1e7SMasatake YAMATO	elif ! [ "$WITH_TIMEOUT" = 0 ] && [ "${class}" = 'i' ]; then
7507d081696SK.Takata	    echo "${category}/${name}" >> ${R_FIXED}
7512b81e1e7SMasatake YAMATO	fi
7522b81e1e7SMasatake YAMATO
7537d081696SK.Takata	echo "${category}/${name}" >> ${R_PASSED}
7547d081696SK.Takata	run_result ok "${msg}" '/dev/null'
7552b81e1e7SMasatake YAMATO	return 0
7562b81e1e7SMasatake YAMATO    else
7572b81e1e7SMasatake YAMATO	if [ "${class}" = 'b' ]; then
7587d081696SK.Takata	    echo "${category}/${name}" >> ${R_KNOWN_BUGS}
7597d081696SK.Takata	    run_result known_error "${msg}" "${oresult}"
7607398f54aSMasatake YAMATO	    run_record_cmdline "${ffilter}" "${ocmdline}"
7612b81e1e7SMasatake YAMATO	    return 0
7622b81e1e7SMasatake YAMATO	else
7637d081696SK.Takata	    echo "${category}/${name}" >> ${R_FAILED_BY_DIFF}
7647d081696SK.Takata	    run_result error "${msg}" "${oresult}" "unexpected output"
7657398f54aSMasatake YAMATO	    run_record_cmdline "${ffilter}" "${ocmdline}"
7662b81e1e7SMasatake YAMATO	    return 1
7672b81e1e7SMasatake YAMATO	fi
7682b81e1e7SMasatake YAMATO    fi
7692b81e1e7SMasatake YAMATO}
7702b81e1e7SMasatake YAMATO
7712b81e1e7SMasatake YAMATO
77227961628SK.Takatafailure_in_globing ()
773d0ca9858SMasatake YAMATO{
77427961628SK.Takata    # skip if globing failed, also ignore backup files
775fca9cfddSleleliu008    case $1 in
776fca9cfddSleleliu008        *\~)  return 0 ;;
777fca9cfddSleleliu008        *\**) return 0 ;;
778fca9cfddSleleliu008         *)   return 1 ;;
779fca9cfddSleleliu008     esac
780d0ca9858SMasatake YAMATO}
781d0ca9858SMasatake YAMATO
7822b81e1e7SMasatake YAMATOrun_dir ()
7832b81e1e7SMasatake YAMATO{
7842b81e1e7SMasatake YAMATO    local category="$1"
7852b81e1e7SMasatake YAMATO    local base_dir="$2"
7865617e54aSMasatake YAMATO    local build_base_dir="$3"
7875617e54aSMasatake YAMATO    shift 3
7882b81e1e7SMasatake YAMATO
7892b81e1e7SMasatake YAMATO    local tcase_dir
7905617e54aSMasatake YAMATO    local build_tcase_dir
7912b81e1e7SMasatake YAMATO    local input
7922b81e1e7SMasatake YAMATO    local name
793f00bd6f0SK.Takata    local dname
7942b81e1e7SMasatake YAMATO    local class
7952b81e1e7SMasatake YAMATO
796d0ca9858SMasatake YAMATO    local extra_tmp
797d0ca9858SMasatake YAMATO    local extra_inputs
798d0ca9858SMasatake YAMATO
7992b81e1e7SMasatake YAMATO    #
8009f3d1f0eSMasatake YAMATO    # Filtered by CATEGORIES
8012b81e1e7SMasatake YAMATO    #
8029f3d1f0eSMasatake YAMATO    if [ -n "$CATEGORIES" ] && ! member_p "${category}" $CATEGORIES; then
8032b81e1e7SMasatake YAMATO	return 1
8042b81e1e7SMasatake YAMATO    fi
8052b81e1e7SMasatake YAMATO
8069f3d1f0eSMasatake YAMATO    echo
8072b81e1e7SMasatake YAMATO    echo "Category: $category"
8082b81e1e7SMasatake YAMATO    line
8092b81e1e7SMasatake YAMATO    for input in ${base_dir}/*.[dbtiv]/input.*; do
81027961628SK.Takata	if failure_in_globing "$input"; then
8112b81e1e7SMasatake YAMATO	    continue
8122b81e1e7SMasatake YAMATO	fi
8132b81e1e7SMasatake YAMATO
814f00bd6f0SK.Takata	dname=$(dirname $input)
815f00bd6f0SK.Takata	extra_inputs=$(for extra_tmp in $dname/input[-_][0-9].* \
816f00bd6f0SK.Takata					$dname/input[-_][0-9][-_]*.* ; do
81727961628SK.Takata	    if failure_in_globing "$extra_tmp"; then
818d0ca9858SMasatake YAMATO		continue
819d0ca9858SMasatake YAMATO	    fi
820d0ca9858SMasatake YAMATO	    echo "$extra_tmp"
821d0ca9858SMasatake YAMATO	done | sort)
822d0ca9858SMasatake YAMATO
8232b81e1e7SMasatake YAMATO	tcase_dir="${input%/input.*}"
8245617e54aSMasatake YAMATO	build_tcase_dir="${build_base_dir}/${tcase_dir#${base_dir}/}"
8252b81e1e7SMasatake YAMATO	name="${tcase_dir%.[dbtiv]}"
8262b81e1e7SMasatake YAMATO	name="${name##*/}"
8272b81e1e7SMasatake YAMATO	class="${tcase_dir#*${name}.}"
8287d081696SK.Takata	# Run this in parallel
8297d081696SK.Takata	run_tcase "${input}" "${tcase_dir}" "${name}" "${class}" "${category}" "${build_tcase_dir}" ${extra_inputs} &
8302b81e1e7SMasatake YAMATO    done
8317d081696SK.Takata    wait
8322b81e1e7SMasatake YAMATO
8332b81e1e7SMasatake YAMATO    return 0
8342b81e1e7SMasatake YAMATO}
8352b81e1e7SMasatake YAMATO
836b8a26e30SMasatake YAMATOrun_show_diff_output ()
837b8a26e30SMasatake YAMATO{
838b8a26e30SMasatake YAMATO    local units_dir="$1"
839b8a26e30SMasatake YAMATO    local t="$2"
840b8a26e30SMasatake YAMATO
841b8a26e30SMasatake YAMATO    printf "	"
842b8a26e30SMasatake YAMATO    line .
84375398ef1SMasatake YAMATO    sed -e 's/^.*$/	&/' ${units_dir}/${t}.*/${_DIFF_OUTPUT_NAME}
844b8a26e30SMasatake YAMATO    echo
845b8a26e30SMasatake YAMATO}
846b8a26e30SMasatake YAMATO
847db1337eaSMasatake YAMATOrun_show_stderr_output ()
848db1337eaSMasatake YAMATO{
849db1337eaSMasatake YAMATO    local units_dir="$1"
850db1337eaSMasatake YAMATO    local t="$2"
851db1337eaSMasatake YAMATO
852db1337eaSMasatake YAMATO    printf "	"
853db1337eaSMasatake YAMATO    line .
85475398ef1SMasatake YAMATO    sed -e 's/^.*$/	&/' ${units_dir}/${t}.*/${_STDERR_OUTPUT_NAME} | tail -50
855db1337eaSMasatake YAMATO    echo
856db1337eaSMasatake YAMATO}
857db1337eaSMasatake YAMATO
8582b81e1e7SMasatake YAMATOrun_summary ()
8592b81e1e7SMasatake YAMATO{
8605617e54aSMasatake YAMATO    local build_dir="${1}"
8612b81e1e7SMasatake YAMATO    local t
8622b81e1e7SMasatake YAMATO
8632b81e1e7SMasatake YAMATO    echo
8642b81e1e7SMasatake YAMATO    echo "Summary (see CMDLINE.tmp to reproduce without test harness)"
8652b81e1e7SMasatake YAMATO    line
8662b81e1e7SMasatake YAMATO
8672b81e1e7SMasatake YAMATO    printf '  %-40s' "#passed:"
8687d081696SK.Takata    L_PASSED=$([ -f $R_PASSED ] && cat $R_PASSED)
8692b81e1e7SMasatake YAMATO    count_list $L_PASSED
8702b81e1e7SMasatake YAMATO
8712b81e1e7SMasatake YAMATO    printf '  %-40s' "#FIXED:"
8727d081696SK.Takata    L_FIXED=$([ -f $R_FIXED ] && cat $R_FIXED)
8732b81e1e7SMasatake YAMATO    count_list $L_FIXED
8742b81e1e7SMasatake YAMATO    for t in $L_FIXED; do
8752b81e1e7SMasatake YAMATO	echo "	${t#${_DEFAULT_CATEGORY}/}"
8762b81e1e7SMasatake YAMATO    done
8772b81e1e7SMasatake YAMATO
87894d30755SMasatake YAMATO    printf '  %-40s' "#FAILED (broken args.ctags?):"
8797d081696SK.Takata    L_BROKEN_ARGS_CTAGS=$([ -f $R_BROKEN_ARGS_CTAGS ] && cat $R_BROKEN_ARGS_CTAGS)
88094d30755SMasatake YAMATO    count_list $L_BROKEN_ARGS_CTAGS
88194d30755SMasatake YAMATO    for t in $L_BROKEN_ARGS_CTAGS; do
88294d30755SMasatake YAMATO	echo "	${t#${_DEFAULT_CATEGORY}/}"
88394d30755SMasatake YAMATO    done
88494d30755SMasatake YAMATO
8852b81e1e7SMasatake YAMATO    printf '  %-40s' "#FAILED (unexpected-exit-status):"
8867d081696SK.Takata    L_FAILED_BY_STATUS=$([ -f $R_FAILED_BY_STATUS ] && cat $R_FAILED_BY_STATUS)
8872b81e1e7SMasatake YAMATO    count_list $L_FAILED_BY_STATUS
8882b81e1e7SMasatake YAMATO    for t in $L_FAILED_BY_STATUS; do
8892b81e1e7SMasatake YAMATO	echo "	${t#${_DEFAULT_CATEGORY}/}"
890db1337eaSMasatake YAMATO	if [ "${SHOW_DIFF_OUTPUT}" = yes ]; then
891db1337eaSMasatake YAMATO	    run_show_stderr_output "${build_dir}" "${t#${_DEFAULT_CATEGORY}/}"
892db1337eaSMasatake YAMATO	fi
8932b81e1e7SMasatake YAMATO    done
8942b81e1e7SMasatake YAMATO
8952b81e1e7SMasatake YAMATO    printf '  %-40s' "#FAILED (unexpected-output):"
8967d081696SK.Takata    L_FAILED_BY_DIFF=$([ -f $R_FAILED_BY_DIFF ] && cat $R_FAILED_BY_DIFF)
8972b81e1e7SMasatake YAMATO    count_list $L_FAILED_BY_DIFF
8982b81e1e7SMasatake YAMATO    for t in $L_FAILED_BY_DIFF; do
8992b81e1e7SMasatake YAMATO	echo "	${t#${_DEFAULT_CATEGORY}/}"
900b8a26e30SMasatake YAMATO	if [ "${SHOW_DIFF_OUTPUT}" = yes ]; then
90170b6f18bSMasatake YAMATO	    run_show_stderr_output "${build_dir}" "${t#${_DEFAULT_CATEGORY}/}"
9025617e54aSMasatake YAMATO	    run_show_diff_output "${build_dir}" "${t#${_DEFAULT_CATEGORY}/}"
903b8a26e30SMasatake YAMATO	fi
9042b81e1e7SMasatake YAMATO    done
9052b81e1e7SMasatake YAMATO
9062b81e1e7SMasatake YAMATO    if ! [ "$WITH_TIMEOUT" = 0 ]; then
90702e819bfSMasatake YAMATO	printf '  %-40s' "#TIMED-OUT (${WITH_TIMEOUT}s)"
9087d081696SK.Takata	L_FAILED_BY_TIMEED_OUT=$([ -f $R_FAILED_BY_TIMEED_OUT ] && cat $R_FAILED_BY_TIMEED_OUT)
9092b81e1e7SMasatake YAMATO	count_list $L_FAILED_BY_TIMEED_OUT
9102b81e1e7SMasatake YAMATO	for t in $L_FAILED_BY_TIMEED_OUT; do
9112b81e1e7SMasatake YAMATO	    echo "	${t#${_DEFAULT_CATEGORY}/}"
9122b81e1e7SMasatake YAMATO	done
9132b81e1e7SMasatake YAMATO    fi
9142b81e1e7SMasatake YAMATO
9152b81e1e7SMasatake YAMATO    printf '  %-40s' "#skipped (features):"
9167d081696SK.Takata    L_SKIPPED_BY_FEATURES=$([ -f $R_SKIPPED_BY_FEATURES ] && cat $R_SKIPPED_BY_FEATURES)
9172b81e1e7SMasatake YAMATO    count_list $L_SKIPPED_BY_FEATURES
9182b81e1e7SMasatake YAMATO    for t in $L_SKIPPED_BY_FEATURES; do
9192b81e1e7SMasatake YAMATO	echo "	${t#${_DEFAULT_CATEGORY}/}"
9202b81e1e7SMasatake YAMATO    done
9212b81e1e7SMasatake YAMATO
9222b81e1e7SMasatake YAMATO    printf '  %-40s' "#skipped (languages):"
9237d081696SK.Takata    L_SKIPPED_BY_LANGUAGES=$([ -f $R_SKIPPED_BY_LANGUAGES ] && cat $R_SKIPPED_BY_LANGUAGES)
9242b81e1e7SMasatake YAMATO    count_list $L_SKIPPED_BY_LANGUAGES
9252b81e1e7SMasatake YAMATO    for t in $L_SKIPPED_BY_LANGUAGES; do
9262b81e1e7SMasatake YAMATO	echo "	${t#${_DEFAULT_CATEGORY}/}"
9272b81e1e7SMasatake YAMATO    done
9282b81e1e7SMasatake YAMATO
9292b81e1e7SMasatake YAMATO    if [ "$WITH_TIMEOUT" = 0 ]; then
9302b81e1e7SMasatake YAMATO	printf '  %-40s' "#skipped (infinite-loop):"
9317d081696SK.Takata	L_SKIPPED_BY_ILOOP=$([ -f $R_SKIPPED_BY_ILOOP ] && cat $R_SKIPPED_BY_ILOOP)
9322b81e1e7SMasatake YAMATO	count_list $L_SKIPPED_BY_ILOOP
9332b81e1e7SMasatake YAMATO	for t in $L_SKIPPED_BY_ILOOP; do
9342b81e1e7SMasatake YAMATO	    echo "	${t#${_DEFAULT_CATEGORY}/}"
9352b81e1e7SMasatake YAMATO	done
9362b81e1e7SMasatake YAMATO    fi
9372b81e1e7SMasatake YAMATO
9382b81e1e7SMasatake YAMATO    printf '  %-40s' "#known-bugs:"
9397d081696SK.Takata    L_KNOWN_BUGS=$([ -f $R_KNOWN_BUGS ] && cat $R_KNOWN_BUGS)
9402b81e1e7SMasatake YAMATO    count_list $L_KNOWN_BUGS
9412b81e1e7SMasatake YAMATO    for t in $L_KNOWN_BUGS; do
9422b81e1e7SMasatake YAMATO	echo "	${t#${_DEFAULT_CATEGORY}/}"
9432b81e1e7SMasatake YAMATO    done
944b3491660SMasatake YAMATO
945fef56926SMasatake YAMATO    if [ "$WITH_VALGRIND" = yes ]; then
946b3491660SMasatake YAMATO	printf '  %-40s' "#valgrind-error:"
9477d081696SK.Takata	L_VALGRIND=$([ -f $R_VALGRIND ] && cat $R_VALGRIND)
948b3491660SMasatake YAMATO	count_list $L_VALGRIND
949b3491660SMasatake YAMATO	for t in $L_VALGRIND; do
950b3491660SMasatake YAMATO	    echo "	${t#${_DEFAULT_CATEGORY}/}"
951b3491660SMasatake YAMATO	done
952fef56926SMasatake YAMATO    fi
9532b81e1e7SMasatake YAMATO}
9542b81e1e7SMasatake YAMATO
955a3f9ddccSMasatake YAMATOmake_pretense_map ()
956a3f9ddccSMasatake YAMATO{
957a3f9ddccSMasatake YAMATO    local ifs=$IFS
958a3f9ddccSMasatake YAMATO    local p
959a3f9ddccSMasatake YAMATO    local r
960a3f9ddccSMasatake YAMATO
961a3f9ddccSMasatake YAMATO    IFS=,
962a3f9ddccSMasatake YAMATO    for p in $1; do
963a3f9ddccSMasatake YAMATO	newlang=${p%/*}
964a3f9ddccSMasatake YAMATO	oldlang=${p#*/}
965a3f9ddccSMasatake YAMATO
966a3f9ddccSMasatake YAMATO	if [ -z "$newlang" ]; then
967a3f9ddccSMasatake YAMATO	    ERROR 1 "newlang part of --pretend option arg is empty"
968a3f9ddccSMasatake YAMATO	fi
969a3f9ddccSMasatake YAMATO	if [ -z "$oldlang" ]; then
970a3f9ddccSMasatake YAMATO	    ERROR 1 "oldlang part of --pretend option arg is empty"
971a3f9ddccSMasatake YAMATO	fi
972a3f9ddccSMasatake YAMATO
973a3f9ddccSMasatake YAMATO	r="$r --_pretend-$newlang=$oldlang"
974a3f9ddccSMasatake YAMATO    done
975a3f9ddccSMasatake YAMATO    IFS=$ifs
976a3f9ddccSMasatake YAMATO    echo $r
977a3f9ddccSMasatake YAMATO}
978a3f9ddccSMasatake YAMATO
9797d081696SK.Takatadelete_result_files ()
9807d081696SK.Takata{
9817d081696SK.Takata    rm -f ${R_PASSED} ${R_FIXED} ${R_FAILED_BY_STATUS} ${R_FAILED_BY_DIFF} \
9827d081696SK.Takata	${R_SKIPPED_BY_FEATURES} ${R_SKIPPED_BY_LANGUAGES} \
9837d081696SK.Takata	${R_SKIPPED_BY_ILOOP} ${R_KNOWN_BUGS} ${R_FAILED_BY_TIMEED_OUT} \
9847d081696SK.Takata	${R_BROKEN_ARGS_CTAGS}
9857d081696SK.Takata}
9867d081696SK.Takata
9872b81e1e7SMasatake YAMATOaction_run ()
9882b81e1e7SMasatake YAMATO{
9892b81e1e7SMasatake YAMATO    local action="$1"
9902b81e1e7SMasatake YAMATO    shift
9912b81e1e7SMasatake YAMATO
9922b81e1e7SMasatake YAMATO    local units_dir
9935617e54aSMasatake YAMATO    local build_dir
9942b81e1e7SMasatake YAMATO    local d
9955617e54aSMasatake YAMATO    local build_d
9962b81e1e7SMasatake YAMATO    local category
9972b81e1e7SMasatake YAMATO
99882fe2d00SMasatake YAMATO    local c
99982fe2d00SMasatake YAMATO
10002b81e1e7SMasatake YAMATO    while [ $# -gt 0 ]; do
10012b81e1e7SMasatake YAMATO	case $1 in
10022b81e1e7SMasatake YAMATO	    --ctags)
10032b81e1e7SMasatake YAMATO		shift
10042b81e1e7SMasatake YAMATO		CTAGS="$1"
10052b81e1e7SMasatake YAMATO		shift
10062b81e1e7SMasatake YAMATO		;;
10072b81e1e7SMasatake YAMATO	    --ctags=*)
10082b81e1e7SMasatake YAMATO		CTAGS="${1#--ctags=}"
10092b81e1e7SMasatake YAMATO		shift
10102b81e1e7SMasatake YAMATO		;;
10119f3d1f0eSMasatake YAMATO	    --categories)
10122b81e1e7SMasatake YAMATO		shift
101382fe2d00SMasatake YAMATO		for c in $(echo "$1" | tr ',' ' '); do
1014884e781aSK.Takata		    if [ "$c" = "ROOT" ]; then
1015884e781aSK.Takata			CATEGORIES="$CATEGORIES ROOT"
1016884e781aSK.Takata		    else
101782fe2d00SMasatake YAMATO			CATEGORIES="$CATEGORIES ${c%.r}.r"
1018884e781aSK.Takata		    fi
101982fe2d00SMasatake YAMATO		done
10202b81e1e7SMasatake YAMATO		shift
10212b81e1e7SMasatake YAMATO		;;
10229f3d1f0eSMasatake YAMATO	    --categories=*)
102382fe2d00SMasatake YAMATO		for c in $(echo "${1#--categories=}" | tr ',' ' '); do
1024884e781aSK.Takata		    if [ "$c" = "ROOT" ]; then
1025884e781aSK.Takata			CATEGORIES="$CATEGORIES ROOT"
1026884e781aSK.Takata		    else
102782fe2d00SMasatake YAMATO			CATEGORIES="$CATEGORIES ${c%.r}.r"
1028884e781aSK.Takata		    fi
102982fe2d00SMasatake YAMATO		done
10302b81e1e7SMasatake YAMATO		shift
10312b81e1e7SMasatake YAMATO		;;
103236fdd421SMasatake YAMATO	    --units)
10332b81e1e7SMasatake YAMATO		shift
103436fdd421SMasatake YAMATO		UNITS=$(echo "$1" | tr ',' ' ')
10352b81e1e7SMasatake YAMATO		shift
10362b81e1e7SMasatake YAMATO		;;
103736fdd421SMasatake YAMATO	    --units=*)
103836fdd421SMasatake YAMATO		UNITS=$(echo "${1#--units=}" | tr ',' ' ')
10392b81e1e7SMasatake YAMATO		shift
10402b81e1e7SMasatake YAMATO		;;
10419619b798SMasatake YAMATO	    --languages)
10422b81e1e7SMasatake YAMATO		shift
10439619b798SMasatake YAMATO		LANGUAGES=$(echo "${1}" | tr ',' ' ')
10442b81e1e7SMasatake YAMATO		shift
10452b81e1e7SMasatake YAMATO		;;
10469619b798SMasatake YAMATO	    --languages=*)
10479619b798SMasatake YAMATO		LANGUAGES=$(echo "${1#--languages=}" | tr ',' ' ')
10482b81e1e7SMasatake YAMATO		shift
10492b81e1e7SMasatake YAMATO		;;
10502b81e1e7SMasatake YAMATO	    --with-timeout)
10512b81e1e7SMasatake YAMATO		shift
10522b81e1e7SMasatake YAMATO		WITH_TIMEOUT="$1"
10532b81e1e7SMasatake YAMATO		shift
10542b81e1e7SMasatake YAMATO		;;
10552b81e1e7SMasatake YAMATO	    --with-timeout=*)
10562b81e1e7SMasatake YAMATO		WITH_TIMEOUT="${1#--with-timeout=}"
10572b81e1e7SMasatake YAMATO		shift
10582b81e1e7SMasatake YAMATO		;;
10592b81e1e7SMasatake YAMATO	    --with-valgrind)
10602b81e1e7SMasatake YAMATO		shift
10612b81e1e7SMasatake YAMATO		WITH_VALGRIND=yes
10622b81e1e7SMasatake YAMATO		;;
1063c2c83b6dSMasatake YAMATO	    --colorized-output)
1064c2c83b6dSMasatake YAMATO		shift
1065c2c83b6dSMasatake YAMATO		COLORIZED_OUTPUT="$1"
1066c2c83b6dSMasatake YAMATO		shift
1067c2c83b6dSMasatake YAMATO		;;
1068c2c83b6dSMasatake YAMATO	    --colorized-output=*)
1069c2c83b6dSMasatake YAMATO		COLORIZED_OUTPUT="${1#--colorized-output=}"
1070c2c83b6dSMasatake YAMATO		shift
1071c2c83b6dSMasatake YAMATO		;;
1072c556017aSMasatake YAMATO	    --run-shrink)
1073c556017aSMasatake YAMATO		RUN_SHRINK=yes
1074c556017aSMasatake YAMATO		shift
1075c556017aSMasatake YAMATO		;;
1076b8a26e30SMasatake YAMATO	    --show-diff-output)
1077b8a26e30SMasatake YAMATO		SHOW_DIFF_OUTPUT=yes
1078b8a26e30SMasatake YAMATO		shift
1079b8a26e30SMasatake YAMATO		;;
1080a3f9ddccSMasatake YAMATO	    --with-pretense-map)
1081a3f9ddccSMasatake YAMATO		shift
1082a3f9ddccSMasatake YAMATO		PRETENSE_OPTS=$(make_pretense_map "$1")
1083a3f9ddccSMasatake YAMATO		shift
1084a3f9ddccSMasatake YAMATO		;;
1085a3f9ddccSMasatake YAMATO	    --with-pretense-map=*)
1086a3f9ddccSMasatake YAMATO		PRETENSE_OPTS=$(make_pretense_map "${1#--with-pretense-map=}")
1087a3f9ddccSMasatake YAMATO		shift
1088a3f9ddccSMasatake YAMATO		;;
10892b81e1e7SMasatake YAMATO	    -*)
10902b81e1e7SMasatake YAMATO		ERROR 1 "unknown option \"${1}\" for ${action} action"
10912b81e1e7SMasatake YAMATO		;;
10922b81e1e7SMasatake YAMATO	    *)
10932b81e1e7SMasatake YAMATO		units_dir="$1"
10942b81e1e7SMasatake YAMATO		shift
10955617e54aSMasatake YAMATO		build_dir="${1:-${units_dir}}"
10965617e54aSMasatake YAMATO		shift
1097eb9b13feSMasatake YAMATO		break
10982b81e1e7SMasatake YAMATO		;;
10992b81e1e7SMasatake YAMATO	esac
11002b81e1e7SMasatake YAMATO    done
11012b81e1e7SMasatake YAMATO
11022b81e1e7SMasatake YAMATO    if [ $# -gt 0 ]; then
11032b81e1e7SMasatake YAMATO	ERROR 1 "too many arguments for ${action} action: $*"
11042b81e1e7SMasatake YAMATO    elif [ -z "$units_dir" ]; then
11052b81e1e7SMasatake YAMATO	ERROR 1 "UNITS_DIR parameter is not given in ${action} action"
11062b81e1e7SMasatake YAMATO    fi
11072b81e1e7SMasatake YAMATO
1108e1476aceSMasatake YAMATO    if ! [ -d "$units_dir" ]; then
1109eaecf8d1SMasatake YAMATO	ERROR 1 "No such directory: ${units_dir}"
1110e1476aceSMasatake YAMATO    fi
1111e1476aceSMasatake YAMATO
11125617e54aSMasatake YAMATO    case "${build_dir}" in
11135617e54aSMasatake YAMATO	/*) ;;
11145617e54aSMasatake YAMATO	*) build_dir=$(pwd)/${build_dir} ;;
11155617e54aSMasatake YAMATO    esac
11165617e54aSMasatake YAMATO
11175617e54aSMasatake YAMATO    if ! [ -d "$build_dir" ]; then
11185617e54aSMasatake YAMATO	ERROR 1 "No such directory(build_dir): ${build_dir}"
11195617e54aSMasatake YAMATO    fi
11205617e54aSMasatake YAMATO
11212b81e1e7SMasatake YAMATO    if ! [ -f "${CTAGS}" ]; then
11222b81e1e7SMasatake YAMATO	ERROR 1 "no such file: ${CTAGS}"
11232b81e1e7SMasatake YAMATO    elif ! [ -e "${CTAGS}" ]; then
11242b81e1e7SMasatake YAMATO	ERROR 1 "${CTAGS} is not an executable file"
11252b81e1e7SMasatake YAMATO    fi
11262b81e1e7SMasatake YAMATO
1127c2c83b6dSMasatake YAMATO    if ! ( [ "${COLORIZED_OUTPUT}" = 'yes' ] || [ "${COLORIZED_OUTPUT}" = 'no' ] ); then
1128c2c83b6dSMasatake YAMATO	ERROR 1 "unexpected option argument for --colorized-output: ${COLORIZED_OUTPUT}"
1129c2c83b6dSMasatake YAMATO    fi
1130c2c83b6dSMasatake YAMATO
11312b81e1e7SMasatake YAMATO    : ${WITH_TIMEOUT:=0}
11322b81e1e7SMasatake YAMATO    [ "$WITH_TIMEOUT" = 0 ] || check_availability timeout
113390486780SK.Takata    [ "$WITH_VALGRIND" = 'yes' ] && check_availability valgrind
113475641482SK.Takata    [ "$MSYSTEM" != '' ] && check_availability dos2unix
11352b81e1e7SMasatake YAMATO    check_availability grep
11362b81e1e7SMasatake YAMATO    check_availability diff
1137f00bd6f0SK.Takata    init_features
11382b81e1e7SMasatake YAMATO
11397d081696SK.Takata    delete_result_files
11402b81e1e7SMasatake YAMATO
11412b81e1e7SMasatake YAMATO    category="${_DEFAULT_CATEGORY}"
11429f3d1f0eSMasatake YAMATO    if [ -z "$CATEGORIES" ] \
11439f3d1f0eSMasatake YAMATO	|| ( [ -n "$CATEGORIES" ] && member_p "${category}" $CATEGORIES ); then
11445617e54aSMasatake YAMATO	run_dir "${category}" "${units_dir}" "${build_dir}"
11459f3d1f0eSMasatake YAMATO    fi
11462b81e1e7SMasatake YAMATO
11472b81e1e7SMasatake YAMATO    for d in ${units_dir}/*.r; do
11482b81e1e7SMasatake YAMATO	[ -d "$d" ] || continue
11492b81e1e7SMasatake YAMATO	category="${d##*/}"
1150401dad43SMasatake YAMATO	build_d=${build_dir}/${category}
11515617e54aSMasatake YAMATO	run_dir "${category}" "$d" "${build_d}"
11522b81e1e7SMasatake YAMATO    done
11532b81e1e7SMasatake YAMATO
11545617e54aSMasatake YAMATO    run_summary "${build_dir}"
11557d081696SK.Takata    delete_result_files
11562b81e1e7SMasatake YAMATO
115794d30755SMasatake YAMATO    if [ -n "${L_FAILED_BY_STATUS}" ] ||
115894d30755SMasatake YAMATO	   [ -n "${L_FAILED_BY_DIFF}" ] ||
115994d30755SMasatake YAMATO	   [ -n "${L_FAILED_BY_TIMEED_OUT}" ] ||
116094d30755SMasatake YAMATO	   [ -n "${L_BROKEN_ARGS_CTAGS}" ]; then
11612b81e1e7SMasatake YAMATO	return 1
11622b81e1e7SMasatake YAMATO    else
11632b81e1e7SMasatake YAMATO	return 0
11642b81e1e7SMasatake YAMATO    fi
11652b81e1e7SMasatake YAMATO}
11662b81e1e7SMasatake YAMATO
11675cc6fe77SMasatake YAMATOhelp_run ()
11685cc6fe77SMasatake YAMATO{
11695cc6fe77SMasatake YAMATOcat <<EOF
11705cc6fe77SMasatake YAMATO$0 run [OPTIONS] UNITS-DIR
1171470fca09SMasatake YAMATO
1172470fca09SMasatake YAMATO	   Run all tests case under UNITS-DIR.
1173470fca09SMasatake YAMATO
11745cc6fe77SMasatake YAMATO	   OPTIONS:
11755e502075SMasanari Iida		--ctags CTAGS: ctags executable file for testing
11769f3d1f0eSMasatake YAMATO		--categories CATEGORY1[,CATEGORY2,...]: run only CATEGORY* related cases.
11779f3d1f0eSMasatake YAMATO							Category selection is done in upper
11789f3d1f0eSMasatake YAMATO							layer than unit selection. This
11799f3d1f0eSMasatake YAMATO							means even if a unit is specified
11809f3d1f0eSMasatake YAMATO							with --units, it can be ignored
11819f3d1f0eSMasatake YAMATO							is a category the units doesn't
11829f3d1f0eSMasatake YAMATO							belong to is specified with
11839f3d1f0eSMasatake YAMATO							--categories option.
1184c2c83b6dSMasatake YAMATO		--colorized-output yes|no: print the result in color.
11855cc6fe77SMasatake YAMATO		--skip NAME: skip the case NAME (TODO: NOT IMPLEMENTED YET)
1186b8a26e30SMasatake YAMATO		--languages PARSER1[,PARSER2,...]: run only PARSER* related cases.
118736fdd421SMasatake YAMATO		--units UNITS1[,UNITS2,...]: run only UNIT(S).
11885cc6fe77SMasatake YAMATO		--with-timeout DURATION: run a test case under timeout
11895cc6fe77SMasatake YAMATO					 command with SECOND.
11905cc6fe77SMasatake YAMATO					 0 means no timeout(default).
11915cc6fe77SMasatake YAMATO		--with-valgrind: run a test case under valgrind
11925cc6fe77SMasatake YAMATO			       If this option given, DURATION is changed to
11935cc6fe77SMasatake YAMATO			       DURATION := DURATION * ${_VG_TIMEOUT_FACTOR}
1194b8a26e30SMasatake YAMATO		--show-diff-output: show diff output for failed test cases in the summary.
1195a3f9ddccSMasatake YAMATO		--with-pretense-map=NEWLANG0/OLDLANG0[,...]: make NEWLANG parser pretend
1196a3f9ddccSMasatake YAMATO							     OLDLANG.
11975cc6fe77SMasatake YAMATOEOF
11985cc6fe77SMasatake YAMATO}
11995cc6fe77SMasatake YAMATO
1200e1476aceSMasatake YAMATOaction_clean ()
1201e1476aceSMasatake YAMATO{
1202e1476aceSMasatake YAMATO    local action="$1"
1203e1476aceSMasatake YAMATO    shift
1204e1476aceSMasatake YAMATO
1205e1476aceSMasatake YAMATO    local units_dir=$1
1206e1476aceSMasatake YAMATO    shift
1207e1476aceSMasatake YAMATO
120869355e1aSMasatake YAMATO    local bundles
120969355e1aSMasatake YAMATO    local b
121069355e1aSMasatake YAMATO
1211e1476aceSMasatake YAMATO    if [ $# -gt 0 ]; then
1212e1476aceSMasatake YAMATO	ERROR 1 "too many arguments for ${action} action: $*"
1213e1476aceSMasatake YAMATO    elif [ -z "$units_dir" ]; then
1214e1476aceSMasatake YAMATO	ERROR 1 "UNITS_DIR parameter is not given in ${action} action"
1215e1476aceSMasatake YAMATO    fi
1216e1476aceSMasatake YAMATO
1217e1476aceSMasatake YAMATO    if ! [ -d "$units_dir" ]; then
12187d4fe82aSK.Takata	ERROR 0 "No such directory: ${units_dir}"
1219e1476aceSMasatake YAMATO    fi
1220e1476aceSMasatake YAMATO
1221e1476aceSMasatake YAMATO    check_availability find
1222e1476aceSMasatake YAMATO    check_availability rm
1223e1476aceSMasatake YAMATO
122469355e1aSMasatake YAMATO    for bundles in $(find "$units_dir" -name "BUNDLES"); do
122569355e1aSMasatake YAMATO	while read b; do
122669355e1aSMasatake YAMATO	    rm -rf "${b}"
122769355e1aSMasatake YAMATO	done < ${bundles}
122869355e1aSMasatake YAMATO	rm ${bundles}
122969355e1aSMasatake YAMATO    done
123069355e1aSMasatake YAMATO
1231e1476aceSMasatake YAMATO    rm -f $(find "$units_dir" -name '*.tmp')
1232e1476aceSMasatake YAMATO    rm -f $(find "$units_dir" -name '*.TMP')
1233e1476aceSMasatake YAMATO    return 0
1234e1476aceSMasatake YAMATO}
1235e1476aceSMasatake YAMATO
12365cc6fe77SMasatake YAMATOhelp_clean ()
12375cc6fe77SMasatake YAMATO{
1238470fca09SMasatake YAMATOcat <<EOF
1239470fca09SMasatake YAMATO$0 clean UNITS-DIR
1240470fca09SMasatake YAMATO
1241be317af6SMasatake YAMATO	   Clean all files created during units testing
1242470fca09SMasatake YAMATOEOF
1243470fca09SMasatake YAMATO
12445cc6fe77SMasatake YAMATO}
12455cc6fe77SMasatake YAMATO
1246470fca09SMasatake YAMATOshrink_prepare ()
1247470fca09SMasatake YAMATO{
1248470fca09SMasatake YAMATO    local output="$1"
1249470fca09SMasatake YAMATO    local input="$2"
1250470fca09SMasatake YAMATO    local start="$3"
1251470fca09SMasatake YAMATO    local len="$4"
1252470fca09SMasatake YAMATO
1253470fca09SMasatake YAMATO
1254470fca09SMasatake YAMATO    dd bs=1 count="${len}" skip="${start}" < "${input}" 2>/dev/null > "${output}"
1255470fca09SMasatake YAMATO}
1256470fca09SMasatake YAMATO
1257470fca09SMasatake YAMATOshrink_test ()
1258470fca09SMasatake YAMATO{
1259470fca09SMasatake YAMATO    local cmdline="$1"
1260470fca09SMasatake YAMATO    local input="$2"
1261470fca09SMasatake YAMATO    local start="$3"
1262470fca09SMasatake YAMATO    local len="$4"
1263470fca09SMasatake YAMATO    local output="$5"
1264470fca09SMasatake YAMATO    local r
1265c556017aSMasatake YAMATO    local msg
1266470fca09SMasatake YAMATO
1267470fca09SMasatake YAMATO    shrink_prepare "${output}" "${input}" "${start}" "${len}"
12689c9fadebSMasatake YAMATO    [ "${QUIET}" = 'yes' ] || printf "[%-5u %6u]..." "${start}" $(( start + len )) 1>&2
1269796e3610SMasatake YAMATO    eval "${cmdline}" > /dev/null 2>&1
1270470fca09SMasatake YAMATO    r="$?"
1271c556017aSMasatake YAMATO    if [ "$r" -eq 0 ]; then
1272c556017aSMasatake YAMATO	msg='ok'
1273c556017aSMasatake YAMATO    elif [ "$r" -eq "${_TIMEOUT_EXIT}" ]; then
1274c556017aSMasatake YAMATO	msg='timeout'
1275c556017aSMasatake YAMATO    else
1276c556017aSMasatake YAMATO	msg='failed'
1277c556017aSMasatake YAMATO    fi
12789c9fadebSMasatake YAMATO    [ "${QUIET}" = 'yes' ] || printf "%s(%u)\n" "$msg" "$r" 1>&2
1279470fca09SMasatake YAMATO    return $r
1280470fca09SMasatake YAMATO}
1281470fca09SMasatake YAMATO
1282470fca09SMasatake YAMATOshrink_bisect ()
1283470fca09SMasatake YAMATO{
1284470fca09SMasatake YAMATO    local cmdline="$1"
1285470fca09SMasatake YAMATO    local input="$2"
1286470fca09SMasatake YAMATO    local len="$3"
1287470fca09SMasatake YAMATO    local output="$4"
1288470fca09SMasatake YAMATO
1289470fca09SMasatake YAMATO    local end
1290470fca09SMasatake YAMATO    local start
1291470fca09SMasatake YAMATO    local step
1292470fca09SMasatake YAMATO    local delta
1293470fca09SMasatake YAMATO
1294470fca09SMasatake YAMATO    local failed
1295470fca09SMasatake YAMATO    local successful
1296470fca09SMasatake YAMATO
1297470fca09SMasatake YAMATO    end="${len}"
1298470fca09SMasatake YAMATO    failed="${len}"
1299470fca09SMasatake YAMATO    successful=0
1300470fca09SMasatake YAMATO
1301470fca09SMasatake YAMATO    step=0
1302470fca09SMasatake YAMATO    while true; do
1303470fca09SMasatake YAMATO	delta=$((len >> (step + 1)))
1304470fca09SMasatake YAMATO	if [ "${delta}" -eq 0 ]; then
1305470fca09SMasatake YAMATO	    delta=1
1306470fca09SMasatake YAMATO	fi
1307470fca09SMasatake YAMATO	if shrink_test "${cmdline}" "${input}" 0 "${end}" "${output}"; then
1308470fca09SMasatake YAMATO	    successful="${end}"
1309470fca09SMasatake YAMATO	    if [ $(( end + 1 )) -eq "${failed}" ]; then
1310470fca09SMasatake YAMATO		end="${failed}"
1311470fca09SMasatake YAMATO		break
1312470fca09SMasatake YAMATO	    else
1313470fca09SMasatake YAMATO		end=$((end + delta))
1314470fca09SMasatake YAMATO	    fi
1315470fca09SMasatake YAMATO	else
1316470fca09SMasatake YAMATO	    failed="$end"
1317470fca09SMasatake YAMATO	    if [ $(( successful + 1 )) -eq "${end}" ]; then
1318470fca09SMasatake YAMATO		break
1319470fca09SMasatake YAMATO	    else
1320470fca09SMasatake YAMATO		end=$((end - delta))
1321470fca09SMasatake YAMATO	    fi
1322470fca09SMasatake YAMATO	fi
1323470fca09SMasatake YAMATO	step=$((step + 1 ))
1324470fca09SMasatake YAMATO    done
1325470fca09SMasatake YAMATO
1326470fca09SMasatake YAMATO    len="${end}"
1327470fca09SMasatake YAMATO    start=0
1328470fca09SMasatake YAMATO    failed=0
1329470fca09SMasatake YAMATO    successful="${end}"
1330470fca09SMasatake YAMATO    step=0
1331470fca09SMasatake YAMATO    while true; do
1332470fca09SMasatake YAMATO	delta=$((len >> (step + 1)))
1333470fca09SMasatake YAMATO	if [ "${delta}" -eq 0 ]; then
1334470fca09SMasatake YAMATO	    delta=1
1335470fca09SMasatake YAMATO	fi
1336470fca09SMasatake YAMATO	if shrink_test "${cmdline}" "${input}" "${start}" $((end - start)) "${output}"; then
1337470fca09SMasatake YAMATO	    successful="${start}"
1338470fca09SMasatake YAMATO	    if [ $(( start - 1 )) -eq "${failed}" ]; then
1339470fca09SMasatake YAMATO		start=$((start - 1))
1340470fca09SMasatake YAMATO		break
1341470fca09SMasatake YAMATO	    else
1342470fca09SMasatake YAMATO		start=$((start - delta))
1343470fca09SMasatake YAMATO	    fi
1344470fca09SMasatake YAMATO	else
1345470fca09SMasatake YAMATO	    failed="${start}"
1346470fca09SMasatake YAMATO	    if [ $((successful - 1)) -eq "${start}" ]; then
1347470fca09SMasatake YAMATO		break
1348470fca09SMasatake YAMATO	    else
1349470fca09SMasatake YAMATO		start=$((start + delta))
1350470fca09SMasatake YAMATO	    fi
1351470fca09SMasatake YAMATO	fi
1352470fca09SMasatake YAMATO	step=$((step + 1))
1353470fca09SMasatake YAMATO    done
1354470fca09SMasatake YAMATO
1355470fca09SMasatake YAMATO    len=$((end - start))
1356470fca09SMasatake YAMATO    shrink_prepare "${output}" "${input}" "${start}" "${len}"
1357796e3610SMasatake YAMATO    [ "${QUIET}" = 'yes' ] || echo "Minimal badinput: ${output}"
13589c9fadebSMasatake YAMATO    [ "${QUIET}" = 'yes' ] || line .
1359470fca09SMasatake YAMATO    cat "${output}"
1360470fca09SMasatake YAMATO    echo
1361470fca09SMasatake YAMATO
1362470fca09SMasatake YAMATO    return 0
1363470fca09SMasatake YAMATO}
1364470fca09SMasatake YAMATO
1365470fca09SMasatake YAMATOshrink_main ()
1366470fca09SMasatake YAMATO{
1367470fca09SMasatake YAMATO    local cmdline_template="$1"
1368470fca09SMasatake YAMATO    local cmdline
1369470fca09SMasatake YAMATO    local input="$2"
1370470fca09SMasatake YAMATO    local len
1371470fca09SMasatake YAMATO    local output="$3"
1372470fca09SMasatake YAMATO    local duration="$4"
1373470fca09SMasatake YAMATO    local foreground="$5"
1374470fca09SMasatake YAMATO
1375470fca09SMasatake YAMATO    if ! [ -f "${input}" ]; then
1376470fca09SMasatake YAMATO	ERROR 1 "No such file: ${input}"
1377470fca09SMasatake YAMATO    elif ! [ -r "${input}" ]; then
1378470fca09SMasatake YAMATO	ERROR 1 "Cannot read a file: ${input}"
1379470fca09SMasatake YAMATO    fi
1380470fca09SMasatake YAMATO
1381470fca09SMasatake YAMATO    if ! cat < /dev/null > "${output}"; then
1382470fca09SMasatake YAMATO	ERROR 1 "Cannot modify a file: ${output}"
1383470fca09SMasatake YAMATO    fi
1384470fca09SMasatake YAMATO
1385470fca09SMasatake YAMATO    cmdline=$(printf "${cmdline_template}" "${output}")
1386470fca09SMasatake YAMATO    if [ -n "${duration}" ] && ! [ "${duration}" -eq 0 ]; then
1387470fca09SMasatake YAMATO	if [ "${foreground}" = 'yes' ]; then
1388470fca09SMasatake YAMATO	    cmdline="timeout --foreground ${duration} ${cmdline}"
1389470fca09SMasatake YAMATO	else
1390470fca09SMasatake YAMATO	    cmdline="timeout ${duration} ${cmdline}"
1391470fca09SMasatake YAMATO	fi
1392470fca09SMasatake YAMATO    fi
1393470fca09SMasatake YAMATO
13942004d7e3SHiroo HAYASHI    len=$(${_FSIZE} "${input}")
1395470fca09SMasatake YAMATO
1396470fca09SMasatake YAMATO    if shrink_test "${cmdline}" "${input}" 0 "${len}" "${output}"; then
1397470fca09SMasatake YAMATO	printf "the target command line exits normally against the original input\n" 1>&2
1398470fca09SMasatake YAMATO	return 1
1399470fca09SMasatake YAMATO    fi
1400470fca09SMasatake YAMATO
1401470fca09SMasatake YAMATO    if ! shrink_test "${cmdline}" "${input}" 0 0 "${output}"; then
1402ecac33f6SMasatake YAMATO	printf "the target command line exits abnormally against the empty input\n" 1>&2
1403470fca09SMasatake YAMATO	return 1
1404470fca09SMasatake YAMATO    fi
1405470fca09SMasatake YAMATO
1406470fca09SMasatake YAMATO    shrink_bisect "${cmdline}" "${input}" "${len}" "${output}"
1407470fca09SMasatake YAMATO}
1408470fca09SMasatake YAMATO
1409470fca09SMasatake YAMATOaction_shrink ()
1410470fca09SMasatake YAMATO{
1411470fca09SMasatake YAMATO    local action="$1"
1412470fca09SMasatake YAMATO    shift
1413470fca09SMasatake YAMATO
1414470fca09SMasatake YAMATO    local cmdline_template
1415470fca09SMasatake YAMATO    local input
1416470fca09SMasatake YAMATO    local output
1417470fca09SMasatake YAMATO
1418470fca09SMasatake YAMATO    local timeout
1419470fca09SMasatake YAMATO    local duration
1420470fca09SMasatake YAMATO    local foreground
1421470fca09SMasatake YAMATO
1422470fca09SMasatake YAMATO
1423470fca09SMasatake YAMATO    while [ $# -gt 0 ]; do
1424470fca09SMasatake YAMATO	case $1 in
1425470fca09SMasatake YAMATO	    --timeout)
1426470fca09SMasatake YAMATO		shift
1427470fca09SMasatake YAMATO		duration=$1
1428470fca09SMasatake YAMATO		shift
1429470fca09SMasatake YAMATO		;;
1430470fca09SMasatake YAMATO	    --timeout=*)
1431470fca09SMasatake YAMATO		duration="${1#--timeout=}"
1432470fca09SMasatake YAMATO		shift
1433470fca09SMasatake YAMATO		;;
1434470fca09SMasatake YAMATO	    --foreground)
1435470fca09SMasatake YAMATO		foreground=yes
1436470fca09SMasatake YAMATO		shift
1437470fca09SMasatake YAMATO		;;
14389c9fadebSMasatake YAMATO	    --quiet)
14399c9fadebSMasatake YAMATO		QUIET=yes
14409c9fadebSMasatake YAMATO		shift
14419c9fadebSMasatake YAMATO		;;
1442470fca09SMasatake YAMATO	    -*)
1443470fca09SMasatake YAMATO		ERROR 1 "unknown option \"${1}\" for ${action} action"
1444470fca09SMasatake YAMATO		;;
1445470fca09SMasatake YAMATO	    *)
1446470fca09SMasatake YAMATO		break
1447470fca09SMasatake YAMATO		;;
1448470fca09SMasatake YAMATO	    esac
1449470fca09SMasatake YAMATO    done
1450470fca09SMasatake YAMATO
1451470fca09SMasatake YAMATO    if [ $# -lt 3 ]; then
1452470fca09SMasatake YAMATO	ERROR 1 "too few arguments for ${action} action: $*"
1453470fca09SMasatake YAMATO    elif [ $# -gt 3 ]; then
1454470fca09SMasatake YAMATO	ERROR 1 "too many arguments for ${action} action: $*"
1455470fca09SMasatake YAMATO    fi
1456470fca09SMasatake YAMATO
1457470fca09SMasatake YAMATO    if [ -n "${foreground}" ] && [ -z "${duration}" ]; then
1458470fca09SMasatake YAMATO	ERROR 1 "--foreground option is meaningful only if --timeout option is specified."
1459470fca09SMasatake YAMATO    fi
1460470fca09SMasatake YAMATO
1461470fca09SMasatake YAMATO    cmdline_template=$1
1462470fca09SMasatake YAMATO    input=$2
1463470fca09SMasatake YAMATO    output=$3
1464470fca09SMasatake YAMATO    shift 3
1465470fca09SMasatake YAMATO
1466470fca09SMasatake YAMATO    shrink_main "${cmdline_template}" "${input}" "${output}" ${duration} ${foreground}
1467470fca09SMasatake YAMATO    return $?
1468470fca09SMasatake YAMATO}
1469470fca09SMasatake YAMATO
1470470fca09SMasatake YAMATOhelp_shrink ()
1471470fca09SMasatake YAMATO{
1472470fca09SMasatake YAMATOcat <<EOF
1473470fca09SMasatake YAMATO$0 shrink [OPTIONS] CMD_TEMPLATE INPUT OUTPUT
1474470fca09SMasatake YAMATO
1475470fca09SMasatake YAMATO	   Shrink the input while the execution of CMD_TEMPLATE is failed
1476470fca09SMasatake YAMATO	   and find minimal unwanted input.
1477470fca09SMasatake YAMATO
1478470fca09SMasatake YAMATO	   OPTIONS:
1479470fca09SMasatake YAMATO		--timeout N: Run CMD under timeout command with duration N
1480470fca09SMasatake YAMATO		--foreground: add --foreground option to timeout command.
1481470fca09SMasatake YAMATO			      can be used with --timeout option.
14822750d4d8SMasatake YAMATO	   EXAMPLES:
14832750d4d8SMasatake YAMATO		misc/units shrink "u-ctags -o - %s" original-input.js  /tmp/anyname.js
1484470fca09SMasatake YAMATOEOF
1485470fca09SMasatake YAMATO}
1486470fca09SMasatake YAMATO#action_shrink shrink --timeout=1 --foreground "./a.out  < %s" input.txt output.txt
1487470fca09SMasatake YAMATO
14886eb4d4b5SMasatake YAMATOfuzz_shrink ()
14896eb4d4b5SMasatake YAMATO{
14906eb4d4b5SMasatake YAMATO    local cmdline_template="$1"
14916eb4d4b5SMasatake YAMATO    local input="$2"
14926eb4d4b5SMasatake YAMATO    local output="$3"
14936eb4d4b5SMasatake YAMATO    local lang="$4"
1494796e3610SMasatake YAMATO    shift 4
14956eb4d4b5SMasatake YAMATO
1496796e3610SMasatake YAMATO    [ "${QUIET}" = 'yes' ] || {
1497796e3610SMasatake YAMATO	echo "Shrinking ${input} as ${lang}"
1498796e3610SMasatake YAMATO	line .
1499796e3610SMasatake YAMATO    }
15006eb4d4b5SMasatake YAMATO    shrink_main "${cmdline_template}" "${input}" "${output}"  1 yes
15016eb4d4b5SMasatake YAMATO}
15026eb4d4b5SMasatake YAMATO
15036eb4d4b5SMasatake YAMATOfuzz_lang_file ()
15046eb4d4b5SMasatake YAMATO{
15056eb4d4b5SMasatake YAMATO    local lang="$1"
15066eb4d4b5SMasatake YAMATO    local file="$2"
15076eb4d4b5SMasatake YAMATO    shift 2
15086eb4d4b5SMasatake YAMATO    local r
15096eb4d4b5SMasatake YAMATO
15106eb4d4b5SMasatake YAMATO    local dir="${file%/*}"
15116eb4d4b5SMasatake YAMATO    local ovalgrind="${dir}/VALGRIND-${lang}.tmp"
15126eb4d4b5SMasatake YAMATO    local ocmdline="${dir}/CMDLINE-${lang}.tmp"
15136eb4d4b5SMasatake YAMATO    local oshrink="${dir}/SHRINK-${lang}.tmp"
15146eb4d4b5SMasatake YAMATO
15156eb4d4b5SMasatake YAMATO    local cmdline
15166eb4d4b5SMasatake YAMATO    local cmdline_for_shirking
15176eb4d4b5SMasatake YAMATO
15186eb4d4b5SMasatake YAMATO    rm -f "${ovalgrind}" "${ocmdline}" "${oshrink}"
15196eb4d4b5SMasatake YAMATO
15206eb4d4b5SMasatake YAMATO
15216eb4d4b5SMasatake YAMATO    if [ "${WITH_VALGRIND}" = 'yes' ]; then
15226eb4d4b5SMasatake YAMATO	cmdline=$( printf "${_CMDLINE} --language-force=${lang} ${file}" "${ovalgrind}" )
15236eb4d4b5SMasatake YAMATO    else
15246eb4d4b5SMasatake YAMATO	cmdline="${_CMDLINE} --language-force=${lang} ${file}"
15256eb4d4b5SMasatake YAMATO
15266eb4d4b5SMasatake YAMATO    fi
15276eb4d4b5SMasatake YAMATO    cmdline_for_shirking="${_CMDLINE_FOR_SHRINKING} --language-force=${lang} %s"
15286eb4d4b5SMasatake YAMATO
15296eb4d4b5SMasatake YAMATO
15306eb4d4b5SMasatake YAMATO    [ "${QUIET}" = 'yes' ] || printf "."
15316eb4d4b5SMasatake YAMATO    echo "${cmdline}" > "${ocmdline}"
15325ac5884bSMasatake YAMATO    ${cmdline} > /dev/null
15336eb4d4b5SMasatake YAMATO    r=$?
15346eb4d4b5SMasatake YAMATO
15356eb4d4b5SMasatake YAMATO    case $r in
15366eb4d4b5SMasatake YAMATO	0)
15371c2e2c12SMasatake YAMATO	    rm -f "${ovalgrind}" "${ocmdline}"
15386eb4d4b5SMasatake YAMATO	    return 0
15396eb4d4b5SMasatake YAMATO	    ;;
15406eb4d4b5SMasatake YAMATO	${_TIMEOUT_EXIT})
15416eb4d4b5SMasatake YAMATO	    [ "${QUIET}" = 'yes' ] || echo
15426eb4d4b5SMasatake YAMATO	    printf '%-40s' "[timeout $lang]"
15436eb4d4b5SMasatake YAMATO	    echo "$f"
1544796e3610SMasatake YAMATO	    [ "${RUN_SHRINK}" = 'yes' ] && fuzz_shrink "${cmdline_for_shirking}" "${file}" "${oshrink}" "${lang}"
15456eb4d4b5SMasatake YAMATO	    return 1
15466eb4d4b5SMasatake YAMATO	    ;;
15476eb4d4b5SMasatake YAMATO	${_VALGRIND_EXIT})
15486eb4d4b5SMasatake YAMATO	    [ "${QUIET}" = 'yes' ] || echo
15496eb4d4b5SMasatake YAMATO	    printf '%-40s' "[valgrind-error $lang]"
15506eb4d4b5SMasatake YAMATO	    echo "$f"
15516eb4d4b5SMasatake YAMATO	    return 1
15526eb4d4b5SMasatake YAMATO	    ;;
15536eb4d4b5SMasatake YAMATO	*)
15546eb4d4b5SMasatake YAMATO	    [ "${QUIET}" = 'yes' ] || echo
15556eb4d4b5SMasatake YAMATO	    printf '%-40s' "[unexpected-status($r) $lang]"
15566eb4d4b5SMasatake YAMATO	    echo "$f"
1557796e3610SMasatake YAMATO	    [ "${RUN_SHRINK}" = 'yes' ] && fuzz_shrink "${cmdline_for_shirking}" "${file}" "${oshrink}" "${lang}"
15586eb4d4b5SMasatake YAMATO	    return 1
15596eb4d4b5SMasatake YAMATO	    ;;
15606eb4d4b5SMasatake YAMATO    esac
15616eb4d4b5SMasatake YAMATO
15626eb4d4b5SMasatake YAMATO    return $r
15636eb4d4b5SMasatake YAMATO}
15646eb4d4b5SMasatake YAMATO
15656eb4d4b5SMasatake YAMATOfuzz_lang ()
15666eb4d4b5SMasatake YAMATO{
15676eb4d4b5SMasatake YAMATO    local lang="$1"
15686eb4d4b5SMasatake YAMATO    local dir="$2"
15696eb4d4b5SMasatake YAMATO    shift 2
15706eb4d4b5SMasatake YAMATO    local f
15719038d055SColomban Wendling    local r=0
15726eb4d4b5SMasatake YAMATO
15736eb4d4b5SMasatake YAMATO    [ "${QUIET}" = 'yes' ] || printf '%-60s\n' "Semi-fuzzing (${lang})"
15746eb4d4b5SMasatake YAMATO    for f in $(find "${dir}" -type f -name 'input.*'); do
15759038d055SColomban Wendling	if ! fuzz_lang_file "${lang}" "${f}"; then
15769038d055SColomban Wendling	    r=1
15779038d055SColomban Wendling	    break
15789038d055SColomban Wendling	fi
15796eb4d4b5SMasatake YAMATO    done
15806eb4d4b5SMasatake YAMATO    [ "${QUIET}" = 'yes' ] || echo
15819038d055SColomban Wendling    return $r
15826eb4d4b5SMasatake YAMATO}
15836eb4d4b5SMasatake YAMATO
15846eb4d4b5SMasatake YAMATOaction_fuzz ()
15856eb4d4b5SMasatake YAMATO{
1586796e3610SMasatake YAMATO    action_fuzz_common fuzz_lang "$@"
1587796e3610SMasatake YAMATO}
1588796e3610SMasatake YAMATO
1589796e3610SMasatake YAMATOaction_fuzz_common ()
1590796e3610SMasatake YAMATO{
1591796e3610SMasatake YAMATO    local fn="$1"
1592796e3610SMasatake YAMATO    local action="$2"
1593796e3610SMasatake YAMATO    shift 2
15946eb4d4b5SMasatake YAMATO
15956eb4d4b5SMasatake YAMATO    local units_dir
15966eb4d4b5SMasatake YAMATO    local cmdline
15976eb4d4b5SMasatake YAMATO    local lang
1598796e3610SMasatake YAMATO    local r
15996eb4d4b5SMasatake YAMATO
16006eb4d4b5SMasatake YAMATO    while [ $# -gt 0 ]; do
16016eb4d4b5SMasatake YAMATO	case $1 in
16026eb4d4b5SMasatake YAMATO	    --ctags)
16036eb4d4b5SMasatake YAMATO		shift
16046eb4d4b5SMasatake YAMATO		CTAGS="$1"
16056eb4d4b5SMasatake YAMATO		shift
16066eb4d4b5SMasatake YAMATO		;;
16076eb4d4b5SMasatake YAMATO	    --ctags=*)
16086eb4d4b5SMasatake YAMATO		CTAGS="${1#--ctags=}"
16096eb4d4b5SMasatake YAMATO		shift
16106eb4d4b5SMasatake YAMATO		;;
16116eb4d4b5SMasatake YAMATO	    --languages)
16126eb4d4b5SMasatake YAMATO		shift
16136eb4d4b5SMasatake YAMATO		LANGUAGES=$(echo "${1}" | tr ',' ' ')
16146eb4d4b5SMasatake YAMATO		shift
16156eb4d4b5SMasatake YAMATO		;;
16166eb4d4b5SMasatake YAMATO	    --languages=*)
16176eb4d4b5SMasatake YAMATO		LANGUAGES=$(echo "${1#--languages=}" | tr ',' ' ')
16186eb4d4b5SMasatake YAMATO		shift
16196eb4d4b5SMasatake YAMATO		;;
16206eb4d4b5SMasatake YAMATO	    --quiet)
16216eb4d4b5SMasatake YAMATO		QUIET=yes
16226eb4d4b5SMasatake YAMATO		shift
16236eb4d4b5SMasatake YAMATO		;;
16246eb4d4b5SMasatake YAMATO	    --with-timeout)
16256eb4d4b5SMasatake YAMATO		shift
16266eb4d4b5SMasatake YAMATO		WITH_TIMEOUT="$1"
16276eb4d4b5SMasatake YAMATO		shift
16286eb4d4b5SMasatake YAMATO		;;
16296eb4d4b5SMasatake YAMATO	    --with-timeout=*)
16306eb4d4b5SMasatake YAMATO		WITH_TIMEOUT="${1#--with-timeout=}"
16316eb4d4b5SMasatake YAMATO		shift
16326eb4d4b5SMasatake YAMATO		;;
16336eb4d4b5SMasatake YAMATO	    --with-valgrind)
16346eb4d4b5SMasatake YAMATO		shift
16356eb4d4b5SMasatake YAMATO		WITH_VALGRIND=yes
16366eb4d4b5SMasatake YAMATO		;;
16376eb4d4b5SMasatake YAMATO	    --colorized-output)
16386eb4d4b5SMasatake YAMATO		shift
16396eb4d4b5SMasatake YAMATO		COLORIZED_OUTPUT="$1"
16406eb4d4b5SMasatake YAMATO		shift
16416eb4d4b5SMasatake YAMATO		;;
16426eb4d4b5SMasatake YAMATO	    --colorized-output=*)
16436eb4d4b5SMasatake YAMATO		COLORIZED_OUTPUT="${1#--colorized-output=}"
16446eb4d4b5SMasatake YAMATO		shift
16456eb4d4b5SMasatake YAMATO		;;
16466eb4d4b5SMasatake YAMATO	    --run-shrink)
16476eb4d4b5SMasatake YAMATO		RUN_SHRINK=yes
16486eb4d4b5SMasatake YAMATO		shift
16496eb4d4b5SMasatake YAMATO		;;
16506eb4d4b5SMasatake YAMATO	    -*)
16516eb4d4b5SMasatake YAMATO		ERROR 1 "unknown option \"${1}\" for ${action} action"
16526eb4d4b5SMasatake YAMATO		;;
16536eb4d4b5SMasatake YAMATO	    *)
16546eb4d4b5SMasatake YAMATO		units_dir="$1"
16556eb4d4b5SMasatake YAMATO		shift
16566eb4d4b5SMasatake YAMATO		break;
16576eb4d4b5SMasatake YAMATO		;;
16586eb4d4b5SMasatake YAMATO	esac
16596eb4d4b5SMasatake YAMATO    done
16606eb4d4b5SMasatake YAMATO
16616eb4d4b5SMasatake YAMATO    if [ $# -gt 0 ]; then
16626eb4d4b5SMasatake YAMATO	ERROR 1 "too many arguments for ${action} action: $*"
16636eb4d4b5SMasatake YAMATO    elif [ -z "$units_dir" ]; then
16646eb4d4b5SMasatake YAMATO	ERROR 1 "UNITS_DIR parameter is not given in ${action} action"
16656eb4d4b5SMasatake YAMATO    fi
16666eb4d4b5SMasatake YAMATO
16676eb4d4b5SMasatake YAMATO    if ! [ -d "$units_dir" ]; then
16687d4fe82aSK.Takata	ERROR 0 "No such directory: ${units_dir}"
16696eb4d4b5SMasatake YAMATO    fi
16706eb4d4b5SMasatake YAMATO
16716eb4d4b5SMasatake YAMATO    if ! [ -f "${CTAGS}" ]; then
16726eb4d4b5SMasatake YAMATO	ERROR 1 "no such file: ${CTAGS}"
16736eb4d4b5SMasatake YAMATO    elif ! [ -e "${CTAGS}" ]; then
16746eb4d4b5SMasatake YAMATO	ERROR 1 "${CTAGS} is not an executable file"
16756eb4d4b5SMasatake YAMATO    fi
16766eb4d4b5SMasatake YAMATO
16776eb4d4b5SMasatake YAMATO    if ! ( [ "${COLORIZED_OUTPUT}" = 'yes' ] || [ "${COLORIZED_OUTPUT}" = 'no' ] ); then
16786eb4d4b5SMasatake YAMATO	ERROR 1 "unexpected option argument for --colorized-output: ${COLORIZED_OUTPUT}"
16796eb4d4b5SMasatake YAMATO    fi
16806eb4d4b5SMasatake YAMATO
1681796e3610SMasatake YAMATO    : ${WITH_TIMEOUT:=2}
16826eb4d4b5SMasatake YAMATO    [ "$WITH_TIMEOUT" = 0 ] || check_availability timeout
168390486780SK.Takata    [ "$WITH_VALGRIND" = 'yes' ] && check_availability valgrind
16846eb4d4b5SMasatake YAMATO    check_availability find
16856eb4d4b5SMasatake YAMATO
16865ac5884bSMasatake YAMATO    cmdline="${CTAGS} --quiet --options=NONE --kinds-all=* --fields=*"
1687e17e5821SMasatake YAMATO    _CMDLINE="${cmdline} -G -o - "
16886eb4d4b5SMasatake YAMATO    _CMDLINE_FOR_SHRINKING="${_CMDLINE}"
16896eb4d4b5SMasatake YAMATO    if [ "$WITH_VALGRIND" = yes ]; then
16902335fe25SMasatake YAMATO	_CMDLINE="valgrind --leak-check=full --error-exitcode=${_VALGRIND_EXIT} --log-file=%s ${_CMDLINE}"
16916eb4d4b5SMasatake YAMATO	WITH_TIMEOUT=$(( WITH_TIMEOUT * ${_VG_TIMEOUT_FACTOR} ))
16926eb4d4b5SMasatake YAMATO    fi
16936eb4d4b5SMasatake YAMATO
16946eb4d4b5SMasatake YAMATO    if ! [ "$WITH_TIMEOUT" = 0 ]; then
16956eb4d4b5SMasatake YAMATO	_CMDLINE="timeout --foreground $WITH_TIMEOUT ${_CMDLINE}"
16966eb4d4b5SMasatake YAMATO	_CMDLINE_FOR_SHRINKING="timeout --foreground 1 ${_CMDLINE_FOR_SHRINKING}"
16976eb4d4b5SMasatake YAMATO    fi
16986eb4d4b5SMasatake YAMATO
169990521286SMasatake YAMATO    for lang in $( ${cmdline} --list-languages 2>/dev/null | "${_LINE_SPLITTER}" |sed -e 's/ //' ) ; do
17006eb4d4b5SMasatake YAMATO	if [ -n "${LANGUAGES}" ] && ! member_p "${lang}" ${LANGUAGES}; then
17016eb4d4b5SMasatake YAMATO	    continue
17026eb4d4b5SMasatake YAMATO	fi
1703796e3610SMasatake YAMATO	"${fn}" "${lang}" "${units_dir}"
1704796e3610SMasatake YAMATO	r=$?
17056eb4d4b5SMasatake YAMATO    done
1706796e3610SMasatake YAMATO
1707796e3610SMasatake YAMATO    return $r
17086eb4d4b5SMasatake YAMATO}
17096eb4d4b5SMasatake YAMATO
17106eb4d4b5SMasatake YAMATOhelp_fuzz ()
17116eb4d4b5SMasatake YAMATO{
17126eb4d4b5SMasatake YAMATOcat <<EOF
17136eb4d4b5SMasatake YAMATO$0 fuzz [OPTIONS] UNITS-DIR
17146eb4d4b5SMasatake YAMATO
17156eb4d4b5SMasatake YAMATO	   Run all tests case under UNITS-DIR.
17166eb4d4b5SMasatake YAMATO
17176eb4d4b5SMasatake YAMATO	   OPTIONS:
17185e502075SMasanari Iida		--ctags CTAGS: ctags executable file for testing
17196eb4d4b5SMasatake YAMATO		--languages PARSER1[,PARSER2,...]: run only PARSER* related cases
17206eb4d4b5SMasatake YAMATO		--quiet: don't print dots as passed test cases.
17216eb4d4b5SMasatake YAMATO		--with-timeout DURATION: run a test case under timeout
17226eb4d4b5SMasatake YAMATO					 command with SECOND.
17236eb4d4b5SMasatake YAMATO					 0 means no timeout.
17246eb4d4b5SMasatake YAMATO					 default is 1.
17256eb4d4b5SMasatake YAMATO		--with-valgrind: run a test case under valgrind
17266eb4d4b5SMasatake YAMATO			       If this option given, DURATION is changed to
17276eb4d4b5SMasatake YAMATO			       DURATION := DURATION * ${_VG_TIMEOUT_FACTOR}
17286eb4d4b5SMasatake YAMATOEOF
17296eb4d4b5SMasatake YAMATO}
17306eb4d4b5SMasatake YAMATO
1731796e3610SMasatake YAMATOnoise_reduce ()
1732796e3610SMasatake YAMATO{
1733796e3610SMasatake YAMATO    local input="$1"
1734796e3610SMasatake YAMATO    local len="$2"
1735796e3610SMasatake YAMATO    local pos="$3"
1736796e3610SMasatake YAMATO    shift 3
1737796e3610SMasatake YAMATO
1738796e3610SMasatake YAMATO    dd bs=1 count=$pos skip=0 if="$input"
1739796e3610SMasatake YAMATO    dd bs=1 count=$(( len - pos - 1 )) skip=$(( pos + 1 )) if="$input"
1740796e3610SMasatake YAMATO}
1741796e3610SMasatake YAMATO
1742796e3610SMasatake YAMATOnoise_inject ()
1743796e3610SMasatake YAMATO{
1744796e3610SMasatake YAMATO    local input="$1"
1745796e3610SMasatake YAMATO    local len="$2"
1746796e3610SMasatake YAMATO    local pos="$3"
1747796e3610SMasatake YAMATO    local c="$4"
1748796e3610SMasatake YAMATO    shift 4
1749796e3610SMasatake YAMATO
1750796e3610SMasatake YAMATO    dd bs=1 count=$pos skip=0 if="$input"
1751796e3610SMasatake YAMATO    printf "%c" "$c"
1752796e3610SMasatake YAMATO    dd bs=1 count=$(( len - pos )) skip=$pos if="$input"
1753796e3610SMasatake YAMATO}
1754796e3610SMasatake YAMATO
1755796e3610SMasatake YAMATOnoise_report_line ()
1756796e3610SMasatake YAMATO{
1757796e3610SMasatake YAMATO    local pos="$1"
1758796e3610SMasatake YAMATO    local len="$2"
175972c31db2SMasatake YAMATO    local status_="$3"
1760796e3610SMasatake YAMATO    local how="$4"
1761796e3610SMasatake YAMATO
1762796e3610SMasatake YAMATO    local progress_offset=$(( pos % _NOISE_REPORT_MAX_COLUMN ))
1763796e3610SMasatake YAMATO    local nspace
1764796e3610SMasatake YAMATO
1765796e3610SMasatake YAMATO
176672c31db2SMasatake YAMATO    if [ $((pos + 1)) -eq "${len}" ] || [ $status_ -gt 0 ]; then
1767796e3610SMasatake YAMATO	nspace=0
1768796e3610SMasatake YAMATO	while [ $nspace -lt $(( _NOISE_REPORT_MAX_COLUMN - progress_offset - 1)) ]; do
1769796e3610SMasatake YAMATO	    printf ' '
1770796e3610SMasatake YAMATO	    nspace=$((nspace + 1))
1771796e3610SMasatake YAMATO	done
1772796e3610SMasatake YAMATO	printf " %s %d/%d" "${how}" "$pos" "${len}"
1773796e3610SMasatake YAMATO    fi
1774796e3610SMasatake YAMATO}
1775796e3610SMasatake YAMATO
1776796e3610SMasatake YAMATOnoise_lang_file_noisespec ()
1777796e3610SMasatake YAMATO{
1778796e3610SMasatake YAMATO    local input="$1"
1779796e3610SMasatake YAMATO    local len="$2"
1780796e3610SMasatake YAMATO    local pos="$3"
1781796e3610SMasatake YAMATO    local c="$4"
1782796e3610SMasatake YAMATO    local genfn="$5"
1783796e3610SMasatake YAMATO    local lang="$6"
1784796e3610SMasatake YAMATO    local how="$7"
1785796e3610SMasatake YAMATO    shift 7
1786796e3610SMasatake YAMATO
1787796e3610SMasatake YAMATO    local msg
1788796e3610SMasatake YAMATO    if [ "${how}" = + ]; then
1789796e3610SMasatake YAMATO	msg=INJECTED
1790796e3610SMasatake YAMATO	how="${how}${c}"
1791796e3610SMasatake YAMATO    else
1792796e3610SMasatake YAMATO	msg=REDUCED
1793796e3610SMasatake YAMATO	how="${how} "
1794796e3610SMasatake YAMATO    fi
1795796e3610SMasatake YAMATO
1796796e3610SMasatake YAMATO    local dir="${input%/*}"
1797796e3610SMasatake YAMATO    local onoised=$(printf "%s/NOISE-INPUT-%s-%s-%d.tmp" "${dir}" "${msg}" "$pos" \'$c)
1798796e3610SMasatake YAMATO    local ocmdline=$(printf "%s/NOISE-CMDLINE-%s-%s-%d.tmp" "${dir}" "${msg}" "$pos" \'$c)
1799796e3610SMasatake YAMATO    local ovalgrind=$(printf "%s/NOISE-VALGRIND-%s-%s-%d.tmp" "${dir}" "${msg}" "$pos" \'$c)
1800796e3610SMasatake YAMATO    local oshrink=$(printf "%s/NOISE-SHRINK-%s-%s-%d.tmp" "${dir}" "${msg}" "$pos" \'$c)
1801796e3610SMasatake YAMATO
1802796e3610SMasatake YAMATO    local cmdline
1803796e3610SMasatake YAMATO    local cmdline_for_shirking
1804796e3610SMasatake YAMATO    local progress_offset
1805796e3610SMasatake YAMATO    local r
1806796e3610SMasatake YAMATO
1807796e3610SMasatake YAMATO    rm -f "${ocmdline}" "${ovalgrind}" "${onoised}" "${oshrink}"
1808796e3610SMasatake YAMATO    if [ "${WITH_VALGRIND}" = 'yes' ]; then
1809796e3610SMasatake YAMATO	cmdline=$( printf "${_CMDLINE} --language-force=${lang} ${onoised}" "${ovalgrind}" )
1810796e3610SMasatake YAMATO	else
1811796e3610SMasatake YAMATO	cmdline="${_CMDLINE} --language-force=${lang} ${onoised}"
1812796e3610SMasatake YAMATO    fi
1813796e3610SMasatake YAMATO    cmdline_for_shirking="${_CMDLINE_FOR_SHRINKING} --language-force=${lang} %s"
1814796e3610SMasatake YAMATO
1815796e3610SMasatake YAMATO    "${genfn}" "${input}" "${len}" "$pos" "$c" > "$onoised"  2> /dev/null
1816796e3610SMasatake YAMATO
1817796e3610SMasatake YAMATO    progress_offset=$(( pos % _NOISE_REPORT_MAX_COLUMN ))
1818796e3610SMasatake YAMATO    if [ "${progress_offset}" -eq 0 ]; then
1819796e3610SMasatake YAMATO	[ $pos -gt 0 ] && printf " %s %d/%d" "${how}" "$pos" "${len}"
1820796e3610SMasatake YAMATO	echo
1821796e3610SMasatake YAMATO    fi
1822796e3610SMasatake YAMATO
1823796e3610SMasatake YAMATO    echo "${cmdline}" > "${ocmdline}"
1824796e3610SMasatake YAMATO    ( exec 2>&-; ${cmdline} 2> /dev/null > /dev/null )
1825796e3610SMasatake YAMATO    r=$?
1826796e3610SMasatake YAMATO    case $r in
1827796e3610SMasatake YAMATO	    0)
1828796e3610SMasatake YAMATO	    printf 'o'
1829796e3610SMasatake YAMATO	    noise_report_line "${pos}" "${len}" "${r}" "${how}"
1830796e3610SMasatake YAMATO	    rm "${onoised}"
1831796e3610SMasatake YAMATO	    rm -f "${ovalgrind}" "${ocmdline}"
1832796e3610SMasatake YAMATO	    ;;
1833796e3610SMasatake YAMATO	${_TIMEOUT_EXIT})
1834796e3610SMasatake YAMATO	    printf "T"
1835796e3610SMasatake YAMATO	    noise_report_line "${pos}" "${len}" "${r}" "${how}"
1836cb7fd27dSMasatake YAMATO	    printf '\n%-20s\n' "[timeout $lang]" "$onoised"
1837796e3610SMasatake YAMATO	    [ "${RUN_SHRINK}" = 'yes' ] && fuzz_shrink "${cmdline_for_shirking}" "${onoised}" "${oshrink}" "${lang}"
1838796e3610SMasatake YAMATO	    ;;
1839796e3610SMasatake YAMATO	${_VALGRIND_EXIT})
1840796e3610SMasatake YAMATO	    printf "V"
1841796e3610SMasatake YAMATO	    noise_report_line "${pos}" "${len}" "${r}" "${how}"
1842796e3610SMasatake YAMATO	    printf '\n%-20s %s\n' "[valgrind-error $lang]" "$onoised"
1843796e3610SMasatake YAMATO	    ;;
1844796e3610SMasatake YAMATO	*)
1845796e3610SMasatake YAMATO	    printf "!"
1846796e3610SMasatake YAMATO	    noise_report_line "${pos}" "${len}" "${r}" "${how}"
1847796e3610SMasatake YAMATO	    printf '\n%-20s %s\n' "[unexpected-status($r) $lang]" "$onoised"
1848796e3610SMasatake YAMATO	    [ "${RUN_SHRINK}" = 'yes' ] && fuzz_shrink "${cmdline_for_shirking}" "${onoised}" "${oshrink}" "${lang}"
1849796e3610SMasatake YAMATO	    ;;
1850796e3610SMasatake YAMATO    esac
1851796e3610SMasatake YAMATO    return $r
1852796e3610SMasatake YAMATO}
1853796e3610SMasatake YAMATO
1854796e3610SMasatake YAMATOnoise_lang_file ()
1855796e3610SMasatake YAMATO{
1856796e3610SMasatake YAMATO    local lang="$1"
1857796e3610SMasatake YAMATO    local input="$2"
1858796e3610SMasatake YAMATO    shift 2
1859796e3610SMasatake YAMATO
1860796e3610SMasatake YAMATO
1861796e3610SMasatake YAMATO    local cmdline
1862796e3610SMasatake YAMATO    local cmdline_for_shirking
18632004d7e3SHiroo HAYASHI    local len=$(${_FSIZE} "${input}")
1864796e3610SMasatake YAMATO    local r
1865796e3610SMasatake YAMATO    local i
1866796e3610SMasatake YAMATO    local c
1867796e3610SMasatake YAMATO    local guessed_lang
1868796e3610SMasatake YAMATO
1869e4b28d8bSVitor Antunes    guessed_lang=$( ${_CMDLINE_FOR_SHRINKING} --print-language "${input}" 2>/dev/null | sed -n 's/^.*: //p')
1870796e3610SMasatake YAMATO    if [ "${lang}" !=  "${guessed_lang}" ]; then
1871796e3610SMasatake YAMATO	return 0
1872796e3610SMasatake YAMATO    fi
1873796e3610SMasatake YAMATO
1874796e3610SMasatake YAMATO    i=0
1875796e3610SMasatake YAMATO    c='!'
1876796e3610SMasatake YAMATO    echo "Testing cases derived from: ${input}"
1877796e3610SMasatake YAMATO    line '.' --no-newline
1878796e3610SMasatake YAMATO    while [ "$i" -lt "$len" ]; do
1879796e3610SMasatake YAMATO	if noise_lang_file_noisespec "${input}" "${len}" "$i" "$c" noise_reduce "${lang}" -; then
1880796e3610SMasatake YAMATO	    i=$(( i + 1 ))
1881796e3610SMasatake YAMATO	else
1882796e3610SMasatake YAMATO	    echo
1883796e3610SMasatake YAMATO	    return 1
1884796e3610SMasatake YAMATO	fi
1885796e3610SMasatake YAMATO    done
1886796e3610SMasatake YAMATO
1887796e3610SMasatake YAMATO    for c in 'a' '0'						\
1888796e3610SMasatake YAMATO	'!' '@' '#' '$' '%' '^' '&' '*' '(' ')' '-' '=' '_'	\
1889796e3610SMasatake YAMATO	'+' '|'  '[' ']' '{' '}' '\' ';' "'" ':' '"' ',' '.'    \
1890796e3610SMasatake YAMATO	'/' '<' '>' '?' '`' '~'; do
1891796e3610SMasatake YAMATO	i=0
1892796e3610SMasatake YAMATO	while [ "$i" -lt "$len" ]; do
1893796e3610SMasatake YAMATO	    if noise_lang_file_noisespec "${input}" "${len}" "$i" "$c" noise_inject "${lang}" +; then
1894796e3610SMasatake YAMATO		i=$(( i + 1 ))
1895796e3610SMasatake YAMATO	    else
1896796e3610SMasatake YAMATO		echo
1897796e3610SMasatake YAMATO		return 1
1898796e3610SMasatake YAMATO	    fi
1899796e3610SMasatake YAMATO	done
1900796e3610SMasatake YAMATO    done
1901796e3610SMasatake YAMATO    echo
190214fe4d40SMasatake YAMATO    return 0
1903796e3610SMasatake YAMATO}
1904796e3610SMasatake YAMATO
1905796e3610SMasatake YAMATOnoise_lang ()
1906796e3610SMasatake YAMATO{
1907796e3610SMasatake YAMATO    local lang="$1"
1908796e3610SMasatake YAMATO    local dir="$2"
1909796e3610SMasatake YAMATO    shift 2
1910796e3610SMasatake YAMATO    local f
1911796e3610SMasatake YAMATO    local r
1912796e3610SMasatake YAMATO    printf '%-60s\n' "Noised-fuzzing (${lang})"
1913796e3610SMasatake YAMATO    line '-'
1914796e3610SMasatake YAMATO
1915796e3610SMasatake YAMATO    r=0
1916796e3610SMasatake YAMATO    for f in $(find "${dir}" -type f -name 'input.*'); do
1917796e3610SMasatake YAMATO	if ! noise_lang_file "${lang}" "${f}"; then
1918796e3610SMasatake YAMATO	    r=1
1919796e3610SMasatake YAMATO	    break
1920796e3610SMasatake YAMATO	fi
1921796e3610SMasatake YAMATO    done
1922796e3610SMasatake YAMATO    echo
1923796e3610SMasatake YAMATO    return $r
1924796e3610SMasatake YAMATO}
1925796e3610SMasatake YAMATO
1926796e3610SMasatake YAMATOaction_noise ()
1927796e3610SMasatake YAMATO{
1928796e3610SMasatake YAMATO    action_fuzz_common noise_lang "$@"
1929796e3610SMasatake YAMATO}
1930796e3610SMasatake YAMATO
1931796e3610SMasatake YAMATOhelp_noise ()
1932796e3610SMasatake YAMATO{
1933796e3610SMasatake YAMATOcat <<EOF
1934796e3610SMasatake YAMATO$0 noise [OPTIONS] UNITS-DIR
1935796e3610SMasatake YAMATO
1936796e3610SMasatake YAMATO	   Run all tests case for LANGUAGE with "noise" for
19375e502075SMasanari Iida	   finding unexpected behavior like entering an
1938796e3610SMasatake YAMATO	   infinite loop.
1939796e3610SMasatake YAMATO	   Here "noise" means removing one byte from
1940796e3610SMasatake YAMATO	   somewhere file position of the original test case;
1941796e3610SMasatake YAMATO	   or adding something one byte to
1942796e3610SMasatake YAMATO	   somewhere file position of the original test case.
1943796e3610SMasatake YAMATO
1944796e3610SMasatake YAMATO	   OPTIONS:
19455e502075SMasanari Iida		--ctags CTAGS: ctags executable file for testing
1946796e3610SMasatake YAMATO		--languages PARSER1[,PARSER2,...]: run only PARSER* related cases
1947796e3610SMasatake YAMATO		--quiet: don't print dots as passed test cases.
1948796e3610SMasatake YAMATO		--with-timeout DURATION: run a test case under timeout
1949796e3610SMasatake YAMATO					 command with SECOND.
1950796e3610SMasatake YAMATO					 0 means no timeout.
1951796e3610SMasatake YAMATO					 default is 1.
1952796e3610SMasatake YAMATO		--with-valgrind: run a test case under valgrind
1953796e3610SMasatake YAMATO			       If this option given, DURATION is changed to
1954796e3610SMasatake YAMATO			       DURATION := DURATION * ${_VG_TIMEOUT_FACTOR}
1955796e3610SMasatake YAMATOEOF
1956796e3610SMasatake YAMATO}
1957796e3610SMasatake YAMATO
1958ec63b4a8SMasatake YAMATO
195901b068cdSMasatake YAMATOtmain_compare_result()
196001b068cdSMasatake YAMATO{
196101b068cdSMasatake YAMATO    local build_topdir=$1
196201b068cdSMasatake YAMATO    local f
196301b068cdSMasatake YAMATO
196401b068cdSMasatake YAMATO    for f in ${build_topdir}/*/*-diff.txt; do
196501b068cdSMasatake YAMATO	if [ -f "$f" ]; then
196601b068cdSMasatake YAMATO	    echo "$f"
196701b068cdSMasatake YAMATO	    echo
196875398ef1SMasatake YAMATO	    cat "$f" | sed -e 's|.*|	&|'
196901b068cdSMasatake YAMATO	    echo
197001b068cdSMasatake YAMATO	fi
197101b068cdSMasatake YAMATO    done
19725d0eaa0bSMasatake YAMATO    if [ -f ${build_topdir}/*/gdb-backtrace.txt ]; then
19735d0eaa0bSMasatake YAMATO	cat ${build_topdir}/*/gdb-backtrace.txt
19745d0eaa0bSMasatake YAMATO    fi
197501b068cdSMasatake YAMATO}
197601b068cdSMasatake YAMATO
1977ec63b4a8SMasatake YAMATOtmain_compare()
1978ec63b4a8SMasatake YAMATO{
1979ec63b4a8SMasatake YAMATO    local subdir=$1
1980f64af9fcSMasatake YAMATO    local build_subdir=$2
1981f64af9fcSMasatake YAMATO    local aspect=$3
1982ec63b4a8SMasatake YAMATO    local generated
19837d081696SK.Takata    local msg
1984ec63b4a8SMasatake YAMATO
19857d081696SK.Takata    msg=$(printf '%-60s' "${aspect}")
1986f64af9fcSMasatake YAMATO    generated=${build_subdir}/${aspect}-diff.txt
1987f64af9fcSMasatake YAMATO    if diff -U 0 --strip-trailing-cr \
1988f64af9fcSMasatake YAMATO	    ${subdir}/${aspect}-expected.txt \
1989a91961f0SHiroo HAYASHI	    ${build_subdir}/${aspect}-actual.txt \
1990f64af9fcSMasatake YAMATO	    > ${generated} 2>&1; then
19917d081696SK.Takata	run_result ok "${msg}" '/dev/null'
1992ec63b4a8SMasatake YAMATO	rm ${generated}
1993ec63b4a8SMasatake YAMATO	return 0
1994ec63b4a8SMasatake YAMATO    else
19957d081696SK.Takata	run_result error "${msg}" '/dev/null' "diff: ${generated}"
1996ec63b4a8SMasatake YAMATO	return 1
1997ec63b4a8SMasatake YAMATO    fi
1998ec63b4a8SMasatake YAMATO}
1999ec63b4a8SMasatake YAMATO
2000ea1cc174SMasatake YAMATOfailed_git_marker ()
2001ea1cc174SMasatake YAMATO{
2002ea1cc174SMasatake YAMATO    local f=$1
2003ea1cc174SMasatake YAMATO    local l
2004ea1cc174SMasatake YAMATO
2005ea1cc174SMasatake YAMATO    if type "git" > /dev/null 2>&1; then
2006ea1cc174SMasatake YAMATO	l=$(git ls-files -- "$f")
2007ea1cc174SMasatake YAMATO	if [ -z "$l" ]; then
2008ea1cc174SMasatake YAMATO	    echo '<G>'
2009ea1cc174SMasatake YAMATO	fi
2010ea1cc174SMasatake YAMATO    fi
2011ea1cc174SMasatake YAMATO}
2012ea1cc174SMasatake YAMATO
20135d0eaa0bSMasatake YAMATOis_crashed ()
20145d0eaa0bSMasatake YAMATO{
20155d0eaa0bSMasatake YAMATO    local f=$1
20165d0eaa0bSMasatake YAMATO
20175d0eaa0bSMasatake YAMATO    grep -q -i "core dump" "$f"
20185d0eaa0bSMasatake YAMATO}
20195d0eaa0bSMasatake YAMATO
20205d0eaa0bSMasatake YAMATOprint_backtraces()
20215d0eaa0bSMasatake YAMATO{
20225d0eaa0bSMasatake YAMATO    local ctags_exe=$1
20235d0eaa0bSMasatake YAMATO    shift 1
20245d0eaa0bSMasatake YAMATO
20255d0eaa0bSMasatake YAMATO    local coref
20265d0eaa0bSMasatake YAMATO    for coref in "$@"; do
20275d0eaa0bSMasatake YAMATO	if [ -f "${coref}" ]; then
20285d0eaa0bSMasatake YAMATO	    gdb "${ctags_exe}" -c "${coref}" -ex where -batch
20295d0eaa0bSMasatake YAMATO	else
20305d0eaa0bSMasatake YAMATO	    echo "no such file: ${coref}"
20315d0eaa0bSMasatake YAMATO	fi
20325d0eaa0bSMasatake YAMATO    done
20335d0eaa0bSMasatake YAMATO}
20345d0eaa0bSMasatake YAMATO
2035383aa712SMasatake YAMATOCODE_FOR_IGNORING_THIS_TMAIN_TEST=77
2036ec63b4a8SMasatake YAMATOtmain_run ()
2037ec63b4a8SMasatake YAMATO{
2038ec63b4a8SMasatake YAMATO    local topdir=$1
2039f64af9fcSMasatake YAMATO    local build_topdir=$2
20400ff3793fSMasatake YAMATO    shift 2
20410ff3793fSMasatake YAMATO    local units="$@"
20420ff3793fSMasatake YAMATO
2043ec63b4a8SMasatake YAMATO    local subdir
2044ec63b4a8SMasatake YAMATO    local basedir
2045ec63b4a8SMasatake YAMATO
2046ec63b4a8SMasatake YAMATO    local test_name
20478335e774SK.Takata    local r_failed="_failed.result"
2048ec63b4a8SMasatake YAMATO    local failed
2049ec63b4a8SMasatake YAMATO    local f
2050ec63b4a8SMasatake YAMATO
2051ec63b4a8SMasatake YAMATO    local aspect
2052ec63b4a8SMasatake YAMATO    local engine
2053ec63b4a8SMasatake YAMATO
2054383aa712SMasatake YAMATO    local r
2055383aa712SMasatake YAMATO    local a
205672c31db2SMasatake YAMATO    local status_=0
20578335e774SK.Takata    local msg
2058ec63b4a8SMasatake YAMATO
20592a377cabSMasatake YAMATO    local need_rearrange
20602a377cabSMasatake YAMATO
20612a377cabSMasatake YAMATO    if ! [ $(basename "${CTAGS}") = 'ctags' ]; then
20622a377cabSMasatake YAMATO	need_rearrange=yes
20632a377cabSMasatake YAMATO    fi
20642a377cabSMasatake YAMATO
20658335e774SK.Takata    rm -f ${r_failed}
2066ec63b4a8SMasatake YAMATO    basedir=$(pwd)
2067ec63b4a8SMasatake YAMATO    for subdir in ${topdir}/*.d; do
2068ec63b4a8SMasatake YAMATO	if [ "${subdir}" = ${topdir}/'*.d' ]; then
2069ec63b4a8SMasatake YAMATO	    return 1
2070ec63b4a8SMasatake YAMATO	fi
2071ec63b4a8SMasatake YAMATO
20720ff3793fSMasatake YAMATO	test_name=$(basename ${subdir} .d)
20730ff3793fSMasatake YAMATO
20740ff3793fSMasatake YAMATO	if [ -n "${units}" ] && ! member_p "${test_name}" ${units}; then
20750ff3793fSMasatake YAMATO	    continue
20760ff3793fSMasatake YAMATO	fi
20770ff3793fSMasatake YAMATO
2078f64af9fcSMasatake YAMATO	build_subdir=${build_topdir}/$(basename ${subdir})
2079f64af9fcSMasatake YAMATO	if ! mkdir -p ${build_subdir}; then
2080f64af9fcSMasatake YAMATO	    return 1
2081f64af9fcSMasatake YAMATO	fi
2082ec63b4a8SMasatake YAMATO
20838335e774SK.Takata	# Run this block in parallel
20848335e774SK.Takata	(
2085f64af9fcSMasatake YAMATO	    rm -f ${build_subdir}/*-actual.txt
208667b798e9SMasatake YAMATO
20878335e774SK.Takata	    msg="\nTesting ${test_name}"
20888335e774SK.Takata	    msg="${msg}\n$(line '-')"
2089ec63b4a8SMasatake YAMATO	    (
2090ec63b4a8SMasatake YAMATO		cd ${subdir}
20915b9e0eddSMasatake YAMATO		${SHELL} run.sh \
20925b9e0eddSMasatake YAMATO			 ${basedir}/${CTAGS} \
20935b9e0eddSMasatake YAMATO			 ${build_subdir} \
20945b9e0eddSMasatake YAMATO			 ${basedir}/${READTAGS}
2095f64af9fcSMasatake YAMATO	    ) > ${build_subdir}/stdout-actual.txt 2> ${build_subdir}/stderr-actual.txt
2096383aa712SMasatake YAMATO	    r=$?
2097f64af9fcSMasatake YAMATO	    echo $r > ${build_subdir}/exit-actual.txt
2098383aa712SMasatake YAMATO
20992a377cabSMasatake YAMATO	    if [ -n "${need_rearrange}" ]; then
21002a377cabSMasatake YAMATO		sed -i -e 's|^'$(basename "${CTAGS}")':|ctags:|' ${build_subdir}/stderr-actual.txt
21012a377cabSMasatake YAMATO	    fi
210276bcd7b4SK.Takata
2103383aa712SMasatake YAMATO	    if [ $r = $CODE_FOR_IGNORING_THIS_TMAIN_TEST ]; then
21048335e774SK.Takata		msg="${msg}\n$(run_result skip "" '/dev/null' "$(cat ${build_subdir}/stdout-actual.txt)")"
2105f64af9fcSMasatake YAMATO		for a in ${build_subdir}/*-actual.txt; do
2106383aa712SMasatake YAMATO		    if [ -f "$a" ]; then
2107383aa712SMasatake YAMATO			rm $a
2108383aa712SMasatake YAMATO		    fi
2109383aa712SMasatake YAMATO		done
21108335e774SK.Takata		printf "%b\n" "${msg}"
21118335e774SK.Takata		exit
2112383aa712SMasatake YAMATO	    fi
2113ec63b4a8SMasatake YAMATO
2114f64af9fcSMasatake YAMATO	    if [ -f ${build_subdir}/tags ]; then
2115f64af9fcSMasatake YAMATO		mv ${build_subdir}/tags ${build_subdir}/tags-actual.txt
211601ac804dSMasatake YAMATO	    fi
211701ac804dSMasatake YAMATO	    for aspect in stdout stderr exit tags; do
2118ec63b4a8SMasatake YAMATO		if [ -f ${subdir}/${aspect}-expected.txt ]; then
2119ec63b4a8SMasatake YAMATO		    engine=compare
21208335e774SK.Takata		    msg="${msg}\n$(tmain_${engine} ${subdir} ${build_subdir} ${aspect})"
21218335e774SK.Takata		    if [ $? -eq 0 ]; then
2122f64af9fcSMasatake YAMATO			rm ${build_subdir}/${aspect}-actual.txt
2123ec63b4a8SMasatake YAMATO		    else
21248335e774SK.Takata			echo "${test_name}/${aspect}-${engine}$(failed_git_marker ${subdir}/${aspect}-expected.txt)" >> ${r_failed}
21255d0eaa0bSMasatake YAMATO			if [ ${aspect} = stderr ] &&
21265d0eaa0bSMasatake YAMATO			       is_crashed ${build_subdir}/${aspect}-actual.txt &&
21275d0eaa0bSMasatake YAMATO			       type "gdb" > /dev/null 2>&1; then
21285d0eaa0bSMasatake YAMATO			    print_backtraces "${basedir}/${CTAGS}" \
21295d0eaa0bSMasatake YAMATO					     ${build_subdir}/core* \
21305d0eaa0bSMasatake YAMATO					     > ${build_subdir}/gdb-backtrace.txt
21315d0eaa0bSMasatake YAMATO			fi
2132ec63b4a8SMasatake YAMATO		    fi
2133f64af9fcSMasatake YAMATO		elif [ -f ${build_subdir}/${aspect}-actual.txt ]; then
2134f64af9fcSMasatake YAMATO		    rm ${build_subdir}/${aspect}-actual.txt
2135ec63b4a8SMasatake YAMATO		fi
2136ec63b4a8SMasatake YAMATO	    done
213701ac804dSMasatake YAMATO
21388335e774SK.Takata	    printf "%b\n" "${msg}"
21398335e774SK.Takata	) &
2140ec63b4a8SMasatake YAMATO    done
21418335e774SK.Takata    wait
2142ec63b4a8SMasatake YAMATO
21438335e774SK.Takata    if [ -f "${r_failed}" ]; then
21448335e774SK.Takata	status_=1
2145ec63b4a8SMasatake YAMATO	echo
2146ec63b4a8SMasatake YAMATO	echo Failed tests
2147ec63b4a8SMasatake YAMATO	line '='
21488335e774SK.Takata	failed=$(cat ${r_failed})
2149ec63b4a8SMasatake YAMATO	for f in ${failed}; do
2150ea1cc174SMasatake YAMATO	    echo $f | sed -e 's|<G>| (not committed/cached yet)|'
2151ec63b4a8SMasatake YAMATO	done
2152ec63b4a8SMasatake YAMATO	echo
215301b068cdSMasatake YAMATO
215401b068cdSMasatake YAMATO	if [ "${SHOW_DIFF_OUTPUT}" = yes ]; then
215501b068cdSMasatake YAMATO	    engine=compare
215601b068cdSMasatake YAMATO	    echo Detail "[$engine]"
215701b068cdSMasatake YAMATO	    line '-'
215801b068cdSMasatake YAMATO	    tmain_${engine}_result ${build_topdir}
215901b068cdSMasatake YAMATO	fi
21608335e774SK.Takata	rm ${r_failed}
2161ec63b4a8SMasatake YAMATO    fi
2162ec63b4a8SMasatake YAMATO
216372c31db2SMasatake YAMATO    return $status_
2164ec63b4a8SMasatake YAMATO}
2165ec63b4a8SMasatake YAMATO
2166ec63b4a8SMasatake YAMATOaction_tmain ()
2167ec63b4a8SMasatake YAMATO{
2168ec63b4a8SMasatake YAMATO    local action="$1"
2169ec63b4a8SMasatake YAMATO    shift
2170ec63b4a8SMasatake YAMATO    local tmain_dir
2171f64af9fcSMasatake YAMATO    local build_dir
2172ec63b4a8SMasatake YAMATO
2173ec63b4a8SMasatake YAMATO    while [ $# -gt 0 ]; do
2174ec63b4a8SMasatake YAMATO	case $1 in
2175ec63b4a8SMasatake YAMATO	    --ctags)
2176ec63b4a8SMasatake YAMATO		shift
2177ec63b4a8SMasatake YAMATO		CTAGS="$1"
2178ec63b4a8SMasatake YAMATO		shift
2179ec63b4a8SMasatake YAMATO		;;
2180ec63b4a8SMasatake YAMATO	    --ctags=*)
2181ec63b4a8SMasatake YAMATO		CTAGS="${1#--ctags=}"
2182ec63b4a8SMasatake YAMATO		shift
2183ec63b4a8SMasatake YAMATO		;;
2184ec63b4a8SMasatake YAMATO	    --colorized-output)
2185ec63b4a8SMasatake YAMATO		shift
2186ec63b4a8SMasatake YAMATO		COLORIZED_OUTPUT="$1"
2187ec63b4a8SMasatake YAMATO		shift
2188ec63b4a8SMasatake YAMATO		;;
2189ec63b4a8SMasatake YAMATO	    --colorized-output=*)
2190ec63b4a8SMasatake YAMATO		COLORIZED_OUTPUT="${1#--colorized-output=}"
2191ec63b4a8SMasatake YAMATO		shift
2192ec63b4a8SMasatake YAMATO		;;
2193ec63b4a8SMasatake YAMATO	    --with-valgrind)
2194ec63b4a8SMasatake YAMATO		shift
2195ec63b4a8SMasatake YAMATO		WITH_VALGRIND=yes
2196ec63b4a8SMasatake YAMATO		;;
2197ec63b4a8SMasatake YAMATO	    --show-diff-output)
2198ec63b4a8SMasatake YAMATO		SHOW_DIFF_OUTPUT=yes
2199ec63b4a8SMasatake YAMATO		shift
2200ec63b4a8SMasatake YAMATO		;;
22015b9e0eddSMasatake YAMATO	    --readtags=*)
22025b9e0eddSMasatake YAMATO		READTAGS="${1#--readtags=}"
22035b9e0eddSMasatake YAMATO		shift
22045b9e0eddSMasatake YAMATO		;;
22050ff3793fSMasatake YAMATO	    --units)
22060ff3793fSMasatake YAMATO		shift
22070ff3793fSMasatake YAMATO		UNITS=$(echo "$1" | tr ',' ' ')
22080ff3793fSMasatake YAMATO		shift
22090ff3793fSMasatake YAMATO		;;
22100ff3793fSMasatake YAMATO	    --units=*)
22110ff3793fSMasatake YAMATO		UNITS=$(echo "${1#--units=}" | tr ',' ' ')
22120ff3793fSMasatake YAMATO		shift
22130ff3793fSMasatake YAMATO		;;
2214ec63b4a8SMasatake YAMATO	    -*)
2215ec63b4a8SMasatake YAMATO		ERROR 1 "unknown option \"${1}\" for ${action} action"
2216ec63b4a8SMasatake YAMATO		;;
2217ec63b4a8SMasatake YAMATO	    *)
2218ec63b4a8SMasatake YAMATO		tmain_dir="$1"
2219ec63b4a8SMasatake YAMATO		shift
2220f64af9fcSMasatake YAMATO		build_dir=${1:-${tmain_dir}}
2221e4452bcdSMasatake YAMATO		if [ -n "$1" ]; then
2222f64af9fcSMasatake YAMATO		    shift
2223e4452bcdSMasatake YAMATO		fi
2224ec63b4a8SMasatake YAMATO		break
2225ec63b4a8SMasatake YAMATO		;;
2226ec63b4a8SMasatake YAMATO	esac
2227ec63b4a8SMasatake YAMATO    done
2228ec63b4a8SMasatake YAMATO
2229ec63b4a8SMasatake YAMATO    if [ $# -gt 0 ]; then
2230ec63b4a8SMasatake YAMATO	ERROR 1 "too many arguments for ${action} action: $*"
2231ec63b4a8SMasatake YAMATO    elif [ -z "$tmain_dir" ]; then
2232ec63b4a8SMasatake YAMATO	ERROR 1 "TMAIN_DIR parameter is not given in ${action} action"
2233ec63b4a8SMasatake YAMATO    fi
2234ec63b4a8SMasatake YAMATO
2235ec63b4a8SMasatake YAMATO    if ! [ -d "$tmain_dir" ]; then
2236f64af9fcSMasatake YAMATO	ERROR 1 "No such directory(tmain_dir): ${tmain_dir}"
2237f64af9fcSMasatake YAMATO    fi
2238f64af9fcSMasatake YAMATO
22395617e54aSMasatake YAMATO    case "${build_dir}" in
22405617e54aSMasatake YAMATO	/*) ;;
22415617e54aSMasatake YAMATO	*) build_dir=$(pwd)/${build_dir} ;;
22425617e54aSMasatake YAMATO    esac
2243f64af9fcSMasatake YAMATO    if ! [ -d "$build_dir" ]; then
2244f64af9fcSMasatake YAMATO	ERROR 1 "No such directory(build_dir): ${build_dir}"
2245ec63b4a8SMasatake YAMATO    fi
2246ec63b4a8SMasatake YAMATO
2247ec63b4a8SMasatake YAMATO    if ! [ -f "${CTAGS}" ]; then
2248ec63b4a8SMasatake YAMATO	ERROR 1 "no such file: ${CTAGS}"
2249ec63b4a8SMasatake YAMATO    elif ! [ -e "${CTAGS}" ]; then
2250ec63b4a8SMasatake YAMATO	ERROR 1 "${CTAGS} is not an executable file"
2251ec63b4a8SMasatake YAMATO    fi
2252ec63b4a8SMasatake YAMATO
2253ec63b4a8SMasatake YAMATO    if ! ( [ "${COLORIZED_OUTPUT}" = 'yes' ] || [ "${COLORIZED_OUTPUT}" = 'no' ] ); then
2254ec63b4a8SMasatake YAMATO	ERROR 1 "unexpected option argument for --colorized-output: ${COLORIZED_OUTPUT}"
2255ec63b4a8SMasatake YAMATO    fi
2256ec63b4a8SMasatake YAMATO
2257cac4cde4SK.Takata    check_availability awk
2258cac4cde4SK.Takata    check_availability diff
2259cac4cde4SK.Takata
22600ff3793fSMasatake YAMATO    tmain_run ${tmain_dir} ${build_dir} ${UNITS}
2261ec63b4a8SMasatake YAMATO    return $?
2262ec63b4a8SMasatake YAMATO}
2263ec63b4a8SMasatake YAMATO
2264ec63b4a8SMasatake YAMATOhelp_tmain ()
2265ec63b4a8SMasatake YAMATO{
2266ec63b4a8SMasatake YAMATO    cat <<EOF
2267f64af9fcSMasatake YAMATO$0 tmain [OPTIONS] TMAIN-DIR [BUILD-DIR]
2268ec63b4a8SMasatake YAMATO
2269ec63b4a8SMasatake YAMATO	   Run tests for main part of ctags.
2270a34c67f7SMasatake YAMATO	   If BUILD-DIR is not given, TMAIN-DIR is reused as BUILD-DIR.
2271a34c67f7SMasatake YAMATO
2272a34c67f7SMasatake YAMATO	   OPTIONS:
2273ec63b4a8SMasatake YAMATO
22745e502075SMasanari Iida		--ctags CTAGS: ctags executable file for testing
2275ec63b4a8SMasatake YAMATO		--colorized-output yes|no: print the result in color.
2276ec63b4a8SMasatake YAMATO		--with-valgrind: (not implemented) run a test case under valgrind
2277ec63b4a8SMasatake YAMATO		--show-diff-output: (not implemented)show diff output for failed test cases in the summary.
22780ff3793fSMasatake YAMATO		--units UNITS1[,UNITS2,...]: run only Tmain/UNIT*.d (.d is not needed)
2279ec63b4a8SMasatake YAMATOEOF
2280ec63b4a8SMasatake YAMATO}
2281ec63b4a8SMasatake YAMATO
2282be317af6SMasatake YAMATOaction_clean_tmain()
2283be317af6SMasatake YAMATO{
2284be317af6SMasatake YAMATO    local action="$1"
2285be317af6SMasatake YAMATO    shift
2286be317af6SMasatake YAMATO
2287be317af6SMasatake YAMATO    local tmain_dir=$1
2288be317af6SMasatake YAMATO    shift
2289be317af6SMasatake YAMATO
2290be317af6SMasatake YAMATO    if [ $# -gt 0 ]; then
2291be317af6SMasatake YAMATO	ERROR 1 "too many arguments for ${action} action: $*"
2292be317af6SMasatake YAMATO    elif [ -z "$tmain_dir" ]; then
2293be317af6SMasatake YAMATO	ERROR 1 "TMAIN_DIR parameter is not given in ${action} action"
2294be317af6SMasatake YAMATO    fi
2295be317af6SMasatake YAMATO
2296be317af6SMasatake YAMATO    if ! [ -d "$tmain_dir" ]; then
2297be317af6SMasatake YAMATO	ERROR 1 "No such directory: ${tmain_dir}"
2298be317af6SMasatake YAMATO    fi
2299be317af6SMasatake YAMATO
2300be317af6SMasatake YAMATO    check_availability find
2301be317af6SMasatake YAMATO    check_availability rm
2302be317af6SMasatake YAMATO
2303be317af6SMasatake YAMATO    local object
2304be317af6SMasatake YAMATO    local type
2305be317af6SMasatake YAMATO    for object in stdout stderr exit tags; do
2306be317af6SMasatake YAMATO	for type in actual diff; do
2307be317af6SMasatake YAMATO	    rm -f $(find "$tmain_dir" -name ${object}-${type}.txt)
23085d0eaa0bSMasatake YAMATO	    rm -f $(find "$tmain_dir" -name gdb-backtrace.txt)
2309be317af6SMasatake YAMATO	done
2310be317af6SMasatake YAMATO    done
2311be317af6SMasatake YAMATO    return 0
2312be317af6SMasatake YAMATO}
2313be317af6SMasatake YAMATO
2314be317af6SMasatake YAMATOhelp_clean_tmain ()
2315be317af6SMasatake YAMATO{
2316be317af6SMasatake YAMATO    cat <<EOF
2317be317af6SMasatake YAMATO$0 clean_tmain TMAIN-DIR
2318be317af6SMasatake YAMATO
2319be317af6SMasatake YAMATO	   Clean all files created during tmain testing
2320be317af6SMasatake YAMATOEOF
2321be317af6SMasatake YAMATO
2322be317af6SMasatake YAMATO}
2323be317af6SMasatake YAMATO
232430bea0aeSMasatake YAMATOhelp_chop ()
232530bea0aeSMasatake YAMATO{
232630bea0aeSMasatake YAMATO    cat <<EOF
2327a379e1ccSMasatake YAMATO$0 chop|slap [OPTIONS] UNITS-DIR
232803c1af8aSMasatake YAMATO
232930bea0aeSMasatake YAMATO	   OPTIONS:
233003c1af8aSMasatake YAMATO
23315e502075SMasanari Iida		--ctags CTAGS: ctags executable file for testing
233230bea0aeSMasatake YAMATO		--languages PARSER1[,PARSER2,...]: run only PARSER* related cases
233330bea0aeSMasatake YAMATO		--quiet: don't print dots as passed test cases.
233430bea0aeSMasatake YAMATO		--with-timeout DURATION: run a test case under timeout
233530bea0aeSMasatake YAMATO					 command with SECOND.
233630bea0aeSMasatake YAMATO					 0 means no timeout.
233730bea0aeSMasatake YAMATO					 default is 1.
233830bea0aeSMasatake YAMATO		--with-valgrind: run a test case under valgrind
233930bea0aeSMasatake YAMATO			       If this option given, DURATION is changed to
234030bea0aeSMasatake YAMATO			       DURATION := DURATION * ${_VG_TIMEOUT_FACTOR}
234130bea0aeSMasatake YAMATOEOF
234230bea0aeSMasatake YAMATO}
234330bea0aeSMasatake YAMATO
234430bea0aeSMasatake YAMATOaction_chop ()
234530bea0aeSMasatake YAMATO{
2346a379e1ccSMasatake YAMATO    if [ "$1" = "chop" ]; then
234730bea0aeSMasatake YAMATO	action_fuzz_common chop_lang "$@"
2348a379e1ccSMasatake YAMATO    else
2349a379e1ccSMasatake YAMATO	action_fuzz_common slap_lang "$@"
2350a379e1ccSMasatake YAMATO    fi
235130bea0aeSMasatake YAMATO}
235230bea0aeSMasatake YAMATO
235330bea0aeSMasatake YAMATOchop_lang()
235430bea0aeSMasatake YAMATO{
2355a379e1ccSMasatake YAMATO    chop_lang_common "tail" "$@"
2356a379e1ccSMasatake YAMATO}
2357a379e1ccSMasatake YAMATO
2358a379e1ccSMasatake YAMATOslap_lang()
2359a379e1ccSMasatake YAMATO{
2360a379e1ccSMasatake YAMATO    chop_lang_common "head" "$@"
2361a379e1ccSMasatake YAMATO}
2362a379e1ccSMasatake YAMATO
2363a379e1ccSMasatake YAMATOchop_lang_common ()
2364a379e1ccSMasatake YAMATO{
2365a379e1ccSMasatake YAMATO    local endpoint=$1
2366a379e1ccSMasatake YAMATO    shift 1
2367a379e1ccSMasatake YAMATO
236830bea0aeSMasatake YAMATO    local lang="$1"
236930bea0aeSMasatake YAMATO    local dir="$2"
237030bea0aeSMasatake YAMATO    shift 2
237130bea0aeSMasatake YAMATO    local f
237230bea0aeSMasatake YAMATO    local r
2373a379e1ccSMasatake YAMATO
2374a379e1ccSMasatake YAMATO    printf '%-60s\n' "Fuzzing by truncating input from ${endpoint} (${lang})"
237530bea0aeSMasatake YAMATO    line '-'
237630bea0aeSMasatake YAMATO
237730bea0aeSMasatake YAMATO    r=0
237830bea0aeSMasatake YAMATO    for f in $(find "${dir}" -type f -name 'input.*'); do
2379a379e1ccSMasatake YAMATO	if ! chop_lang_file "$1" "${lang}" "${f}"; then
238030bea0aeSMasatake YAMATO	    r=1
238130bea0aeSMasatake YAMATO	    break
238230bea0aeSMasatake YAMATO	fi
238330bea0aeSMasatake YAMATO    done
238430bea0aeSMasatake YAMATO    echo
238530bea0aeSMasatake YAMATO    return $r
238630bea0aeSMasatake YAMATO}
238730bea0aeSMasatake YAMATO
238830bea0aeSMasatake YAMATOchop_lang_file ()
238930bea0aeSMasatake YAMATO{
2390a379e1ccSMasatake YAMATO    local endpoint=$1
2391a379e1ccSMasatake YAMATO    shift 1
2392a379e1ccSMasatake YAMATO
239330bea0aeSMasatake YAMATO    local lang="$1"
239430bea0aeSMasatake YAMATO    local input="$2"
239530bea0aeSMasatake YAMATO    shift 2
239630bea0aeSMasatake YAMATO
239730bea0aeSMasatake YAMATO    local r
239830bea0aeSMasatake YAMATO    local cmdline
239930bea0aeSMasatake YAMATO    local cmdline_for_shirking
24002004d7e3SHiroo HAYASHI    local len=$(${_FSIZE} "${input}")
240130bea0aeSMasatake YAMATO
240230bea0aeSMasatake YAMATO    local guessed_lang
240330bea0aeSMasatake YAMATO    guessed_lang=$( ${_CMDLINE_FOR_SHRINKING} --print-language "${input}" 2>/dev/null | sed -n 's/^.*: //p')
240430bea0aeSMasatake YAMATO    if [ "${lang}" !=  "${guessed_lang}" ]; then
240530bea0aeSMasatake YAMATO	return 0
240630bea0aeSMasatake YAMATO    fi
240730bea0aeSMasatake YAMATO
240830bea0aeSMasatake YAMATO    i=0
240930bea0aeSMasatake YAMATO    echo "Testing cases derived from: ${input}"
241030bea0aeSMasatake YAMATO    line '.' --no-newline
241130bea0aeSMasatake YAMATO
241230bea0aeSMasatake YAMATO    r=0
241330bea0aeSMasatake YAMATO    while [ "$i" -lt "$len" ]; do
2414a379e1ccSMasatake YAMATO	if chop_lang_file_chopspec "${endpoint}" "${input}" "${len}" "$i" "${lang}"; then
241530bea0aeSMasatake YAMATO	    i=$(( i + 1 ))
241630bea0aeSMasatake YAMATO	else
241730bea0aeSMasatake YAMATO	    r=1
241830bea0aeSMasatake YAMATO	    break
241930bea0aeSMasatake YAMATO	fi
242030bea0aeSMasatake YAMATO    done
242130bea0aeSMasatake YAMATO    echo
242230bea0aeSMasatake YAMATO    return $r
242330bea0aeSMasatake YAMATO}
242430bea0aeSMasatake YAMATO
242530bea0aeSMasatake YAMATOchop()
242630bea0aeSMasatake YAMATO{
2427a379e1ccSMasatake YAMATO    local endpoint=$1
2428a379e1ccSMasatake YAMATO    local input=$2
2429a379e1ccSMasatake YAMATO    local pos=$3
2430a379e1ccSMasatake YAMATO    local len=$4
243130bea0aeSMasatake YAMATO
2432a379e1ccSMasatake YAMATO    if [ "${endpoint}" = "tail" ]; then
243330bea0aeSMasatake YAMATO	dd if=$input bs=1 count=$pos
2434a379e1ccSMasatake YAMATO    else
2435a379e1ccSMasatake YAMATO	dd if=$input bs=1 count=$((len - pos)) skip=$pos
2436a379e1ccSMasatake YAMATO    fi
243730bea0aeSMasatake YAMATO}
243830bea0aeSMasatake YAMATO
243930bea0aeSMasatake YAMATOchop_lang_file_chopspec()
244030bea0aeSMasatake YAMATO{
2441a379e1ccSMasatake YAMATO    local endpoint=$1
2442a379e1ccSMasatake YAMATO    shift 1
2443a379e1ccSMasatake YAMATO
244430bea0aeSMasatake YAMATO    local input="$1"
244530bea0aeSMasatake YAMATO    local len="$2"
244630bea0aeSMasatake YAMATO    local pos="$3"
244730bea0aeSMasatake YAMATO    local lang="$4"
244830bea0aeSMasatake YAMATO    shift 4
244930bea0aeSMasatake YAMATO
245030bea0aeSMasatake YAMATO    local dir="${input%/*}"
245130bea0aeSMasatake YAMATO    local ochopped=$(printf "%s/CHOP-INPUT-%s.tmp" "${dir}" "$pos")
245230bea0aeSMasatake YAMATO    local ocmdline=$(printf "%s/CHOP-CMDLINE-%s.tmp" "${dir}" "$pos")
245330bea0aeSMasatake YAMATO    local ovalgrind=$(printf "%s/CHOP-VALGRIND-%s.tmp" "${dir}" "$pos")
245430bea0aeSMasatake YAMATO    local oshrink=$(printf "%s/CHOP-SHRINK-%s.tmp" "${dir}" "$pos")
245530bea0aeSMasatake YAMATO
245630bea0aeSMasatake YAMATO    local cmdline
245730bea0aeSMasatake YAMATO    local cmdline_for_shirking
245830bea0aeSMasatake YAMATO    local progress_offset
245930bea0aeSMasatake YAMATO    local r
246030bea0aeSMasatake YAMATO
246130bea0aeSMasatake YAMATO    rm -f "${ocmdline}" "${ovalgrind}" "${ochopped}" "${oshrink}"
246230bea0aeSMasatake YAMATO
246330bea0aeSMasatake YAMATO    if [ "${WITH_VALGRIND}" = 'yes' ]; then
246430bea0aeSMasatake YAMATO	cmdline=$( printf "${_CMDLINE} --language-force=${lang} ${ochopped}" "${ovalgrind}" )
246530bea0aeSMasatake YAMATO    else
246630bea0aeSMasatake YAMATO	cmdline="${_CMDLINE} --language-force=${lang} ${ochopped}"
246730bea0aeSMasatake YAMATO    fi
246830bea0aeSMasatake YAMATO    cmdline_for_shirking="${_CMDLINE_FOR_SHRINKING} --language-force=${lang} %s"
246930bea0aeSMasatake YAMATO
2470a379e1ccSMasatake YAMATO    chop "${endpoint}" "${input}" "${pos}" "${len}" > "$ochopped"  2> /dev/null
247130bea0aeSMasatake YAMATO
247230bea0aeSMasatake YAMATO    progress_offset=$(( pos % _NOISE_REPORT_MAX_COLUMN ))
247330bea0aeSMasatake YAMATO    if [ "${progress_offset}" -eq 0 ]; then
247430bea0aeSMasatake YAMATO	[ $pos -gt 0 ] && printf " %d/%d" "$pos" "${len}"
247530bea0aeSMasatake YAMATO	echo
247630bea0aeSMasatake YAMATO    fi
247730bea0aeSMasatake YAMATO
247830bea0aeSMasatake YAMATO    echo "${cmdline}" > "${ocmdline}"
247930bea0aeSMasatake YAMATO    ( exec 2>&-; ${cmdline} 2> /dev/null > /dev/null )
248030bea0aeSMasatake YAMATO    r=$?
248130bea0aeSMasatake YAMATO    case $r in
248230bea0aeSMasatake YAMATO	0)
248330bea0aeSMasatake YAMATO	    printf 'o'
248430bea0aeSMasatake YAMATO	    noise_report_line "${pos}" "${len}" "${r}" ""
248530bea0aeSMasatake YAMATO	    rm "${ochopped}"
248630bea0aeSMasatake YAMATO	    rm -f "${ovalgrind}" "${ocmdline}"
248730bea0aeSMasatake YAMATO	    ;;
248830bea0aeSMasatake YAMATO	${_TIMEOUT_EXIT})
248930bea0aeSMasatake YAMATO	    printf "T"
249030bea0aeSMasatake YAMATO	    noise_report_line "${pos}" "${len}" "${r}" ""
249130bea0aeSMasatake YAMATO	    printf '\n%-20s\n' "[timeout $lang]" "$ochopped"
249230bea0aeSMasatake YAMATO	    [ "${RUN_SHRINK}" = 'yes' ] && fuzz_shrink "${cmdline_for_shirking}" "${ochopped}" "${oshrink}" "${lang}"
249330bea0aeSMasatake YAMATO	    ;;
249430bea0aeSMasatake YAMATO	${_VALGRIND_EXIT})
249530bea0aeSMasatake YAMATO	    printf "V"
249630bea0aeSMasatake YAMATO	    noise_report_line "${pos}" "${len}" "${r}" ""
249730bea0aeSMasatake YAMATO	    printf '\n%-20s %s\n' "[valgrind-error $lang]" "$ochopped"
249830bea0aeSMasatake YAMATO	    ;;
249930bea0aeSMasatake YAMATO	*)
250030bea0aeSMasatake YAMATO	    printf "!"
250130bea0aeSMasatake YAMATO	    noise_report_line "${pos}" "${len}" "${r}" ""
250230bea0aeSMasatake YAMATO	    printf '\n%-20s %s\n' "[unexpected-status($r) $lang]" "$ochopped"
250330bea0aeSMasatake YAMATO	    [ "${RUN_SHRINK}" = 'yes' ] && fuzz_shrink "${cmdline_for_shirking}" "${ochopped}" "${oshrink}" "${lang}"
250430bea0aeSMasatake YAMATO	    ;;
250530bea0aeSMasatake YAMATO    esac
250630bea0aeSMasatake YAMATO    return $r
250730bea0aeSMasatake YAMATO}
250830bea0aeSMasatake YAMATO
2509e5399325SMasatake YAMATOhelp_validate_input ()
25108cee4794SMasatake YAMATO{
25118cee4794SMasatake YAMATO    cat <<EOF
2512e5399325SMasatake YAMATO$0 validate-input [OPTIONS] UNITS-DIR VALIDATORS-DIR
25138cee4794SMasatake YAMATO
2514e5399325SMasatake YAMATO	Validate the input files (only for the test cases specifying validators.)
25158cee4794SMasatake YAMATO
25168cee4794SMasatake YAMATO	OPTIONS:
2517e5399325SMasatake YAMATO		--validators=validator[,...]: Validate test cases specifying
2518e5399325SMasatake YAMATO					    given validators.
25198cee4794SMasatake YAMATO		--colorized-output: yes|no: print the result in color.
25208cee4794SMasatake YAMATOEOF
25218cee4794SMasatake YAMATO}
25228cee4794SMasatake YAMATO
2523e5399325SMasatake YAMATOhas_validator_acceptable_name ()
25248cee4794SMasatake YAMATO{
2525e5399325SMasatake YAMATO    local validator=$1
2526e5399325SMasatake YAMATO    if [ -z "${validator}" ]; then
25278cee4794SMasatake YAMATO	return 1
25288cee4794SMasatake YAMATO    fi
25298cee4794SMasatake YAMATO
2530e5399325SMasatake YAMATO    echo "${validator}" | grep -q "^[-a-zA-Z+#0-9]\+$"
25318cee4794SMasatake YAMATO}
25328cee4794SMasatake YAMATO
2533e5399325SMasatake YAMATOis_validator_runnable ()
25348cee4794SMasatake YAMATO{
25358cee4794SMasatake YAMATO    local v=$1
25368cee4794SMasatake YAMATO    local d=$2
25378cee4794SMasatake YAMATO    shift 2
25388cee4794SMasatake YAMATO
2539e5399325SMasatake YAMATO    "$d/"validator-"$v" is_runnable
25408cee4794SMasatake YAMATO}
25418cee4794SMasatake YAMATO
2542e5399325SMasatake YAMATOupdate_validator_list ()
25438cee4794SMasatake YAMATO{
25448cee4794SMasatake YAMATO    local type=$1
25458cee4794SMasatake YAMATO    local v=$2
25468cee4794SMasatake YAMATO
25478cee4794SMasatake YAMATO    case $type in
25488cee4794SMasatake YAMATO	runnable)
2549e5399325SMasatake YAMATO	    if ! member_p "$v" ${_RUNNABLE_VALIDATORS}; then
2550e5399325SMasatake YAMATO		_RUNNABLE_VALIDATORS="${_RUNNABLE_VALIDATORS} $v"
25518cee4794SMasatake YAMATO	    fi
25528cee4794SMasatake YAMATO	    ;;
25538cee4794SMasatake YAMATO	unavailable)
2554e5399325SMasatake YAMATO	    if ! member_p "$v" ${_UNAVAILABLE_VALIDATORS}; then
2555e5399325SMasatake YAMATO		_UNAVAILABLE_VALIDATORS="${_UNAVAILABLE_VALIDATORS} $v"
25568cee4794SMasatake YAMATO	    fi
25578cee4794SMasatake YAMATO	    ;;
25588cee4794SMasatake YAMATO	*)
2559e5399325SMasatake YAMATO	    ERROR 1 "INTERNAL ERROR: wrong validator list type: ${type}"
25608cee4794SMasatake YAMATO	    ;;
25618cee4794SMasatake YAMATO    esac
25628cee4794SMasatake YAMATO}
25638cee4794SMasatake YAMATO
25648cee4794SMasatake YAMATO#
2565e5399325SMasatake YAMATO# Whether a validator can be run or not.
25668cee4794SMasatake YAMATO#
2567e5399325SMasatake YAMATO# This runs "is_runnable" subcommand of the validator.
25688cee4794SMasatake YAMATO#
2569e5399325SMasatake YAMATOvalidate_validator ()
25708cee4794SMasatake YAMATO{
25718cee4794SMasatake YAMATO    local v=$1
2572e5399325SMasatake YAMATO    local validators_dir=$2
25738cee4794SMasatake YAMATO    local make_error=$3
25748cee4794SMasatake YAMATO
2575e5399325SMasatake YAMATO    if member_p "$v" ${_RUNNABLE_VALIDATORS}; then
25768cee4794SMasatake YAMATO	return 0
2577e5399325SMasatake YAMATO    elif member_p "$v" ${_UNAVAILABLE_VALIDATORS}; then
25788cee4794SMasatake YAMATO	return 1
25798cee4794SMasatake YAMATO    fi
25808cee4794SMasatake YAMATO
2581e5399325SMasatake YAMATO    if ! has_validator_acceptable_name "$v"; then
25828cee4794SMasatake YAMATO	if [ "${make_error}" = "error" ]; then
2583e5399325SMasatake YAMATO	    ERROR 1 "Unacceptable validator name: $v"
25848cee4794SMasatake YAMATO	else
2585e5399325SMasatake YAMATO	    update_validator_list unavailable "$v"
25868cee4794SMasatake YAMATO	    return 1
25878cee4794SMasatake YAMATO	fi
2588e5399325SMasatake YAMATO    elif ! [ -f "${validators_dir}/validator-$v" ]; then
25898cee4794SMasatake YAMATO	if [ "${make_error}" = "error" ]; then
2590e5399325SMasatake YAMATO	    ERROR 1 "No such validator: $v (${validators_dir}/validator-$v)"
25918cee4794SMasatake YAMATO	else
2592e5399325SMasatake YAMATO	    update_validator_list unavailable "$v"
25938cee4794SMasatake YAMATO	    return 1
25948cee4794SMasatake YAMATO	fi
2595e5399325SMasatake YAMATO    elif ! [ -x "${validators_dir}/validator-$v" ]; then
25968cee4794SMasatake YAMATO	if [ "$make_error" = "error" ]; then
2597ebdbd8e2SK.Takata	    ERROR 1 "Not executable: $v (${validators_dir}/validator-$v)"
25988cee4794SMasatake YAMATO	else
2599e5399325SMasatake YAMATO	    update_validator_list unavailable "$v"
26008cee4794SMasatake YAMATO	    return 1
26018cee4794SMasatake YAMATO	fi
2602e5399325SMasatake YAMATO    elif ! is_validator_runnable "$v" "${validators_dir}"; then
26038cee4794SMasatake YAMATO	if [ "${make_error}" = "error" ]; then
2604e5399325SMasatake YAMATO	    ERROR 1 "$v (${validators_dir}/validator-$v) is not ready to run"
26058cee4794SMasatake YAMATO	else
2606e5399325SMasatake YAMATO	    update_validator_list unavailable "$v"
26078cee4794SMasatake YAMATO	    return 1
26088cee4794SMasatake YAMATO	fi
26098cee4794SMasatake YAMATO    fi
26108cee4794SMasatake YAMATO
2611e5399325SMasatake YAMATO    update_validator_list runnable "$v"
26128cee4794SMasatake YAMATO    return 0
26138cee4794SMasatake YAMATO}
26148cee4794SMasatake YAMATO
26158cee4794SMasatake YAMATO#
2616e5399325SMasatake YAMATO# Choose a validator suitable for the current context.
26178cee4794SMasatake YAMATO#
26188cee4794SMasatake YAMATO# Return value
2619e5399325SMasatake YAMATO# 0: The caller should run echo'ed validator.
26208cee4794SMasatake YAMATO#
26218cee4794SMasatake YAMATO# 1: The caller should skip the input. It means
2622e5399325SMasatake YAMATO#    - the suitable validator is not listed in VALIDATORS, or
2623e5399325SMasatake YAMATO#    - no expected.tags and no validator file exist.
2624e5399325SMasatake YAMATO#    The caller doesn't have to update any validation counters.
26258cee4794SMasatake YAMATO# 2: The caller should skip the input and update the unavailable
26268cee4794SMasatake YAMATO#    counter.
26278cee4794SMasatake YAMATO#
2628e5399325SMasatake YAMATOresolve_validator ()
26298cee4794SMasatake YAMATO{
2630e5399325SMasatake YAMATO    local validator_file=$1
2631e5399325SMasatake YAMATO    local default_validator=$2
26328cee4794SMasatake YAMATO    local has_expected_tags=$3
2633e5399325SMasatake YAMATO    local validators_dir=$4
26348cee4794SMasatake YAMATO
26358cee4794SMasatake YAMATO    shift 4
26368cee4794SMasatake YAMATO
2637e5399325SMasatake YAMATO    local candidate_validator
2638e5399325SMasatake YAMATO    local local_validator
26398cee4794SMasatake YAMATO
2640e5399325SMasatake YAMATO    if [ -r "$validator_file" ]; then
2641e5399325SMasatake YAMATO	local_validator=$(cat "${validator_file}" | grep -v '#')
2642e5399325SMasatake YAMATO	if [ -z "${local_validator}" ]; then
2643e5399325SMasatake YAMATO	    ERROR 1 "Empty validator specfile: ${local_validator}"
26448cee4794SMasatake YAMATO	else
2645e5399325SMasatake YAMATO	    candidate_validator=${local_validator}
26468cee4794SMasatake YAMATO	fi
26478cee4794SMasatake YAMATO    elif [ "$has_expected_tags" = no ]; then
26488cee4794SMasatake YAMATO	return 1
26498cee4794SMasatake YAMATO    else
2650e5399325SMasatake YAMATO	candidate_validator=${default_validator}
26518cee4794SMasatake YAMATO    fi
26528cee4794SMasatake YAMATO
2653e5399325SMasatake YAMATO    if [ -z "${candidate_validator}" ]; then
26548cee4794SMasatake YAMATO	return 2
2655e5399325SMasatake YAMATO    elif [ -z "${VALIDATORS}" ] || member_p "${candidate_validator}" ${VALIDATORS}; then
2656e5399325SMasatake YAMATO	echo "${candidate_validator}"
2657e5399325SMasatake YAMATO	if validate_validator "${candidate_validator}" "${validators_dir}" noerror; then
26588cee4794SMasatake YAMATO	    return 0
26598cee4794SMasatake YAMATO	else
26608cee4794SMasatake YAMATO	    return 2
26618cee4794SMasatake YAMATO	fi
26628cee4794SMasatake YAMATO    else
26638cee4794SMasatake YAMATO	return 1
26648cee4794SMasatake YAMATO    fi
26658cee4794SMasatake YAMATO}
26668cee4794SMasatake YAMATO
26678cee4794SMasatake YAMATO#
2668e5399325SMasatake YAMATO# Report the result of validation for INPUT with decoration
2669e5399325SMasatake YAMATO# The validation result counters are updated here.
26708cee4794SMasatake YAMATO#
2671e5399325SMasatake YAMATOvalidate_report_one ()
26728cee4794SMasatake YAMATO{
26738cee4794SMasatake YAMATO    local input=$1
2674e5399325SMasatake YAMATO    local validator=$2
26758cee4794SMasatake YAMATO    local status=$3
26768cee4794SMasatake YAMATO    shift 3
26778cee4794SMasatake YAMATO
2678e5399325SMasatake YAMATO    if [ "${validator}" = "${_NOOP_VALIDATOR}" ]; then
26798cee4794SMasatake YAMATO	return
26808cee4794SMasatake YAMATO    fi
26818cee4794SMasatake YAMATO
26828cee4794SMasatake YAMATO    local i=$(basename $input)
26838cee4794SMasatake YAMATO    local d=$(basename $(dirname $input))
26848cee4794SMasatake YAMATO
2685e5399325SMasatake YAMATO    printf '%-65s' "$d/$i with ${validator}"
26868cee4794SMasatake YAMATO    case "${status}" in
26878cee4794SMasatake YAMATO	valid)
2688e5399325SMasatake YAMATO	    if [ "${validator}" = "${_KNOWN_INVALIDATION_VALIDATOR}" ]; then
26898cee4794SMasatake YAMATO		printf '%b\n' $(decorate yellow "known-invalidation")
26908cee4794SMasatake YAMATO		V_SKIP_KNOWN_INVALIDATION=$(( V_SKIP_KNOWN_INVALIDATION + 1 ))
26918cee4794SMasatake YAMATO	    else
26928cee4794SMasatake YAMATO		printf '%b\n' $(decorate green "valid")
26938cee4794SMasatake YAMATO		V_VALID=$(( V_VALID + 1))
26948cee4794SMasatake YAMATO	    fi
26958cee4794SMasatake YAMATO	    ;;
26968cee4794SMasatake YAMATO	invalid)
26978cee4794SMasatake YAMATO	    printf '%b\n' $(decorate red "invalid")
26988cee4794SMasatake YAMATO	    V_INVALID=$(( V_INVALID + 1))
26998cee4794SMasatake YAMATO	    ;;
27008cee4794SMasatake YAMATO	unavailable)
27018cee4794SMasatake YAMATO	    printf '%b\n' $(decorate yellow "unavailable")
2702e5399325SMasatake YAMATO	    V_SKIP_VALIDATOR_UNAVAILABLE=$(( V_SKIP_VALIDATOR_UNAVAILABLE + 1))
27038cee4794SMasatake YAMATO	    ;;
27048cee4794SMasatake YAMATO	*)
2705e5399325SMasatake YAMATO	    ERROR 1 "INTERNAL ERROR: wrong validation status: ${status}"
27068cee4794SMasatake YAMATO	    ;;
27078cee4794SMasatake YAMATO    esac
27088cee4794SMasatake YAMATO}
27098cee4794SMasatake YAMATO
27108cee4794SMasatake YAMATO#
2711e5399325SMasatake YAMATO# Run a validator for the given input
27128cee4794SMasatake YAMATO#
2713e5399325SMasatake YAMATO# This runs "validate" subcommand of the validator.
27148cee4794SMasatake YAMATO#
2715e5399325SMasatake YAMATOvalidate_file ()
27168cee4794SMasatake YAMATO{
27178cee4794SMasatake YAMATO    local input=$1
2718e5399325SMasatake YAMATO    local validator=$2
2719e5399325SMasatake YAMATO    local validators_dir=$3
27208cee4794SMasatake YAMATO    shift 3
27218cee4794SMasatake YAMATO
2722e5399325SMasatake YAMATO    ${validators_dir}/validator-${validator} validate $input
27238cee4794SMasatake YAMATO    return $?
27248cee4794SMasatake YAMATO}
27258cee4794SMasatake YAMATO
27268cee4794SMasatake YAMATO#
2727e5399325SMasatake YAMATO# Validate input files under *.[dbtiv].
27288cee4794SMasatake YAMATO#
2729e5399325SMasatake YAMATOvalidate_dir ()
27308cee4794SMasatake YAMATO{
27318cee4794SMasatake YAMATO    local base_dir=$1
2732e5399325SMasatake YAMATO    local default_validator=$2
2733e5399325SMasatake YAMATO    local validators_dir=$3
27348cee4794SMasatake YAMATO    shift 3
27358cee4794SMasatake YAMATO
27368cee4794SMasatake YAMATO    local f
27378cee4794SMasatake YAMATO    local t
27388cee4794SMasatake YAMATO
27398cee4794SMasatake YAMATO    local v0 s0 inputs0
27408cee4794SMasatake YAMATO    local v s inputs
27418cee4794SMasatake YAMATO
27428cee4794SMasatake YAMATO    #
27438cee4794SMasatake YAMATO    # No expected.tags* implies the input is invalid.
2744e5399325SMasatake YAMATO    # We don't have to run any validator as far as no
2745e5399325SMasatake YAMATO    # ./validator explicitly is given.
27468cee4794SMasatake YAMATO    #
27478cee4794SMasatake YAMATO    local has_expected_tags=no
27488cee4794SMasatake YAMATO    for f in "${base_dir}"/expected.tags*; do
27498cee4794SMasatake YAMATO	[ -r "$f" ] || continue
27503b5447bcSMasatake YAMATO	failure_in_globing "$f" && continue
27518cee4794SMasatake YAMATO	has_expected_tags=yes
27528cee4794SMasatake YAMATO	break
27538cee4794SMasatake YAMATO    done
27548cee4794SMasatake YAMATO
2755e5399325SMasatake YAMATO    # A validator specified in ./validator is used for validating ./input.foo.
2756e5399325SMasatake YAMATO    # It will be used for validating ./input[-_]*.foo, too if ./validator[-_]*.
27578cee4794SMasatake YAMATO    # doesn't exit.
27588cee4794SMasatake YAMATO    inputs0=$(for f in "${base_dir}"/input.*; do
27598cee4794SMasatake YAMATO		  [ -r "$f" ] || continue
27603b5447bcSMasatake YAMATO		  failure_in_globing "$f" && continue
27618cee4794SMasatake YAMATO		  echo $f
27628cee4794SMasatake YAMATO	      done | sort)
2763e5399325SMasatake YAMATO    v0=$(resolve_validator "${base_dir}"/validator \
2764e5399325SMasatake YAMATO			  "${default_validator}" \
27658cee4794SMasatake YAMATO			  "${has_expected_tags}" \
2766e5399325SMasatake YAMATO			  "${validators_dir}")
27678cee4794SMasatake YAMATO    s0=$?
27688cee4794SMasatake YAMATO
27698cee4794SMasatake YAMATO    case "$s0" in
27708cee4794SMasatake YAMATO	0)
2771e5399325SMasatake YAMATO	    update_validator_list runnable "$v0"
27728cee4794SMasatake YAMATO	    for f in $inputs0; do
2773e5399325SMasatake YAMATO		if validate_file "$f" "$v0" "${validators_dir}"; then
2774e5399325SMasatake YAMATO		    validate_report_one "$f" "$v0" valid
27758cee4794SMasatake YAMATO		else
2776e5399325SMasatake YAMATO		    validate_report_one "$f" "$v0" invalid
27778cee4794SMasatake YAMATO		fi
27788cee4794SMasatake YAMATO	    done
2779e5399325SMasatake YAMATO	    default_validator=$v0
27808cee4794SMasatake YAMATO	    ;;
27818cee4794SMasatake YAMATO	1)
2782ebdbd8e2SK.Takata	    # no action needed
27838cee4794SMasatake YAMATO	    ;;
27848cee4794SMasatake YAMATO	2)
2785e5399325SMasatake YAMATO	    update_validator_list unavailable "$v0"
27868cee4794SMasatake YAMATO	    for f in $inputs0; do
2787e5399325SMasatake YAMATO		validate_report_one "$f" "$v0" unavailable
27888cee4794SMasatake YAMATO	    done
2789e5399325SMasatake YAMATO	    default_validator=
27908cee4794SMasatake YAMATO	    ;;
27918cee4794SMasatake YAMATO    esac
27928cee4794SMasatake YAMATO
27938cee4794SMasatake YAMATO    inputs=$(for f in "${base_dir}"/input[-_][0-9].* \
27948cee4794SMasatake YAMATO		      "${base_dir}"/input[-_][0-9][-_]*.*; do
27958cee4794SMasatake YAMATO		 [ -r "$f" ] || continue
27963b5447bcSMasatake YAMATO		 failure_in_globing "$f" && continue
27978cee4794SMasatake YAMATO		 echo $f
27988cee4794SMasatake YAMATO	     done | sort)
27998cee4794SMasatake YAMATO
28008cee4794SMasatake YAMATO    for f in $inputs; do
2801*aba929e4SMasatake YAMATO	t=$(basename $f)
2802*aba929e4SMasatake YAMATO	t=${t#input}; t=${t%.*}
2803e5399325SMasatake YAMATO	v=$(resolve_validator "${base_dir}"/validator"$t" \
2804e5399325SMasatake YAMATO			     "$default_validator" \
28058cee4794SMasatake YAMATO			     "$has_expected_tags" \
2806e5399325SMasatake YAMATO			     "$validators_dir")
28078cee4794SMasatake YAMATO	s=$?
28088cee4794SMasatake YAMATO	case "$s" in
28098cee4794SMasatake YAMATO	    0)
2810e5399325SMasatake YAMATO		update_validator_list runnable "$v0"
2811e5399325SMasatake YAMATO		if validate_file "$f" "$v" "${validators_dir}"; then
2812e5399325SMasatake YAMATO		    validate_report_one "$f" "$v" valid
28138cee4794SMasatake YAMATO		else
2814e5399325SMasatake YAMATO		    validate_report_one "$f" "$v" invalid
28158cee4794SMasatake YAMATO		fi
28168cee4794SMasatake YAMATO		;;
28178cee4794SMasatake YAMATO	    1)
2818ebdbd8e2SK.Takata		# no action needed
28198cee4794SMasatake YAMATO		;;
28208cee4794SMasatake YAMATO	    2)
2821e5399325SMasatake YAMATO		update_validator_list unavailable "$v0"
2822e5399325SMasatake YAMATO		validate_report_one "$f" "$v" unavailable
28238cee4794SMasatake YAMATO		;;
28248cee4794SMasatake YAMATO	esac
28258cee4794SMasatake YAMATO    done
28268cee4794SMasatake YAMATO}
28278cee4794SMasatake YAMATO
28288cee4794SMasatake YAMATO#
2829e5399325SMasatake YAMATO# Validate input files under *.r.
28308cee4794SMasatake YAMATO#
2831e5399325SMasatake YAMATOvalidate_category ()
28328cee4794SMasatake YAMATO{
28338cee4794SMasatake YAMATO    local category=$1
28348cee4794SMasatake YAMATO    local base_dir=$2
2835e5399325SMasatake YAMATO    local validators_dir=$3
28368cee4794SMasatake YAMATO    shift 3
28378cee4794SMasatake YAMATO
28388cee4794SMasatake YAMATO    local d
2839e5399325SMasatake YAMATO    local default_validator=${_NOOP_VALIDATOR}
28408cee4794SMasatake YAMATO
2841e5399325SMasatake YAMATO    if [ -r "${base_dir}/validator" ]; then
2842e5399325SMasatake YAMATO	default_validator=$(cat "${base_dir}/validator" | grep -v '#')
2843e5399325SMasatake YAMATO	if [ -z "${default_validator}" ]; then
2844e5399325SMasatake YAMATO	    ERROR 1 "Empty validator specfile (in ${base_dir}/validator)"
28458cee4794SMasatake YAMATO	fi
28468cee4794SMasatake YAMATO
2847e5399325SMasatake YAMATO	validate_validator "${default_validator}" "${validators_dir}" noerror
28488cee4794SMasatake YAMATO    fi
28498cee4794SMasatake YAMATO
28508cee4794SMasatake YAMATO    for d in "${base_dir}"/*.[dbtiv]; do
28518cee4794SMasatake YAMATO	[ -d "$d" ] || continue
2852e5399325SMasatake YAMATO	validate_dir "$d" "${default_validator}" "${validators_dir}"
28538cee4794SMasatake YAMATO    done
28548cee4794SMasatake YAMATO}
28558cee4794SMasatake YAMATO
28568cee4794SMasatake YAMATO#
2857e5399325SMasatake YAMATO# Report the summary of validations
28588cee4794SMasatake YAMATO#
2859e5399325SMasatake YAMATOvalidate_summary ()
28608cee4794SMasatake YAMATO{
28618cee4794SMasatake YAMATO    echo
28628cee4794SMasatake YAMATO    echo "Summary"
28638cee4794SMasatake YAMATO    line
28648cee4794SMasatake YAMATO
28658cee4794SMasatake YAMATO    printf '  %-40s' "#valid:"
28668cee4794SMasatake YAMATO    printf '%b\n' $(decorate green "${V_VALID}")
28678cee4794SMasatake YAMATO
28688cee4794SMasatake YAMATO    printf '  %-40s' "#invalid:"
28698cee4794SMasatake YAMATO    if [ "${V_INVALID}" = 0 ]; then
28708cee4794SMasatake YAMATO	echo "${V_INVALID}"
28718cee4794SMasatake YAMATO    else
28728cee4794SMasatake YAMATO	printf '%b\n' $(decorate red "${V_INVALID}")
28738cee4794SMasatake YAMATO    fi
28748cee4794SMasatake YAMATO
28758cee4794SMasatake YAMATO    printf '  %-40s' "#skipped (known invalidation)"
28768cee4794SMasatake YAMATO    if [ "${V_SKIP_KNOWN_INVALIDATION}" = 0 ]; then
28778cee4794SMasatake YAMATO	echo 0
28788cee4794SMasatake YAMATO    else
28798cee4794SMasatake YAMATO	printf '%b\n' $(decorate yellow "${V_SKIP_KNOWN_INVALIDATION}")
28808cee4794SMasatake YAMATO    fi
28818cee4794SMasatake YAMATO
2882e5399325SMasatake YAMATO    printf '  %-40s' "#skipped (validator unavailable)"
2883e5399325SMasatake YAMATO    if [ "${V_SKIP_VALIDATOR_UNAVAILABLE}" = 0 ]; then
28848cee4794SMasatake YAMATO	echo 0
28858cee4794SMasatake YAMATO    else
28868cee4794SMasatake YAMATO	local u
2887e5399325SMasatake YAMATO	printf '%b\n' $(decorate yellow "${V_SKIP_VALIDATOR_UNAVAILABLE}")
28888cee4794SMasatake YAMATO
28898cee4794SMasatake YAMATO	echo
2890e5399325SMasatake YAMATO	echo "Unavailable validators"
28918cee4794SMasatake YAMATO	line
2892e5399325SMasatake YAMATO	for u in ${_UNAVAILABLE_VALIDATORS}; do
28938cee4794SMasatake YAMATO	    echo "	$u"
28948cee4794SMasatake YAMATO	done
28958cee4794SMasatake YAMATO    fi
28968cee4794SMasatake YAMATO
28978cee4794SMasatake YAMATO    if [ "${V_INVALID}" = 0 ]; then
28988cee4794SMasatake YAMATO	return 0
28998cee4794SMasatake YAMATO    else
29008cee4794SMasatake YAMATO	return "${_VALIDATION_EXIT_INVALID}"
29018cee4794SMasatake YAMATO    fi
29028cee4794SMasatake YAMATO}
29038cee4794SMasatake YAMATO
2904e5399325SMasatake YAMATOaction_validate_input ()
29058cee4794SMasatake YAMATO{
29068cee4794SMasatake YAMATO    local action=$1
29078cee4794SMasatake YAMATO    shift
29088cee4794SMasatake YAMATO
29098cee4794SMasatake YAMATO    local units_dir
2910e5399325SMasatake YAMATO    local validators_dir
2911e5399325SMasatake YAMATO    local validators
29128cee4794SMasatake YAMATO
29138cee4794SMasatake YAMATO    local v
29148cee4794SMasatake YAMATO    local d
29158cee4794SMasatake YAMATO
29168cee4794SMasatake YAMATO    while [ $# -gt 0 ]; do
29178cee4794SMasatake YAMATO	case $1 in
2918e5399325SMasatake YAMATO	    --validators)
29198cee4794SMasatake YAMATO		shift
2920e5399325SMasatake YAMATO		validators=$1
29218cee4794SMasatake YAMATO		shift
29228cee4794SMasatake YAMATO		;;
2923e5399325SMasatake YAMATO	    --validators=*)
2924e5399325SMasatake YAMATO		validators=${1#--validators=}
29258cee4794SMasatake YAMATO		shift
29268cee4794SMasatake YAMATO		;;
29278cee4794SMasatake YAMATO	    --colorized-output)
29288cee4794SMasatake YAMATO		shift
29298cee4794SMasatake YAMATO		COLORIZED_OUTPUT=$1
29308cee4794SMasatake YAMATO		shift
29318cee4794SMasatake YAMATO		;;
29328cee4794SMasatake YAMATO	    --colorized-output=*)
29338cee4794SMasatake YAMATO		COLORIZED_OUTPUT=${1#--colorized-output=}
29348cee4794SMasatake YAMATO		shift
29358cee4794SMasatake YAMATO		;;
29368cee4794SMasatake YAMATO	    -*)
29378cee4794SMasatake YAMATO		ERROR 1 "unknown option \"${1}\" for ${action} action"
29388cee4794SMasatake YAMATO		;;
29398cee4794SMasatake YAMATO	    *)
29408cee4794SMasatake YAMATO		units_dir=$1
29418cee4794SMasatake YAMATO		shift
2942e5399325SMasatake YAMATO		validators_dir=$1
29438cee4794SMasatake YAMATO		shift
29448cee4794SMasatake YAMATO		break;
29458cee4794SMasatake YAMATO		;;
29468cee4794SMasatake YAMATO	esac
29478cee4794SMasatake YAMATO    done
29488cee4794SMasatake YAMATO
29498cee4794SMasatake YAMATO    if [ $# -gt 0 ]; then
29508cee4794SMasatake YAMATO	ERROR 1 "too many arguments for ${action} action: $*"
29518cee4794SMasatake YAMATO    elif [ -z "${units_dir}" ]; then
29528cee4794SMasatake YAMATO	ERROR 1 "UNITS_DIR parameter is not given in ${action} action"
2953e5399325SMasatake YAMATO    elif [ -z "${validators_dir}" ]; then
2954e5399325SMasatake YAMATO	ERROR 1 "VALIDATORS_DIR parameter is not given in ${action} action"
29558cee4794SMasatake YAMATO    fi
29568cee4794SMasatake YAMATO
29578cee4794SMasatake YAMATO    if ! [ -d "${units_dir}" ]; then
29588cee4794SMasatake YAMATO	ERROR 1 "No such directory: ${units_dir}"
2959e5399325SMasatake YAMATO    elif ! [ -d "${validators_dir}" ]; then
29608cee4794SMasatake YAMATO	ERROR 1 "No such directory: ${units_dir}"
29618cee4794SMasatake YAMATO    fi
29628cee4794SMasatake YAMATO
29638cee4794SMasatake YAMATO    if ! ( [ "${COLORIZED_OUTPUT}" = 'yes' ] || [ "${COLORIZED_OUTPUT}" = 'no' ] ); then
29648cee4794SMasatake YAMATO	ERROR 1 "unexpected option argument for --colorized-output: ${COLORIZED_OUTPUT}"
29658cee4794SMasatake YAMATO    fi
29668cee4794SMasatake YAMATO
2967e5399325SMasatake YAMATO    if [ -n "${validators}" ]; then
2968e5399325SMasatake YAMATO	VALIDATORS=$(echo "${validators}" | tr ',' ' ')
2969e5399325SMasatake YAMATO	for v in ${VALIDATORS}; do
2970e5399325SMasatake YAMATO	    validate_validator "$v" "${validators_dir}" error
29718cee4794SMasatake YAMATO	done
29728cee4794SMasatake YAMATO    fi
29738cee4794SMasatake YAMATO
29748cee4794SMasatake YAMATO    for d in ${units_dir}/*.r; do
29758cee4794SMasatake YAMATO	[ -d "$d" ] || continue
29768cee4794SMasatake YAMATO	category=${d##*/}
29778cee4794SMasatake YAMATO	echo
29788cee4794SMasatake YAMATO	echo "Category: ${category}"
29798cee4794SMasatake YAMATO	line
2980e5399325SMasatake YAMATO	validate_category "${category}" "$d" "${validators_dir}"
29818cee4794SMasatake YAMATO    done
29828cee4794SMasatake YAMATO
29838cee4794SMasatake YAMATO    echo
29848cee4794SMasatake YAMATO    echo "Category: ${_DEFAULT_CATEGORY}"
29858cee4794SMasatake YAMATO    line
29868cee4794SMasatake YAMATO    for d in ${units_dir}/*.[dbtiv]; do
29878cee4794SMasatake YAMATO	[ -d "$d" ] || continue
2988e5399325SMasatake YAMATO	validate_dir "$d" "${_NOOP_VALIDATOR}" "$validators_dir"
29898cee4794SMasatake YAMATO    done
29908cee4794SMasatake YAMATO
2991e5399325SMasatake YAMATO    validate_summary
29928cee4794SMasatake YAMATO    return $?
29938cee4794SMasatake YAMATO}
29948cee4794SMasatake YAMATO
29959bca788aSK.Takata# * Avoid issues between sed and the locale settings by overriding it using
29969cb031d2SVitor Antunes#   LC_ALL, which takes precedence over all other locale configurations:
29979cb031d2SVitor Antunes#   https://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html
29989bca788aSK.Takata#
29999bca788aSK.Takata# * Avoid unexpected pathname conversion on MSYS2.
300067d954b8SMasatake YAMATO#   https://github.com/msys2/msys2/wiki/Porting#filesystem-namespaces
30019cb031d2SVitor Antunesprepare_environment ()
30029cb031d2SVitor Antunes{
30039bca788aSK.Takata    _PREPERE_ENV=$(cat <<'EOF'
30049cb031d2SVitor AntunesLC_ALL="C"; export LC_ALL
3005acf93fd6SMasatake YAMATOMSYS2_ARG_CONV_EXCL='--regex-;--_scopesep' export MSYS2_ARG_CONV_EXCL
30069bca788aSK.TakataEOF
30079bca788aSK.Takata)
30089bca788aSK.Takata    eval ${_PREPERE_ENV}
30099cb031d2SVitor Antunes}
30109cb031d2SVitor Antunes
30112b81e1e7SMasatake YAMATOmain ()
30122b81e1e7SMasatake YAMATO{
30132b81e1e7SMasatake YAMATO    if [ $# = 0 ]; then
30142b81e1e7SMasatake YAMATO	action_help 1>&2
3015796e3610SMasatake YAMATO	exit 1
30162b81e1e7SMasatake YAMATO    fi
30172b81e1e7SMasatake YAMATO
30182b81e1e7SMasatake YAMATO    case $1 in
30192b81e1e7SMasatake YAMATO	help|-h|--help)
30202b81e1e7SMasatake YAMATO	    action_help
30212b81e1e7SMasatake YAMATO	    return 0
30222b81e1e7SMasatake YAMATO	    ;;
30232b81e1e7SMasatake YAMATO	run)
30242b81e1e7SMasatake YAMATO	    action_run "$@"
30252b81e1e7SMasatake YAMATO	    return $?
30262b81e1e7SMasatake YAMATO	    ;;
3027e1476aceSMasatake YAMATO	clean)
3028e1476aceSMasatake YAMATO	    action_clean "$@"
3029e1476aceSMasatake YAMATO	    return $?
3030e1476aceSMasatake YAMATO	    ;;
30316eb4d4b5SMasatake YAMATO	fuzz)
30326eb4d4b5SMasatake YAMATO	    action_fuzz "$@"
30336eb4d4b5SMasatake YAMATO	    return $?
30346eb4d4b5SMasatake YAMATO	    ;;
3035796e3610SMasatake YAMATO	noise)
3036796e3610SMasatake YAMATO	    action_noise "$@"
3037796e3610SMasatake YAMATO	    return $?
3038796e3610SMasatake YAMATO	    ;;
3039ec63b4a8SMasatake YAMATO	tmain)
3040ec63b4a8SMasatake YAMATO	    action_tmain "$@"
3041ec63b4a8SMasatake YAMATO	    return $?
3042ec63b4a8SMasatake YAMATO	    ;;
3043be317af6SMasatake YAMATO	clean-tmain)
3044be317af6SMasatake YAMATO	    action_clean_tmain "$@"
3045be317af6SMasatake YAMATO	    return $?
3046be317af6SMasatake YAMATO	    ;;
3047470fca09SMasatake YAMATO	shrink)
3048470fca09SMasatake YAMATO	    action_shrink "$@"
3049470fca09SMasatake YAMATO	    return $?
3050470fca09SMasatake YAMATO	    ;;
305130bea0aeSMasatake YAMATO	chop)
305230bea0aeSMasatake YAMATO	    action_chop "$@"
305330bea0aeSMasatake YAMATO	    return $?
305430bea0aeSMasatake YAMATO	    ;;
3055a379e1ccSMasatake YAMATO	slap)
3056a379e1ccSMasatake YAMATO	    action_chop "$@"
3057a379e1ccSMasatake YAMATO	    return $?
3058a379e1ccSMasatake YAMATO	    ;;
3059e5399325SMasatake YAMATO	validate-input)
3060e5399325SMasatake YAMATO	    action_validate_input "$@"
30618cee4794SMasatake YAMATO	    return $?
30628cee4794SMasatake YAMATO	    ;;
30632b81e1e7SMasatake YAMATO	*)
30642b81e1e7SMasatake YAMATO	    ERROR 1 "unknown action: $1"
30652b81e1e7SMasatake YAMATO	    ;;
30662b81e1e7SMasatake YAMATO    esac
30672b81e1e7SMasatake YAMATO}
30682b81e1e7SMasatake YAMATO
30699cb031d2SVitor Antunesprepare_environment
30702b81e1e7SMasatake YAMATOmain "$@"
30712b81e1e7SMasatake YAMATOexit $?
3072