blob: 7f97fa9d45c59d2ed09141a4ce2ed9b12cdcebc9 [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",
18 "xpathInternals", "xmlunicode", "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 = {}
149def add_missing_functions(name, module):
150 try:
151 list = missing_functions[module]
152 list.append(name)
153 except:
154 missing_functions[module] = [name]
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000155
156#
157# Provide the type generators and destructors for the parameters
158#
159
Daniel Veillarda03e3652004-11-02 18:45:30 +0000160def type_convert(str, name, info, module, function, pos):
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000161 res = string.replace(str, " *", "_ptr")
162 res = string.replace(res, " ", "_")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000163 res = string.replace(res, "htmlNode", "xmlNode")
164 res = string.replace(res, "htmlDoc", "xmlDoc")
165 res = string.replace(res, "htmlParser", "xmlParser")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000166 if res == 'const_char_ptr':
167 if string.find(name, "file") != -1 or \
168 string.find(name, "uri") != -1 or \
169 string.find(name, "URI") != -1 or \
170 string.find(info, "filename") != -1 or \
171 string.find(info, "URI") != -1 or \
172 string.find(info, "URL") != -1:
173 if string.find(function, "Save") != -1:
174 return('fileoutput')
175 return('filepath')
176 if res == 'void_ptr':
177 if module == 'nanoftp' and name == 'ctx':
178 return('xmlNanoFTPCtxtPtr')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000179 if function == 'xmlNanoFTPNewCtxt':
180 return('xmlNanoFTPCtxtPtr')
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000181 if module == 'nanohttp' and name == 'ctx':
182 return('xmlNanoHTTPCtxtPtr')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000183 if function == 'xmlIOHTTPOpenW':
184 return('xmlNanoHTTPCtxtPtr')
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000185 if string.find(name, "data") != -1:
186 return('userdata');
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000187 if string.find(name, "user") != -1:
188 return('userdata');
Daniel Veillard3d97e662004-11-04 10:49:00 +0000189 if res == 'xmlDoc_ptr':
190 res = 'xmlDocPtr';
191 if res == 'xmlNode_ptr':
192 res = 'xmlNodePtr';
193 if res == 'xmlDict_ptr':
194 res = 'xmlDictPtr';
Daniel Veillarda03e3652004-11-02 18:45:30 +0000195 if res == 'xmlNodePtr' and pos != 0:
196 if (function == 'xmlAddChild' and pos == 2) or \
197 (function == 'xmlAddChildList' and pos == 2) or \
198 (function == 'xmlAddNextSibling' and pos == 2) or \
199 (function == 'xmlAddSibling' and pos == 2) or \
200 (function == 'xmlDocSetRootElement' and pos == 2) or \
201 (function == 'xmlReplaceNode' and pos == 2) or \
202 (function == 'xmlTextMerge') or \
203 (function == 'xmlAddPrevSibling' and pos == 2):
204 return('xmlNodePtr_in');
Daniel Veillard34099b42004-11-04 17:34:35 +0000205 if res == 'const xmlBufferPtr':
206 res = 'xmlBufferPtr';
Daniel Veillard27f20102004-11-05 11:50:11 +0000207 if res == 'xmlChar_ptr' and name == 'name' and \
208 string.find(function, "EatName") != -1:
209 return('eaten_name')
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000210
211 return res
212
Daniel Veillard34099b42004-11-04 17:34:35 +0000213known_param_types = []
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000214
215def is_known_param_type(name):
216 for type in known_param_types:
217 if type == name:
218 return 1
219 return 0
220
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000221#
222# Provide the type destructors for the return values
223#
224
Daniel Veillard34099b42004-11-04 17:34:35 +0000225known_return_types = []
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000226
227def is_known_return_type(name):
228 for type in known_return_types:
229 if type == name:
230 return 1
231 return 0
232
Daniel Veillard34099b42004-11-04 17:34:35 +0000233#
234# Copy the beginning of the C test program result
235#
236
237input = open("testapi.c", "r")
238test = open('testapi.c.new', 'w')
239
240def compare_and_save():
241 global test
242
243 test.close()
244 input = open("testapi.c", "r").read()
245 test = open('testapi.c.new', "r").read()
246 if input != test:
247 os.system("rm testapi.c ; mv testapi.c.new testapi.c")
248 print("Updated testapi.c")
249 else:
250 print("Generated testapi.c is identical")
251
252line = input.readline()
253while line != "":
254 if line == "/* CUT HERE: everything below that line is generated */\n":
255 break;
256 if line[0:15] == "#define gen_nb_":
257 type = string.split(line[15:])[0]
258 known_param_types.append(type)
259 if line[0:19] == "static void desret_":
260 type = string.split(line[19:], '(')[0]
261 known_return_types.append(type)
262 test.write(line)
263 line = input.readline()
264input.close()
265
266if line == "":
267 print "Could not find the CUT marker in testapi.c skipping generation"
268 test.close()
269 sys.exit(0)
270
271print("Scanned testapi.c: found %d parameters types and %d return types\n" % (
272 len(known_param_types), len(known_return_types)))
273test.write("/* CUT HERE: everything below that line is generated */\n")
274
275
276#
277# Open the input API description
278#
279doc = libxml2.readFile('doc/libxml2-api.xml', None, 0)
280if doc == None:
281 print "Failed to load doc/libxml2-api.xml"
282 sys.exit(1)
283ctxt = doc.xpathNewContext()
284headers = ctxt.xpathEval("/api/files/file")
285
286#
287# Load the interfaces
288#
289for file in headers:
290 name = file.xpathEval('string(@name)')
291 if (name == None) or (name == ''):
292 continue
293
294 #
295 # Some module may be skipped because they don't really consists
296 # of user callable APIs
297 #
298 if is_skipped_module(name):
299 continue
300
301 #
302 # do not test deprecated APIs
303 #
304 desc = file.xpathEval('string(description)')
305 if string.find(desc, 'DEPRECATED') != -1:
306 print "Skipping deprecated interface %s" % name
307 continue;
308
309 test.write("#include <libxml/%s.h>\n" % name)
310 modules.append(name)
311
312#
313# Generate the callers signatures
314#
315for module in modules:
316 test.write("static int test_%s(void);\n" % module);
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000317
318#
319# Generate the top caller
320#
321
322test.write("""
323/**
324 * testlibxml2:
325 *
326 * Main entry point of the tester for the full libxml2 module,
327 * it calls all the tester entry point for each module.
328 *
329 * Returns the number of error found
330 */
331static int
332testlibxml2(void)
333{
334 int ret = 0;
335
336""")
337
338for module in modules:
339 test.write(" ret += test_%s();\n" % module)
340
341test.write("""
Daniel Veillard3d97e662004-11-04 10:49:00 +0000342 printf("Total: %d functions, %d tests, %d errors\\n",
343 function_tests, call_tests, ret);
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000344 return(ret);
345}
346
347""")
348
349#
350# How to handle a function
351#
352nb_tests = 0
353
354def generate_test(module, node):
355 global test
356 global nb_tests
357 nb_cond = 0
358 no_gen = 0
359
360 name = node.xpathEval('string(@name)')
361 if is_skipped_function(name):
362 return
363
364 test.write("""
365static int
366test_%s(void) {
367 int ret = 0;
368
369""" % (name))
370
371 #
372 # check we know how to handle the args and return values
373 # and store the informations for the generation
374 #
375 try:
376 args = node.xpathEval("arg")
377 except:
378 args = []
379 t_args = []
Daniel Veillarda03e3652004-11-02 18:45:30 +0000380 n = 0
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000381 for arg in args:
Daniel Veillarda03e3652004-11-02 18:45:30 +0000382 n = n + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000383 rtype = arg.xpathEval("string(@type)")
384 if rtype == 'void':
385 break;
386 info = arg.xpathEval("string(@info)")
387 nam = arg.xpathEval("string(@name)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000388 type = type_convert(rtype, nam, info, module, name, n)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000389 if is_known_param_type(type) == 0:
390 add_missing_type(type, name);
391 no_gen = 1
392 t_args.append((nam, type, rtype, info))
393
394 try:
395 rets = node.xpathEval("return")
396 except:
397 rets = []
398 t_ret = None
399 for ret in rets:
400 rtype = ret.xpathEval("string(@type)")
401 info = ret.xpathEval("string(@info)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000402 type = type_convert(rtype, 'return', info, module, name, 0)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000403 if rtype == 'void':
404 break
405 if is_known_return_type(type) == 0:
406 add_missing_type(type, name);
407 no_gen = 1
408 t_ret = (type, rtype, info)
409 break
410
411 if no_gen == 1:
Daniel Veillard34099b42004-11-04 17:34:35 +0000412 add_missing_functions(name, module)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000413 test.write("""
414 /* missing type support */
415 return(ret);
416}
417
418""")
419 return
420
421 try:
422 conds = node.xpathEval("cond")
423 for cond in conds:
424 test.write("#ifdef %s\n" % (cond.get_content()))
425 nb_cond = nb_cond + 1
426 except:
427 pass
428
429 # Declare the memory usage counter
430 no_mem = is_skipped_memcheck(name)
431 if no_mem == 0:
432 test.write(" int mem_base;\n");
433
434 # Declare the return value
435 if t_ret != None:
436 test.write(" %s ret_val;\n" % (t_ret[1]))
437
438 # Declare the arguments
439 for arg in t_args:
440 (nam, type, rtype, info) = arg;
441 # add declaration
442 test.write(" %s %s; /* %s */\n" % (rtype, nam, info))
443 test.write(" int n_%s;\n" % (nam))
444 test.write("\n")
445
446 # Cascade loop on of each argument list of values
447 for arg in t_args:
448 (nam, type, rtype, info) = arg;
449 #
450 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
451 nam, nam, type, nam))
452
453 # log the memory usage
454 if no_mem == 0:
455 test.write(" mem_base = xmlMemBlocks();\n");
456
457 # prepare the call
Daniel Veillard3d97e662004-11-04 10:49:00 +0000458 i = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000459 for arg in t_args:
460 (nam, type, rtype, info) = arg;
461 #
Daniel Veillard3d97e662004-11-04 10:49:00 +0000462 test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
463 i = i + 1;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000464
465 # do the call, and clanup the result
Daniel Veillard34099b42004-11-04 17:34:35 +0000466 if extra_pre_call.has_key(name):
467 test.write(" %s\n"% (extra_pre_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000468 if t_ret != None:
469 test.write("\n ret_val = %s(" % (name))
470 need = 0
471 for arg in t_args:
472 (nam, type, rtype, info) = arg
473 if need:
474 test.write(", ")
475 else:
476 need = 1
477 test.write("%s" % nam);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000478 test.write(");\n")
479 if extra_post_call.has_key(name):
480 test.write(" %s\n"% (extra_post_call[name]))
481 test.write(" desret_%s(ret_val);\n" % t_ret[0])
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000482 else:
483 test.write("\n %s(" % (name));
484 need = 0;
485 for arg in t_args:
486 (nam, type, rtype, info) = arg;
487 if need:
488 test.write(", ")
489 else:
490 need = 1
491 test.write("%s" % nam)
492 test.write(");\n")
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000493 if extra_post_call.has_key(name):
494 test.write(" %s\n"% (extra_post_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000495
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000496 test.write(" call_tests++;\n");
Daniel Veillarda03e3652004-11-02 18:45:30 +0000497
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000498 # Free the arguments
Daniel Veillard3d97e662004-11-04 10:49:00 +0000499 i = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000500 for arg in t_args:
501 (nam, type, rtype, info) = arg;
502 #
Daniel Veillard3d97e662004-11-04 10:49:00 +0000503 test.write(" des_%s(n_%s, %s, %d);\n" % (type, nam, nam, i))
504 i = i + 1;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000505
506 test.write(" xmlResetLastError();\n");
507 # Check the memory usage
508 if no_mem == 0:
509 test.write(""" if (mem_base != xmlMemBlocks()) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000510 printf("Leak of %%d blocks found in %s",
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000511 xmlMemBlocks() - mem_base);
512 ret++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000513""" % (name));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000514 for arg in t_args:
515 (nam, type, rtype, info) = arg;
516 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
517 test.write(""" printf("\\n");\n""")
518 test.write(" }\n")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000519
520 for arg in t_args:
521 test.write(" }\n")
522
523 #
524 # end of conditional
525 #
526 while nb_cond > 0:
527 test.write("#endif\n")
528 nb_cond = nb_cond -1
529
530 nb_tests = nb_tests + 1;
531
532 test.write("""
Daniel Veillard3d97e662004-11-04 10:49:00 +0000533 function_tests++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000534 return(ret);
535}
536
537""")
538
539#
540# Generate all module callers
541#
542for module in modules:
543 # gather all the functions exported by that module
544 try:
545 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
546 except:
547 print "Failed to gather functions from module %s" % (module)
548 continue;
549
550 # iterate over all functions in the module generating the test
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000551 i = 0
552 nb_tests_old = nb_tests
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000553 for function in functions:
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000554 i = i + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000555 generate_test(module, function);
556
557 # header
558 test.write("""static int
559test_%s(void) {
560 int ret = 0;
561
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000562 printf("Testing %s : %d of %d functions ...\\n");
563""" % (module, module, nb_tests - nb_tests_old, i))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000564
565 # iterate over all functions in the module generating the call
566 for function in functions:
567 name = function.xpathEval('string(@name)')
568 if is_skipped_function(name):
569 continue
570 test.write(" ret += test_%s();\n" % (name))
571
572 # footer
573 test.write("""
574 if (ret != 0)
575 printf("Module %s: %%d errors\\n", ret);
576 return(ret);
577}
578""" % (module))
579
Daniel Veillardce244ad2004-11-05 10:03:46 +0000580#
581# Generate direct module caller
582#
583test.write("""static int
584test_module(const char *module) {
585""");
586for module in modules:
587 test.write(""" if (!strcmp(module, "%s")) return(test_%s());\n""" % (
588 module, module))
589test.write(""" return(0);
590}
591""");
592
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000593print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000594
Daniel Veillard34099b42004-11-04 17:34:35 +0000595compare_and_save()
596
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000597missing_list = []
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000598for missing in missing_types.keys():
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000599 if missing == 'va_list' or missing == '...':
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000600 continue;
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000601
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000602 n = len(missing_types[missing])
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000603 missing_list.append((n, missing))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000604
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000605def compare_missing(a, b):
606 return b[0] - a[0]
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000607
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000608missing_list.sort(compare_missing)
609print "Missing support for %d types see missing.lst" % (len(missing_list))
610lst = open("missing.lst", "w")
Daniel Veillard34099b42004-11-04 17:34:35 +0000611lst.write("Missing support for %d types" % (len(missing_list)))
612lst.write("\n")
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000613for miss in missing_list:
614 lst.write("%s: %d :" % (miss[1], miss[0]))
615 i = 0
616 for n in missing_types[miss[1]]:
617 i = i + 1
618 if i > 5:
619 lst.write(" ...")
620 break
621 lst.write(" %s" % (n))
622 lst.write("\n")
Daniel Veillard34099b42004-11-04 17:34:35 +0000623lst.write("\n")
624lst.write("\n")
625lst.write("Missing support per module");
626for module in missing_functions.keys():
627 lst.write("module %s:\n %s\n" % (module, missing_functions[module]))
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000628
629lst.close()
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000630
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000631