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:
Dylan Baker 2018-01-09 15:26:39 -08:00
parent 8cb96c4031
commit db8cd8e367
3 changed files with 223 additions and 267 deletions

View File

@ -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
$PYTHON2 $srcdir/glsl/glcpp/tests/glcpp_test.py $abs_builddir/glsl/glcpp/glcpp $srcdir/glsl/glcpp/tests --windows --oldmac --bizarro

View File

@ -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
$PYTHON2 $srcdir/glsl/glcpp/tests/glcpp_test.py $abs_builddir/glsl/glcpp/glcpp $srcdir/glsl/glcpp/tests --unix

View 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()