1# encoding=utf-8 2# Copyright © 2018 Intel Corporation 3 4# Permission is hereby granted, free of charge, to any person obtaining a copy 5# of this software and associated documentation files (the "Software"), to deal 6# in the Software without restriction, including without limitation the rights 7# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8# copies of the Software, and to permit persons to whom the Software is 9# furnished to do so, subject to the following conditions: 10 11# The above copyright notice and this permission notice shall be included in 12# all copies or substantial portions of the Software. 13 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20# SOFTWARE. 21 22"""Script to generate and run glsl optimization tests.""" 23 24from __future__ import print_function 25import argparse 26import difflib 27import errno 28import os 29import subprocess 30import sys 31 32import sexps 33import lower_jump_cases 34 35# The meson version handles windows paths better, but if it's not available 36# fall back to shlex 37try: 38 from meson.mesonlib import split_args 39except ImportError: 40 from shlex import split as split_args 41 42 43def arg_parser(): 44 parser = argparse.ArgumentParser() 45 parser.add_argument( 46 '--test-runner', 47 required=True, 48 help='The glsl_test binary.') 49 return parser.parse_args() 50 51 52def compare(actual, expected): 53 """Compare the s-expresions and return a diff if they are different.""" 54 actual = sexps.sort_decls(sexps.parse_sexp(actual)) 55 expected = sexps.sort_decls(sexps.parse_sexp(expected)) 56 57 if actual == expected: 58 return None 59 60 actual = sexps.sexp_to_string(actual) 61 expected = sexps.sexp_to_string(expected) 62 63 return difflib.unified_diff(expected.splitlines(), actual.splitlines()) 64 65 66def get_test_runner(runner): 67 """Wrap the test runner in the exe wrapper if necessary.""" 68 wrapper = os.environ.get('MESON_EXE_WRAPPER', None) 69 if wrapper is None: 70 return [runner] 71 return split_args(wrapper) + [runner] 72 73 74def main(): 75 """Generate each test and report pass or fail.""" 76 args = arg_parser() 77 78 total = 0 79 passes = 0 80 81 runner = get_test_runner(args.test_runner) 82 83 for gen in lower_jump_cases.CASES: 84 for name, opt, source, expected in gen(): 85 total += 1 86 print('{}: '.format(name), end='') 87 proc = subprocess.Popen( 88 runner + ['optpass', '--quiet', '--input-ir', opt], 89 stdout=subprocess.PIPE, 90 stderr=subprocess.PIPE, 91 stdin=subprocess.PIPE) 92 out, err = proc.communicate(source.encode('utf-8')) 93 out = out.decode('utf-8') 94 err = err.decode('utf-8') 95 96 if proc.returncode == 255: 97 print("Test returned general error, possibly missing linker") 98 sys.exit(77) 99 100 if err: 101 print('FAIL') 102 print('Unexpected output on stderr: {}'.format(err), 103 file=sys.stdout) 104 continue 105 106 result = compare(out, expected) 107 if result is not None: 108 print('FAIL') 109 for l in result: 110 print(l, file=sys.stderr) 111 else: 112 print('PASS') 113 passes += 1 114 115 print('{}/{} tests returned correct results'.format(passes, total)) 116 exit(0 if passes == total else 1) 117 118 119if __name__ == '__main__': 120 try: 121 main() 122 except OSError as e: 123 if e.errno == errno.ENOEXEC: 124 print('Skipping due to inability to run host binaries', file=sys.stderr) 125 sys.exit(77) 126 raise 127