mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-19 20:37:41 +00:00
310 lines
16 KiB
Python
Executable File
310 lines
16 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
from __future__ import with_statement
|
|
from string import Template
|
|
import re, fnmatch, os
|
|
|
|
VERSION = "0.10.0"
|
|
|
|
TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\(\s*void\s*\))\s*\{"
|
|
|
|
EVENT_CB_REGEX = re.compile(
|
|
r"^(void\s+clar_on_(\w+)\(\s*void\s*\))\s*\{",
|
|
re.MULTILINE)
|
|
|
|
SKIP_COMMENTS_REGEX = re.compile(
|
|
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
|
|
re.DOTALL | re.MULTILINE)
|
|
|
|
CLAR_HEADER = """
|
|
/*
|
|
* Clar v%s
|
|
*
|
|
* This is an autogenerated file. Do not modify.
|
|
* To add new unit tests or suites, regenerate the whole
|
|
* file with `./clar`
|
|
*/
|
|
""" % VERSION
|
|
|
|
CLAR_EVENTS = [
|
|
'init',
|
|
'shutdown',
|
|
'test',
|
|
'suite'
|
|
]
|
|
|
|
def main():
|
|
from optparse import OptionParser
|
|
|
|
parser = OptionParser()
|
|
|
|
parser.add_option('-c', '--clar-path', dest='clar_path')
|
|
parser.add_option('-v', '--report-to', dest='print_mode', default='default')
|
|
|
|
options, args = parser.parse_args()
|
|
|
|
for folder in args or ['.']:
|
|
builder = ClarTestBuilder(folder,
|
|
clar_path = options.clar_path,
|
|
print_mode = options.print_mode)
|
|
|
|
builder.render()
|
|
|
|
|
|
class ClarTestBuilder:
|
|
def __init__(self, path, clar_path = None, print_mode = 'default'):
|
|
self.declarations = []
|
|
self.suite_names = []
|
|
self.callback_data = {}
|
|
self.suite_data = {}
|
|
self.event_callbacks = []
|
|
|
|
self.clar_path = os.path.abspath(clar_path) if clar_path else None
|
|
|
|
self.path = os.path.abspath(path)
|
|
self.modules = [
|
|
"clar_sandbox.c",
|
|
"clar_fixtures.c",
|
|
"clar_fs.c"
|
|
]
|
|
|
|
self.modules.append("clar_print_%s.c" % print_mode)
|
|
|
|
print("Loading test suites...")
|
|
|
|
for root, dirs, files in os.walk(self.path):
|
|
module_root = root[len(self.path):]
|
|
module_root = [c for c in module_root.split(os.sep) if c]
|
|
|
|
tests_in_module = fnmatch.filter(files, "*.c")
|
|
|
|
for test_file in tests_in_module:
|
|
full_path = os.path.join(root, test_file)
|
|
test_name = "_".join(module_root + [test_file[:-2]])
|
|
|
|
with open(full_path) as f:
|
|
self._process_test_file(test_name, f.read())
|
|
|
|
if not self.suite_data:
|
|
raise RuntimeError(
|
|
'No tests found under "%s"' % path)
|
|
|
|
def render(self):
|
|
main_file = os.path.join(self.path, 'clar_main.c')
|
|
with open(main_file, "w") as out:
|
|
out.write(self._render_main())
|
|
|
|
header_file = os.path.join(self.path, 'clar.h')
|
|
with open(header_file, "w") as out:
|
|
out.write(self._render_header())
|
|
|
|
print ('Written Clar suite to "%s"' % self.path)
|
|
|
|
#####################################################
|
|
# Internal methods
|
|
#####################################################
|
|
|
|
def _render_cb(self, cb):
|
|
return '{"%s", &%s}' % (cb['short_name'], cb['symbol'])
|
|
|
|
def _render_suite(self, suite):
|
|
template = Template(
|
|
r"""
|
|
{
|
|
"${clean_name}",
|
|
${initialize},
|
|
${cleanup},
|
|
${cb_ptr}, ${cb_count}
|
|
}
|
|
""")
|
|
|
|
callbacks = {}
|
|
for cb in ['initialize', 'cleanup']:
|
|
callbacks[cb] = (self._render_cb(suite[cb])
|
|
if suite[cb] else "{NULL, NULL}")
|
|
|
|
return template.substitute(
|
|
clean_name = suite['name'].replace("_", "::"),
|
|
initialize = callbacks['initialize'],
|
|
cleanup = callbacks['cleanup'],
|
|
cb_ptr = "_clar_cb_%s" % suite['name'],
|
|
cb_count = suite['cb_count']
|
|
).strip()
|
|
|
|
def _render_callbacks(self, suite_name, callbacks):
|
|
template = Template(
|
|
r"""
|
|
static const struct clar_func _clar_cb_${suite_name}[] = {
|
|
${callbacks}
|
|
};
|
|
""")
|
|
callbacks = [
|
|
self._render_cb(cb)
|
|
for cb in callbacks
|
|
if cb['short_name'] not in ('initialize', 'cleanup')
|
|
]
|
|
|
|
return template.substitute(
|
|
suite_name = suite_name,
|
|
callbacks = ",\n\t".join(callbacks)
|
|
).strip()
|
|
|
|
def _render_event_overrides(self):
|
|
overrides = []
|
|
for event in CLAR_EVENTS:
|
|
if event in self.event_callbacks:
|
|
continue
|
|
|
|
overrides.append(
|
|
"#define clar_on_%s() /* nop */" % event
|
|
)
|
|
|
|
return '\n'.join(overrides)
|
|
|
|
def _render_header(self):
|
|
template = Template(self._load_file('clar.h'))
|
|
|
|
declarations = "\n".join(
|
|
"extern %s;" % decl
|
|
for decl in sorted(self.declarations)
|
|
)
|
|
|
|
return template.substitute(
|
|
extern_declarations = declarations,
|
|
)
|
|
|
|
def _render_main(self):
|
|
template = Template(self._load_file('clar.c'))
|
|
suite_names = sorted(self.suite_names)
|
|
|
|
suite_data = [
|
|
self._render_suite(self.suite_data[s])
|
|
for s in suite_names
|
|
]
|
|
|
|
callbacks = [
|
|
self._render_callbacks(s, self.callback_data[s])
|
|
for s in suite_names
|
|
]
|
|
|
|
callback_count = sum(
|
|
len(cbs) for cbs in self.callback_data.values()
|
|
)
|
|
|
|
return template.substitute(
|
|
clar_modules = self._get_modules(),
|
|
clar_callbacks = "\n".join(callbacks),
|
|
clar_suites = ",\n\t".join(suite_data),
|
|
clar_suite_count = len(suite_data),
|
|
clar_callback_count = callback_count,
|
|
clar_event_overrides = self._render_event_overrides(),
|
|
)
|
|
|
|
def _load_file(self, filename):
|
|
if self.clar_path:
|
|
filename = os.path.join(self.clar_path, filename)
|
|
with open(filename) as cfile:
|
|
return cfile.read()
|
|
|
|
else:
|
|
import zlib, base64, sys
|
|
content = CLAR_FILES[filename]
|
|
|
|
if sys.version_info >= (3, 0):
|
|
content = bytearray(content, 'utf_8')
|
|
content = base64.b64decode(content)
|
|
content = zlib.decompress(content)
|
|
return str(content, 'utf-8')
|
|
else:
|
|
content = base64.b64decode(content)
|
|
return zlib.decompress(content)
|
|
|
|
def _get_modules(self):
|
|
return "\n".join(self._load_file(f) for f in self.modules)
|
|
|
|
def _skip_comments(self, text):
|
|
def _replacer(match):
|
|
s = match.group(0)
|
|
return "" if s.startswith('/') else s
|
|
|
|
return re.sub(SKIP_COMMENTS_REGEX, _replacer, text)
|
|
|
|
def _process_test_file(self, suite_name, contents):
|
|
contents = self._skip_comments(contents)
|
|
|
|
self._process_events(contents)
|
|
self._process_declarations(suite_name, contents)
|
|
|
|
def _process_events(self, contents):
|
|
for (decl, event) in EVENT_CB_REGEX.findall(contents):
|
|
if event not in CLAR_EVENTS:
|
|
continue
|
|
|
|
self.declarations.append(decl)
|
|
self.event_callbacks.append(event)
|
|
|
|
def _process_declarations(self, suite_name, contents):
|
|
callbacks = []
|
|
initialize = cleanup = None
|
|
|
|
regex_string = TEST_FUNC_REGEX % suite_name
|
|
regex = re.compile(regex_string, re.MULTILINE)
|
|
|
|
for (declaration, symbol, short_name) in regex.findall(contents):
|
|
data = {
|
|
"short_name" : short_name,
|
|
"declaration" : declaration,
|
|
"symbol" : symbol
|
|
}
|
|
|
|
if short_name == 'initialize':
|
|
initialize = data
|
|
elif short_name == 'cleanup':
|
|
cleanup = data
|
|
else:
|
|
callbacks.append(data)
|
|
|
|
if not callbacks:
|
|
return
|
|
|
|
tests_in_suite = len(callbacks)
|
|
|
|
suite = {
|
|
"name" : suite_name,
|
|
"initialize" : initialize,
|
|
"cleanup" : cleanup,
|
|
"cb_count" : tests_in_suite
|
|
}
|
|
|
|
if initialize:
|
|
self.declarations.append(initialize['declaration'])
|
|
|
|
if cleanup:
|
|
self.declarations.append(cleanup['declaration'])
|
|
|
|
self.declarations += [
|
|
callback['declaration']
|
|
for callback in callbacks
|
|
]
|
|
|
|
callbacks.sort(key=lambda x: x['short_name'])
|
|
self.callback_data[suite_name] = callbacks
|
|
self.suite_data[suite_name] = suite
|
|
self.suite_names.append(suite_name)
|
|
|
|
print(" %s (%d tests)" % (suite_name, tests_in_suite))
|
|
|
|
|
|
|
|
CLAR_FILES = {
|
|
"clar.c" : r"""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""",
|
|
"clar_print_default.c" : r"""eJyFU01P4zAQPSe/YqgU1a5Cuadi98ap4rLaE6DIxA5YSu3InnQPK/479jgFB9FycuZ53vObj5QeBeoOjlZL6Abh2tFpg602Gln4AFQe285OBmuIsZ80qhPQWeMRulfhYJMujDgoz8v/ZcGiJP+k78qCpHu22lshlYRKJjXfQOUfzaqG+CJfvJCrZgp/UDhUMpAC+laWZ6rwrxNK+8/8XEkElHPWJeBcBQnKmB9YRt6Vn0YfTfJYkCunRuuwpVzPLlqnHPJtpsOp0x7d1GFKowTY0EF2T09CaCyHO6GHyamG+hokeO6q8k1TeWCV5/AQgko+wcM1hiOml0VBqte/qNAsjr2I4cpYkMp3To+o7YLS6yFnDNqE8U2HZ+W+6MzowhecFmHOS009+BfK0j2w+SJ7HK5u4f7vfs+D/DmdLJ0vp3N5f6yJTlm+5sl62Me0M1klCehD35X8uj+RsFsixMlWuuqC38SG37C+W0MD6+36B380Ifb9f0gmbjZgrB1hc7Pc3uTokrR4Dru6kA6DqGG73ZLwUbSDDlfCvYw7Cn38KVmMa0gzK479XJ5HGWZBeE0UnjjKSDaHb+U7mrWGAw==""",
|
|
"clar_print_tap.c" : r"""eJyNVMFu2zAMPVtfwbgIYBu2gWK3BmuxnYthh+02wFBtORXmSIYkZxiG/vso2m6lJF12skk9ko+PlJh13MkWjlp20A7cNKORyjVSSZfhDzhhXdPqSbkSvG0n6cTqaLWyDtpnbqCYDxQ/CJuzPyzJfMr8LXy3ugLgiW/FEYU+S799+gpHYazUCm4//FBpvmMvjL1D2T5PrtO/1HXa3iGM0WZ2/A/d2BcE7xhLZA/ZJkqYvPZwAyO3VnTAhwG2HRHLbI7NlAFJbCwRgxVRYM/lgIEYxA9a7U+jg4IlxiVxtjXNbV1vu/Nq78tIaUlDNR3WEVtnptbNMAJAQZ9AOkR7Lda6AFVVzSMLfDhzy/cC7mBr35qo7udeDnYfw63A8Uv3+460OMtGowE4y0b+GOqbhwtQ74+RPYp+Cen9MXKQakV2IdL7G5TjSZh8XY/lqBO2NXJ0fqM3H+HL98fHcFkAAsApgeAoj5Wu6/ra5dCKVie8sLQP/hrOF2I2ifXsmNePJryW2lq/hNVCDIkvK/oAqdIO9M8UxUjx48/ChK8mlmMJ0SdyRozaLDtnsysd0Fizy29ORPMGiqJAkv5DCga4f5fgT0gnKoE7WXqBqcCRN4PEI272445MzIQB3i5hWd9+oWHxNZrwtUk/o0iAvxug/T2eAqiET5HPOYXqssV8YX8BFTvXlQ==""",
|
|
"clar_sandbox.c" : r"""eJydVWtP4kAU/dz+iism0gpKfWQ3G9YPm+gasioEMJgomdR2KhPplMwM7KLxv++dTqEP0DVrTKjcO+eec+6cKpWvWADBxBdAgqkvyMxXk/tT79uXcdu2pSkzrmwmycKfspCoeJY2OUHCpTJH9/UXrv1qW4PhjyEZglR42mIROBrC0eUm7Enlws4ZeK5tWYKqueDgrfp2BqQzOO/08cChVCROQupW+7Jnxw8CKmWGOiLdXy6cadi2/VbiHDFe5JsyfZxHERVNkOyFEgVTyp8M9V0W8ZBGQEadm5Nj28pwjMqse4EGBcmcKziD03alx+BTvkCjhLwfYw8aYtWG1z3UVWuCfko/Lszn7eCi3+t3f3auLmo2WG8oEaxsEtN6o0SAwxDHawOD7/n4NjQazE3hK7Ox+YkqfHDWRNgYjbGMyfilNlWfUozPqZ6SVjbXq1vNCJQpeDBbOivvsNRcOaehC0uyrDcbf22rtQ+dCNSE6m4mEh5TtC1MqOR19NNfgs+XasL4UxOUWIJKYC4ptHA+7Lfsd0jVdL2W8arSMsUSswIxJLVLp5Ia6EuqhjSe9TSocz7q9s9dc6wJBq5y+XYpD1lkdA0nTIJcSkXjtaApe6YooKRFiw/mQqTCmaCBSrD4gbjDd5UdfiRr9efBUTEAi4SFkEZ6zqXPw8fkj6O/S2OqCRTy7o11gOoPXj1XjVcDI1FMRDBBFcgSaRYMiSQRcQGsmkL0k01DklEwStc8CrdXF4jy2TRNTi3F09bcpT81nbZ1ZFcvjXLAcw4m3klUpOVigIpvHu2WbSEYTkO/8aEsoqr+FXD1PBExLu2FpnT1onvdQecOMKm/fRGCnPpyQmW65EKUrY0oaxF5iKv7YNk+HtJ9WFalBPVWfR219SIqGFrZARyN9RsX+82gcr3RyMH0PVpdu7wLGpppM1/ONmdxDDZllgF6xjgNHUKuOzeXo5NjQtyMXPyMkZmVjqLMm9urq4296P74Wd+34la9r5638S9EH8BkF0enKytPJfKf92ML7v8QWb1i8NQn5a5XmOe6HKEU4fMhhr29banbngCNYpJdJLrVixK9v7GvgW8=""",
|
|
"clar_fixtures.c" : r"""eJyFUV1LwzAUfW5+xZU9rLUVJ4ggZQ9DFAUfZEwQSglZmrBAl5Qkk6n43236tWbKfMvNOfecc+81llhBgSppLNAN0XCOuNjbnWa4InYTjpE1MSzxuD1Vki2L0BcKTKfn0EYgu57d3uRpjYhPhi1opSwumUwRCvo3zMFYXT9C5xA5stWSVh9hI5FAa+wUFG//osgJCA5tmQ1SF3CVw9kcppfTCAWBj8ZxDg3UN4/zZ7MaHBrHSBw7vpcJ4mGS5Ijtai9qnannNqk1q7myXU+KvhGaCF4wDnfPiyV+eHpbvS7v8cti9YjGq6Yl7lzCkxfo1L0j/lJOwOtrUrwrUcDBBRsii7Xan3bjBlNVL2WUzuMkgGlJdLuIP21oyYjcVf/a6G3ozXTQPRqmsZkwWQiOfgAVGffP""",
|
|
"clar_fs.c" : r"""eJylVdtu20YQfSa/YkAD8TKWY8dJX6L0wXDEVqgsBhINN7UFhiGX1qIkl9hd+dLG/57ZCynJUWEkfZE0s7NnZufMGe2xsqAlpJfj6ZsT399DgzUUojhKo8npb3Mg+ud8PBlNE/hq/NP4LJ5G49n5aTKOp71zNJvFs4vx06DzPz6MZ6HvS5UplkO+zAS89EtWUd7KtM3UkuS8kcqdGE/o/+t71tYm/ArTi8lk6HuS/UNTBRVtbtRyAGzo+x4rgaQ2zMaFvucJqlaicdd8z15AHKkE/rbxIQI6+DqrKp4TF3YAJ2GH/AxwTeu8fTBRA0jtl0Xp0K+sucAsx9suzPPauX2v5AIIMxYweO9AhnBwwELAbvTFXLGFrmf/aF+X4/Uu2L++3scEjwjmitRnQ/+x7/0tZ0XXecIaBTUv6AC22i/5SuRPnQWVynAy/z3CSYg/zpPZxVkCJQLp4m2YvYqVbJHrEHU7bJgG+y7IZNBQf1HBz2nNxQN5oeEHoDnnJdlOHYa2aa18dRetmlxziI8ZOl8bCV5ruk3u3ptw9OlUnaeMquxGorOfd/OcKs2kpEKlBFuMibHUuKUCm8gbW1aoOTge4HFwyZqC30l4EgdlhmYR+J4tVVBK1q0wpnv0U4JkKmqygxTDQEdfFKcfRpNRMsKx6zgzM7oLL+c4oz9A80aSs/jjp40U6bpmA46t0vgVzZpVS7TLApg3lOwe55A6ivMqE04hwcsgtCB7tJK0KxdH0pdLWlUpXylii3IVZuLm9mphsPXg6gsrqeXECtwH+Kl7jF96sLj4m6z1i773cGw1VLYCb5dEqoIKodnzgvmDVLQGtLl4B5/t7c+Q40ZwFL66bgLNmUfvmSKHr0Onsg5eT4LFp/c0vyWm1uPFwBTdBd9lTGGwvjCAF7b+Ad4b9mq9HP05TubJaXIxJ/b8f3DZU2lNU9Ivi+G2VNcL1dopLh3dt17IuC0LpHVDwuvA9TLtT21LrHm1EXlo9ly/s/4rwC5C1z00g6MvrDnK22DovCYoOJz1jpPFpsaN6412udkJndTNwdtF/zdiFF6vpMJxlNKIfD12hjQj7MiwD4qD7jkovbfcSEvtlVlTfOH3uxX+rKg3NL3B0dvFrh6I+rselNtN6F68oxk/+2araVBLuv3SZ6RvZL5q3BVi9r52bTgeUfZNwUr/G9kaoSs=""",
|
|
"clar.h" : r"""eJy9VU1P4zAQPZNfYZo9JJUFlCMLSAi1AqlCKyjavVmO4xBrEyfYztLVav874yRtmq922QOX1pnxzHvOe+O4IpIhjxAht8ubR7KaP63IHSGOC0EheS/uuEKypAg5utQmTERwEl87zq9MhIglVBFCtebKeM6RkAaxTIbCiExi5wjWGiIxVWgaiYTjaksCKJ0sVypTnVjINVMir3vZQh1nRRISGmTK+F8HOBD+WtCEaG+3Dx5/gKa9ADQe6ys8WzBUNNRl04ZobghLOJVF7pUxb1o/+tXz1MeoWmQ5fS14Q4FEulVq27oisvKVIi3uf6yeH+fk283qztnlYEvF2hSKe20VyhiRNG2h1GFNZRhk64+UbNjtKXE5WCJynNPp1EFTdFO+UlAVpZSpTKM3YWLE13kimDCotAJKudb0hcP+060xATUttCE5iEI8KFAYWZP4bR+WGR9dX6EzDGZe3C/nhNjV8v6hXE0WhWQlAUaTBEUUrBleoAlym54YzfwesN15GPhyFHe+zjkzPERRi4DJSg4HGNROPAh/PH5uwFfwXi2w0EhmBhlV8CHcjVa3MWc//0MnZus+Sagzv4/8yUoNUfgEoc78A0Mls38cp5rS0IQ9PC+Xw6PQKdp9572i+ujbirabq+3jpjt0jsZuDULfgj1SjVe6ZXvPUm7pVgyeZJEpZk0E3eA+PH2jSgr50mVfEhjwyZg7Vhxu2moYTibDl0WN9JGu36sSFBbK/hkLwtecFdZVF5MBz61+53A42nFe93SdL7OeYX3eprTNQdLHHqTxluGW4OTJlLxSoVNqWFwOg57BL8yRXZ6PXJjbT/cMi2Fg4UESgMUgsCsaELEfJPCCGQ7GQI6PIe1j+zcMFDRAwX6g3MtnOD/fmSQPIj66ukIehHcksiqm3MRZCPpZWtRKVYn05Q9fG64k2c38dTbf63eIKlZw"""
|
|
}
|
|
if __name__ == '__main__':
|
|
main()
|