blob: bc8aa3088550a6b1c066db118341ce69a94de390 [file] [log] [blame]
Daniel Veillard36e5cd52004-11-02 14:52:23 +00001#!/usr/bin/python -u
2#
3# generate a tester program for the API
4#
5import sys
Daniel Veillard34099b42004-11-04 17:34:35 +00006import os
Daniel Veillard36e5cd52004-11-02 14:52:23 +00007import string
8try:
9 import libxml2
10except:
11 print "libxml2 python bindings not available, skipping testapi.c generation"
12 sys.exit(0)
13
14#
15# Modules we don't want skip in API test
16#
17skipped_modules = [ "SAX", "SAX2", "xlink", "threads", "globals",
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +000018 "xpathInternals", "parserInternals", "xmlmemory",
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +000019 "xmlversion", "debugXML", "xmlexports", "DOCBparser",
Daniel Veillardd005b9e2004-11-03 17:07:05 +000020
21 # temporary
Daniel Veillard3d97e662004-11-04 10:49:00 +000022 "xmlautomata", "xmlregexp", "c14n",
Daniel Veillardd005b9e2004-11-03 17:07:05 +000023
24]
Daniel Veillard36e5cd52004-11-02 14:52:23 +000025
26#
27# Some function really need to be skipped for the tests.
28#
Daniel Veillarddd6d3002004-11-03 14:20:29 +000029skipped_functions = [
30# block on I/O
31"xmlFdRead", "xmlReadFd", "xmlCtxtReadFd",
32"htmlFdRead", "htmlReadFd", "htmlCtxtReadFd",
Daniel Veillard1ba06bb2004-11-04 12:32:18 +000033"xmlReaderNewFd", "xmlReaderForFd",
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +000034"xmlIORead", "xmlReadIO", "xmlCtxtReadIO",
35"htmlIORead", "htmlReadIO", "htmlCtxtReadIO",
Daniel Veillard27f20102004-11-05 11:50:11 +000036"xmlReaderNewIO", "xmlBufferDump", "xmlNanoFTPConnect",
37"xmlNanoFTPConnectTo",
Daniel Veillarddd6d3002004-11-03 14:20:29 +000038# library state cleanup, generate false leak informations and other
39# troubles, heavillyb tested otherwise.
Daniel Veillardce244ad2004-11-05 10:03:46 +000040"xmlCleanupParser", "xmlRelaxNGCleanupTypes", "xmlSetListDoc",
41"xmlSetTreeDoc", "xmlUnlinkNode",
Daniel Veillarddd6d3002004-11-03 14:20:29 +000042# hard to avoid leaks in the tests
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +000043"xmlStrcat", "xmlStrncat", "xmlCatalogAddLocal",
Daniel Veillarddd6d3002004-11-03 14:20:29 +000044# unimplemented
45"xmlTextReaderReadInnerXml", "xmlTextReaderReadOuterXml",
Daniel Veillardd005b9e2004-11-03 17:07:05 +000046"xmlTextReaderReadString",
47# destructor
Daniel Veillard27f20102004-11-05 11:50:11 +000048"xmlListDelete", "xmlOutputBufferClose", "xmlNanoFTPClose",
Daniel Veillardd005b9e2004-11-03 17:07:05 +000049# deprecated
50"xmlCatalogGetPublic", "xmlCatalogGetSystem", "xmlEncodeEntities",
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +000051# allocators
52"xmlMemFree",
Daniel Veillarddd6d3002004-11-03 14:20:29 +000053]
Daniel Veillard36e5cd52004-11-02 14:52:23 +000054
55#
56# Those functions have side effect on the global state
57# and hence generate errors on memory allocation tests
58#
59skipped_memcheck = [ "xmlLoadCatalog", "xmlAddEncodingAlias",
60 "xmlSchemaInitTypes", "xmlNanoFTPProxy", "xmlNanoFTPScanProxy",
61 "xmlNanoHTTPScanProxy", "xmlResetLastError", "xmlCatalogConvert",
62 "xmlCatalogRemove", "xmlLoadCatalogs", "xmlCleanupCharEncodingHandlers",
Daniel Veillarda03e3652004-11-02 18:45:30 +000063 "xmlInitCharEncodingHandlers", "xmlCatalogCleanup",
64 "htmlParseFile" # loads the catalogs
65]
66
67#
68# Extra code needed for some test cases
69#
Daniel Veillard34099b42004-11-04 17:34:35 +000070extra_pre_call = {
71 "xmlSAXUserParseFile":
Daniel Veillardce244ad2004-11-05 10:03:46 +000072 "if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;",
Daniel Veillard34099b42004-11-04 17:34:35 +000073 "xmlSAXUserParseMemory":
Daniel Veillardce244ad2004-11-05 10:03:46 +000074 "if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;",
Daniel Veillard34099b42004-11-04 17:34:35 +000075}
Daniel Veillarda03e3652004-11-02 18:45:30 +000076extra_post_call = {
77 "xmlAddChild":
78 "if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; }",
79 "xmlAddChildList":
80 "if (ret_val == NULL) { xmlFreeNodeList(cur) ; cur = NULL ; }",
81 "xmlAddSibling":
82 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
83 "xmlAddNextSibling":
84 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
85 "xmlAddPrevSibling":
86 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
87 "xmlDocSetRootElement":
88 "if (doc == NULL) { xmlFreeNode(root) ; root = NULL ; }",
89 "xmlReplaceNode":
Daniel Veillardce244ad2004-11-05 10:03:46 +000090 """if (cur != NULL) {
91 xmlUnlinkNode(cur);
92 xmlFreeNode(cur) ; cur = NULL ; }
93 if (old != NULL) {
94 xmlUnlinkNode(old);
95 xmlFreeNode(old) ; old = NULL ; }
96 ret_val = NULL;""",
Daniel Veillarda03e3652004-11-02 18:45:30 +000097 "xmlTextMerge":
98 """if ((first != NULL) && (first->type != XML_TEXT_NODE)) {
Daniel Veillardce244ad2004-11-05 10:03:46 +000099 xmlUnlinkNode(second);
Daniel Veillarda03e3652004-11-02 18:45:30 +0000100 xmlFreeNode(second) ; second = NULL ; }""",
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000101 "xmlBuildQName":
102 """if ((ret_val != NULL) && (ret_val != ncname) &&
103 (ret_val != prefix) && (ret_val != memory))
104 xmlFree(ret_val);
105 ret_val = NULL;""",
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000106 "xmlDictReference": "xmlDictFree(dict);",
Daniel Veillard3d97e662004-11-04 10:49:00 +0000107 # Functions which deallocates one of their parameters
108 "xmlXPathConvertBoolean": """val = NULL;""",
109 "xmlXPathConvertNumber": """val = NULL;""",
110 "xmlXPathConvertString": """val = NULL;""",
111 "xmlSaveFileTo": """buf = NULL;""",
Daniel Veillard34099b42004-11-04 17:34:35 +0000112 "xmlSaveFormatFileTo": """buf = NULL;""",
113 "xmlIOParseDTD": "input = NULL;",
Daniel Veillardce244ad2004-11-05 10:03:46 +0000114 "xmlRemoveProp": "cur = NULL;",
Daniel Veillarda03e3652004-11-02 18:45:30 +0000115}
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000116
117modules = []
118
119def is_skipped_module(name):
120 for mod in skipped_modules:
121 if mod == name:
122 return 1
123 return 0
124
125def is_skipped_function(name):
126 for fun in skipped_functions:
127 if fun == name:
128 return 1
129 # Do not test destructors
130 if string.find(name, 'Free') != -1:
131 return 1
132 return 0
133
134def is_skipped_memcheck(name):
135 for fun in skipped_memcheck:
136 if fun == name:
137 return 1
138 return 0
139
140missing_types = {}
141def add_missing_type(name, func):
142 try:
143 list = missing_types[name]
144 list.append(func)
145 except:
146 missing_types[name] = [func]
147
Daniel Veillard34099b42004-11-04 17:34:35 +0000148missing_functions = {}
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +0000149missing_functions_nr = 0
Daniel Veillard34099b42004-11-04 17:34:35 +0000150def add_missing_functions(name, module):
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +0000151 global missing_functions_nr
152
153 missing_functions_nr = missing_functions_nr + 1
Daniel Veillard34099b42004-11-04 17:34:35 +0000154 try:
155 list = missing_functions[module]
156 list.append(name)
157 except:
158 missing_functions[module] = [name]
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000159
160#
161# Provide the type generators and destructors for the parameters
162#
163
Daniel Veillarda03e3652004-11-02 18:45:30 +0000164def type_convert(str, name, info, module, function, pos):
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000165 res = string.replace(str, " *", "_ptr")
166 res = string.replace(res, " ", "_")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000167 res = string.replace(res, "htmlNode", "xmlNode")
168 res = string.replace(res, "htmlDoc", "xmlDoc")
169 res = string.replace(res, "htmlParser", "xmlParser")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000170 if res == 'const_char_ptr':
171 if string.find(name, "file") != -1 or \
172 string.find(name, "uri") != -1 or \
173 string.find(name, "URI") != -1 or \
174 string.find(info, "filename") != -1 or \
175 string.find(info, "URI") != -1 or \
176 string.find(info, "URL") != -1:
177 if string.find(function, "Save") != -1:
178 return('fileoutput')
179 return('filepath')
180 if res == 'void_ptr':
181 if module == 'nanoftp' and name == 'ctx':
182 return('xmlNanoFTPCtxtPtr')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000183 if function == 'xmlNanoFTPNewCtxt':
184 return('xmlNanoFTPCtxtPtr')
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000185 if module == 'nanohttp' and name == 'ctx':
186 return('xmlNanoHTTPCtxtPtr')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000187 if function == 'xmlIOHTTPOpenW':
188 return('xmlNanoHTTPCtxtPtr')
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000189 if string.find(name, "data") != -1:
190 return('userdata');
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000191 if string.find(name, "user") != -1:
192 return('userdata');
Daniel Veillard3d97e662004-11-04 10:49:00 +0000193 if res == 'xmlDoc_ptr':
194 res = 'xmlDocPtr';
195 if res == 'xmlNode_ptr':
196 res = 'xmlNodePtr';
197 if res == 'xmlDict_ptr':
198 res = 'xmlDictPtr';
Daniel Veillarda03e3652004-11-02 18:45:30 +0000199 if res == 'xmlNodePtr' and pos != 0:
200 if (function == 'xmlAddChild' and pos == 2) or \
201 (function == 'xmlAddChildList' and pos == 2) or \
202 (function == 'xmlAddNextSibling' and pos == 2) or \
203 (function == 'xmlAddSibling' and pos == 2) or \
204 (function == 'xmlDocSetRootElement' and pos == 2) or \
205 (function == 'xmlReplaceNode' and pos == 2) or \
206 (function == 'xmlTextMerge') or \
207 (function == 'xmlAddPrevSibling' and pos == 2):
208 return('xmlNodePtr_in');
Daniel Veillard34099b42004-11-04 17:34:35 +0000209 if res == 'const xmlBufferPtr':
210 res = 'xmlBufferPtr';
Daniel Veillard27f20102004-11-05 11:50:11 +0000211 if res == 'xmlChar_ptr' and name == 'name' and \
212 string.find(function, "EatName") != -1:
213 return('eaten_name')
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000214
215 return res
216
Daniel Veillard34099b42004-11-04 17:34:35 +0000217known_param_types = []
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000218
219def is_known_param_type(name):
220 for type in known_param_types:
221 if type == name:
222 return 1
223 return 0
224
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000225#
226# Provide the type destructors for the return values
227#
228
Daniel Veillard34099b42004-11-04 17:34:35 +0000229known_return_types = []
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000230
231def is_known_return_type(name):
232 for type in known_return_types:
233 if type == name:
234 return 1
235 return 0
236
Daniel Veillard34099b42004-11-04 17:34:35 +0000237#
238# Copy the beginning of the C test program result
239#
240
241input = open("testapi.c", "r")
242test = open('testapi.c.new', 'w')
243
244def compare_and_save():
245 global test
246
247 test.close()
248 input = open("testapi.c", "r").read()
249 test = open('testapi.c.new', "r").read()
250 if input != test:
251 os.system("rm testapi.c ; mv testapi.c.new testapi.c")
252 print("Updated testapi.c")
253 else:
254 print("Generated testapi.c is identical")
255
256line = input.readline()
257while line != "":
258 if line == "/* CUT HERE: everything below that line is generated */\n":
259 break;
260 if line[0:15] == "#define gen_nb_":
261 type = string.split(line[15:])[0]
262 known_param_types.append(type)
263 if line[0:19] == "static void desret_":
264 type = string.split(line[19:], '(')[0]
265 known_return_types.append(type)
266 test.write(line)
267 line = input.readline()
268input.close()
269
270if line == "":
271 print "Could not find the CUT marker in testapi.c skipping generation"
272 test.close()
273 sys.exit(0)
274
275print("Scanned testapi.c: found %d parameters types and %d return types\n" % (
276 len(known_param_types), len(known_return_types)))
277test.write("/* CUT HERE: everything below that line is generated */\n")
278
279
280#
281# Open the input API description
282#
283doc = libxml2.readFile('doc/libxml2-api.xml', None, 0)
284if doc == None:
285 print "Failed to load doc/libxml2-api.xml"
286 sys.exit(1)
287ctxt = doc.xpathNewContext()
288headers = ctxt.xpathEval("/api/files/file")
289
290#
291# Load the interfaces
292#
293for file in headers:
294 name = file.xpathEval('string(@name)')
295 if (name == None) or (name == ''):
296 continue
297
298 #
299 # Some module may be skipped because they don't really consists
300 # of user callable APIs
301 #
302 if is_skipped_module(name):
303 continue
304
305 #
306 # do not test deprecated APIs
307 #
308 desc = file.xpathEval('string(description)')
309 if string.find(desc, 'DEPRECATED') != -1:
310 print "Skipping deprecated interface %s" % name
311 continue;
312
313 test.write("#include <libxml/%s.h>\n" % name)
314 modules.append(name)
315
316#
317# Generate the callers signatures
318#
319for module in modules:
320 test.write("static int test_%s(void);\n" % module);
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000321
322#
323# Generate the top caller
324#
325
326test.write("""
327/**
328 * testlibxml2:
329 *
330 * Main entry point of the tester for the full libxml2 module,
331 * it calls all the tester entry point for each module.
332 *
333 * Returns the number of error found
334 */
335static int
336testlibxml2(void)
337{
338 int ret = 0;
339
340""")
341
342for module in modules:
343 test.write(" ret += test_%s();\n" % module)
344
345test.write("""
Daniel Veillard3d97e662004-11-04 10:49:00 +0000346 printf("Total: %d functions, %d tests, %d errors\\n",
347 function_tests, call_tests, ret);
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000348 return(ret);
349}
350
351""")
352
353#
354# How to handle a function
355#
356nb_tests = 0
357
358def generate_test(module, node):
359 global test
360 global nb_tests
361 nb_cond = 0
362 no_gen = 0
363
364 name = node.xpathEval('string(@name)')
365 if is_skipped_function(name):
366 return
367
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000368 #
369 # check we know how to handle the args and return values
370 # and store the informations for the generation
371 #
372 try:
373 args = node.xpathEval("arg")
374 except:
375 args = []
376 t_args = []
Daniel Veillarda03e3652004-11-02 18:45:30 +0000377 n = 0
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000378 for arg in args:
Daniel Veillarda03e3652004-11-02 18:45:30 +0000379 n = n + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000380 rtype = arg.xpathEval("string(@type)")
381 if rtype == 'void':
382 break;
383 info = arg.xpathEval("string(@info)")
384 nam = arg.xpathEval("string(@name)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000385 type = type_convert(rtype, nam, info, module, name, n)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000386 if is_known_param_type(type) == 0:
387 add_missing_type(type, name);
388 no_gen = 1
389 t_args.append((nam, type, rtype, info))
390
391 try:
392 rets = node.xpathEval("return")
393 except:
394 rets = []
395 t_ret = None
396 for ret in rets:
397 rtype = ret.xpathEval("string(@type)")
398 info = ret.xpathEval("string(@info)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000399 type = type_convert(rtype, 'return', info, module, name, 0)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000400 if rtype == 'void':
401 break
402 if is_known_return_type(type) == 0:
403 add_missing_type(type, name);
404 no_gen = 1
405 t_ret = (type, rtype, info)
406 break
407
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +0000408 test.write("""
409static int
410test_%s(void) {
411 int ret = 0;
412
413""" % (name))
414
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000415 if no_gen == 1:
Daniel Veillard34099b42004-11-04 17:34:35 +0000416 add_missing_functions(name, module)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000417 test.write("""
418 /* missing type support */
419 return(ret);
420}
421
422""")
423 return
424
425 try:
426 conds = node.xpathEval("cond")
427 for cond in conds:
428 test.write("#ifdef %s\n" % (cond.get_content()))
429 nb_cond = nb_cond + 1
430 except:
431 pass
432
433 # Declare the memory usage counter
434 no_mem = is_skipped_memcheck(name)
435 if no_mem == 0:
436 test.write(" int mem_base;\n");
437
438 # Declare the return value
439 if t_ret != None:
440 test.write(" %s ret_val;\n" % (t_ret[1]))
441
442 # Declare the arguments
443 for arg in t_args:
444 (nam, type, rtype, info) = arg;
445 # add declaration
446 test.write(" %s %s; /* %s */\n" % (rtype, nam, info))
447 test.write(" int n_%s;\n" % (nam))
448 test.write("\n")
449
450 # Cascade loop on of each argument list of values
451 for arg in t_args:
452 (nam, type, rtype, info) = arg;
453 #
454 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
455 nam, nam, type, nam))
456
457 # log the memory usage
458 if no_mem == 0:
459 test.write(" mem_base = xmlMemBlocks();\n");
460
461 # prepare the call
Daniel Veillard3d97e662004-11-04 10:49:00 +0000462 i = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000463 for arg in t_args:
464 (nam, type, rtype, info) = arg;
465 #
Daniel Veillard3d97e662004-11-04 10:49:00 +0000466 test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
467 i = i + 1;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000468
469 # do the call, and clanup the result
Daniel Veillard34099b42004-11-04 17:34:35 +0000470 if extra_pre_call.has_key(name):
471 test.write(" %s\n"% (extra_pre_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000472 if t_ret != None:
473 test.write("\n ret_val = %s(" % (name))
474 need = 0
475 for arg in t_args:
476 (nam, type, rtype, info) = arg
477 if need:
478 test.write(", ")
479 else:
480 need = 1
481 test.write("%s" % nam);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000482 test.write(");\n")
483 if extra_post_call.has_key(name):
484 test.write(" %s\n"% (extra_post_call[name]))
485 test.write(" desret_%s(ret_val);\n" % t_ret[0])
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000486 else:
487 test.write("\n %s(" % (name));
488 need = 0;
489 for arg in t_args:
490 (nam, type, rtype, info) = arg;
491 if need:
492 test.write(", ")
493 else:
494 need = 1
495 test.write("%s" % nam)
496 test.write(");\n")
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000497 if extra_post_call.has_key(name):
498 test.write(" %s\n"% (extra_post_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000499
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000500 test.write(" call_tests++;\n");
Daniel Veillarda03e3652004-11-02 18:45:30 +0000501
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000502 # Free the arguments
Daniel Veillard3d97e662004-11-04 10:49:00 +0000503 i = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000504 for arg in t_args:
505 (nam, type, rtype, info) = arg;
506 #
Daniel Veillard3d97e662004-11-04 10:49:00 +0000507 test.write(" des_%s(n_%s, %s, %d);\n" % (type, nam, nam, i))
508 i = i + 1;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000509
510 test.write(" xmlResetLastError();\n");
511 # Check the memory usage
512 if no_mem == 0:
513 test.write(""" if (mem_base != xmlMemBlocks()) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000514 printf("Leak of %%d blocks found in %s",
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000515 xmlMemBlocks() - mem_base);
516 ret++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000517""" % (name));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000518 for arg in t_args:
519 (nam, type, rtype, info) = arg;
520 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
521 test.write(""" printf("\\n");\n""")
522 test.write(" }\n")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000523
524 for arg in t_args:
525 test.write(" }\n")
526
527 #
528 # end of conditional
529 #
530 while nb_cond > 0:
531 test.write("#endif\n")
532 nb_cond = nb_cond -1
533
534 nb_tests = nb_tests + 1;
535
536 test.write("""
Daniel Veillard3d97e662004-11-04 10:49:00 +0000537 function_tests++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000538 return(ret);
539}
540
541""")
542
543#
544# Generate all module callers
545#
546for module in modules:
547 # gather all the functions exported by that module
548 try:
549 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
550 except:
551 print "Failed to gather functions from module %s" % (module)
552 continue;
553
554 # iterate over all functions in the module generating the test
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000555 i = 0
556 nb_tests_old = nb_tests
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000557 for function in functions:
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000558 i = i + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000559 generate_test(module, function);
560
561 # header
562 test.write("""static int
563test_%s(void) {
564 int ret = 0;
565
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000566 printf("Testing %s : %d of %d functions ...\\n");
567""" % (module, module, nb_tests - nb_tests_old, i))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000568
569 # iterate over all functions in the module generating the call
570 for function in functions:
571 name = function.xpathEval('string(@name)')
572 if is_skipped_function(name):
573 continue
574 test.write(" ret += test_%s();\n" % (name))
575
576 # footer
577 test.write("""
578 if (ret != 0)
579 printf("Module %s: %%d errors\\n", ret);
580 return(ret);
581}
582""" % (module))
583
Daniel Veillardce244ad2004-11-05 10:03:46 +0000584#
585# Generate direct module caller
586#
587test.write("""static int
588test_module(const char *module) {
589""");
590for module in modules:
591 test.write(""" if (!strcmp(module, "%s")) return(test_%s());\n""" % (
592 module, module))
593test.write(""" return(0);
594}
595""");
596
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000597print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000598
Daniel Veillard34099b42004-11-04 17:34:35 +0000599compare_and_save()
600
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000601missing_list = []
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000602for missing in missing_types.keys():
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000603 if missing == 'va_list' or missing == '...':
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000604 continue;
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000605
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000606 n = len(missing_types[missing])
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000607 missing_list.append((n, missing))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000608
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000609def compare_missing(a, b):
610 return b[0] - a[0]
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000611
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000612missing_list.sort(compare_missing)
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +0000613print "Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list))
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000614lst = open("missing.lst", "w")
Daniel Veillard34099b42004-11-04 17:34:35 +0000615lst.write("Missing support for %d types" % (len(missing_list)))
616lst.write("\n")
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000617for miss in missing_list:
618 lst.write("%s: %d :" % (miss[1], miss[0]))
619 i = 0
620 for n in missing_types[miss[1]]:
621 i = i + 1
622 if i > 5:
623 lst.write(" ...")
624 break
625 lst.write(" %s" % (n))
626 lst.write("\n")
Daniel Veillard34099b42004-11-04 17:34:35 +0000627lst.write("\n")
628lst.write("\n")
629lst.write("Missing support per module");
630for module in missing_functions.keys():
631 lst.write("module %s:\n %s\n" % (module, missing_functions[module]))
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000632
633lst.close()
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000634
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000635