📄 gentest.py
字号:
known_return_types.append(type) test.write(line) line = input.readline()input.close()if line == "": print "Could not find the CUT marker in testapi.c skipping generation" test.close() sys.exit(0)print("Scanned testapi.c: found %d parameters types and %d return types\n" % ( len(known_param_types), len(known_return_types)))test.write("/* CUT HERE: everything below that line is generated */\n")## Open the input API description#doc = libxml2.readFile(srcPref + 'doc/libxml2-api.xml', None, 0)if doc == None: print "Failed to load doc/libxml2-api.xml" sys.exit(1)ctxt = doc.xpathNewContext()## Generate a list of all function parameters and select only# those used in the api tests#argtypes = {}args = ctxt.xpathEval("/api/symbols/function/arg")for arg in args: mod = arg.xpathEval('string(../@file)') func = arg.xpathEval('string(../@name)') if (mod not in skipped_modules) and (func not in skipped_functions): type = arg.xpathEval('string(@type)') if not argtypes.has_key(type): argtypes[type] = func# similarly for return typesrettypes = {}rets = ctxt.xpathEval("/api/symbols/function/return")for ret in rets: mod = ret.xpathEval('string(../@file)') func = ret.xpathEval('string(../@name)') if (mod not in skipped_modules) and (func not in skipped_functions): type = ret.xpathEval('string(@type)') if not rettypes.has_key(type): rettypes[type] = func## Generate constructors and return type handling for all enums# which are used as function parameters#enums = ctxt.xpathEval("/api/symbols/typedef[@type='enum']")for enum in enums: module = enum.xpathEval('string(@file)') name = enum.xpathEval('string(@name)') # # Skip any enums which are not in our filtered lists # if (name == None) or ((name not in argtypes) and (name not in rettypes)): continue; define = 0 if argtypes.has_key(name) and is_known_param_type(name, name) == 0: values = ctxt.xpathEval("/api/symbols/enum[@type='%s']" % name) i = 0 vals = [] for value in values: vname = value.xpathEval('string(@name)') if vname == None: continue; i = i + 1 if i >= 5: break; vals.append(vname) if vals == []: print "Didn't find any value for enum %s" % (name) continue if modules_defines.has_key(module): test.write("#ifdef %s\n" % (modules_defines[module])) define = 1 test.write("#define gen_nb_%s %d\n" % (name, len(vals))) test.write("""static %s gen_%s(int no, int nr ATTRIBUTE_UNUSED) {\n""" % (name, name)) i = 1 for value in vals: test.write(" if (no == %d) return(%s);\n" % (i, value)) i = i + 1 test.write(""" return(0);}static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {}""" % (name, name)); known_param_types.append(name) if (is_known_return_type(name) == 0) and (name in rettypes): if define == 0 and modules_defines.has_key(module): test.write("#ifdef %s\n" % (modules_defines[module])) define = 1 test.write("""static void desret_%s(%s val ATTRIBUTE_UNUSED) {}""" % (name, name)) known_return_types.append(name) if define == 1: test.write("#endif\n\n")## Load the interfaces# headers = ctxt.xpathEval("/api/files/file")for file in headers: name = file.xpathEval('string(@name)') if (name == None) or (name == ''): continue # # Some module may be skipped because they don't really consists # of user callable APIs # if is_skipped_module(name): continue # # do not test deprecated APIs # desc = file.xpathEval('string(description)') if string.find(desc, 'DEPRECATED') != -1: print "Skipping deprecated interface %s" % name continue; test.write("#include <libxml/%s.h>\n" % name) modules.append(name) ## Generate the callers signatures# for module in modules: test.write("static int test_%s(void);\n" % module);## Generate the top caller# test.write("""/** * testlibxml2: * * Main entry point of the tester for the full libxml2 module, * it calls all the tester entry point for each module. * * Returns the number of error found */static inttestlibxml2(void){ int test_ret = 0;""")for module in modules: test.write(" test_ret += test_%s();\n" % module)test.write(""" printf("Total: %d functions, %d tests, %d errors\\n", function_tests, call_tests, test_ret); return(test_ret);}""")## How to handle a function# nb_tests = 0def generate_test(module, node): global test global nb_tests nb_cond = 0 no_gen = 0 name = node.xpathEval('string(@name)') if is_skipped_function(name): return # # check we know how to handle the args and return values # and store the informations for the generation # try: args = node.xpathEval("arg") except: args = [] t_args = [] n = 0 for arg in args: n = n + 1 rtype = arg.xpathEval("string(@type)") if rtype == 'void': break; info = arg.xpathEval("string(@info)") nam = arg.xpathEval("string(@name)") type = type_convert(rtype, nam, info, module, name, n) if is_known_param_type(type, rtype) == 0: add_missing_type(type, name); no_gen = 1 if (type[-3:] == 'Ptr' or type[-4:] == '_ptr') and \ rtype[0:6] == 'const ': crtype = rtype[6:] else: crtype = rtype t_args.append((nam, type, rtype, crtype, info)) try: rets = node.xpathEval("return") except: rets = [] t_ret = None for ret in rets: rtype = ret.xpathEval("string(@type)") info = ret.xpathEval("string(@info)") type = type_convert(rtype, 'return', info, module, name, 0) if rtype == 'void': break if is_known_return_type(type) == 0: add_missing_type(type, name); no_gen = 1 t_ret = (type, rtype, info) break test.write("""static inttest_%s(void) { int test_ret = 0;""" % (name)) if no_gen == 1: add_missing_functions(name, module) test.write(""" /* missing type support */ return(test_ret);}""") return try: conds = node.xpathEval("cond") for cond in conds: test.write("#if %s\n" % (cond.get_content())) nb_cond = nb_cond + 1 except: pass define = 0 if function_defines.has_key(name): test.write("#ifdef %s\n" % (function_defines[name])) define = 1 # Declare the memory usage counter no_mem = is_skipped_memcheck(name) if no_mem == 0: test.write(" int mem_base;\n"); # Declare the return value if t_ret != None: test.write(" %s ret_val;\n" % (t_ret[1])) # Declare the arguments for arg in t_args: (nam, type, rtype, crtype, info) = arg; # add declaration test.write(" %s %s; /* %s */\n" % (crtype, nam, info)) test.write(" int n_%s;\n" % (nam)) test.write("\n") # Cascade loop on of each argument list of values for arg in t_args: (nam, type, rtype, crtype, info) = arg; # test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % ( nam, nam, type, nam)) # log the memory usage if no_mem == 0: test.write(" mem_base = xmlMemBlocks();\n"); # prepare the call i = 0; for arg in t_args: (nam, type, rtype, crtype, info) = arg; # test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i)) i = i + 1; # do the call, and clanup the result if extra_pre_call.has_key(name): test.write(" %s\n"% (extra_pre_call[name])) if t_ret != None: test.write("\n ret_val = %s(" % (name)) need = 0 for arg in t_args: (nam, type, rtype, crtype, info) = arg if need: test.write(", ") else: need = 1 if rtype != crtype: test.write("(%s)" % rtype) test.write("%s" % nam); test.write(");\n") if extra_post_call.has_key(name): test.write(" %s\n"% (extra_post_call[name])) test.write(" desret_%s(ret_val);\n" % t_ret[0]) else: test.write("\n %s(" % (name)); need = 0; for arg in t_args: (nam, type, rtype, crtype, info) = arg; if need: test.write(", ") else: need = 1 if rtype != crtype: test.write("(%s)" % rtype) test.write("%s" % nam) test.write(");\n") if extra_post_call.has_key(name): test.write(" %s\n"% (extra_post_call[name])) test.write(" call_tests++;\n"); # Free the arguments i = 0; for arg in t_args: (nam, type, rtype, crtype, info) = arg; # test.write(" des_%s(n_%s, " % (type, nam)) if rtype != crtype: test.write("(%s)" % rtype) test.write("%s, %d);\n" % (nam, i)) i = i + 1; test.write(" xmlResetLastError();\n"); # Check the memory usage if no_mem == 0: test.write(""" if (mem_base != xmlMemBlocks()) { printf("Leak of %%d blocks found in %s", xmlMemBlocks() - mem_base); test_ret++;""" % (name)); for arg in t_args: (nam, type, rtype, crtype, info) = arg; test.write(""" printf(" %%d", n_%s);\n""" % (nam)) test.write(""" printf("\\n");\n""") test.write(" }\n") for arg in t_args: test.write(" }\n") test.write(" function_tests++;\n") # # end of conditional # while nb_cond > 0: test.write("#endif\n") nb_cond = nb_cond -1 if define == 1: test.write("#endif\n") nb_tests = nb_tests + 1; test.write(""" return(test_ret);}""") ## Generate all module callers#for module in modules: # gather all the functions exported by that module try: functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module)) except: print "Failed to gather functions from module %s" % (module) continue; # iterate over all functions in the module generating the test i = 0 nb_tests_old = nb_tests for function in functions: i = i + 1 generate_test(module, function); # header test.write("""static inttest_%s(void) { int test_ret = 0; if (quiet == 0) printf("Testing %s : %d of %d functions ...\\n");""" % (module, module, nb_tests - nb_tests_old, i)) # iterate over all functions in the module generating the call for function in functions: name = function.xpathEval('string(@name)') if is_skipped_function(name): continue test.write(" test_ret += test_%s();\n" % (name)) # footer test.write(""" if (test_ret != 0) printf("Module %s: %%d errors\\n", test_ret); return(test_ret);}""" % (module))## Generate direct module caller#test.write("""static inttest_module(const char *module) {""");for module in modules: test.write(""" if (!strcmp(module, "%s")) return(test_%s());\n""" % ( module, module))test.write(""" return(0);}""");print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)compare_and_save()missing_list = []for missing in missing_types.keys(): if missing == 'va_list' or missing == '...': continue; n = len(missing_types[missing]) missing_list.append((n, missing))def compare_missing(a, b): return b[0] - a[0]missing_list.sort(compare_missing)print "Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list))lst = open("missing.lst", "w")lst.write("Missing support for %d types" % (len(missing_list)))lst.write("\n")for miss in missing_list: lst.write("%s: %d :" % (miss[1], miss[0])) i = 0 for n in missing_types[miss[1]]: i = i + 1 if i > 5: lst.write(" ...") break lst.write(" %s" % (n)) lst.write("\n")lst.write("\n")lst.write("\n")lst.write("Missing support per module");for module in missing_functions.keys(): lst.write("module %s:\n %s\n" % (module, missing_functions[module]))lst.close()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -