[Mesa-dev] [PATCH v2 06/12] glcpp/tests: Convert shell scripts to a python script

Juan A. Suarez Romero jasuarez at igalia.com
Fri Apr 20 17:18:03 UTC 2018


On Thu, 2018-04-05 at 14:51 -0700, Dylan Baker wrote:
> This ports glcpp-test.sh and glcpp-test-cr-lf.sh to a python script that
> accepts arguments for each line ending type. This should allow for
> better reporting to users.
> 
> Signed-off-by: Dylan Baker <dylan.c.baker at intel.com>

Hi!


I think this patch is causing failing tests in "macOs Make"

https://travis-ci.org/Igalia/release-mesa/builds/369006234


	J.A.


> ---
>  src/compiler/glsl/glcpp/tests/glcpp-test-cr-lf.sh | 148 +----------
>  src/compiler/glsl/glcpp/tests/glcpp-test.sh       | 121 +--------
>  src/compiler/glsl/glcpp/tests/glcpp_test.py       | 221 +++++++++++++++-
>  3 files changed, 223 insertions(+), 267 deletions(-)
>  create mode 100755 src/compiler/glsl/glcpp/tests/glcpp_test.py
> 
> diff --git a/src/compiler/glsl/glcpp/tests/glcpp-test-cr-lf.sh b/src/compiler/glsl/glcpp/tests/glcpp-test-cr-lf.sh
> index c1e3929..5b5335f 100755
> --- a/src/compiler/glsl/glcpp/tests/glcpp-test-cr-lf.sh
> +++ b/src/compiler/glsl/glcpp/tests/glcpp-test-cr-lf.sh
> @@ -1,149 +1,3 @@
>  #!/bin/sh
>  
> -if [ -z "$srcdir" -o -z "$abs_builddir" ]; then
> -    echo ""
> -    echo "Warning: you're invoking the script manually and things may fail."
> -    echo "Attempting to determine/set srcdir and abs_builddir variables."
> -    echo ""
> -
> -    # Should point to `dirname Makefile.glsl.am`
> -    srcdir=./../../../
> -    cd `dirname "$0"`
> -    # Should point to `dirname Makefile` equivalent to the above.
> -    abs_builddir=`pwd`/../../../
> -fi
> -
> -testdir="$srcdir/glsl/glcpp/tests"
> -glcpp_test="$srcdir/glsl/glcpp/tests/glcpp-test.sh"
> -
> -total=0
> -pass=0
> -
> -# This supports a pipe that doesn't destroy the exit status of first command
> -#
> -# http://unix.stackexchange.com/questions/14270/get-exit-status-of-process-thats-piped-to-another
> -stdintoexitstatus() {
> -    read exitstatus
> -    return $exitstatus
> -}
> -
> -run_test ()
> -{
> -    cmd="$1"
> -
> -    total=$((total+1))
> -
> -    if [ "$VERBOSE" = "yes" ]; then
> -	if $cmd; then
> -	    echo "PASS"
> -	    pass=$((pass+1))
> -	else
> -	    echo "FAIL"
> -	fi
> -    else
> -	# This is "$cmd | tail -2" but with the exit status of "$cmd" not "tail -2"
> -	if (((($cmd; echo $? >&3) | tail -2 | head -1 >&4) 3>&1) | stdintoexitstatus) 4>&1; then
> -	    echo "PASS"
> -	    pass=$((pass+1))
> -	else
> -	    echo "FAIL"
> -	fi
> -    fi
> -}
> -
> -usage ()
> -{
> -	cat <<EOF
> -Usage: `basename "$0"` [options...]
> -
> -Run the entire glcpp-test suite several times, each time with each source
> -file transformed to use a non-standard line-termination character. Each
> -entire run with a different line-termination character is considered a
> -single test.
> -
> -Valid options include:
> -
> -	-v|--verbose	Print all output from the various sub-tests
> -EOF
> -}
> -
> -# Parse command-line options
> -for option; do
> -    case "${option}" in
> -	-v|--verbose)
> -	    VERBOSE=yes;
> -	    ;;
> -	*)
> -	    echo "Unrecognized option: $option" >&2
> -	    echo >&2
> -	    usage
> -	    exit 1
> -	    ;;
> -	esac
> -done
> -
> -# All tests depend on the .out files being present. So first do a
> -# normal run of the test suite, (silently) just to create the .out
> -# files as a side effect.
> -rm -rf ./subtest-lf
> -mkdir subtest-lf
> -for file in "$testdir"/*.c; do
> -    base=$(basename "$file")
> -    cp "$file" subtest-lf
> -done
> -
> -${glcpp_test} --testdir=subtest-lf >/dev/null 2>&1
> -
> -echo "===== Testing with \\\\r line terminators (old Mac format) ====="
> -
> -# Prepare test files with '\r' instead of '\n'
> -rm -rf ./subtest-cr
> -mkdir subtest-cr
> -for file in "$testdir"/*.c; do
> -    base=$(basename "$file")
> -    tr "\n" "\r" < "$file" > subtest-cr/"$base"
> -    cp $abs_builddir/glsl/glcpp/tests/subtest-lf/"$base".out subtest-cr/"$base".expected
> -done
> -
> -run_test "${glcpp_test} --testdir=subtest-cr"
> -
> -echo "===== Testing with \\\\r\\\\n line terminators (DOS format) ====="
> -
> -# Prepare test files with '\r\n' instead of '\n'
> -rm -rf ./subtest-cr-lf
> -mkdir subtest-cr-lf
> -for file in "$testdir"/*.c; do
> -    base=$(basename "$file")
> -    sed -e 's/$/
> /' < "$file" > subtest-cr-lf/"$base"
> -    cp $abs_builddir/glsl/glcpp/tests/subtest-lf/"$base".out subtest-cr-lf/"$base".expected
> -done
> -
> -run_test "${glcpp_test} --testdir=subtest-cr-lf"
> -
> -echo "===== Testing with \\\\n\\\\r (bizarre, but allowed by GLSL spec.) ====="
> -
> -# Prepare test files with '\n\r' instead of '\n'
> -rm -rf ./subtest-lf-cr
> -mkdir subtest-lf-cr
> -for file in "$testdir"/*.c; do
> -    base=$(basename "$file")
> -    sed -e 's/$/
> /' < "$file" | tr "\n\r" "\r\n" > subtest-lf-cr/"$base"
> -    cp $abs_builddir/glsl/glcpp/tests/subtest-lf/"$base".out subtest-lf-cr/"$base".expected
> -done
> -
> -run_test "${glcpp_test} --testdir=subtest-lf-cr"
> -
> -if [ $total -eq 0 ]; then
> -    echo "Could not find any tests."
> -    exit 1
> -fi
> -
> -echo ""
> -echo "$pass/$total tests returned correct results"
> -echo ""
> -
> -if [ "$pass" = "$total" ]; then
> -    exit 0
> -else
> -    exit 1
> -fi
> +$srcdir/glsl/glcpp/tests/glcpp_test.py $abs_builddir/glsl/glcpp/glcpp $srcdir/glsl/glcpp/tests --windows --oldmac --bizarro
> diff --git a/src/compiler/glsl/glcpp/tests/glcpp-test.sh b/src/compiler/glsl/glcpp/tests/glcpp-test.sh
> index 44c9451..d16e2cd 100755
> --- a/src/compiler/glsl/glcpp/tests/glcpp-test.sh
> +++ b/src/compiler/glsl/glcpp/tests/glcpp-test.sh
> @@ -1,122 +1,3 @@
>  #!/bin/sh
>  
> -if [ -z "$srcdir" -o -z "$abs_builddir" ]; then
> -    echo ""
> -    echo "Warning: you're invoking the script manually and things may fail."
> -    echo "Attempting to determine/set srcdir and abs_builddir variables."
> -    echo ""
> -
> -    # Should point to `dirname Makefile.glsl.am`
> -    srcdir=./../../../
> -    cd `dirname "$0"`
> -    # Should point to `dirname Makefile` equivalent to the above.
> -    abs_builddir=`pwd`/../../../
> -fi
> -
> -testdir=$srcdir/glsl/glcpp/tests
> -outdir=$abs_builddir/glsl/glcpp/tests
> -glcpp=$abs_builddir/glsl/glcpp/glcpp
> -
> -trap 'rm $test.valgrind-errors; exit 1' INT QUIT
> -
> -usage ()
> -{
> -    cat <<EOF
> -Usage: `basename "$0"` [options...]
> -
> -Run the test suite for mesa's GLSL pre-processor.
> -
> -Valid options include:
> -
> -	--testdir=<DIR>	Use tests in the given <DIR> (default is ".")
> -	--valgrind	Run the test suite a second time under valgrind
> -EOF
> -}
> -
> -test_specific_args ()
> -{
> -    test="$1"
> -
> -    tr "\r" "\n" < "$test" | grep 'glcpp-args:' | sed -e 's,^.*glcpp-args: *,,'
> -}
> -
> -# Parse command-line options
> -for option; do
> -    case "${option}" in
> -        "--help")
> -            usage
> -            exit 0
> -            ;;
> -        "--valgrind")
> -	    do_valgrind=yes
> -            ;;
> -        "--testdir="*)
> -            testdir="${option#--testdir=}"
> -            outdir="${outdir}/${option#--testdir=}"
> -            ;;
> -        *)
> -	    echo "Unrecognized option: $option" >&2
> -	    echo >&2
> -	    usage
> -	    exit 1
> -            ;;
> -        esac
> -done
> -
> -total=0
> -pass=0
> -clean=0
> -
> -mkdir -p $outdir
> -
> -echo "====== Testing for correctness ======"
> -for test in $testdir/*.c; do
> -    out=$outdir/${test##*/}.out
> -
> -    printf "Testing `basename $test`... "
> -    $glcpp $(test_specific_args $test) < $test > $out 2>&1
> -    total=$((total+1))
> -    if cmp $test.expected $out >/dev/null 2>&1; then
> -	echo "PASS"
> -	pass=$((pass+1))
> -    else
> -	echo "FAIL"
> -	diff -u $test.expected $out
> -    fi
> -done
> -
> -if [ $total -eq 0 ]; then
> -    echo "Could not find any tests."
> -    exit 1
> -fi
> -
> -echo ""
> -echo "$pass/$total tests returned correct results"
> -echo ""
> -
> -if [ "$do_valgrind" = "yes" ]; then
> -    echo "====== Testing for valgrind cleanliness ======"
> -    for test in $testdir/*.c; do
> -	printf "Testing `basename $test` with valgrind..."
> -	valgrind --error-exitcode=31 --log-file=$test.valgrind-errors $glcpp $(test_specific_args $test) < $test >/dev/null 2>&1
> -	if [ "$?" = "31" ]; then
> -	    echo "ERRORS"
> -	    cat $test.valgrind-errors
> -	else
> -	    echo "CLEAN"
> -	    clean=$((clean+1))
> -	    rm $test.valgrind-errors
> -	fi
> -    done
> -
> -    echo ""
> -    echo "$pass/$total tests returned correct results"
> -    echo "$clean/$total tests are valgrind-clean"
> -fi
> -
> -if [ "$pass" = "$total" ] && [ "$do_valgrind" != "yes" ] || [ "$pass" = "$total" ]; then
> -    exit 0
> -else
> -    exit 1
> -fi
> -
> +$srcdir/glsl/glcpp/tests/glcpp_test.py $abs_builddir/glsl/glcpp/glcpp $srcdir/glsl/glcpp/tests --unix
> diff --git a/src/compiler/glsl/glcpp/tests/glcpp_test.py b/src/compiler/glsl/glcpp/tests/glcpp_test.py
> new file mode 100755
> index 0000000..f07c241
> --- /dev/null
> +++ b/src/compiler/glsl/glcpp/tests/glcpp_test.py
> @@ -0,0 +1,221 @@
> +#!/usr/bin/env python2
> +# encoding=utf-8
> +# Copyright © 2018 Intel Corporation
> +
> +# Permission is hereby granted, free of charge, to any person obtaining a copy
> +# of this software and associated documentation files (the "Software"), to deal
> +# in the Software without restriction, including without limitation the rights
> +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> +# copies of the Software, and to permit persons to whom the Software is
> +# furnished to do so, subject to the following conditions:
> +
> +# The above copyright notice and this permission notice shall be included in
> +# all copies or substantial portions of the Software.
> +
> +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> +# SOFTWARE.
> +
> +"""Run glcpp tests with various line endings."""
> +
> +from __future__ import print_function
> +import argparse
> +import difflib
> +import io
> +import os
> +import subprocess
> +import sys
> +import tempfile
> +
> +
> +def arg_parser():
> +    parser = argparse.ArgumentParser()
> +    parser.add_argument('glcpp', help='Path to the he glcpp binary.')
> +    parser.add_argument('testdir', help='Path to tests and expected output.')
> +    parser.add_argument('--unix', action='store_true', help='Run tests for Unix style newlines')
> +    parser.add_argument('--windows', action='store_true', help='Run tests for Windows/Dos style newlines')
> +    parser.add_argument('--oldmac', action='store_true', help='Run tests for Old Mac (pre-OSX) style newlines')
> +    parser.add_argument('--bizarro', action='store_true', help='Run tests for Bizarro world style newlines')
> +    parser.add_argument('--valgrind', action='store_true', help='Run with valgrind for errors')
> +    return parser.parse_args()
> +
> +
> +def parse_test_file(filename, nl_format):
> +    """Check for any special arguments and return them as a list."""
> +    with open(filename) as f:
> +        for l in f.read().split(nl_format):
> +            if 'glcpp-args:' in l:
> +                return l.split('glcpp-args:')[1].strip().split()
> +    return []
> +
> +
> +def test_output(glcpp, filename, expfile, nl_format='\n'):
> +    """Test that the output of glcpp is what we expect."""
> +    extra_args = parse_test_file(filename, nl_format)
> +
> +    with open(filename, 'rb') as f:
> +        proc = subprocess.Popen(
> +            [glcpp] + extra_args,
> +            stdout=subprocess.PIPE,
> +            stderr=subprocess.STDOUT,
> +            stdin=subprocess.PIPE)
> +        actual, _ = proc.communicate(f.read())
> +
> +    with open(expfile, 'rb') as f:
> +        expected = f.read()
> +
> +    if actual == expected:
> +        return (True, [])
> +    return (False, difflib.unified_diff(actual.splitlines(), expected.splitlines()))
> +
> +
> +def _valgrind(glcpp, filename):
> +    """Run valgrind and report any warnings."""
> +    extra_args = parse_test_file(filename, nl_format='\n')
> +
> +    try:
> +        _, tmpfile = tempfile.mkstemp()
> +        with open(filename, 'rb') as f:
> +            proc = subprocess.Popen(
> +                ['valgrind', '--error-exitcode=31', '--log-file', tmpfile, glcpp] + extra_args,
> +                stdout=subprocess.PIPE,
> +                stderr=subprocess.STDOUT,
> +                stdin=subprocess.PIPE)
> +            proc.communicate(f.read())
> +            if proc.returncode != 31:
> +                return (True, [])
> +        with open(tmpfile, 'rb') as f:
> +            contents = f.read()
> +        return (False, contents)
> +    finally:
> +        os.unlink(tmpfile)
> +
> +
> +def test_unix(args):
> +    """Test files with unix style (\n) new lines."""
> +    total = 0
> +    passed = 0
> +
> +    print('============= Testing for Correctness (Unix) =============')
> +    for filename in os.listdir(args.testdir):
> +        if not filename.endswith('.c'):
> +            continue
> +
> +        print(   '{}:'.format(os.path.splitext(filename)[0]), end=' ')
> +        total += 1
> +
> +        testfile = os.path.join(args.testdir, filename)
> +        valid, diff = test_output(args.glcpp, testfile, testfile + '.expected')
> +        if valid:
> +            passed += 1
> +            print('PASS')
> +        else:
> +            print('FAIL')
> +            for l in diff:
> +                print(l, file=sys.stderr)
> +
> +    print('{}/{}'.format(passed, total), 'tests returned correct results')
> +    return total == passed
> +
> +
> +def _replace_test(args, replace):
> +    """Test files with non-unix style line endings. Print your own header."""
> +    total = 0
> +    passed = 0
> +
> +    for filename in os.listdir(args.testdir):
> +        if not filename.endswith('.c'):
> +            continue
> +
> +        print(   '{}:'.format(os.path.splitext(filename)[0]), end=' ')
> +        total += 1
> +        testfile = os.path.join(args.testdir, filename)
> +        try:
> +            _, tmpfile = tempfile.mkstemp()
> +            with io.open(testfile, 'rt') as f:
> +                contents = f.read()
> +            with io.open(tmpfile, 'wt') as f:
> +                f.write(contents.replace('\n', replace))
> +            valid, diff = test_output(
> +                args.glcpp, tmpfile, testfile + '.expected', nl_format=replace)
> +        finally:
> +            os.unlink(tmpfile)
> +
> +        if valid:
> +            passed += 1
> +            print('PASS')
> +        else:
> +            print('FAIL')
> +            for l in diff:
> +                print(l, file=sys.stderr)
> +
> +    print('{}/{}'.format(passed, total), 'tests returned correct results')
> +    return total == passed
> +
> +
> +def test_windows(args):
> +    """Test files with windows/dos style (\r\n) new lines."""
> +    print('============= Testing for Correctness (Windows) =============')
> +    return _replace_test(args, '\r\n')
> +
> +
> +def test_oldmac(args):
> +    """Test files with Old Mac style (\r) new lines."""
> +    print('============= Testing for Correctness (Old Mac) =============')
> +    return _replace_test(args, '\r')
> +
> +
> +def test_bizarro(args):
> +    """Test files with Bizarro world style (\n\r) new lines."""
> +    # This is allowed by the spec, but why?
> +    print('============= Testing for Correctness (Bizarro) =============')
> +    return _replace_test(args, '\n\r')
> +
> +
> +def test_valgrind(args):
> +    total = 0
> +    passed = 0
> +
> +    print('============= Testing for Valgrind Warnings =============')
> +    for filename in os.listdir(args.testdir):
> +        if not filename.endswith('.c'):
> +            continue
> +
> +        print(   '{}:'.format(os.path.splitext(filename)[0]), end=' ')
> +        total += 1
> +        valid, log = _valgrind(args.glcpp, os.path.join(args.testdir, filename))
> +        if valid:
> +            passed += 1
> +            print('PASS')
> +        else:
> +            print('FAIL')
> +            print(log, file=sys.stderr)
> +
> +    print('{}/{}'.format(passed, total), 'tests returned correct results')
> +    return total == passed
> +
> +
> +def main():
> +    args = arg_parser()
> +
> +    success = True
> +    if args.unix:
> +        success = success and test_unix(args)
> +    if args.windows:
> +        success = success and test_windows(args)
> +    if args.oldmac:
> +        success = success and test_oldmac(args)
> +    if args.bizarro:
> +        success = success and test_bizarro(args)
> +    if args.valgrind:
> +        success = success and test_valgrind(args)
> +
> +    exit(0 if success else 1)
> +
> +
> +if __name__ == '__main__':
> +    main()


More information about the mesa-dev mailing list