blob: 50fa34d8c6d30589703e614a167b82a2d3c3b35c [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
6import string
7try:
8 import libxml2
9except:
10 print "libxml2 python bindings not available, skipping testapi.c generation"
11 sys.exit(0)
12
13#
14# Modules we don't want skip in API test
15#
16skipped_modules = [ "SAX", "SAX2", "xlink", "threads", "globals",
17 "xpathInternals", "xmlunicode", "parserInternals", "xmlmemory",
Daniel Veillarddd6d3002004-11-03 14:20:29 +000018 "xmlversion", "debugXML", "xmlexports" ]
Daniel Veillard36e5cd52004-11-02 14:52:23 +000019
20#
21# Some function really need to be skipped for the tests.
22#
Daniel Veillarddd6d3002004-11-03 14:20:29 +000023skipped_functions = [
24# block on I/O
25"xmlFdRead", "xmlReadFd", "xmlCtxtReadFd",
26"htmlFdRead", "htmlReadFd", "htmlCtxtReadFd",
27"xmlReaderNewFd",
28# library state cleanup, generate false leak informations and other
29# troubles, heavillyb tested otherwise.
30"xmlCleanupParser", "xmlRelaxNGCleanupTypes",
31# hard to avoid leaks in the tests
32"xmlStrcat", "xmlStrncat",
33# unimplemented
34"xmlTextReaderReadInnerXml", "xmlTextReaderReadOuterXml",
35"xmlTextReaderReadString"
36]
Daniel Veillard36e5cd52004-11-02 14:52:23 +000037
38#
39# Those functions have side effect on the global state
40# and hence generate errors on memory allocation tests
41#
42skipped_memcheck = [ "xmlLoadCatalog", "xmlAddEncodingAlias",
43 "xmlSchemaInitTypes", "xmlNanoFTPProxy", "xmlNanoFTPScanProxy",
44 "xmlNanoHTTPScanProxy", "xmlResetLastError", "xmlCatalogConvert",
45 "xmlCatalogRemove", "xmlLoadCatalogs", "xmlCleanupCharEncodingHandlers",
Daniel Veillarda03e3652004-11-02 18:45:30 +000046 "xmlInitCharEncodingHandlers", "xmlCatalogCleanup",
47 "htmlParseFile" # loads the catalogs
48]
49
50#
51# Extra code needed for some test cases
52#
53extra_post_call = {
54 "xmlAddChild":
55 "if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; }",
56 "xmlAddChildList":
57 "if (ret_val == NULL) { xmlFreeNodeList(cur) ; cur = NULL ; }",
58 "xmlAddSibling":
59 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
60 "xmlAddNextSibling":
61 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
62 "xmlAddPrevSibling":
63 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
64 "xmlDocSetRootElement":
65 "if (doc == NULL) { xmlFreeNode(root) ; root = NULL ; }",
66 "xmlReplaceNode":
67 """if ((old == NULL) || (old->parent == NULL)) {
68 xmlFreeNode(cur) ; cur = NULL ; }""",
69 "xmlTextMerge":
70 """if ((first != NULL) && (first->type != XML_TEXT_NODE)) {
71 xmlFreeNode(second) ; second = NULL ; }""",
Daniel Veillard8a32fe42004-11-02 22:10:16 +000072 "xmlBuildQName":
73 """if ((ret_val != NULL) && (ret_val != ncname) &&
74 (ret_val != prefix) && (ret_val != memory))
75 xmlFree(ret_val);
76 ret_val = NULL;""",
Daniel Veillarda03e3652004-11-02 18:45:30 +000077}
Daniel Veillard36e5cd52004-11-02 14:52:23 +000078
79modules = []
80
81def is_skipped_module(name):
82 for mod in skipped_modules:
83 if mod == name:
84 return 1
85 return 0
86
87def is_skipped_function(name):
88 for fun in skipped_functions:
89 if fun == name:
90 return 1
91 # Do not test destructors
92 if string.find(name, 'Free') != -1:
93 return 1
94 return 0
95
96def is_skipped_memcheck(name):
97 for fun in skipped_memcheck:
98 if fun == name:
99 return 1
100 return 0
101
102missing_types = {}
103def add_missing_type(name, func):
104 try:
105 list = missing_types[name]
106 list.append(func)
107 except:
108 missing_types[name] = [func]
109
110#
111# Open the input API description and the C test program result
112#
113doc = libxml2.readFile('doc/libxml2-api.xml', None, 0)
114if doc == None:
115 print "Failed to load doc/libxml2-api.xml"
116 sys.exit(1)
117test = open('testapi.c', 'w')
118ctxt = doc.xpathNewContext()
119headers = ctxt.xpathEval("/api/files/file")
120
121#
122# Generate the test header
123#
124test.write("""/*
125 * testapi.c: libxml2 API tester program.
126 *
127 * Automatically generated by gentest.py from libxml2-api.xml
128 *
129 * See Copyright for the status of this software.
130 *
131 * daniel@veillard.com
132 */
133
134#include <stdio.h>
135#include <libxml/xmlerror.h>
136
137static int testlibxml2(void);
138
139static int generic_errors = 0;
140static int call_tests = 0;
141
Daniel Veillard348636d2004-11-02 22:34:52 +0000142static xmlChar chartab[1024] = " chartab\\n";
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000143
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000144static void
145structured_errors(void *userData ATTRIBUTE_UNUSED,
146 xmlErrorPtr error ATTRIBUTE_UNUSED) {
147 generic_errors++;
148}
149
150int main(void) {
151 int ret;
152 int blocks, mem;
153
Daniel Veillarda03e3652004-11-02 18:45:30 +0000154 xmlInitParser();
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000155 xmlRelaxNGInitTypes();
Daniel Veillarda03e3652004-11-02 18:45:30 +0000156
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000157 LIBXML_TEST_VERSION
158
159 xmlSetStructuredErrorFunc(NULL, structured_errors);
160
161 ret = testlibxml2();
162
163 xmlCleanupParser();
164 blocks = xmlMemBlocks();
165 mem = xmlMemUsed();
166 if ((blocks != 0) || (mem != 0)) {
167 printf("testapi leaked %d bytes in %d blocks\\n", mem, blocks);
168 }
169 xmlMemoryDump();
170
171 return (ret != 0);
172}
173
174""");
175
176#
177# Load the interfaces
178#
179for file in headers:
180 name = file.xpathEval('string(@name)')
181 if (name == None) or (name == ''):
182 continue
183
184 #
185 # do not test deprecated APIs
186 #
187 desc = file.xpathEval('string(description)')
188 if string.find(desc, 'DEPRECATED') != -1:
189 print "Skipping deprecated interface %s" % name
190 continue;
191
192 #
193 # Some module may be skipped because they don't really consists
194 # of user callable APIs
195 #
196 if is_skipped_module(name):
197 continue
198
199 test.write("#include <libxml/%s.h>\n" % name)
200 modules.append(name)
201
202#
203# Generate the callers signatures
204#
205for module in modules:
206 test.write("static int test_%s(void);\n" % module);
207
208#
209# Provide the type generators and destructors for the parameters
210#
211
Daniel Veillarda03e3652004-11-02 18:45:30 +0000212def type_convert(str, name, info, module, function, pos):
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000213 res = string.replace(str, " *", "_ptr")
214 res = string.replace(res, " ", "_")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000215 res = string.replace(res, "htmlNode", "xmlNode")
216 res = string.replace(res, "htmlDoc", "xmlDoc")
217 res = string.replace(res, "htmlParser", "xmlParser")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000218 if res == 'const_char_ptr':
219 if string.find(name, "file") != -1 or \
220 string.find(name, "uri") != -1 or \
221 string.find(name, "URI") != -1 or \
222 string.find(info, "filename") != -1 or \
223 string.find(info, "URI") != -1 or \
224 string.find(info, "URL") != -1:
225 if string.find(function, "Save") != -1:
226 return('fileoutput')
227 return('filepath')
228 if res == 'void_ptr':
229 if module == 'nanoftp' and name == 'ctx':
230 return('xmlNanoFTPCtxtPtr')
231 if module == 'nanohttp' and name == 'ctx':
232 return('xmlNanoHTTPCtxtPtr')
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000233 if string.find(name, "data") != -1:
234 return('userdata');
Daniel Veillarda03e3652004-11-02 18:45:30 +0000235 if res == 'xmlNodePtr' and pos != 0:
236 if (function == 'xmlAddChild' and pos == 2) or \
237 (function == 'xmlAddChildList' and pos == 2) or \
238 (function == 'xmlAddNextSibling' and pos == 2) or \
239 (function == 'xmlAddSibling' and pos == 2) or \
240 (function == 'xmlDocSetRootElement' and pos == 2) or \
241 (function == 'xmlReplaceNode' and pos == 2) or \
242 (function == 'xmlTextMerge') or \
243 (function == 'xmlAddPrevSibling' and pos == 2):
244 return('xmlNodePtr_in');
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000245
246 return res
247
248known_param_types = [ "int", "const_char_ptr", "const_xmlChar_ptr",
Daniel Veillarde43cc572004-11-03 11:50:29 +0000249 "xmlParserCtxtPtr", "xmlDocPtr", "filepath", "fileoutput",
250 "xmlNodePtr", "xmlNodePtr_in", "userdata", "xmlChar_ptr",
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000251 "xmlTextWriterPtr", "xmlTextReaderPtr" ];
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000252
253def is_known_param_type(name):
254 for type in known_param_types:
255 if type == name:
256 return 1
257 return 0
258
259test.write("""
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000260#define gen_nb_userdata 3
261
262static void *gen_userdata(int no) {
263 if (no == 0) return((void *) &call_tests);
264 if (no == 1) return((void *) -1);
265 return(NULL);
266}
267static void des_userdata(int no ATTRIBUTE_UNUSED, void *val ATTRIBUTE_UNUSED) {
268}
269
270
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000271#define gen_nb_int 4
272
273static int gen_int(int no) {
274 if (no == 0) return(0);
275 if (no == 1) return(1);
276 if (no == 2) return(122);
277 return(-1);
278}
279
280static void des_int(int no ATTRIBUTE_UNUSED, int val ATTRIBUTE_UNUSED) {
281}
282
283#define gen_nb_const_char_ptr 4
284
285static const char *gen_const_char_ptr(int no) {
286 if (no == 0) return("foo");
287 if (no == 1) return("<foo/>");
288 if (no == 2) return("test/ent2");
289 return(NULL);
290}
291static void des_const_char_ptr(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED) {
292}
293
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000294#define gen_nb_xmlChar_ptr 2
295
296static xmlChar *gen_xmlChar_ptr(int no) {
297 if (no == 0) return(&chartab);
298 return(NULL);
299}
300static void des_xmlChar_ptr(int no ATTRIBUTE_UNUSED, xmlChar *val ATTRIBUTE_UNUSED) {
301}
302
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000303#define gen_nb_const_xmlChar_ptr 5
304
305static const xmlChar *gen_const_xmlChar_ptr(int no) {
306 if (no == 0) return((const xmlChar *) "foo");
307 if (no == 1) return((const xmlChar *) "<foo/>");
308 if (no == 2) return((const xmlChar *) "nøne");
309 if (no == 3) return((const xmlChar *) " 2ab ");
310 return(NULL);
311}
312static void des_const_xmlChar_ptr(int no ATTRIBUTE_UNUSED, const xmlChar *val ATTRIBUTE_UNUSED) {
313}
314
315#define gen_nb_filepath 8
316
317static const char *gen_filepath(int no) {
318 if (no == 0) return("missing.xml");
319 if (no == 1) return("<foo/>");
320 if (no == 2) return("test/ent2");
321 if (no == 3) return("test/valid/REC-xml-19980210.xml");
322 if (no == 4) return("test/valid/xhtml1-strict.dtd");
323 if (no == 5) return("http://missing.example.org/");
324 if (no == 6) return("http://missing. example.org/");
325 return(NULL);
326}
327static void des_filepath(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED) {
328}
329
330#define gen_nb_fileoutput 6
331
332static const char *gen_fileoutput(int no) {
333 if (no == 0) return("/missing.xml");
334 if (no == 1) return("<foo/>");
335 if (no == 2) return("ftp://missing.example.org/foo");
336 if (no == 3) return("http://missing.example.org/");
337 if (no == 4) return("http://missing. example.org/");
338 return(NULL);
339}
340static void des_fileoutput(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED) {
341}
342
343#define gen_nb_xmlParserCtxtPtr 2
344static xmlParserCtxtPtr gen_xmlParserCtxtPtr(int no) {
345 if (no == 0) return(xmlNewParserCtxt());
346 return(NULL);
347}
348static void des_xmlParserCtxtPtr(int no ATTRIBUTE_UNUSED, xmlParserCtxtPtr val) {
349 if (val != NULL)
350 xmlFreeParserCtxt(val);
351}
352
Daniel Veillarda03e3652004-11-02 18:45:30 +0000353#define gen_nb_xmlDocPtr 3
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000354static xmlDocPtr gen_xmlDocPtr(int no) {
355 if (no == 0) return(xmlNewDoc(BAD_CAST "1.0"));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000356 if (no == 1) return(xmlReadMemory("<foo/>", 6, "test", NULL, 0));
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000357 return(NULL);
358}
359static void des_xmlDocPtr(int no ATTRIBUTE_UNUSED, xmlDocPtr val) {
360 if (val != NULL)
361 xmlFreeDoc(val);
362}
363
Daniel Veillarda03e3652004-11-02 18:45:30 +0000364#define gen_nb_xmlNodePtr 2
365static xmlNodePtr gen_xmlNodePtr(int no) {
366 if (no == 0) return(xmlNewPI(BAD_CAST "test", NULL));
367 return(NULL);
368}
369static void des_xmlNodePtr(int no ATTRIBUTE_UNUSED, xmlNodePtr val) {
370 if (val != NULL) {
371 xmlUnlinkNode(val);
372 xmlFreeNode(val);
373 }
374}
375
376#define gen_nb_xmlNodePtr_in 3
377static xmlNodePtr gen_xmlNodePtr_in(int no) {
378 if (no == 0) return(xmlNewPI(BAD_CAST "test", NULL));
379 if (no == 0) return(xmlNewText(BAD_CAST "text"));
380 return(NULL);
381}
382static void des_xmlNodePtr_in(int no ATTRIBUTE_UNUSED, xmlNodePtr val ATTRIBUTE_UNUSED) {
383}
384
Daniel Veillarde43cc572004-11-03 11:50:29 +0000385#define gen_nb_xmlTextWriterPtr 2
386static xmlTextWriterPtr gen_xmlTextWriterPtr(int no) {
387 if (no == 0) return(xmlNewTextWriterFilename("test.out", 0));
388 return(NULL);
389}
390static void des_xmlTextWriterPtr(int no ATTRIBUTE_UNUSED, xmlTextWriterPtr val) {
391 if (val != NULL) xmlFreeTextWriter(val);
392}
393
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000394#define gen_nb_xmlTextReaderPtr 4
395static xmlTextReaderPtr gen_xmlTextReaderPtr(int no) {
396 if (no == 0) return(xmlNewTextReaderFilename("test/ent2"));
397 if (no == 1) return(xmlNewTextReaderFilename("test/valid/REC-xml-19980210.xml"));
398 if (no == 2) return(xmlNewTextReaderFilename("test/valid/dtds/xhtml1-strict.dtd"));
399 return(NULL);
400}
401static void des_xmlTextReaderPtr(int no ATTRIBUTE_UNUSED, xmlTextReaderPtr val) {
402 if (val != NULL) xmlFreeTextReader(val);
403}
404
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000405""");
406
407#
408# Provide the type destructors for the return values
409#
410
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000411known_return_types = [ "int", "const_char_ptr", "xmlDocPtr", "xmlNodePtr",
412 "xmlChar_ptr" ];
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000413
414def is_known_return_type(name):
415 for type in known_return_types:
416 if type == name:
417 return 1
418 return 0
419
420test.write("""
421static void desret_int(int val ATTRIBUTE_UNUSED) {
422}
423static void desret_const_char_ptr(const char *val ATTRIBUTE_UNUSED) {
424}
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000425static void desret_xmlChar_ptr(xmlChar *val) {
426 if (val != NULL)
427 xmlFree(val);
428}
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000429static void desret_xmlDocPtr(xmlDocPtr val) {
430 xmlFreeDoc(val);
431}
432static void desret_xmlNodePtr(xmlNodePtr val) {
433 xmlUnlinkNode(val);
434 xmlFreeNode(val);
435}
436""");
437
438#
439# Generate the top caller
440#
441
442test.write("""
443/**
444 * testlibxml2:
445 *
446 * Main entry point of the tester for the full libxml2 module,
447 * it calls all the tester entry point for each module.
448 *
449 * Returns the number of error found
450 */
451static int
452testlibxml2(void)
453{
454 int ret = 0;
455
456""")
457
458for module in modules:
459 test.write(" ret += test_%s();\n" % module)
460
461test.write("""
462 printf("Total: %d tests, %d errors\\n", call_tests, ret);
463 return(ret);
464}
465
466""")
467
468#
469# How to handle a function
470#
471nb_tests = 0
472
473def generate_test(module, node):
474 global test
475 global nb_tests
476 nb_cond = 0
477 no_gen = 0
478
479 name = node.xpathEval('string(@name)')
480 if is_skipped_function(name):
481 return
482
483 test.write("""
484static int
485test_%s(void) {
486 int ret = 0;
487
488""" % (name))
489
490 #
491 # check we know how to handle the args and return values
492 # and store the informations for the generation
493 #
494 try:
495 args = node.xpathEval("arg")
496 except:
497 args = []
498 t_args = []
Daniel Veillarda03e3652004-11-02 18:45:30 +0000499 n = 0
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000500 for arg in args:
Daniel Veillarda03e3652004-11-02 18:45:30 +0000501 n = n + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000502 rtype = arg.xpathEval("string(@type)")
503 if rtype == 'void':
504 break;
505 info = arg.xpathEval("string(@info)")
506 nam = arg.xpathEval("string(@name)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000507 type = type_convert(rtype, nam, info, module, name, n)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000508 if is_known_param_type(type) == 0:
509 add_missing_type(type, name);
510 no_gen = 1
511 t_args.append((nam, type, rtype, info))
512
513 try:
514 rets = node.xpathEval("return")
515 except:
516 rets = []
517 t_ret = None
518 for ret in rets:
519 rtype = ret.xpathEval("string(@type)")
520 info = ret.xpathEval("string(@info)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000521 type = type_convert(rtype, 'return', info, module, name, 0)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000522 if rtype == 'void':
523 break
524 if is_known_return_type(type) == 0:
525 add_missing_type(type, name);
526 no_gen = 1
527 t_ret = (type, rtype, info)
528 break
529
530 if no_gen == 1:
531 test.write("""
532 /* missing type support */
533 return(ret);
534}
535
536""")
537 return
538
539 try:
540 conds = node.xpathEval("cond")
541 for cond in conds:
542 test.write("#ifdef %s\n" % (cond.get_content()))
543 nb_cond = nb_cond + 1
544 except:
545 pass
546
547 # Declare the memory usage counter
548 no_mem = is_skipped_memcheck(name)
549 if no_mem == 0:
550 test.write(" int mem_base;\n");
551
552 # Declare the return value
553 if t_ret != None:
554 test.write(" %s ret_val;\n" % (t_ret[1]))
555
556 # Declare the arguments
557 for arg in t_args:
558 (nam, type, rtype, info) = arg;
559 # add declaration
560 test.write(" %s %s; /* %s */\n" % (rtype, nam, info))
561 test.write(" int n_%s;\n" % (nam))
562 test.write("\n")
563
564 # Cascade loop on of each argument list of values
565 for arg in t_args:
566 (nam, type, rtype, info) = arg;
567 #
568 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
569 nam, nam, type, nam))
570
571 # log the memory usage
572 if no_mem == 0:
573 test.write(" mem_base = xmlMemBlocks();\n");
574
575 # prepare the call
576 for arg in t_args:
577 (nam, type, rtype, info) = arg;
578 #
579 test.write(" %s = gen_%s(n_%s);\n" % (nam, type, nam))
580
581 # do the call, and clanup the result
582 if t_ret != None:
583 test.write("\n ret_val = %s(" % (name))
584 need = 0
585 for arg in t_args:
586 (nam, type, rtype, info) = arg
587 if need:
588 test.write(", ")
589 else:
590 need = 1
591 test.write("%s" % nam);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000592 test.write(");\n")
593 if extra_post_call.has_key(name):
594 test.write(" %s\n"% (extra_post_call[name]))
595 test.write(" desret_%s(ret_val);\n" % t_ret[0])
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000596 else:
597 test.write("\n %s(" % (name));
598 need = 0;
599 for arg in t_args:
600 (nam, type, rtype, info) = arg;
601 if need:
602 test.write(", ")
603 else:
604 need = 1
605 test.write("%s" % nam)
606 test.write(");\n")
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000607 if extra_post_call.has_key(name):
608 test.write(" %s\n"% (extra_post_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000609
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000610 test.write(" call_tests++;\n");
Daniel Veillarda03e3652004-11-02 18:45:30 +0000611
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000612 # Free the arguments
613 for arg in t_args:
614 (nam, type, rtype, info) = arg;
615 #
616 test.write(" des_%s(n_%s, %s);\n" % (type, nam, nam))
617
618 test.write(" xmlResetLastError();\n");
619 # Check the memory usage
620 if no_mem == 0:
621 test.write(""" if (mem_base != xmlMemBlocks()) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000622 printf("Leak of %%d blocks found in %s",
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000623 xmlMemBlocks() - mem_base);
624 ret++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000625""" % (name));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000626 for arg in t_args:
627 (nam, type, rtype, info) = arg;
628 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
629 test.write(""" printf("\\n");\n""")
630 test.write(" }\n")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000631
632 for arg in t_args:
633 test.write(" }\n")
634
635 #
636 # end of conditional
637 #
638 while nb_cond > 0:
639 test.write("#endif\n")
640 nb_cond = nb_cond -1
641
642 nb_tests = nb_tests + 1;
643
644 test.write("""
645 return(ret);
646}
647
648""")
649
650#
651# Generate all module callers
652#
653for module in modules:
654 # gather all the functions exported by that module
655 try:
656 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
657 except:
658 print "Failed to gather functions from module %s" % (module)
659 continue;
660
661 # iterate over all functions in the module generating the test
662 for function in functions:
663 generate_test(module, function);
664
665 # header
666 test.write("""static int
667test_%s(void) {
668 int ret = 0;
669
670 printf("Testing %s ...\\n");
671""" % (module, module))
672
673 # iterate over all functions in the module generating the call
674 for function in functions:
675 name = function.xpathEval('string(@name)')
676 if is_skipped_function(name):
677 continue
678 test.write(" ret += test_%s();\n" % (name))
679
680 # footer
681 test.write("""
682 if (ret != 0)
683 printf("Module %s: %%d errors\\n", ret);
684 return(ret);
685}
686""" % (module))
687
688print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
689nr = 0
690miss = 'none'
691for missing in missing_types.keys():
692 n = len(missing_types[missing])
693 if n > nr:
694 miss = missing
695 nr = n
696
697if nr > 0:
698 print "most needed type support: %s %d times" % (miss, nr)
699
700