⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gentest.py

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 PY
📖 第 1 页 / 共 2 页
字号:
        type = string.split(line[19:], '(')[0]
	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 types
rettypes = {}
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 int
testlibxml2(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 = 0

def 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 int
test_%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 int
test_%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 int
test_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 + -