mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-09 18:22:16 +00:00
229 lines
12 KiB
Python
Executable File
229 lines
12 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
from __future__ import with_statement
|
|
from string import Template
|
|
import re, fnmatch, os
|
|
|
|
VERSION = "0.7.0"
|
|
|
|
TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\(\s*(void)?\s*\))\s*\{"
|
|
|
|
TEMPLATE_MAIN = Template(
|
|
r"""
|
|
/*
|
|
* Clay v${version}
|
|
*
|
|
* This is an autogenerated file. Do not modify.
|
|
* To add new unit tests or suites, regenerate the whole
|
|
* file with `./clay`
|
|
*/
|
|
|
|
#define clay_print(...) ${clay_print}
|
|
|
|
${clay_library}
|
|
|
|
${extern_declarations}
|
|
|
|
static const struct clay_func _all_callbacks[] = {
|
|
${test_callbacks}
|
|
};
|
|
|
|
static const struct clay_suite _all_suites[] = {
|
|
${test_suites}
|
|
};
|
|
|
|
static const char _suites_str[] = "${suites_str}";
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
return clay_test(
|
|
argc, argv, _suites_str,
|
|
_all_callbacks, ${cb_count},
|
|
_all_suites, ${suite_count}
|
|
);
|
|
}
|
|
""")
|
|
|
|
TEMPLATE_SUITE = Template(
|
|
r"""
|
|
{
|
|
"${clean_name}",
|
|
${initialize},
|
|
${cleanup},
|
|
${cb_ptr}, ${cb_count}
|
|
}
|
|
""")
|
|
|
|
def main():
|
|
from optparse import OptionParser
|
|
|
|
parser = OptionParser()
|
|
|
|
parser.add_option('-c', '--clay-path', dest='clay_path')
|
|
parser.add_option('-o', '--output', dest='output')
|
|
parser.add_option('-v', '--report-to', dest='print_mode', default='stdout')
|
|
|
|
options, args = parser.parse_args()
|
|
|
|
for folder in args:
|
|
builder = ClayTestBuilder(folder,
|
|
clay_path = options.clay_path,
|
|
output_folder = options.output,
|
|
print_mode = options.print_mode)
|
|
|
|
builder.render()
|
|
|
|
|
|
class ClayTestBuilder:
|
|
def __init__(self, folder_name, output_folder = None, clay_path = None, print_mode = 'stdout'):
|
|
self.declarations = []
|
|
self.callbacks = []
|
|
self.suites = []
|
|
self.suite_list = []
|
|
|
|
self.clay_path = os.path.abspath(clay_path) if clay_path else None
|
|
self.print_mode = print_mode
|
|
|
|
folder_name = os.path.abspath(folder_name)
|
|
if not output_folder:
|
|
output_folder = folder_name
|
|
|
|
self.output = os.path.join(output_folder, "clay_main.c")
|
|
self.output_header = os.path.join(output_folder, "clay.h")
|
|
|
|
self.modules = ["clay.c", "clay_sandbox.c", "clay_fixtures.c", "clay_fs.c"]
|
|
|
|
print("Loading test suites...")
|
|
|
|
for root, dirs, files in os.walk(folder_name):
|
|
module_root = root[len(folder_name):]
|
|
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.suites:
|
|
raise RuntimeError(
|
|
'No tests found under "%s"' % folder_name)
|
|
|
|
def render(self):
|
|
template = TEMPLATE_MAIN.substitute(
|
|
version = VERSION,
|
|
clay_print = self._get_print_method(),
|
|
clay_library = self._get_library(),
|
|
extern_declarations = "\n".join(self.declarations),
|
|
|
|
suites_str = ", ".join(self.suite_list),
|
|
|
|
test_callbacks = ",\n\t".join(self.callbacks),
|
|
cb_count = len(self.callbacks),
|
|
|
|
test_suites = ",\n\t".join(self.suites),
|
|
suite_count = len(self.suites),
|
|
)
|
|
|
|
with open(self.output, "w") as out:
|
|
out.write(template)
|
|
|
|
with open(self.output_header, "w") as out:
|
|
out.write(self._load_file('clay.h'))
|
|
|
|
print ('Written test suite to "%s"' % self.output)
|
|
print ('Written header to "%s"' % self.output_header)
|
|
|
|
#####################################################
|
|
# Internal methods
|
|
#####################################################
|
|
def _get_print_method(self):
|
|
return {
|
|
'stdout' : 'printf(__VA_ARGS__)',
|
|
'stderr' : 'fprintf(stderr, __VA_ARGS__)',
|
|
'silent' : ''
|
|
}[self.print_mode]
|
|
|
|
def _load_file(self, filename):
|
|
if self.clay_path:
|
|
filename = os.path.join(self.clay_path, filename)
|
|
with open(filename) as cfile:
|
|
return cfile.read()
|
|
|
|
else:
|
|
import zlib, base64, sys
|
|
content = CLAY_FILES[filename]
|
|
|
|
if sys.version_info >= (3, 0):
|
|
content = bytearray(content, 'utf_8')
|
|
content = base64.b64decode(content)
|
|
content = zlib.decompress(content)
|
|
return str(content)
|
|
else:
|
|
content = base64.b64decode(content)
|
|
return zlib.decompress(content)
|
|
|
|
def _get_library(self):
|
|
return "\n".join(self._load_file(f) for f in self.modules)
|
|
|
|
def _parse_comment(self, comment):
|
|
comment = comment[2:-2]
|
|
comment = comment.splitlines()
|
|
comment = [line.strip() for line in comment]
|
|
comment = "\n".join(comment)
|
|
|
|
return comment
|
|
|
|
def _process_test_file(self, test_name, contents):
|
|
regex_string = TEST_FUNC_REGEX % test_name
|
|
regex = re.compile(regex_string, re.MULTILINE)
|
|
|
|
callbacks = []
|
|
initialize = cleanup = "{NULL, NULL, 0}"
|
|
|
|
for (declaration, symbol, short_name, _) in regex.findall(contents):
|
|
self.declarations.append("extern %s;" % declaration)
|
|
func_ptr = '{"%s", &%s, %d}' % (
|
|
short_name, symbol, len(self.suites)
|
|
)
|
|
|
|
if short_name == 'initialize':
|
|
initialize = func_ptr
|
|
elif short_name == 'cleanup':
|
|
cleanup = func_ptr
|
|
else:
|
|
callbacks.append(func_ptr)
|
|
|
|
if not callbacks:
|
|
return
|
|
|
|
clean_name = test_name.replace("_", "::")
|
|
|
|
suite = TEMPLATE_SUITE.substitute(
|
|
clean_name = clean_name,
|
|
initialize = initialize,
|
|
cleanup = cleanup,
|
|
cb_ptr = "&_all_callbacks[%d]" % len(self.callbacks),
|
|
cb_count = len(callbacks)
|
|
).strip()
|
|
|
|
self.callbacks += callbacks
|
|
self.suites.append(suite)
|
|
self.suite_list.append(clean_name)
|
|
|
|
print(" %s (%d tests)" % (clean_name, len(callbacks)))
|
|
|
|
CLAY_FILES = {
|
|
"clay.c" : r"""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""",
|
|
"clay_sandbox.c" : r"""eJyNlW1P2zAQx187n+IIEk1ooWFDm6aOF5NgUzVGq7YIJKiikDjUWuNUttutIL77znbaPBTQqkpxcufz7+7+l0gVKRZDPIsEhPE8WoeLSM3uToMvn6Y9x5HWzLhymAxX0ZwlocoWxsmLcy6V3XqoH/jOs0PGk2+TcAJS4W7CUvB0CE+bO3AglQ97ZxD4DiGCqqXgEGz89sZhf3zeH+GGY6nCLE+o3/Qr1l4Ux1TKIupNOPjpw5kO23Neaswp41VeQ/qwTFMqOiDZEw0VzCl/LNCLjTatwryKRBjnS67gDE57DR8bkPIVVkbIuyn6YBjiTn4NMRG3A3plLhf2ej2+GA1Hg+/9ywvXAfKCOQEpTmJ4s8/ShKYQ3vSvPn6wZflB1YRmi6FOwDu/GYzOfYvcAZtJo0j7lCcsxVqluQCPIVLQAwZfy0x60G4z35A20kDnR6pw4W1zYlMsKrENwof6LL1LMb6kuiPGsisN7WqPwIoJHi/W3qbuaOpsqq5DV9gJeXHw75DuIfRTUDOqvZnIeUaxA0lOJW9ha6I1RHytZow/dkCJNagclpJCF8+Hw67zBpSr7W7B1cSyxhpZBayAmsyYBLmWimZbmjn7TfH0Gogmj5dCGGomaKxyNL5Ddvwm1vG7TMXt0UlV+aucJWBmecllxJOH/K+nnxmRa4DKoAdTPTmt+6BVymhXiPEMs0BKxKwqTIYiqwRrjh8KlM2TsECwmW45KtLThlBFbG4myDXxdGluzc/VU7ed1c3boj7ZJYOd6zytYvmo/uorR1fLIRgMT8N646KeRDP7Z8DW81xk2LQnanB1o4eDcf8WcMz+RCIBOY/kjErT5MpIk5051EmUE9jsByv6cW/6QUjDBK1uazsn20Y0YujMjuBkql+16G8Pqtvb7TKY1hGWQauudIK2Bu2UvfE3lc9+o/oX1Ypp4qvry8udEpdirevCbP1/ZcLBwWtSer2tFlHLtSqK4HMQ7Hx6yg1W39WUXnWt5fMPA9kzbQ==""",
|
|
"clay_fixtures.c" : r"""eJyFUV1LwzAUfW5+xZU9rLUVJ4ggZQ9DFAUfRCZMRglZmrBAl5Qkk03xv9v0a82U+Zabc+45595rLLGCAlXSWKBrouEccbGzW81wSew6HCIrYljicTuqJBsWoS8UmFbPobXA8npye5OlFSI+GbaglbK4YDJFKOjeMAVjdfUInUPkyFZLWu7DWiKBxtgpKN78RZETEByactlLXcBVBmdTGF+OIxQEPhrHGdRQ1zzMv5xUYN84ROLY8b1MEPeTJEdsV3tRq0wdt06tWcWVzXpS9I3QSPCccbh7nr3jh6fF/O31Hr/M5o9ouGpa4NYlPHmBVt074i/lBLy+OsWHEjkcXLAhMl+p3Wk3bjBV1VIG6TxOApgWZN8s4k8bWjAit+W/NnoTejMddI+GqW1GTOaCox8pOffr""",
|
|
"clay_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/jjp40U6bpmA46t0vgVzZpVS7TLApg3lOwe55A6ivMqe3AKCV4GoQXZo5WkXbk4kr5c0qpK+UoRW5SrMBM3t1cLg60HV19YSS0nVuA+wE/dY/zSg8XF32StX/S9h2OrobIVeLskUhVUCM2eF8wfpKI1oM3FO/hsb3+GHDeCo/DVdRNozjx6zxQ5fB06lXXwehIsPr2n+S0xtR4vBqboLvguYwqD9YUBvLD1D/DesFfr5ejPcTJPTpOLObHn/4PLnkprmpJ+WQy3pbpeqNZOcenovvVCxm1ZIK0bEl4Hrpdpf2pbYs2rjchDs+f6nfVfAXYRuu6hGRx9Yc1R3gZD5zVBweGsd5wsNjVuXG+0y81O6KRuDt4u+r8Ro/B6JRWOo5RG5OuxM6QZYUeGfVAcdM9B6b3lRlpqr8ya4gu/363wZ0W9oekNjt4udvVA1N/1oNxuQvfiHc342TdbTYNa0u2XPiN9I/NV464Qs/e1a8PxiLJvClb63wD3Q6FA""",
|
|
"clay.h" : r"""eJy9VF1v2jAUfW5+xR15IVFU2GvXVkIVqEiomjaqbU+WcW6KtWBntrOyfz/bCR8JpFn3wBPmxsfn3HuOHfJMpJgBIQ+LyQ+ynH5dkkdCgtAWucCTehBywfIyRbjVJs356np9HwS/JU+B5fQPIVRrVGYYXHFhgEmRcsOlSIIru9a2sqYK4oznmFRbcsvS+opKSdWqpaiZ4kV9lgPqtSzzlNCVVCb6tNdANBrCcqSiLIa+Nozrv1H1P44SqBayoL9KtOAdNtMNqDs25Jmbj5/CbP59+fxlSj5Plo/BsToH5VtTKhw22/Q1IuimwVKXNRXpSm7fA9mpewMSop15FgSjOA4ghon3w44NNpQpqeGVmzXgtsg54wb8rGGDWtMXtPtHe+ct66bUhhTWUTK0AJWAcyFqGu2/RHB/B+PEpmU2X0wJcavF/MmvBrNSMC+A0TyHjFrv0xsYQHg4M4GP0Qmx29lPfNvJO90WyAymkDUEGOk19CioSPrpP3T3bfmVnasj5hqENGBUied4d149rJH9/A+fmMNdyKhxdMp8YafOSbiAUeOo51IJ+Y/XqZbUvGFVMYGn58Xi/GVowaqpd8Lq9veYXaKbgO7o9XVzCN2B4ziIncIOmWkDezrym9qYdj+7hmZSMZcoe6R9HEevVAkuXtpNeBVnQtMVlSXaZ7e6GdeD8y9HzfSeU79VEEhL5X6MI8EtstJF7GZwHMD6df8LLiKMPg=="""
|
|
}
|
|
|
|
if __name__ == '__main__':
|
|
main()
|