Merge branch 'wjt/glib-mkenums-filename-basename-in-fhead-ftail' into 'master'

glib-mkenums: forbid @filename@/@basename@ in fhead and ftail

See merge request GNOME/glib!241
This commit is contained in:
Philip Withnall 2018-08-11 21:25:05 +00:00
commit f92359b593
2 changed files with 166 additions and 89 deletions

View File

@ -303,15 +303,15 @@ parser = argparse.ArgumentParser(epilog=help_epilog,
parser.add_argument('--identifier-prefix', default='', dest='idprefix',
help='Identifier prefix')
parser.add_argument('--symbol-prefix', default='', dest='symprefix',
help='symbol-prefix')
help='Symbol prefix')
parser.add_argument('--fhead', default=[], dest='fhead', action='append',
help='Output file header')
parser.add_argument('--ftail', default=[], dest='ftail', action='append',
help='Per input file production')
help='Output file footer')
parser.add_argument('--fprod', default=[], dest='fprod', action='append',
help='Put out TEXT everytime a new input file is being processed.')
help='Put out TEXT every time a new input file is being processed.')
parser.add_argument('--eprod', default=[], dest='eprod', action='append',
help='Per enum text (produced prior to value iterations)')
help='Per enum text, produced prior to value iterations')
parser.add_argument('--vhead', default=[], dest='vhead', action='append',
help='Value header, produced before iterating over enum values')
parser.add_argument('--vprod', default=[], dest='vprod', action='append',
@ -324,8 +324,9 @@ parser.add_argument('--template', default='', dest='template',
help='Template file')
parser.add_argument('--output', default=None, dest='output')
parser.add_argument('--version', '-v', default=False, action='store_true', dest='version',
help='Print version informations')
parser.add_argument('args', nargs='*')
help='Print version information')
parser.add_argument('args', nargs='*',
help='Input files')
options = parser.parse_args()
@ -415,12 +416,17 @@ def replace_specials(prod):
prod = prod.rstrip()
return prod
def warn_if_filename_basename_used(section, prod):
for substitution in ('\u0040filename\u0040',
'\u0040basename\u0040'):
if substitution in prod:
print_warning('{} used in {} section.'.format(substitution,
section))
if len(fhead) > 0:
prod = fhead
base = os.path.basename(options.args[0])
prod = prod.replace('\u0040filename\u0040', options.args[0])
prod = prod.replace('\u0040basename\u0040', base)
warn_if_filename_basename_used('file-header', prod)
prod = replace_specials(prod)
write_output(prod)
@ -712,10 +718,7 @@ for fname in sorted(options.args):
if len(ftail) > 0:
prod = ftail
base = os.path.basename(options.args[-1]) # FIXME, wrong
prod = prod.replace('\u0040filename\u0040', 'ARGV') # wrong too
prod = prod.replace('\u0040basename\u0040', base)
warn_if_filename_basename_used('file-tail', prod)
prod = replace_specials(prod)
write_output(prod)

View File

@ -20,14 +20,19 @@
"""Integration tests for glib-mkenums utility."""
import collections
import os
import subprocess
import tempfile
import textwrap
import unittest
import taptestrunner
Result = collections.namedtuple('Result', ('info', 'out', 'err', 'subs'))
class TestMkenums(unittest.TestCase):
"""Integration test for running glib-mkenums.
@ -70,15 +75,40 @@ class TestMkenums(unittest.TestCase):
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=env)
print('Output:', info.stdout.decode('utf-8'))
return info
info.check_returncode()
out = info.stdout.decode('utf-8').strip()
err = info.stderr.decode('utf-8').strip()
def runMkenumsWithHeader(self, h_contents, encoding='utf-8', *args):
# Known substitutions for standard boilerplate
subs = {
'standard_top_comment':
'This file is generated by glib-mkenums, do not modify '
'it. This code is licensed under the same license as the '
'containing project. Note that it links to GLib, so must '
'comply with the LGPL linking clauses.',
'standard_bottom_comment': 'Generated data ends here'
}
result = Result(info, out, err, subs)
print('Output:', result.out)
return result
def runMkenumsWithTemplate(self, template_contents, *args):
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
suffix='.template') as template_file:
# Write out the template.
template_file.write(template_contents.encode('utf-8'))
print(template_file.name + ':', template_contents)
template_file.flush()
return self.runMkenums('--template', template_file.name, *args)
def runMkenumsWithAllSubstitutions(self, *args):
'''Run glib-mkenums with a template which outputs all substitutions.'''
template_contents = '''
/*** BEGIN file-header ***/
file-header
filename: @filename@
basename: @basename@
/*** END file-header ***/
/*** BEGIN file-production ***/
@ -140,48 +170,30 @@ comment: @comment@
/*** BEGIN file-tail ***/
file-tail
filename: @filename@
basename: @basename@
/*** END file-tail ***/
'''
return self.runMkenumsWithTemplate(template_contents, *args)
def runMkenumsWithHeader(self, h_contents, encoding='utf-8'):
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
suffix='.template') as template_file, \
tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
suffix='.h') as h_file:
# Write out the template.
template_file.write(template_contents.encode('utf-8'))
print(template_file.name + ':', template_contents)
# Write out the header to be scanned.
h_file.write(h_contents.encode(encoding))
print(h_file.name + ':', h_contents)
template_file.flush()
h_file.flush()
# Run glib-mkenums with a template which outputs all substitutions.
info = self.runMkenums('--template', template_file.name,
h_file.name)
info.check_returncode()
out = info.stdout.decode('utf-8').strip()
err = info.stderr.decode('utf-8').strip()
result = self.runMkenumsWithAllSubstitutions(h_file.name)
# Known substitutions for generated filenames.
subs = {
result.subs.update({
'filename': h_file.name,
'basename': os.path.basename(h_file.name),
'standard_top_comment':
'This file is generated by glib-mkenums, do not modify '
'it. This code is licensed under the same license as the '
'containing project. Note that it links to GLib, so must '
'comply with the LGPL linking clauses.',
'standard_bottom_comment': 'Generated data ends here'
}
})
return (info, out, err, subs)
return result
def assertSingleEnum(self, out, subs, enum_name_camel, enum_name_lower,
def assertSingleEnum(self, result, enum_name_camel, enum_name_lower,
enum_name_upper, enum_name_short, enum_prefix,
type_lower, type_camel, type_upper,
value_name, value_nick, value_num):
@ -199,7 +211,7 @@ basename: @basename@
'value_name': value_name,
'value_nick': value_nick,
'value_num': value_num,
}, **subs)
}, **result.subs)
self.assertEqual('''
comment
@ -207,8 +219,6 @@ comment: {standard_top_comment}
file-header
filename: {filename}
basename: {basename}
file-production
filename: {filename}
basename: {basename}
@ -247,40 +257,67 @@ type: {type_lower}
Type: {type_camel}
TYPE: {type_upper}
file-tail
filename: ARGV
basename: {basename}
comment
comment: {standard_bottom_comment}
'''.format(**subs).strip(), out)
'''.format(**subs).strip(), result.out)
def test_help(self):
"""Test the --help argument."""
info = self.runMkenums('--help')
info.check_returncode()
result = self.runMkenums('--help')
self.assertIn('usage: glib-mkenums', result.out)
out = info.stdout.decode('utf-8').strip()
self.assertIn('usage: glib-mkenums', out)
def test_no_args(self):
"""Test running with no arguments at all."""
result = self.runMkenums()
self.assertEqual('', result.err)
self.assertEquals('''/* {standard_top_comment} */
/* {standard_bottom_comment} */'''.format(**result.subs),
result.out.strip())
def test_empty_template(self):
"""Test running with an empty template and no header files."""
result = self.runMkenumsWithTemplate('')
self.assertEqual('', result.err)
self.assertEquals('''/* {standard_top_comment} */
/* {standard_bottom_comment} */'''.format(**result.subs),
result.out.strip())
def test_no_headers(self):
"""Test running with a complete template, but no header files."""
result = self.runMkenumsWithAllSubstitutions()
self.assertEqual('', result.err)
self.assertEquals('''
comment
comment: {standard_top_comment}
file-header
file-tail
comment
comment: {standard_bottom_comment}
'''.format(**result.subs).strip(), result.out)
def test_empty_header(self):
"""Test an empty header."""
(info, out, err, subs) = self.runMkenumsWithHeader('')
self.assertEqual('', err)
result = self.runMkenumsWithHeader('')
self.assertEqual('', result.err)
self.assertEqual('''
comment
comment: {standard_top_comment}
file-header
filename: {filename}
basename: {basename}
file-tail
filename: ARGV
basename: {basename}
comment
comment: {standard_bottom_comment}
'''.format(**subs).strip(), out)
'''.format(**result.subs).strip(), result.out)
def test_enum_name(self):
"""Test typedefs with an enum and a typedef name. Bug #794506."""
@ -289,9 +326,9 @@ comment: {standard_bottom_comment}
ENUM_VALUE
} SomeEnumIdentifier;
'''
(info, out, err, subs) = self.runMkenumsWithHeader(h_contents)
self.assertEqual('', err)
self.assertSingleEnum(out, subs, 'SomeEnumIdentifier',
result = self.runMkenumsWithHeader(h_contents)
self.assertEqual('', result.err)
self.assertSingleEnum(result, 'SomeEnumIdentifier',
'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
'ENUM_IDENTIFIER', 'SOME', 'enum', 'Enum',
'ENUM', 'ENUM_VALUE', 'value', '0')
@ -304,10 +341,9 @@ comment: {standard_bottom_comment}
ENUM_VALUE
} SomeEnumIdentifier;
'''
(info, out, err, subs) = \
self.runMkenumsWithHeader(h_contents, encoding='iso-8859-1')
self.assertIn('WARNING: UnicodeWarning: ', err)
self.assertSingleEnum(out, subs, 'SomeEnumIdentifier',
result = self.runMkenumsWithHeader(h_contents, encoding='iso-8859-1')
self.assertIn('WARNING: UnicodeWarning: ', result.err)
self.assertSingleEnum(result, 'SomeEnumIdentifier',
'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
'ENUM_IDENTIFIER', 'SOME', 'enum', 'Enum',
'ENUM', 'ENUM_VALUE', 'value', '0')
@ -315,6 +351,8 @@ comment: {standard_bottom_comment}
def test_reproducible(self):
"""Test builds are reproducible regardless of file ordering.
Bug #691436."""
template_contents = 'template'
h_contents1 = '''
typedef enum {
FIRST,
@ -328,36 +366,28 @@ comment: {standard_bottom_comment}
'''
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
suffix='.template') as template_file, \
tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
suffix='1.h') as h_file1, \
tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
suffix='2.h') as h_file2:
# Write out the template and headers.
template_file.write('template'.encode('utf-8'))
tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
suffix='2.h') as h_file2:
# Write out the headers.
h_file1.write(h_contents1.encode('utf-8'))
h_file2.write(h_contents2.encode('utf-8'))
template_file.flush()
h_file1.flush()
h_file2.flush()
# Run glib-mkenums with the headers in one order, and then again
# in another order.
info1 = self.runMkenums('--template', template_file.name,
h_file1.name, h_file2.name)
info1.check_returncode()
out1 = info1.stdout.decode('utf-8').strip()
self.assertEqual('', info1.stderr.decode('utf-8').strip())
result1 = self.runMkenumsWithTemplate(template_contents,
h_file1.name, h_file2.name)
self.assertEqual('', result1.err)
info2 = self.runMkenums('--template', template_file.name,
h_file2.name, h_file1.name)
info2.check_returncode()
out2 = info2.stdout.decode('utf-8').strip()
self.assertEqual('', info2.stderr.decode('utf-8').strip())
result2 = self.runMkenumsWithTemplate(template_contents,
h_file2.name, h_file1.name)
self.assertEqual('', result2.err)
# The output should be the same.
self.assertEqual(out1, out2)
self.assertEqual(result1.out, result2.out)
def test_no_nick(self):
"""Test trigraphs with a desc but no nick. Issue #1360."""
@ -366,13 +396,57 @@ comment: {standard_bottom_comment}
GEGL_SAMPLER_NEAREST = 0, /*< desc="nearest" >*/
} GeglSamplerType;
'''
(info, out, err, subs) = self.runMkenumsWithHeader(h_contents)
self.assertEqual('', err)
self.assertSingleEnum(out, subs, 'GeglSamplerType',
result = self.runMkenumsWithHeader(h_contents)
self.assertEqual('', result.err)
self.assertSingleEnum(result, 'GeglSamplerType',
'gegl_sampler_type', 'GEGL_SAMPLER_TYPE',
'SAMPLER_TYPE', 'GEGL', 'enum', 'Enum',
'ENUM', 'GEGL_SAMPLER_NEAREST', 'nearest', '0')
def test_filename_basename_in_fhead_ftail(self):
template_contents = '''
/*** BEGIN file-header ***/
file-header
filename: @filename@
basename: @basename@
/*** END file-header ***/
/*** BEGIN comment ***/
comment
comment: @comment@
/*** END comment ***/
/*** BEGIN file-tail ***/
file-tail
filename: @filename@
basename: @basename@
/*** END file-tail ***/'''
result = self.runMkenumsWithTemplate(template_contents)
self.assertEqual(
textwrap.dedent(
'''
WARNING: @filename@ used in file-header section.
WARNING: @basename@ used in file-header section.
WARNING: @filename@ used in file-tail section.
WARNING: @basename@ used in file-tail section.
''').strip(),
result.err)
self.assertEqual('''
comment
comment: {standard_top_comment}
file-header
filename: @filename@
basename: @basename@
file-tail
filename: @filename@
basename: @basename@
comment
comment: {standard_bottom_comment}
'''.format(**result.subs).strip(), result.out)
if __name__ == '__main__':
unittest.main(testRunner=taptestrunner.TAPTestRunner())