mirror of
				https://git.proxmox.com/git/libgit2
				synced 2025-11-04 05:12:54 +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 _CC 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"""eJyNVe9v2jAQ/Zz8FVcqlaTQkm7Vpon1w6R2ExorCKhaqUVRmjjFauIg27DRiv99ZzuQH9BuCIkod7577909I2QgaQjhLODgh0mw8ueBnN2fe18+Tbu2LUyYMmlT4S+DhEa+TOc6yQkzJqQ5eqxeuParbY0n3yb+BITE0xaNwVElHBVuw5GQLhxcgOfalsWJXHAG3ibvYOz3xpe9ER44FdJPs4i49bz82QnCkAiRV731Bz9duFBlu/a6gjmmrIxXI31cxDHhbRD0hfgSEsKecuj5QUMrDy8D7ofZgkm4gPNuLccUJGyJynBxP8UcLGM1Jr+GSKTRBvWkf67M7834ajQcDb73+lcNG6w1cjqkcURi8G971x8/GCV+EDkh6XyoMDuXt4PRpWtQtsGAr+lySBJBsFwOmSql4oyDQxGQ1wUKXwseXWi1qKtx1khg8hOR+OBsGdEpSmqZ8eBL1VadkpQtiOqiI7uLoVJNC9SLs3C+cjaqY6i90VyVLtGwrLWNX9vqHEMvBjkjKpvyjKUE9Y8yIlgTBxOsIGArOaPsqQ2Sr0BmsBAEOtgfjjv2G6AaKt7IcdVhmWAFWQnYGiVmEY0NtsmMChArIUm6BZXQZ4IgKngUgXDBuQZPOQllhsF3AJ6+ie70HWhbV5ycldd/mdEItKEXTAQsesz+OOqd3nQFoOR2b6rs03zwmsVi7a5mOEMWiBJhdgtBYuHztFSs7kFcWZpEfg7BMN3iKG2gCvgyoIm2UUPXU9Lc6U9DWW9r2M2VUbV3gcGYO4vLsFw0QfneUWrZFhbDbqg3PlRJ1Nm/Ao6eZTzFob0QDVcNejgY9+4A3fY74BGIJBAzIvSQS3a0duyoSBRGrM+D5vN40POwrFoImp3m1i7bQdRqKGYncDZV9y3mm0bVeKtVFFN7tFm7IgtaCmm7GM4+ZbENJu2RTCNKn9Enc1/8czy1/wU1H3Ox6TqmTKUtSnR90+/vnMn1KExS3Udd4f8dAUdH+1Z4/zoZpMomZbbeZ8/by88cML4qM9ubWuHzF4WiW5U=""",
 | 
						|
"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()
 |