Meson: Remove hack that got fixed a while ago
[glib.git] / gobject / tests / mkenums.py
blob431453d01e8d5c21d45dd07243c1c9adb9109414
1 #!/usr/bin/python3
2 # -*- coding: utf-8 -*-
4 # Copyright © 2018 Endless Mobile, Inc.
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301 USA
21 """Integration tests for glib-mkenums utility."""
23 import os
24 import subprocess
25 import tempfile
26 import unittest
28 import taptestrunner
31 class TestMkenums(unittest.TestCase):
32 """Integration test for running glib-mkenums.
34 This can be run when installed or uninstalled. When uninstalled, it
35 requires G_TEST_BUILDDIR and G_TEST_SRCDIR to be set.
37 The idea with this test harness is to test the glib-mkenums utility, its
38 handling of command line arguments, its exit statuses, and its handling of
39 various C source codes. In future we could split the core glib-mkenums
40 parsing and generation code out into a library and unit test that, and
41 convert this test to just check command line behaviour.
42 """
44 def setUp(self):
45 self.timeout_seconds = 10 # seconds per test
46 self.tmpdir = tempfile.TemporaryDirectory()
47 os.chdir(self.tmpdir.name)
48 print('tmpdir:', self.tmpdir.name)
49 if 'G_TEST_BUILDDIR' in os.environ:
50 self.__mkenums = \
51 os.path.join(os.environ['G_TEST_BUILDDIR'], '..',
52 'glib-mkenums')
53 else:
54 self.__mkenums = os.path.join('/', 'usr', 'bin', 'glib-mkenums')
55 print('mkenums:', self.__mkenums)
57 def tearDown(self):
58 self.tmpdir.cleanup()
60 def runMkenums(self, *args):
61 argv = [self.__mkenums]
62 argv.extend(args)
63 print('Running:', argv)
65 env = os.environ.copy()
66 env['LC_ALL'] = 'C.UTF-8'
67 print('Environment:', env)
69 info = subprocess.run(argv, timeout=self.timeout_seconds,
70 stdout=subprocess.PIPE,
71 stderr=subprocess.PIPE,
72 env=env)
73 print('Output:', info.stdout.decode('utf-8'))
74 return info
76 def runMkenumsWithHeader(self, h_contents, encoding='utf-8', *args):
77 template_contents = '''
78 /*** BEGIN file-header ***/
79 file-header
80 filename: @filename@
81 basename: @basename@
82 /*** END file-header ***/
84 /*** BEGIN file-production ***/
85 file-production
86 filename: @filename@
87 basename: @basename@
88 /*** END file-production ***/
90 /*** BEGIN enumeration-production ***/
91 enumeration-production
92 EnumName: @EnumName@
93 enum_name: @enum_name@
94 ENUMNAME: @ENUMNAME@
95 ENUMSHORT: @ENUMSHORT@
96 ENUMPREFIX: @ENUMPREFIX@
97 type: @type@
98 Type: @Type@
99 TYPE: @TYPE@
100 /*** END enumeration-production ***/
102 /*** BEGIN value-header ***/
103 value-header
104 EnumName: @EnumName@
105 enum_name: @enum_name@
106 ENUMNAME: @ENUMNAME@
107 ENUMSHORT: @ENUMSHORT@
108 ENUMPREFIX: @ENUMPREFIX@
109 type: @type@
110 Type: @Type@
111 TYPE: @TYPE@
112 /*** END value-header ***/
114 /*** BEGIN value-production ***/
115 value-production
116 VALUENAME: @VALUENAME@
117 valuenick: @valuenick@
118 valuenum: @valuenum@
119 type: @type@
120 Type: @Type@
121 TYPE: @TYPE@
122 /*** END value-production ***/
124 /*** BEGIN value-tail ***/
125 value-tail
126 EnumName: @EnumName@
127 enum_name: @enum_name@
128 ENUMNAME: @ENUMNAME@
129 ENUMSHORT: @ENUMSHORT@
130 ENUMPREFIX: @ENUMPREFIX@
131 type: @type@
132 Type: @Type@
133 TYPE: @TYPE@
134 /*** END value-tail ***/
136 /*** BEGIN comment ***/
137 comment
138 comment: @comment@
139 /*** END comment ***/
141 /*** BEGIN file-tail ***/
142 file-tail
143 filename: @filename@
144 basename: @basename@
145 /*** END file-tail ***/
148 with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
149 suffix='.template') as template_file, \
150 tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
151 suffix='.h') as h_file:
152 # Write out the template.
153 template_file.write(template_contents.encode('utf-8'))
154 print(template_file.name + ':', template_contents)
156 # Write out the header to be scanned.
157 h_file.write(h_contents.encode(encoding))
158 print(h_file.name + ':', h_contents)
160 template_file.flush()
161 h_file.flush()
163 # Run glib-mkenums with a template which outputs all substitutions.
164 info = self.runMkenums('--template', template_file.name,
165 h_file.name)
166 info.check_returncode()
167 out = info.stdout.decode('utf-8').strip()
168 err = info.stderr.decode('utf-8').strip()
170 # Known substitutions for generated filenames.
171 subs = {
172 'filename': h_file.name,
173 'basename': os.path.basename(h_file.name),
174 'standard_top_comment':
175 'This file is generated by glib-mkenums, do not modify '
176 'it. This code is licensed under the same license as the '
177 'containing project. Note that it links to GLib, so must '
178 'comply with the LGPL linking clauses.',
179 'standard_bottom_comment': 'Generated data ends here'
182 return (info, out, err, subs)
184 def assertSingleEnum(self, out, subs, enum_name_camel, enum_name_lower,
185 enum_name_upper, enum_name_short, enum_prefix,
186 type_lower, type_camel, type_upper,
187 value_name, value_nick, value_num):
188 """Assert that out (from runMkenumsWithHeader()) contains a single
189 enum and value matching the given arguments."""
190 subs = dict({
191 'enum_name_camel': enum_name_camel,
192 'enum_name_lower': enum_name_lower,
193 'enum_name_upper': enum_name_upper,
194 'enum_name_short': enum_name_short,
195 'enum_prefix': enum_prefix,
196 'type_lower': type_lower,
197 'type_camel': type_camel,
198 'type_upper': type_upper,
199 'value_name': value_name,
200 'value_nick': value_nick,
201 'value_num': value_num,
202 }, **subs)
204 self.assertEqual('''
205 comment
206 comment: {standard_top_comment}
209 file-header
210 filename: {filename}
211 basename: {basename}
212 file-production
213 filename: {filename}
214 basename: {basename}
215 enumeration-production
216 EnumName: {enum_name_camel}
217 enum_name: {enum_name_lower}
218 ENUMNAME: {enum_name_upper}
219 ENUMSHORT: {enum_name_short}
220 ENUMPREFIX: {enum_prefix}
221 type: {type_lower}
222 Type: {type_camel}
223 TYPE: {type_upper}
224 value-header
225 EnumName: {enum_name_camel}
226 enum_name: {enum_name_lower}
227 ENUMNAME: {enum_name_upper}
228 ENUMSHORT: {enum_name_short}
229 ENUMPREFIX: {enum_prefix}
230 type: {type_lower}
231 Type: {type_camel}
232 TYPE: {type_upper}
233 value-production
234 VALUENAME: {value_name}
235 valuenick: {value_nick}
236 valuenum: {value_num}
237 type: {type_lower}
238 Type: {type_camel}
239 TYPE: {type_upper}
240 value-tail
241 EnumName: {enum_name_camel}
242 enum_name: {enum_name_lower}
243 ENUMNAME: {enum_name_upper}
244 ENUMSHORT: {enum_name_short}
245 ENUMPREFIX: {enum_prefix}
246 type: {type_lower}
247 Type: {type_camel}
248 TYPE: {type_upper}
249 file-tail
250 filename: ARGV
251 basename: {basename}
253 comment
254 comment: {standard_bottom_comment}
255 '''.format(**subs).strip(), out)
257 def test_help(self):
258 """Test the --help argument."""
259 info = self.runMkenums('--help')
260 info.check_returncode()
262 out = info.stdout.decode('utf-8').strip()
263 self.assertIn('usage: glib-mkenums', out)
265 def test_empty_header(self):
266 """Test an empty header."""
267 (info, out, err, subs) = self.runMkenumsWithHeader('')
268 self.assertEqual('', err)
269 self.assertEqual('''
270 comment
271 comment: {standard_top_comment}
274 file-header
275 filename: {filename}
276 basename: {basename}
277 file-tail
278 filename: ARGV
279 basename: {basename}
281 comment
282 comment: {standard_bottom_comment}
283 '''.format(**subs).strip(), out)
285 def test_enum_name(self):
286 """Test typedefs with an enum and a typedef name. Bug #794506."""
287 h_contents = '''
288 typedef enum _SomeEnumIdentifier {
289 ENUM_VALUE
290 } SomeEnumIdentifier;
292 (info, out, err, subs) = self.runMkenumsWithHeader(h_contents)
293 self.assertEqual('', err)
294 self.assertSingleEnum(out, subs, 'SomeEnumIdentifier',
295 'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
296 'ENUM_IDENTIFIER', 'SOME', 'enum', 'Enum',
297 'ENUM', 'ENUM_VALUE', 'value', '0')
299 def test_non_utf8_encoding(self):
300 """Test source files with non-UTF-8 encoding. Bug #785113."""
301 h_contents = '''
302 /* Copyright © La Peña */
303 typedef enum {
304 ENUM_VALUE
305 } SomeEnumIdentifier;
307 (info, out, err, subs) = \
308 self.runMkenumsWithHeader(h_contents, encoding='iso-8859-1')
309 self.assertIn('WARNING: UnicodeWarning: ', err)
310 self.assertSingleEnum(out, subs, 'SomeEnumIdentifier',
311 'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
312 'ENUM_IDENTIFIER', 'SOME', 'enum', 'Enum',
313 'ENUM', 'ENUM_VALUE', 'value', '0')
315 def test_reproducible(self):
316 """Test builds are reproducible regardless of file ordering.
317 Bug #691436."""
318 h_contents1 = '''
319 typedef enum {
320 FIRST,
321 } Header1;
324 h_contents2 = '''
325 typedef enum {
326 SECOND,
327 } Header2;
330 with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
331 suffix='.template') as template_file, \
332 tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
333 suffix='1.h') as h_file1, \
334 tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
335 suffix='2.h') as h_file2:
336 # Write out the template and headers.
337 template_file.write('template'.encode('utf-8'))
338 h_file1.write(h_contents1.encode('utf-8'))
339 h_file2.write(h_contents2.encode('utf-8'))
341 template_file.flush()
342 h_file1.flush()
343 h_file2.flush()
345 # Run glib-mkenums with the headers in one order, and then again
346 # in another order.
347 info1 = self.runMkenums('--template', template_file.name,
348 h_file1.name, h_file2.name)
349 info1.check_returncode()
350 out1 = info1.stdout.decode('utf-8').strip()
351 self.assertEqual('', info1.stderr.decode('utf-8').strip())
353 info2 = self.runMkenums('--template', template_file.name,
354 h_file2.name, h_file1.name)
355 info2.check_returncode()
356 out2 = info2.stdout.decode('utf-8').strip()
357 self.assertEqual('', info2.stderr.decode('utf-8').strip())
359 # The output should be the same.
360 self.assertEqual(out1, out2)
362 def test_no_nick(self):
363 """Test trigraphs with a desc but no nick. Issue #1360."""
364 h_contents = '''
365 typedef enum {
366 GEGL_SAMPLER_NEAREST = 0, /*< desc="nearest" >*/
367 } GeglSamplerType;
369 (info, out, err, subs) = self.runMkenumsWithHeader(h_contents)
370 self.assertEqual('', err)
371 self.assertSingleEnum(out, subs, 'GeglSamplerType',
372 'gegl_sampler_type', 'GEGL_SAMPLER_TYPE',
373 'SAMPLER_TYPE', 'GEGL', 'enum', 'Enum',
374 'ENUM', 'GEGL_SAMPLER_NEAREST', 'nearest', '0')
377 if __name__ == '__main__':
378 unittest.main(testRunner=taptestrunner.TAPTestRunner())