101e04c3fSmrg# encoding=utf-8
201e04c3fSmrg# Copyright © 2018 Intel Corporation
301e04c3fSmrg
401e04c3fSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
501e04c3fSmrg# of this software and associated documentation files (the "Software"), to deal
601e04c3fSmrg# in the Software without restriction, including without limitation the rights
701e04c3fSmrg# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
801e04c3fSmrg# copies of the Software, and to permit persons to whom the Software is
901e04c3fSmrg# furnished to do so, subject to the following conditions:
1001e04c3fSmrg
1101e04c3fSmrg# The above copyright notice and this permission notice shall be included in
1201e04c3fSmrg# all copies or substantial portions of the Software.
1301e04c3fSmrg
1401e04c3fSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1501e04c3fSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1601e04c3fSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1701e04c3fSmrg# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1801e04c3fSmrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1901e04c3fSmrg# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2001e04c3fSmrg# SOFTWARE.
2101e04c3fSmrg
2201e04c3fSmrg"""Script to generate and run glsl optimization tests."""
2301e04c3fSmrg
2401e04c3fSmrgimport argparse
2501e04c3fSmrgimport difflib
267ec681f3Smrgimport errno
277ec681f3Smrgimport os
2801e04c3fSmrgimport subprocess
2901e04c3fSmrgimport sys
3001e04c3fSmrg
3101e04c3fSmrgimport sexps
3201e04c3fSmrgimport lower_jump_cases
3301e04c3fSmrg
347ec681f3Smrg# The meson version handles windows paths better, but if it's not available
357ec681f3Smrg# fall back to shlex
367ec681f3Smrgtry:
377ec681f3Smrg    from meson.mesonlib import split_args
387ec681f3Smrgexcept ImportError:
397ec681f3Smrg    from shlex import split as split_args
407ec681f3Smrg
4101e04c3fSmrg
4201e04c3fSmrgdef arg_parser():
4301e04c3fSmrg    parser = argparse.ArgumentParser()
4401e04c3fSmrg    parser.add_argument(
4501e04c3fSmrg        '--test-runner',
4601e04c3fSmrg        required=True,
4701e04c3fSmrg        help='The glsl_test binary.')
4801e04c3fSmrg    return parser.parse_args()
4901e04c3fSmrg
5001e04c3fSmrg
5101e04c3fSmrgdef compare(actual, expected):
5201e04c3fSmrg    """Compare the s-expresions and return a diff if they are different."""
5301e04c3fSmrg    actual = sexps.sort_decls(sexps.parse_sexp(actual))
5401e04c3fSmrg    expected = sexps.sort_decls(sexps.parse_sexp(expected))
5501e04c3fSmrg
5601e04c3fSmrg    if actual == expected:
5701e04c3fSmrg        return None
5801e04c3fSmrg
5901e04c3fSmrg    actual = sexps.sexp_to_string(actual)
6001e04c3fSmrg    expected = sexps.sexp_to_string(expected)
6101e04c3fSmrg
6201e04c3fSmrg    return difflib.unified_diff(expected.splitlines(), actual.splitlines())
6301e04c3fSmrg
6401e04c3fSmrg
657ec681f3Smrgdef get_test_runner(runner):
667ec681f3Smrg    """Wrap the test runner in the exe wrapper if necessary."""
677ec681f3Smrg    wrapper = os.environ.get('MESON_EXE_WRAPPER', None)
687ec681f3Smrg    if wrapper is None:
697ec681f3Smrg        return [runner]
707ec681f3Smrg    return split_args(wrapper) + [runner]
717ec681f3Smrg
727ec681f3Smrg
7301e04c3fSmrgdef main():
7401e04c3fSmrg    """Generate each test and report pass or fail."""
7501e04c3fSmrg    args = arg_parser()
7601e04c3fSmrg
7701e04c3fSmrg    total = 0
7801e04c3fSmrg    passes = 0
7901e04c3fSmrg
807ec681f3Smrg    runner = get_test_runner(args.test_runner)
817ec681f3Smrg
8201e04c3fSmrg    for gen in lower_jump_cases.CASES:
8301e04c3fSmrg        for name, opt, source, expected in gen():
8401e04c3fSmrg            total += 1
8501e04c3fSmrg            print('{}: '.format(name), end='')
8601e04c3fSmrg            proc = subprocess.Popen(
877ec681f3Smrg                runner + ['optpass', '--quiet', '--input-ir', opt],
8801e04c3fSmrg                stdout=subprocess.PIPE,
8901e04c3fSmrg                stderr=subprocess.PIPE,
9001e04c3fSmrg                stdin=subprocess.PIPE)
9101e04c3fSmrg            out, err = proc.communicate(source.encode('utf-8'))
9201e04c3fSmrg            out = out.decode('utf-8')
9301e04c3fSmrg            err = err.decode('utf-8')
947ec681f3Smrg
957ec681f3Smrg            if proc.returncode == 255:
967ec681f3Smrg                print("Test returned general error, possibly missing linker")
977ec681f3Smrg                sys.exit(77)
987ec681f3Smrg
9901e04c3fSmrg            if err:
10001e04c3fSmrg                print('FAIL')
10101e04c3fSmrg                print('Unexpected output on stderr: {}'.format(err),
10201e04c3fSmrg                      file=sys.stdout)
10301e04c3fSmrg                continue
10401e04c3fSmrg
10501e04c3fSmrg            result = compare(out, expected)
10601e04c3fSmrg            if result is not None:
10701e04c3fSmrg                print('FAIL')
10801e04c3fSmrg                for l in result:
10901e04c3fSmrg                    print(l, file=sys.stderr)
11001e04c3fSmrg            else:
11101e04c3fSmrg                print('PASS')
11201e04c3fSmrg                passes += 1
11301e04c3fSmrg
11401e04c3fSmrg    print('{}/{} tests returned correct results'.format(passes, total))
11501e04c3fSmrg    exit(0 if passes == total else 1)
11601e04c3fSmrg
11701e04c3fSmrg
11801e04c3fSmrgif __name__ == '__main__':
1197ec681f3Smrg    try:
1207ec681f3Smrg        main()
1217ec681f3Smrg    except OSError as e:
1227ec681f3Smrg        if e.errno == errno.ENOEXEC:
1237ec681f3Smrg            print('Skipping due to inability to run host binaries', file=sys.stderr)
1247ec681f3Smrg            sys.exit(77)
1257ec681f3Smrg        raise
126