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