2 # Copyright © 2018 Intel Corporation
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:
11 # The above copyright notice and this permission notice shall be included in
12 # all copies or substantial portions of the Software.
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
22 """Run glcpp tests with various line endings."""
24 from __future__
import print_function
34 # The meson version handles windows paths better, but if it's not available
37 from meson
.mesonlib
import split_args
39 from shlex
import split
as split_args
43 parser
= argparse
.ArgumentParser()
44 parser
.add_argument('glcpp', help='Path to the he glcpp binary.')
45 parser
.add_argument('testdir', help='Path to tests and expected output.')
46 parser
.add_argument('--unix', action
='store_true', help='Run tests for Unix style newlines')
47 parser
.add_argument('--windows', action
='store_true', help='Run tests for Windows/Dos style newlines')
48 parser
.add_argument('--oldmac', action
='store_true', help='Run tests for Old Mac (pre-OSX) style newlines')
49 parser
.add_argument('--bizarro', action
='store_true', help='Run tests for Bizarro world style newlines')
50 parser
.add_argument('--valgrind', action
='store_true', help='Run with valgrind for errors')
51 return parser
.parse_args()
54 def parse_test_file(filename
, nl_format
):
55 """Check for any special arguments and return them as a list."""
56 # Disable "universal newlines" mode; we can't directly use `nl_format` as
57 # the `newline` argument, because the "bizarro" test uses something Python
59 with io
.open(filename
, newline
='') as f
:
60 for l
in f
.read().split(nl_format
):
61 if 'glcpp-args:' in l
:
62 return l
.split('glcpp-args:')[1].strip().split()
66 def test_output(glcpp
, filename
, expfile
, nl_format
='\n'):
67 """Test that the output of glcpp is what we expect."""
68 extra_args
= parse_test_file(filename
, nl_format
)
70 with
open(filename
, 'rb') as f
:
71 proc
= subprocess
.Popen(
73 stdout
=subprocess
.PIPE
,
74 stderr
=subprocess
.STDOUT
,
75 stdin
=subprocess
.PIPE
)
76 actual
, _
= proc
.communicate(f
.read())
77 actual
= actual
.decode('utf-8')
79 with
open(expfile
, 'r') as f
:
82 if actual
== expected
:
84 return (False, difflib
.unified_diff(actual
.splitlines(), expected
.splitlines()))
87 def _valgrind(glcpp
, filename
):
88 """Run valgrind and report any warnings."""
89 extra_args
= parse_test_file(filename
, nl_format
='\n')
92 fd
, tmpfile
= tempfile
.mkstemp()
94 with
open(filename
, 'rb') as f
:
95 proc
= subprocess
.Popen(
96 ['valgrind', '--error-exitcode=31', '--log-file', tmpfile
] + glcpp
+ extra_args
,
97 stdout
=subprocess
.PIPE
,
98 stderr
=subprocess
.STDOUT
,
99 stdin
=subprocess
.PIPE
)
100 proc
.communicate(f
.read())
101 if proc
.returncode
!= 31:
103 with
open(tmpfile
, 'rb') as f
:
105 return (False, contents
)
111 """Test files with unix style (\n) new lines."""
115 print('============= Testing for Correctness (Unix) =============')
116 for filename
in os
.listdir(args
.testdir
):
117 if not filename
.endswith('.c'):
120 print( '{}:'.format(os
.path
.splitext(filename
)[0]), end
=' ')
123 testfile
= os
.path
.join(args
.testdir
, filename
)
124 valid
, diff
= test_output(args
.glcpp
, testfile
, testfile
+ '.expected')
131 print(l
, file=sys
.stderr
)
134 raise Exception('Could not find any tests.')
136 print('{}/{}'.format(passed
, total
), 'tests returned correct results')
137 return total
== passed
140 def _replace_test(args
, replace
):
141 """Test files with non-unix style line endings. Print your own header."""
145 for filename
in os
.listdir(args
.testdir
):
146 if not filename
.endswith('.c'):
149 print( '{}:'.format(os
.path
.splitext(filename
)[0]), end
=' ')
151 testfile
= os
.path
.join(args
.testdir
, filename
)
153 fd
, tmpfile
= tempfile
.mkstemp()
155 with io
.open(testfile
, 'rt') as f
:
157 with io
.open(tmpfile
, 'wt') as f
:
158 f
.write(contents
.replace('\n', replace
))
159 valid
, diff
= test_output(
160 args
.glcpp
, tmpfile
, testfile
+ '.expected', nl_format
=replace
)
170 print(l
, file=sys
.stderr
)
173 raise Exception('Could not find any tests.')
175 print('{}/{}'.format(passed
, total
), 'tests returned correct results')
176 return total
== passed
179 def test_windows(args
):
180 """Test files with windows/dos style (\r\n) new lines."""
181 print('============= Testing for Correctness (Windows) =============')
182 return _replace_test(args
, '\r\n')
185 def test_oldmac(args
):
186 """Test files with Old Mac style (\r) new lines."""
187 print('============= Testing for Correctness (Old Mac) =============')
188 return _replace_test(args
, '\r')
191 def test_bizarro(args
):
192 """Test files with Bizarro world style (\n\r) new lines."""
193 # This is allowed by the spec, but why?
194 print('============= Testing for Correctness (Bizarro) =============')
195 return _replace_test(args
, '\n\r')
198 def test_valgrind(args
):
202 print('============= Testing for Valgrind Warnings =============')
203 for filename
in os
.listdir(args
.testdir
):
204 if not filename
.endswith('.c'):
207 print( '{}:'.format(os
.path
.splitext(filename
)[0]), end
=' ')
209 valid
, log
= _valgrind(args
.glcpp
, os
.path
.join(args
.testdir
, filename
))
215 print(log
, file=sys
.stderr
)
218 raise Exception('Could not find any tests.')
220 print('{}/{}'.format(passed
, total
), 'tests returned correct results')
221 return total
== passed
227 wrapper
= os
.environ
.get('MESON_EXE_WRAPPER')
228 if wrapper
is not None:
229 args
.glcpp
= split_args(wrapper
) + [args
.glcpp
]
231 args
.glcpp
= [args
.glcpp
]
236 success
= success
and test_unix(args
)
238 success
= success
and test_windows(args
)
240 success
= success
and test_oldmac(args
)
242 success
= success
and test_bizarro(args
)
244 success
= success
and test_valgrind(args
)
246 if e
.errno
== errno
.ENOEXEC
:
247 print('Skipping due to inability to run host binaries.',
252 exit(0 if success
else 1)
255 if __name__
== '__main__':