1bf215546Sopenharmony_ci# encoding=utf-8 2bf215546Sopenharmony_ci# Copyright © 2018 Intel Corporation 3bf215546Sopenharmony_ci 4bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a copy 5bf215546Sopenharmony_ci# of this software and associated documentation files (the "Software"), to deal 6bf215546Sopenharmony_ci# in the Software without restriction, including without limitation the rights 7bf215546Sopenharmony_ci# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8bf215546Sopenharmony_ci# copies of the Software, and to permit persons to whom the Software is 9bf215546Sopenharmony_ci# furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci 11bf215546Sopenharmony_ci# The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci# all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci 14bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17bf215546Sopenharmony_ci# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18bf215546Sopenharmony_ci# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19bf215546Sopenharmony_ci# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20bf215546Sopenharmony_ci# SOFTWARE. 21bf215546Sopenharmony_ci 22bf215546Sopenharmony_ci"""Run glcpp tests with various line endings.""" 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ciimport argparse 25bf215546Sopenharmony_ciimport difflib 26bf215546Sopenharmony_ciimport errno 27bf215546Sopenharmony_ciimport io 28bf215546Sopenharmony_ciimport os 29bf215546Sopenharmony_ciimport subprocess 30bf215546Sopenharmony_ciimport sys 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci# The meson version handles windows paths better, but if it's not available 33bf215546Sopenharmony_ci# fall back to shlex 34bf215546Sopenharmony_citry: 35bf215546Sopenharmony_ci from meson.mesonlib import split_args 36bf215546Sopenharmony_ciexcept ImportError: 37bf215546Sopenharmony_ci from shlex import split as split_args 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_cidef arg_parser(): 41bf215546Sopenharmony_ci parser = argparse.ArgumentParser() 42bf215546Sopenharmony_ci parser.add_argument('glcpp', help='Path to the he glcpp binary.') 43bf215546Sopenharmony_ci parser.add_argument('testdir', help='Path to tests and expected output.') 44bf215546Sopenharmony_ci parser.add_argument('--unix', action='store_true', help='Run tests for Unix style newlines') 45bf215546Sopenharmony_ci parser.add_argument('--windows', action='store_true', help='Run tests for Windows/Dos style newlines') 46bf215546Sopenharmony_ci parser.add_argument('--oldmac', action='store_true', help='Run tests for Old Mac (pre-OSX) style newlines') 47bf215546Sopenharmony_ci parser.add_argument('--bizarro', action='store_true', help='Run tests for Bizarro world style newlines') 48bf215546Sopenharmony_ci return parser.parse_args() 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_cidef parse_test_file(contents, nl_format): 52bf215546Sopenharmony_ci """Check for any special arguments and return them as a list.""" 53bf215546Sopenharmony_ci # Disable "universal newlines" mode; we can't directly use `nl_format` as 54bf215546Sopenharmony_ci # the `newline` argument, because the "bizarro" test uses something Python 55bf215546Sopenharmony_ci # considers invalid. 56bf215546Sopenharmony_ci for l in contents.decode('utf-8').split(nl_format): 57bf215546Sopenharmony_ci if 'glcpp-args:' in l: 58bf215546Sopenharmony_ci return l.split('glcpp-args:')[1].strip().split() 59bf215546Sopenharmony_ci return [] 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cidef test_output(glcpp, contents, expfile, nl_format='\n'): 63bf215546Sopenharmony_ci """Test that the output of glcpp is what we expect.""" 64bf215546Sopenharmony_ci extra_args = parse_test_file(contents, nl_format) 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci proc = subprocess.Popen( 67bf215546Sopenharmony_ci glcpp + extra_args, 68bf215546Sopenharmony_ci stdout=subprocess.PIPE, 69bf215546Sopenharmony_ci stderr=subprocess.STDOUT, 70bf215546Sopenharmony_ci stdin=subprocess.PIPE) 71bf215546Sopenharmony_ci actual, _ = proc.communicate(contents) 72bf215546Sopenharmony_ci actual = actual.decode('utf-8') 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci if proc.returncode == 255: 75bf215546Sopenharmony_ci print("Test returned general error, possibly missing linker") 76bf215546Sopenharmony_ci sys.exit(77) 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci with open(expfile, 'r') as f: 79bf215546Sopenharmony_ci expected = f.read() 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci # Bison 3.6 changed '$end' to 'end of file' in its error messages 82bf215546Sopenharmony_ci # See: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3181 83bf215546Sopenharmony_ci actual = actual.replace('$end', 'end of file') 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci if actual == expected: 86bf215546Sopenharmony_ci return (True, []) 87bf215546Sopenharmony_ci return (False, difflib.unified_diff(actual.splitlines(), expected.splitlines())) 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_cidef test_unix(args): 91bf215546Sopenharmony_ci """Test files with unix style (\n) new lines.""" 92bf215546Sopenharmony_ci total = 0 93bf215546Sopenharmony_ci passed = 0 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci print('============= Testing for Correctness (Unix) =============') 96bf215546Sopenharmony_ci for filename in os.listdir(args.testdir): 97bf215546Sopenharmony_ci if not filename.endswith('.c'): 98bf215546Sopenharmony_ci continue 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci print( '{}:'.format(os.path.splitext(filename)[0]), end=' ') 101bf215546Sopenharmony_ci total += 1 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci testfile = os.path.join(args.testdir, filename) 104bf215546Sopenharmony_ci with open(testfile, 'rb') as f: 105bf215546Sopenharmony_ci contents = f.read() 106bf215546Sopenharmony_ci valid, diff = test_output(args.glcpp, contents, testfile + '.expected') 107bf215546Sopenharmony_ci if valid: 108bf215546Sopenharmony_ci passed += 1 109bf215546Sopenharmony_ci print('PASS') 110bf215546Sopenharmony_ci else: 111bf215546Sopenharmony_ci print('FAIL') 112bf215546Sopenharmony_ci for l in diff: 113bf215546Sopenharmony_ci print(l, file=sys.stderr) 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci if not total: 116bf215546Sopenharmony_ci raise Exception('Could not find any tests.') 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci print('{}/{}'.format(passed, total), 'tests returned correct results') 119bf215546Sopenharmony_ci return total == passed 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_cidef _replace_test(args, replace): 123bf215546Sopenharmony_ci """Test files with non-unix style line endings. Print your own header.""" 124bf215546Sopenharmony_ci total = 0 125bf215546Sopenharmony_ci passed = 0 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci for filename in os.listdir(args.testdir): 128bf215546Sopenharmony_ci if not filename.endswith('.c'): 129bf215546Sopenharmony_ci continue 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci print( '{}:'.format(os.path.splitext(filename)[0]), end=' ') 132bf215546Sopenharmony_ci total += 1 133bf215546Sopenharmony_ci testfile = os.path.join(args.testdir, filename) 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci with open(testfile, 'rt') as f: 136bf215546Sopenharmony_ci contents = f.read() 137bf215546Sopenharmony_ci contents = contents.replace('\n', replace).encode('utf-8') 138bf215546Sopenharmony_ci valid, diff = test_output( 139bf215546Sopenharmony_ci args.glcpp, contents, testfile + '.expected', nl_format=replace) 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci if valid: 142bf215546Sopenharmony_ci passed += 1 143bf215546Sopenharmony_ci print('PASS') 144bf215546Sopenharmony_ci else: 145bf215546Sopenharmony_ci print('FAIL') 146bf215546Sopenharmony_ci for l in diff: 147bf215546Sopenharmony_ci print(l, file=sys.stderr) 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci if not total: 150bf215546Sopenharmony_ci raise Exception('Could not find any tests.') 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci print('{}/{}'.format(passed, total), 'tests returned correct results') 153bf215546Sopenharmony_ci return total == passed 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cidef test_windows(args): 157bf215546Sopenharmony_ci """Test files with windows/dos style (\r\n) new lines.""" 158bf215546Sopenharmony_ci print('============= Testing for Correctness (Windows) =============') 159bf215546Sopenharmony_ci return _replace_test(args, '\r\n') 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_cidef test_oldmac(args): 163bf215546Sopenharmony_ci """Test files with Old Mac style (\r) new lines.""" 164bf215546Sopenharmony_ci print('============= Testing for Correctness (Old Mac) =============') 165bf215546Sopenharmony_ci return _replace_test(args, '\r') 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_cidef test_bizarro(args): 169bf215546Sopenharmony_ci """Test files with Bizarro world style (\n\r) new lines.""" 170bf215546Sopenharmony_ci # This is allowed by the spec, but why? 171bf215546Sopenharmony_ci print('============= Testing for Correctness (Bizarro) =============') 172bf215546Sopenharmony_ci return _replace_test(args, '\n\r') 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_cidef main(): 176bf215546Sopenharmony_ci args = arg_parser() 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci wrapper = os.environ.get('MESON_EXE_WRAPPER') 179bf215546Sopenharmony_ci if wrapper is not None: 180bf215546Sopenharmony_ci args.glcpp = split_args(wrapper) + [args.glcpp] 181bf215546Sopenharmony_ci else: 182bf215546Sopenharmony_ci args.glcpp = [args.glcpp] 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci success = True 185bf215546Sopenharmony_ci try: 186bf215546Sopenharmony_ci if args.unix: 187bf215546Sopenharmony_ci success = success and test_unix(args) 188bf215546Sopenharmony_ci if args.windows: 189bf215546Sopenharmony_ci success = success and test_windows(args) 190bf215546Sopenharmony_ci if args.oldmac: 191bf215546Sopenharmony_ci success = success and test_oldmac(args) 192bf215546Sopenharmony_ci if args.bizarro: 193bf215546Sopenharmony_ci success = success and test_bizarro(args) 194bf215546Sopenharmony_ci except OSError as e: 195bf215546Sopenharmony_ci if e.errno == errno.ENOEXEC: 196bf215546Sopenharmony_ci print('Skipping due to inability to run host binaries.', 197bf215546Sopenharmony_ci file=sys.stderr) 198bf215546Sopenharmony_ci sys.exit(77) 199bf215546Sopenharmony_ci raise 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci exit(0 if success else 1) 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ciif __name__ == '__main__': 205bf215546Sopenharmony_ci main() 206