blob: d4790f229a27460698357e8125b7c080ed1c606c [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 Veillardce682bc2004-11-05 17:22:25 +000075 "xmlParseBalancedChunkMemory":
76 "if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;",
77 "xmlParseBalancedChunkMemoryRecover":
78 "if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;",
Daniel Veillard34099b42004-11-04 17:34:35 +000079}
Daniel Veillarda03e3652004-11-02 18:45:30 +000080extra_post_call = {
81 "xmlAddChild":
82 "if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; }",
83 "xmlAddChildList":
84 "if (ret_val == NULL) { xmlFreeNodeList(cur) ; cur = NULL ; }",
85 "xmlAddSibling":
86 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
87 "xmlAddNextSibling":
88 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
89 "xmlAddPrevSibling":
90 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
91 "xmlDocSetRootElement":
92 "if (doc == NULL) { xmlFreeNode(root) ; root = NULL ; }",
93 "xmlReplaceNode":
Daniel Veillardce244ad2004-11-05 10:03:46 +000094 """if (cur != NULL) {
95 xmlUnlinkNode(cur);
96 xmlFreeNode(cur) ; cur = NULL ; }
97 if (old != NULL) {
98 xmlUnlinkNode(old);
99 xmlFreeNode(old) ; old = NULL ; }
100 ret_val = NULL;""",
Daniel Veillarda03e3652004-11-02 18:45:30 +0000101 "xmlTextMerge":
102 """if ((first != NULL) && (first->type != XML_TEXT_NODE)) {
Daniel Veillardce244ad2004-11-05 10:03:46 +0000103 xmlUnlinkNode(second);
Daniel Veillarda03e3652004-11-02 18:45:30 +0000104 xmlFreeNode(second) ; second = NULL ; }""",
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000105 "xmlBuildQName":
106 """if ((ret_val != NULL) && (ret_val != ncname) &&
107 (ret_val != prefix) && (ret_val != memory))
108 xmlFree(ret_val);
109 ret_val = NULL;""",
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000110 "xmlDictReference": "xmlDictFree(dict);",
Daniel Veillard3d97e662004-11-04 10:49:00 +0000111 # Functions which deallocates one of their parameters
112 "xmlXPathConvertBoolean": """val = NULL;""",
113 "xmlXPathConvertNumber": """val = NULL;""",
114 "xmlXPathConvertString": """val = NULL;""",
115 "xmlSaveFileTo": """buf = NULL;""",
Daniel Veillard34099b42004-11-04 17:34:35 +0000116 "xmlSaveFormatFileTo": """buf = NULL;""",
117 "xmlIOParseDTD": "input = NULL;",
Daniel Veillardce244ad2004-11-05 10:03:46 +0000118 "xmlRemoveProp": "cur = NULL;",
Daniel Veillarda03e3652004-11-02 18:45:30 +0000119}
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000120
121modules = []
122
123def is_skipped_module(name):
124 for mod in skipped_modules:
125 if mod == name:
126 return 1
127 return 0
128
129def is_skipped_function(name):
130 for fun in skipped_functions:
131 if fun == name:
132 return 1
133 # Do not test destructors
134 if string.find(name, 'Free') != -1:
135 return 1
136 return 0
137
138def is_skipped_memcheck(name):
139 for fun in skipped_memcheck:
140 if fun == name:
141 return 1
142 return 0
143
144missing_types = {}
145def add_missing_type(name, func):
146 try:
147 list = missing_types[name]
148 list.append(func)
149 except:
150 missing_types[name] = [func]
151
Daniel Veillardce682bc2004-11-05 17:22:25 +0000152generated_param_types = []
153def add_generated_param_type(name):
154 generated_param_types.append(name)
155
156generated_return_types = []
157def add_generated_return_type(name):
158 generated_return_types.append(name)
159
Daniel Veillard34099b42004-11-04 17:34:35 +0000160missing_functions = {}
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +0000161missing_functions_nr = 0
Daniel Veillard34099b42004-11-04 17:34:35 +0000162def add_missing_functions(name, module):
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +0000163 global missing_functions_nr
164
165 missing_functions_nr = missing_functions_nr + 1
Daniel Veillard34099b42004-11-04 17:34:35 +0000166 try:
167 list = missing_functions[module]
168 list.append(name)
169 except:
170 missing_functions[module] = [name]
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000171
172#
173# Provide the type generators and destructors for the parameters
174#
175
Daniel Veillarda03e3652004-11-02 18:45:30 +0000176def type_convert(str, name, info, module, function, pos):
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000177 res = string.replace(str, " *", "_ptr")
178 res = string.replace(res, " ", "_")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000179 res = string.replace(res, "htmlNode", "xmlNode")
180 res = string.replace(res, "htmlDoc", "xmlDoc")
181 res = string.replace(res, "htmlParser", "xmlParser")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000182 if res == 'const_char_ptr':
183 if string.find(name, "file") != -1 or \
184 string.find(name, "uri") != -1 or \
185 string.find(name, "URI") != -1 or \
186 string.find(info, "filename") != -1 or \
187 string.find(info, "URI") != -1 or \
188 string.find(info, "URL") != -1:
189 if string.find(function, "Save") != -1:
190 return('fileoutput')
191 return('filepath')
192 if res == 'void_ptr':
193 if module == 'nanoftp' and name == 'ctx':
194 return('xmlNanoFTPCtxtPtr')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000195 if function == 'xmlNanoFTPNewCtxt':
196 return('xmlNanoFTPCtxtPtr')
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000197 if module == 'nanohttp' and name == 'ctx':
198 return('xmlNanoHTTPCtxtPtr')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000199 if function == 'xmlIOHTTPOpenW':
200 return('xmlNanoHTTPCtxtPtr')
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000201 if string.find(name, "data") != -1:
202 return('userdata');
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000203 if string.find(name, "user") != -1:
204 return('userdata');
Daniel Veillard3d97e662004-11-04 10:49:00 +0000205 if res == 'xmlDoc_ptr':
206 res = 'xmlDocPtr';
207 if res == 'xmlNode_ptr':
208 res = 'xmlNodePtr';
209 if res == 'xmlDict_ptr':
210 res = 'xmlDictPtr';
Daniel Veillarda03e3652004-11-02 18:45:30 +0000211 if res == 'xmlNodePtr' and pos != 0:
212 if (function == 'xmlAddChild' and pos == 2) or \
213 (function == 'xmlAddChildList' and pos == 2) or \
214 (function == 'xmlAddNextSibling' and pos == 2) or \
215 (function == 'xmlAddSibling' and pos == 2) or \
216 (function == 'xmlDocSetRootElement' and pos == 2) or \
217 (function == 'xmlReplaceNode' and pos == 2) or \
218 (function == 'xmlTextMerge') or \
219 (function == 'xmlAddPrevSibling' and pos == 2):
220 return('xmlNodePtr_in');
Daniel Veillard34099b42004-11-04 17:34:35 +0000221 if res == 'const xmlBufferPtr':
222 res = 'xmlBufferPtr';
Daniel Veillard27f20102004-11-05 11:50:11 +0000223 if res == 'xmlChar_ptr' and name == 'name' and \
224 string.find(function, "EatName") != -1:
225 return('eaten_name')
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000226
227 return res
228
Daniel Veillard34099b42004-11-04 17:34:35 +0000229known_param_types = []
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000230
Daniel Veillardce682bc2004-11-05 17:22:25 +0000231def is_known_param_type(name, rtype):
232 global test
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000233 for type in known_param_types:
234 if type == name:
235 return 1
Daniel Veillardce682bc2004-11-05 17:22:25 +0000236 for type in generated_param_types:
237 if type == name:
238 return 1
239
240 if name[-3:] == 'Ptr' or name[-4:] == '_ptr':
241 if rtype[0:6] == 'const ':
242 crtype = rtype[6:]
243 else:
244 crtype = rtype
245
246 test.write("""
247#define gen_nb_%s 1
248static %s gen_%s(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
249 return(NULL);
250}
251static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
252}
253""" % (name, crtype, name, name, rtype))
254 add_generated_param_type(name)
255 return 1
256
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000257 return 0
258
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000259#
260# Provide the type destructors for the return values
261#
262
Daniel Veillard34099b42004-11-04 17:34:35 +0000263known_return_types = []
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000264
265def is_known_return_type(name):
266 for type in known_return_types:
267 if type == name:
268 return 1
269 return 0
270
Daniel Veillard34099b42004-11-04 17:34:35 +0000271#
272# Copy the beginning of the C test program result
273#
274
275input = open("testapi.c", "r")
276test = open('testapi.c.new', 'w')
277
278def compare_and_save():
279 global test
280
281 test.close()
282 input = open("testapi.c", "r").read()
283 test = open('testapi.c.new', "r").read()
284 if input != test:
285 os.system("rm testapi.c ; mv testapi.c.new testapi.c")
286 print("Updated testapi.c")
287 else:
288 print("Generated testapi.c is identical")
289
290line = input.readline()
291while line != "":
292 if line == "/* CUT HERE: everything below that line is generated */\n":
293 break;
294 if line[0:15] == "#define gen_nb_":
295 type = string.split(line[15:])[0]
296 known_param_types.append(type)
297 if line[0:19] == "static void desret_":
298 type = string.split(line[19:], '(')[0]
299 known_return_types.append(type)
300 test.write(line)
301 line = input.readline()
302input.close()
303
304if line == "":
305 print "Could not find the CUT marker in testapi.c skipping generation"
306 test.close()
307 sys.exit(0)
308
309print("Scanned testapi.c: found %d parameters types and %d return types\n" % (
310 len(known_param_types), len(known_return_types)))
311test.write("/* CUT HERE: everything below that line is generated */\n")
312
313
314#
315# Open the input API description
316#
317doc = libxml2.readFile('doc/libxml2-api.xml', None, 0)
318if doc == None:
319 print "Failed to load doc/libxml2-api.xml"
320 sys.exit(1)
321ctxt = doc.xpathNewContext()
322headers = ctxt.xpathEval("/api/files/file")
323
324#
325# Load the interfaces
326#
327for file in headers:
328 name = file.xpathEval('string(@name)')
329 if (name == None) or (name == ''):
330 continue
331
332 #
333 # Some module may be skipped because they don't really consists
334 # of user callable APIs
335 #
336 if is_skipped_module(name):
337 continue
338
339 #
340 # do not test deprecated APIs
341 #
342 desc = file.xpathEval('string(description)')
343 if string.find(desc, 'DEPRECATED') != -1:
344 print "Skipping deprecated interface %s" % name
345 continue;
346
347 test.write("#include <libxml/%s.h>\n" % name)
348 modules.append(name)
349
350#
351# Generate the callers signatures
352#
353for module in modules:
354 test.write("static int test_%s(void);\n" % module);
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000355
356#
357# Generate the top caller
358#
359
360test.write("""
361/**
362 * testlibxml2:
363 *
364 * Main entry point of the tester for the full libxml2 module,
365 * it calls all the tester entry point for each module.
366 *
367 * Returns the number of error found
368 */
369static int
370testlibxml2(void)
371{
372 int ret = 0;
373
374""")
375
376for module in modules:
377 test.write(" ret += test_%s();\n" % module)
378
379test.write("""
Daniel Veillard3d97e662004-11-04 10:49:00 +0000380 printf("Total: %d functions, %d tests, %d errors\\n",
381 function_tests, call_tests, ret);
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000382 return(ret);
383}
384
385""")
386
387#
388# How to handle a function
389#
390nb_tests = 0
391
392def generate_test(module, node):
393 global test
394 global nb_tests
395 nb_cond = 0
396 no_gen = 0
397
398 name = node.xpathEval('string(@name)')
399 if is_skipped_function(name):
400 return
401
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000402 #
403 # check we know how to handle the args and return values
404 # and store the informations for the generation
405 #
406 try:
407 args = node.xpathEval("arg")
408 except:
409 args = []
410 t_args = []
Daniel Veillarda03e3652004-11-02 18:45:30 +0000411 n = 0
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000412 for arg in args:
Daniel Veillarda03e3652004-11-02 18:45:30 +0000413 n = n + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000414 rtype = arg.xpathEval("string(@type)")
415 if rtype == 'void':
416 break;
417 info = arg.xpathEval("string(@info)")
418 nam = arg.xpathEval("string(@name)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000419 type = type_convert(rtype, nam, info, module, name, n)
Daniel Veillardce682bc2004-11-05 17:22:25 +0000420 if is_known_param_type(type, rtype) == 0:
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000421 add_missing_type(type, name);
422 no_gen = 1
423 t_args.append((nam, type, rtype, info))
424
425 try:
426 rets = node.xpathEval("return")
427 except:
428 rets = []
429 t_ret = None
430 for ret in rets:
431 rtype = ret.xpathEval("string(@type)")
432 info = ret.xpathEval("string(@info)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000433 type = type_convert(rtype, 'return', info, module, name, 0)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000434 if rtype == 'void':
435 break
436 if is_known_return_type(type) == 0:
437 add_missing_type(type, name);
438 no_gen = 1
439 t_ret = (type, rtype, info)
440 break
441
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +0000442 test.write("""
443static int
444test_%s(void) {
445 int ret = 0;
446
447""" % (name))
448
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000449 if no_gen == 1:
Daniel Veillard34099b42004-11-04 17:34:35 +0000450 add_missing_functions(name, module)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000451 test.write("""
452 /* missing type support */
453 return(ret);
454}
455
456""")
457 return
458
459 try:
460 conds = node.xpathEval("cond")
461 for cond in conds:
462 test.write("#ifdef %s\n" % (cond.get_content()))
463 nb_cond = nb_cond + 1
464 except:
465 pass
466
467 # Declare the memory usage counter
468 no_mem = is_skipped_memcheck(name)
469 if no_mem == 0:
470 test.write(" int mem_base;\n");
471
472 # Declare the return value
473 if t_ret != None:
474 test.write(" %s ret_val;\n" % (t_ret[1]))
475
476 # Declare the arguments
477 for arg in t_args:
478 (nam, type, rtype, info) = arg;
Daniel Veillardce682bc2004-11-05 17:22:25 +0000479 if (type[-3:] == 'Ptr' or type[-4:] == '_ptr') and \
480 rtype[0:6] == 'const ':
481 crtype = rtype[6:]
482 else:
483 crtype = rtype
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000484 # add declaration
Daniel Veillardce682bc2004-11-05 17:22:25 +0000485 test.write(" %s %s; /* %s */\n" % (crtype, nam, info))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000486 test.write(" int n_%s;\n" % (nam))
487 test.write("\n")
488
489 # Cascade loop on of each argument list of values
490 for arg in t_args:
491 (nam, type, rtype, info) = arg;
492 #
493 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
494 nam, nam, type, nam))
495
496 # log the memory usage
497 if no_mem == 0:
498 test.write(" mem_base = xmlMemBlocks();\n");
499
500 # prepare the call
Daniel Veillard3d97e662004-11-04 10:49:00 +0000501 i = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000502 for arg in t_args:
503 (nam, type, rtype, info) = arg;
504 #
Daniel Veillard3d97e662004-11-04 10:49:00 +0000505 test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
506 i = i + 1;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000507
508 # do the call, and clanup the result
Daniel Veillard34099b42004-11-04 17:34:35 +0000509 if extra_pre_call.has_key(name):
510 test.write(" %s\n"% (extra_pre_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000511 if t_ret != None:
512 test.write("\n ret_val = %s(" % (name))
513 need = 0
514 for arg in t_args:
515 (nam, type, rtype, info) = arg
516 if need:
517 test.write(", ")
518 else:
519 need = 1
520 test.write("%s" % nam);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000521 test.write(");\n")
522 if extra_post_call.has_key(name):
523 test.write(" %s\n"% (extra_post_call[name]))
524 test.write(" desret_%s(ret_val);\n" % t_ret[0])
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000525 else:
526 test.write("\n %s(" % (name));
527 need = 0;
528 for arg in t_args:
529 (nam, type, rtype, info) = arg;
530 if need:
531 test.write(", ")
532 else:
533 need = 1
534 test.write("%s" % nam)
535 test.write(");\n")
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000536 if extra_post_call.has_key(name):
537 test.write(" %s\n"% (extra_post_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000538
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000539 test.write(" call_tests++;\n");
Daniel Veillarda03e3652004-11-02 18:45:30 +0000540
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000541 # Free the arguments
Daniel Veillard3d97e662004-11-04 10:49:00 +0000542 i = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000543 for arg in t_args:
544 (nam, type, rtype, info) = arg;
545 #
Daniel Veillard3d97e662004-11-04 10:49:00 +0000546 test.write(" des_%s(n_%s, %s, %d);\n" % (type, nam, nam, i))
547 i = i + 1;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000548
549 test.write(" xmlResetLastError();\n");
550 # Check the memory usage
551 if no_mem == 0:
552 test.write(""" if (mem_base != xmlMemBlocks()) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000553 printf("Leak of %%d blocks found in %s",
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000554 xmlMemBlocks() - mem_base);
555 ret++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000556""" % (name));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000557 for arg in t_args:
558 (nam, type, rtype, info) = arg;
559 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
560 test.write(""" printf("\\n");\n""")
561 test.write(" }\n")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000562
563 for arg in t_args:
564 test.write(" }\n")
565
566 #
567 # end of conditional
568 #
569 while nb_cond > 0:
570 test.write("#endif\n")
571 nb_cond = nb_cond -1
572
573 nb_tests = nb_tests + 1;
574
575 test.write("""
Daniel Veillard3d97e662004-11-04 10:49:00 +0000576 function_tests++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000577 return(ret);
578}
579
580""")
581
582#
583# Generate all module callers
584#
585for module in modules:
586 # gather all the functions exported by that module
587 try:
588 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
589 except:
590 print "Failed to gather functions from module %s" % (module)
591 continue;
592
593 # iterate over all functions in the module generating the test
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000594 i = 0
595 nb_tests_old = nb_tests
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000596 for function in functions:
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000597 i = i + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000598 generate_test(module, function);
599
600 # header
601 test.write("""static int
602test_%s(void) {
603 int ret = 0;
604
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000605 printf("Testing %s : %d of %d functions ...\\n");
606""" % (module, module, nb_tests - nb_tests_old, i))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000607
608 # iterate over all functions in the module generating the call
609 for function in functions:
610 name = function.xpathEval('string(@name)')
611 if is_skipped_function(name):
612 continue
613 test.write(" ret += test_%s();\n" % (name))
614
615 # footer
616 test.write("""
617 if (ret != 0)
618 printf("Module %s: %%d errors\\n", ret);
619 return(ret);
620}
621""" % (module))
622
Daniel Veillardce244ad2004-11-05 10:03:46 +0000623#
624# Generate direct module caller
625#
626test.write("""static int
627test_module(const char *module) {
628""");
629for module in modules:
630 test.write(""" if (!strcmp(module, "%s")) return(test_%s());\n""" % (
631 module, module))
632test.write(""" return(0);
633}
634""");
635
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000636print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000637
Daniel Veillard34099b42004-11-04 17:34:35 +0000638compare_and_save()
639
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000640missing_list = []
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000641for missing in missing_types.keys():
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000642 if missing == 'va_list' or missing == '...':
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000643 continue;
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000644
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000645 n = len(missing_types[missing])
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000646 missing_list.append((n, missing))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000647
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000648def compare_missing(a, b):
649 return b[0] - a[0]
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000650
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000651missing_list.sort(compare_missing)
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +0000652print "Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list))
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000653lst = open("missing.lst", "w")
Daniel Veillard34099b42004-11-04 17:34:35 +0000654lst.write("Missing support for %d types" % (len(missing_list)))
655lst.write("\n")
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000656for miss in missing_list:
657 lst.write("%s: %d :" % (miss[1], miss[0]))
658 i = 0
659 for n in missing_types[miss[1]]:
660 i = i + 1
661 if i > 5:
662 lst.write(" ...")
663 break
664 lst.write(" %s" % (n))
665 lst.write("\n")
Daniel Veillard34099b42004-11-04 17:34:35 +0000666lst.write("\n")
667lst.write("\n")
668lst.write("Missing support per module");
669for module in missing_functions.keys():
670 lst.write("module %s:\n %s\n" % (module, missing_functions[module]))
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000671
672lst.close()
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000673
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000674