blob: 126444100943bf3e92b4bf7ae1e59fffe11bb899 [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()
Daniel Veillard57b25162004-11-06 14:50:18 +0000322
323#
324# Generate constructors and return type handling for all enums
325#
326enums = ctxt.xpathEval("/api/symbols/typedef[@type='enum']")
327for enum in enums:
328 name = enum.xpathEval('string(@name)')
329 if name == None:
330 continue;
331
332 if is_known_param_type(name, name) == 0:
333 values = ctxt.xpathEval("/api/symbols/enum[@type='%s']" % name)
334 i = 0
335 vals = []
336 for value in values:
337 vname = value.xpathEval('string(@name)')
338 if vname == None:
339 continue;
340 i = i + 1
341 if i >= 5:
342 break;
343 vals.append(vname)
344 if vals == []:
345 print "Didn't found any value for enum %s" % (name)
346 continue
347 test.write("#define gen_nb_%s %d\n" % (name, len(vals)))
348 test.write("""static %s gen_%s(int no, int nr ATTRIBUTE_UNUSED) {\n""" %
349 (name, name))
350 i = 1
351 for value in vals:
352 test.write(" if (no == %d) return(%s);\n" % (i, value))
353 i = i + 1
354 test.write(""" return(0);
355}
356""");
357 known_param_types.append(name)
358
359 if is_known_return_type(name) == 0:
360 test.write("""static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
361}
362static void desret_%s(%s val ATTRIBUTE_UNUSED) {
363}
364
365""" % (name, name, name, name))
366 known_return_types.append(name)
Daniel Veillard34099b42004-11-04 17:34:35 +0000367
368#
369# Load the interfaces
370#
Daniel Veillard57b25162004-11-06 14:50:18 +0000371headers = ctxt.xpathEval("/api/files/file")
Daniel Veillard34099b42004-11-04 17:34:35 +0000372for file in headers:
373 name = file.xpathEval('string(@name)')
374 if (name == None) or (name == ''):
375 continue
376
377 #
378 # Some module may be skipped because they don't really consists
379 # of user callable APIs
380 #
381 if is_skipped_module(name):
382 continue
383
384 #
385 # do not test deprecated APIs
386 #
387 desc = file.xpathEval('string(description)')
388 if string.find(desc, 'DEPRECATED') != -1:
389 print "Skipping deprecated interface %s" % name
390 continue;
391
392 test.write("#include <libxml/%s.h>\n" % name)
393 modules.append(name)
394
395#
396# Generate the callers signatures
397#
398for module in modules:
399 test.write("static int test_%s(void);\n" % module);
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000400
401#
402# Generate the top caller
403#
404
405test.write("""
406/**
407 * testlibxml2:
408 *
409 * Main entry point of the tester for the full libxml2 module,
410 * it calls all the tester entry point for each module.
411 *
412 * Returns the number of error found
413 */
414static int
415testlibxml2(void)
416{
417 int ret = 0;
418
419""")
420
421for module in modules:
422 test.write(" ret += test_%s();\n" % module)
423
424test.write("""
Daniel Veillard3d97e662004-11-04 10:49:00 +0000425 printf("Total: %d functions, %d tests, %d errors\\n",
426 function_tests, call_tests, ret);
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000427 return(ret);
428}
429
430""")
431
432#
433# How to handle a function
434#
435nb_tests = 0
436
437def generate_test(module, node):
438 global test
439 global nb_tests
440 nb_cond = 0
441 no_gen = 0
442
443 name = node.xpathEval('string(@name)')
444 if is_skipped_function(name):
445 return
446
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000447 #
448 # check we know how to handle the args and return values
449 # and store the informations for the generation
450 #
451 try:
452 args = node.xpathEval("arg")
453 except:
454 args = []
455 t_args = []
Daniel Veillarda03e3652004-11-02 18:45:30 +0000456 n = 0
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000457 for arg in args:
Daniel Veillarda03e3652004-11-02 18:45:30 +0000458 n = n + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000459 rtype = arg.xpathEval("string(@type)")
460 if rtype == 'void':
461 break;
462 info = arg.xpathEval("string(@info)")
463 nam = arg.xpathEval("string(@name)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000464 type = type_convert(rtype, nam, info, module, name, n)
Daniel Veillardce682bc2004-11-05 17:22:25 +0000465 if is_known_param_type(type, rtype) == 0:
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000466 add_missing_type(type, name);
467 no_gen = 1
468 t_args.append((nam, type, rtype, info))
469
470 try:
471 rets = node.xpathEval("return")
472 except:
473 rets = []
474 t_ret = None
475 for ret in rets:
476 rtype = ret.xpathEval("string(@type)")
477 info = ret.xpathEval("string(@info)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000478 type = type_convert(rtype, 'return', info, module, name, 0)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000479 if rtype == 'void':
480 break
481 if is_known_return_type(type) == 0:
482 add_missing_type(type, name);
483 no_gen = 1
484 t_ret = (type, rtype, info)
485 break
486
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +0000487 test.write("""
488static int
489test_%s(void) {
490 int ret = 0;
491
492""" % (name))
493
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000494 if no_gen == 1:
Daniel Veillard34099b42004-11-04 17:34:35 +0000495 add_missing_functions(name, module)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000496 test.write("""
497 /* missing type support */
498 return(ret);
499}
500
501""")
502 return
503
504 try:
505 conds = node.xpathEval("cond")
506 for cond in conds:
507 test.write("#ifdef %s\n" % (cond.get_content()))
508 nb_cond = nb_cond + 1
509 except:
510 pass
511
512 # Declare the memory usage counter
513 no_mem = is_skipped_memcheck(name)
514 if no_mem == 0:
515 test.write(" int mem_base;\n");
516
517 # Declare the return value
518 if t_ret != None:
519 test.write(" %s ret_val;\n" % (t_ret[1]))
520
521 # Declare the arguments
522 for arg in t_args:
523 (nam, type, rtype, info) = arg;
Daniel Veillardce682bc2004-11-05 17:22:25 +0000524 if (type[-3:] == 'Ptr' or type[-4:] == '_ptr') and \
525 rtype[0:6] == 'const ':
526 crtype = rtype[6:]
527 else:
528 crtype = rtype
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000529 # add declaration
Daniel Veillardce682bc2004-11-05 17:22:25 +0000530 test.write(" %s %s; /* %s */\n" % (crtype, nam, info))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000531 test.write(" int n_%s;\n" % (nam))
532 test.write("\n")
533
534 # Cascade loop on of each argument list of values
535 for arg in t_args:
536 (nam, type, rtype, info) = arg;
537 #
538 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
539 nam, nam, type, nam))
540
541 # log the memory usage
542 if no_mem == 0:
543 test.write(" mem_base = xmlMemBlocks();\n");
544
545 # prepare the call
Daniel Veillard3d97e662004-11-04 10:49:00 +0000546 i = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000547 for arg in t_args:
548 (nam, type, rtype, info) = arg;
549 #
Daniel Veillard3d97e662004-11-04 10:49:00 +0000550 test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
551 i = i + 1;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000552
553 # do the call, and clanup the result
Daniel Veillard34099b42004-11-04 17:34:35 +0000554 if extra_pre_call.has_key(name):
555 test.write(" %s\n"% (extra_pre_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000556 if t_ret != None:
557 test.write("\n ret_val = %s(" % (name))
558 need = 0
559 for arg in t_args:
560 (nam, type, rtype, info) = arg
561 if need:
562 test.write(", ")
563 else:
564 need = 1
565 test.write("%s" % nam);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000566 test.write(");\n")
567 if extra_post_call.has_key(name):
568 test.write(" %s\n"% (extra_post_call[name]))
569 test.write(" desret_%s(ret_val);\n" % t_ret[0])
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000570 else:
571 test.write("\n %s(" % (name));
572 need = 0;
573 for arg in t_args:
574 (nam, type, rtype, info) = arg;
575 if need:
576 test.write(", ")
577 else:
578 need = 1
579 test.write("%s" % nam)
580 test.write(");\n")
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000581 if extra_post_call.has_key(name):
582 test.write(" %s\n"% (extra_post_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000583
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000584 test.write(" call_tests++;\n");
Daniel Veillarda03e3652004-11-02 18:45:30 +0000585
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000586 # Free the arguments
Daniel Veillard3d97e662004-11-04 10:49:00 +0000587 i = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000588 for arg in t_args:
589 (nam, type, rtype, info) = arg;
590 #
Daniel Veillard3d97e662004-11-04 10:49:00 +0000591 test.write(" des_%s(n_%s, %s, %d);\n" % (type, nam, nam, i))
592 i = i + 1;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000593
594 test.write(" xmlResetLastError();\n");
595 # Check the memory usage
596 if no_mem == 0:
597 test.write(""" if (mem_base != xmlMemBlocks()) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000598 printf("Leak of %%d blocks found in %s",
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000599 xmlMemBlocks() - mem_base);
600 ret++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000601""" % (name));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000602 for arg in t_args:
603 (nam, type, rtype, info) = arg;
604 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
605 test.write(""" printf("\\n");\n""")
606 test.write(" }\n")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000607
608 for arg in t_args:
609 test.write(" }\n")
610
611 #
612 # end of conditional
613 #
614 while nb_cond > 0:
615 test.write("#endif\n")
616 nb_cond = nb_cond -1
617
618 nb_tests = nb_tests + 1;
619
620 test.write("""
Daniel Veillard3d97e662004-11-04 10:49:00 +0000621 function_tests++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000622 return(ret);
623}
624
625""")
626
627#
628# Generate all module callers
629#
630for module in modules:
631 # gather all the functions exported by that module
632 try:
633 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
634 except:
635 print "Failed to gather functions from module %s" % (module)
636 continue;
637
638 # iterate over all functions in the module generating the test
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000639 i = 0
640 nb_tests_old = nb_tests
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000641 for function in functions:
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000642 i = i + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000643 generate_test(module, function);
644
645 # header
646 test.write("""static int
647test_%s(void) {
648 int ret = 0;
649
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000650 printf("Testing %s : %d of %d functions ...\\n");
651""" % (module, module, nb_tests - nb_tests_old, i))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000652
653 # iterate over all functions in the module generating the call
654 for function in functions:
655 name = function.xpathEval('string(@name)')
656 if is_skipped_function(name):
657 continue
658 test.write(" ret += test_%s();\n" % (name))
659
660 # footer
661 test.write("""
662 if (ret != 0)
663 printf("Module %s: %%d errors\\n", ret);
664 return(ret);
665}
666""" % (module))
667
Daniel Veillardce244ad2004-11-05 10:03:46 +0000668#
669# Generate direct module caller
670#
671test.write("""static int
672test_module(const char *module) {
673""");
674for module in modules:
675 test.write(""" if (!strcmp(module, "%s")) return(test_%s());\n""" % (
676 module, module))
677test.write(""" return(0);
678}
679""");
680
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000681print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000682
Daniel Veillard34099b42004-11-04 17:34:35 +0000683compare_and_save()
684
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000685missing_list = []
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000686for missing in missing_types.keys():
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000687 if missing == 'va_list' or missing == '...':
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000688 continue;
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000689
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000690 n = len(missing_types[missing])
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000691 missing_list.append((n, missing))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000692
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000693def compare_missing(a, b):
694 return b[0] - a[0]
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000695
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000696missing_list.sort(compare_missing)
Daniel Veillard0ea9c9f2004-11-05 14:30:41 +0000697print "Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list))
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000698lst = open("missing.lst", "w")
Daniel Veillard34099b42004-11-04 17:34:35 +0000699lst.write("Missing support for %d types" % (len(missing_list)))
700lst.write("\n")
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000701for miss in missing_list:
702 lst.write("%s: %d :" % (miss[1], miss[0]))
703 i = 0
704 for n in missing_types[miss[1]]:
705 i = i + 1
706 if i > 5:
707 lst.write(" ...")
708 break
709 lst.write(" %s" % (n))
710 lst.write("\n")
Daniel Veillard34099b42004-11-04 17:34:35 +0000711lst.write("\n")
712lst.write("\n")
713lst.write("Missing support per module");
714for module in missing_functions.keys():
715 lst.write("module %s:\n %s\n" % (module, missing_functions[module]))
Daniel Veillard1ba06bb2004-11-04 12:32:18 +0000716
717lst.close()
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000718
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000719