glcpp/tests: Convert shell scripts to a python script
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. v2: - Use $PYTHON2 to be consistent with other tests in mesa Signed-off-by: Dylan Baker <dylan.c.baker@intel.com> Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
@@ -1,149 +1,3 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ -z "$srcdir" -o -z "$abs_builddir" ]; then
|
$PYTHON2 $srcdir/glsl/glcpp/tests/glcpp_test.py $abs_builddir/glsl/glcpp/glcpp $srcdir/glsl/glcpp/tests --windows --oldmac --bizarro
|
||||||
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
|
|
||||||
|
@@ -1,122 +1,3 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ -z "$srcdir" -o -z "$abs_builddir" ]; then
|
$PYTHON2 $srcdir/glsl/glcpp/tests/glcpp_test.py $abs_builddir/glsl/glcpp/glcpp $srcdir/glsl/glcpp/tests --unix
|
||||||
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
|
|
||||||
|
|
||||||
|
221
src/compiler/glsl/glcpp/tests/glcpp_test.py
Executable file
221
src/compiler/glsl/glcpp/tests/glcpp_test.py
Executable file
@@ -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()
|
Reference in New Issue
Block a user