blob: fc3e7101649ab86c12fd6aee84858c5a01157dfb [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 Veillardd005b9e2004-11-03 17:07:05 +000018 "xmlversion", "debugXML", "xmlexports",
19
20 # temporary
21 "xmlautomata", "xmlregexp",
22
23]
Daniel Veillard36e5cd52004-11-02 14:52:23 +000024
25#
26# Some function really need to be skipped for the tests.
27#
Daniel Veillarddd6d3002004-11-03 14:20:29 +000028skipped_functions = [
29# block on I/O
30"xmlFdRead", "xmlReadFd", "xmlCtxtReadFd",
31"htmlFdRead", "htmlReadFd", "htmlCtxtReadFd",
32"xmlReaderNewFd",
33# library state cleanup, generate false leak informations and other
34# troubles, heavillyb tested otherwise.
35"xmlCleanupParser", "xmlRelaxNGCleanupTypes",
36# hard to avoid leaks in the tests
37"xmlStrcat", "xmlStrncat",
38# unimplemented
39"xmlTextReaderReadInnerXml", "xmlTextReaderReadOuterXml",
Daniel Veillardd005b9e2004-11-03 17:07:05 +000040"xmlTextReaderReadString",
41# destructor
42"xmlListDelete",
43# deprecated
44"xmlCatalogGetPublic", "xmlCatalogGetSystem", "xmlEncodeEntities",
Daniel Veillarddd6d3002004-11-03 14:20:29 +000045]
Daniel Veillard36e5cd52004-11-02 14:52:23 +000046
47#
48# Those functions have side effect on the global state
49# and hence generate errors on memory allocation tests
50#
51skipped_memcheck = [ "xmlLoadCatalog", "xmlAddEncodingAlias",
52 "xmlSchemaInitTypes", "xmlNanoFTPProxy", "xmlNanoFTPScanProxy",
53 "xmlNanoHTTPScanProxy", "xmlResetLastError", "xmlCatalogConvert",
54 "xmlCatalogRemove", "xmlLoadCatalogs", "xmlCleanupCharEncodingHandlers",
Daniel Veillarda03e3652004-11-02 18:45:30 +000055 "xmlInitCharEncodingHandlers", "xmlCatalogCleanup",
56 "htmlParseFile" # loads the catalogs
57]
58
59#
60# Extra code needed for some test cases
61#
62extra_post_call = {
63 "xmlAddChild":
64 "if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; }",
65 "xmlAddChildList":
66 "if (ret_val == NULL) { xmlFreeNodeList(cur) ; cur = NULL ; }",
67 "xmlAddSibling":
68 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
69 "xmlAddNextSibling":
70 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
71 "xmlAddPrevSibling":
72 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
73 "xmlDocSetRootElement":
74 "if (doc == NULL) { xmlFreeNode(root) ; root = NULL ; }",
75 "xmlReplaceNode":
76 """if ((old == NULL) || (old->parent == NULL)) {
77 xmlFreeNode(cur) ; cur = NULL ; }""",
78 "xmlTextMerge":
79 """if ((first != NULL) && (first->type != XML_TEXT_NODE)) {
80 xmlFreeNode(second) ; second = NULL ; }""",
Daniel Veillard8a32fe42004-11-02 22:10:16 +000081 "xmlBuildQName":
82 """if ((ret_val != NULL) && (ret_val != ncname) &&
83 (ret_val != prefix) && (ret_val != memory))
84 xmlFree(ret_val);
85 ret_val = NULL;""",
Daniel Veillarda03e3652004-11-02 18:45:30 +000086}
Daniel Veillard36e5cd52004-11-02 14:52:23 +000087
88modules = []
89
90def is_skipped_module(name):
91 for mod in skipped_modules:
92 if mod == name:
93 return 1
94 return 0
95
96def is_skipped_function(name):
97 for fun in skipped_functions:
98 if fun == name:
99 return 1
100 # Do not test destructors
101 if string.find(name, 'Free') != -1:
102 return 1
103 return 0
104
105def is_skipped_memcheck(name):
106 for fun in skipped_memcheck:
107 if fun == name:
108 return 1
109 return 0
110
111missing_types = {}
112def add_missing_type(name, func):
113 try:
114 list = missing_types[name]
115 list.append(func)
116 except:
117 missing_types[name] = [func]
118
119#
120# Open the input API description and the C test program result
121#
122doc = libxml2.readFile('doc/libxml2-api.xml', None, 0)
123if doc == None:
124 print "Failed to load doc/libxml2-api.xml"
125 sys.exit(1)
126test = open('testapi.c', 'w')
127ctxt = doc.xpathNewContext()
128headers = ctxt.xpathEval("/api/files/file")
129
130#
131# Generate the test header
132#
133test.write("""/*
134 * testapi.c: libxml2 API tester program.
135 *
136 * Automatically generated by gentest.py from libxml2-api.xml
137 *
138 * See Copyright for the status of this software.
139 *
140 * daniel@veillard.com
141 */
142
143#include <stdio.h>
144#include <libxml/xmlerror.h>
145
146static int testlibxml2(void);
147
148static int generic_errors = 0;
149static int call_tests = 0;
150
Daniel Veillard348636d2004-11-02 22:34:52 +0000151static xmlChar chartab[1024] = " chartab\\n";
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000152
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000153static void
154structured_errors(void *userData ATTRIBUTE_UNUSED,
155 xmlErrorPtr error ATTRIBUTE_UNUSED) {
156 generic_errors++;
157}
158
159int main(void) {
160 int ret;
161 int blocks, mem;
162
Daniel Veillarda03e3652004-11-02 18:45:30 +0000163 xmlInitParser();
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000164 xmlRelaxNGInitTypes();
Daniel Veillarda03e3652004-11-02 18:45:30 +0000165
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000166 LIBXML_TEST_VERSION
167
168 xmlSetStructuredErrorFunc(NULL, structured_errors);
169
170 ret = testlibxml2();
171
172 xmlCleanupParser();
173 blocks = xmlMemBlocks();
174 mem = xmlMemUsed();
175 if ((blocks != 0) || (mem != 0)) {
176 printf("testapi leaked %d bytes in %d blocks\\n", mem, blocks);
177 }
178 xmlMemoryDump();
179
180 return (ret != 0);
181}
182
183""");
184
185#
186# Load the interfaces
187#
188for file in headers:
189 name = file.xpathEval('string(@name)')
190 if (name == None) or (name == ''):
191 continue
192
193 #
194 # do not test deprecated APIs
195 #
196 desc = file.xpathEval('string(description)')
197 if string.find(desc, 'DEPRECATED') != -1:
198 print "Skipping deprecated interface %s" % name
199 continue;
200
201 #
202 # Some module may be skipped because they don't really consists
203 # of user callable APIs
204 #
205 if is_skipped_module(name):
206 continue
207
208 test.write("#include <libxml/%s.h>\n" % name)
209 modules.append(name)
210
211#
212# Generate the callers signatures
213#
214for module in modules:
215 test.write("static int test_%s(void);\n" % module);
216
217#
218# Provide the type generators and destructors for the parameters
219#
220
Daniel Veillarda03e3652004-11-02 18:45:30 +0000221def type_convert(str, name, info, module, function, pos):
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000222 res = string.replace(str, " *", "_ptr")
223 res = string.replace(res, " ", "_")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000224 res = string.replace(res, "htmlNode", "xmlNode")
225 res = string.replace(res, "htmlDoc", "xmlDoc")
226 res = string.replace(res, "htmlParser", "xmlParser")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000227 if res == 'const_char_ptr':
228 if string.find(name, "file") != -1 or \
229 string.find(name, "uri") != -1 or \
230 string.find(name, "URI") != -1 or \
231 string.find(info, "filename") != -1 or \
232 string.find(info, "URI") != -1 or \
233 string.find(info, "URL") != -1:
234 if string.find(function, "Save") != -1:
235 return('fileoutput')
236 return('filepath')
237 if res == 'void_ptr':
238 if module == 'nanoftp' and name == 'ctx':
239 return('xmlNanoFTPCtxtPtr')
240 if module == 'nanohttp' and name == 'ctx':
241 return('xmlNanoHTTPCtxtPtr')
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000242 if string.find(name, "data") != -1:
243 return('userdata');
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000244 if string.find(name, "user") != -1:
245 return('userdata');
Daniel Veillarda03e3652004-11-02 18:45:30 +0000246 if res == 'xmlNodePtr' and pos != 0:
247 if (function == 'xmlAddChild' and pos == 2) or \
248 (function == 'xmlAddChildList' and pos == 2) or \
249 (function == 'xmlAddNextSibling' and pos == 2) or \
250 (function == 'xmlAddSibling' and pos == 2) or \
251 (function == 'xmlDocSetRootElement' and pos == 2) or \
252 (function == 'xmlReplaceNode' and pos == 2) or \
253 (function == 'xmlTextMerge') or \
254 (function == 'xmlAddPrevSibling' and pos == 2):
255 return('xmlNodePtr_in');
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000256
257 return res
258
259known_param_types = [ "int", "const_char_ptr", "const_xmlChar_ptr",
Daniel Veillarde43cc572004-11-03 11:50:29 +0000260 "xmlParserCtxtPtr", "xmlDocPtr", "filepath", "fileoutput",
261 "xmlNodePtr", "xmlNodePtr_in", "userdata", "xmlChar_ptr",
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000262 "xmlTextWriterPtr", "xmlTextReaderPtr", "xmlBufferPtr",
263 "xmlListPtr", "xmlXPathObjectPtr", "xmlHashTablePtr",
264]
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000265
266def is_known_param_type(name):
267 for type in known_param_types:
268 if type == name:
269 return 1
270 return 0
271
272test.write("""
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000273#define gen_nb_userdata 3
274
275static void *gen_userdata(int no) {
276 if (no == 0) return((void *) &call_tests);
277 if (no == 1) return((void *) -1);
278 return(NULL);
279}
280static void des_userdata(int no ATTRIBUTE_UNUSED, void *val ATTRIBUTE_UNUSED) {
281}
282
283
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000284#define gen_nb_int 4
285
286static int gen_int(int no) {
287 if (no == 0) return(0);
288 if (no == 1) return(1);
289 if (no == 2) return(122);
290 return(-1);
291}
292
293static void des_int(int no ATTRIBUTE_UNUSED, int val ATTRIBUTE_UNUSED) {
294}
295
296#define gen_nb_const_char_ptr 4
297
298static const char *gen_const_char_ptr(int no) {
299 if (no == 0) return("foo");
300 if (no == 1) return("<foo/>");
301 if (no == 2) return("test/ent2");
302 return(NULL);
303}
304static void des_const_char_ptr(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED) {
305}
306
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000307#define gen_nb_xmlChar_ptr 2
308
309static xmlChar *gen_xmlChar_ptr(int no) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000310 if (no == 0) return(&chartab[0]);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000311 return(NULL);
312}
313static void des_xmlChar_ptr(int no ATTRIBUTE_UNUSED, xmlChar *val ATTRIBUTE_UNUSED) {
314}
315
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000316#define gen_nb_const_xmlChar_ptr 5
317
318static const xmlChar *gen_const_xmlChar_ptr(int no) {
319 if (no == 0) return((const xmlChar *) "foo");
320 if (no == 1) return((const xmlChar *) "<foo/>");
321 if (no == 2) return((const xmlChar *) "nøne");
322 if (no == 3) return((const xmlChar *) " 2ab ");
323 return(NULL);
324}
325static void des_const_xmlChar_ptr(int no ATTRIBUTE_UNUSED, const xmlChar *val ATTRIBUTE_UNUSED) {
326}
327
328#define gen_nb_filepath 8
329
330static const char *gen_filepath(int no) {
331 if (no == 0) return("missing.xml");
332 if (no == 1) return("<foo/>");
333 if (no == 2) return("test/ent2");
334 if (no == 3) return("test/valid/REC-xml-19980210.xml");
335 if (no == 4) return("test/valid/xhtml1-strict.dtd");
336 if (no == 5) return("http://missing.example.org/");
337 if (no == 6) return("http://missing. example.org/");
338 return(NULL);
339}
340static void des_filepath(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED) {
341}
342
343#define gen_nb_fileoutput 6
344
345static const char *gen_fileoutput(int no) {
346 if (no == 0) return("/missing.xml");
347 if (no == 1) return("<foo/>");
348 if (no == 2) return("ftp://missing.example.org/foo");
349 if (no == 3) return("http://missing.example.org/");
350 if (no == 4) return("http://missing. example.org/");
351 return(NULL);
352}
353static void des_fileoutput(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED) {
354}
355
356#define gen_nb_xmlParserCtxtPtr 2
357static xmlParserCtxtPtr gen_xmlParserCtxtPtr(int no) {
358 if (no == 0) return(xmlNewParserCtxt());
359 return(NULL);
360}
361static void des_xmlParserCtxtPtr(int no ATTRIBUTE_UNUSED, xmlParserCtxtPtr val) {
362 if (val != NULL)
363 xmlFreeParserCtxt(val);
364}
365
Daniel Veillarda03e3652004-11-02 18:45:30 +0000366#define gen_nb_xmlDocPtr 3
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000367static xmlDocPtr gen_xmlDocPtr(int no) {
368 if (no == 0) return(xmlNewDoc(BAD_CAST "1.0"));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000369 if (no == 1) return(xmlReadMemory("<foo/>", 6, "test", NULL, 0));
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000370 return(NULL);
371}
372static void des_xmlDocPtr(int no ATTRIBUTE_UNUSED, xmlDocPtr val) {
373 if (val != NULL)
374 xmlFreeDoc(val);
375}
376
Daniel Veillarda03e3652004-11-02 18:45:30 +0000377#define gen_nb_xmlNodePtr 2
378static xmlNodePtr gen_xmlNodePtr(int no) {
379 if (no == 0) return(xmlNewPI(BAD_CAST "test", NULL));
380 return(NULL);
381}
382static void des_xmlNodePtr(int no ATTRIBUTE_UNUSED, xmlNodePtr val) {
383 if (val != NULL) {
384 xmlUnlinkNode(val);
385 xmlFreeNode(val);
386 }
387}
388
389#define gen_nb_xmlNodePtr_in 3
390static xmlNodePtr gen_xmlNodePtr_in(int no) {
391 if (no == 0) return(xmlNewPI(BAD_CAST "test", NULL));
392 if (no == 0) return(xmlNewText(BAD_CAST "text"));
393 return(NULL);
394}
395static void des_xmlNodePtr_in(int no ATTRIBUTE_UNUSED, xmlNodePtr val ATTRIBUTE_UNUSED) {
396}
397
Daniel Veillarde43cc572004-11-03 11:50:29 +0000398#define gen_nb_xmlTextWriterPtr 2
399static xmlTextWriterPtr gen_xmlTextWriterPtr(int no) {
400 if (no == 0) return(xmlNewTextWriterFilename("test.out", 0));
401 return(NULL);
402}
403static void des_xmlTextWriterPtr(int no ATTRIBUTE_UNUSED, xmlTextWriterPtr val) {
404 if (val != NULL) xmlFreeTextWriter(val);
405}
406
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000407#define gen_nb_xmlTextReaderPtr 4
408static xmlTextReaderPtr gen_xmlTextReaderPtr(int no) {
409 if (no == 0) return(xmlNewTextReaderFilename("test/ent2"));
410 if (no == 1) return(xmlNewTextReaderFilename("test/valid/REC-xml-19980210.xml"));
411 if (no == 2) return(xmlNewTextReaderFilename("test/valid/dtds/xhtml1-strict.dtd"));
412 return(NULL);
413}
414static void des_xmlTextReaderPtr(int no ATTRIBUTE_UNUSED, xmlTextReaderPtr val) {
415 if (val != NULL) xmlFreeTextReader(val);
416}
417
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000418#define gen_nb_xmlBufferPtr 2
419static xmlBufferPtr gen_xmlBufferPtr(int no) {
420 if (no == 0) return(xmlBufferCreate());
421 return(NULL);
422}
423static void des_xmlBufferPtr(int no ATTRIBUTE_UNUSED, xmlBufferPtr val) {
424 if (val != NULL) {
425 xmlBufferFree(val);
426 }
427}
428
429#define gen_nb_xmlListPtr 2
430static xmlListPtr gen_xmlListPtr(int no) {
431 if (no == 0) return(xmlListCreate(NULL, NULL));
432 return(NULL);
433}
434static void des_xmlListPtr(int no ATTRIBUTE_UNUSED, xmlListPtr val) {
435 if (val != NULL) {
436 xmlListDelete(val);
437 }
438}
439
440#define gen_nb_xmlHashTablePtr 2
441static xmlHashTablePtr gen_xmlHashTablePtr(int no) {
442 if (no == 0) return(xmlHashCreate(10));
443 return(NULL);
444}
445static void des_xmlHashTablePtr(int no ATTRIBUTE_UNUSED, xmlHashTablePtr val) {
446 if (val != NULL) {
447 xmlHashFree(val, NULL);
448 }
449}
450
451#include <libxml/xpathInternals.h>
452
453#define gen_nb_xmlXPathObjectPtr 5
454static xmlXPathObjectPtr gen_xmlXPathObjectPtr(int no) {
455 if (no == 0) return(xmlXPathNewString(BAD_CAST "string object"));
456 if (no == 1) return(xmlXPathNewFloat(1.1));
457 if (no == 2) return(xmlXPathNewBoolean(1));
458 if (no == 3) return(xmlXPathNewNodeSet(NULL));
459 return(NULL);
460}
461static void des_xmlXPathObjectPtr(int no ATTRIBUTE_UNUSED, xmlXPathObjectPtr val) {
462 if (val != NULL) {
463 xmlXPathFreeObject(val);
464 }
465}
466
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000467""");
468
469#
470# Provide the type destructors for the return values
471#
472
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000473known_return_types = [ "int", "const_char_ptr", "xmlDocPtr", "xmlNodePtr",
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000474 "xmlChar_ptr", "const_xmlChar_ptr" ];
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000475
476def is_known_return_type(name):
477 for type in known_return_types:
478 if type == name:
479 return 1
480 return 0
481
482test.write("""
483static void desret_int(int val ATTRIBUTE_UNUSED) {
484}
485static void desret_const_char_ptr(const char *val ATTRIBUTE_UNUSED) {
486}
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000487static void desret_const_xmlChar_ptr(const xmlChar *val ATTRIBUTE_UNUSED) {
488}
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000489static void desret_xmlChar_ptr(xmlChar *val) {
490 if (val != NULL)
491 xmlFree(val);
492}
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000493static void desret_xmlDocPtr(xmlDocPtr val) {
494 xmlFreeDoc(val);
495}
496static void desret_xmlNodePtr(xmlNodePtr val) {
497 xmlUnlinkNode(val);
498 xmlFreeNode(val);
499}
500""");
501
502#
503# Generate the top caller
504#
505
506test.write("""
507/**
508 * testlibxml2:
509 *
510 * Main entry point of the tester for the full libxml2 module,
511 * it calls all the tester entry point for each module.
512 *
513 * Returns the number of error found
514 */
515static int
516testlibxml2(void)
517{
518 int ret = 0;
519
520""")
521
522for module in modules:
523 test.write(" ret += test_%s();\n" % module)
524
525test.write("""
526 printf("Total: %d tests, %d errors\\n", call_tests, ret);
527 return(ret);
528}
529
530""")
531
532#
533# How to handle a function
534#
535nb_tests = 0
536
537def generate_test(module, node):
538 global test
539 global nb_tests
540 nb_cond = 0
541 no_gen = 0
542
543 name = node.xpathEval('string(@name)')
544 if is_skipped_function(name):
545 return
546
547 test.write("""
548static int
549test_%s(void) {
550 int ret = 0;
551
552""" % (name))
553
554 #
555 # check we know how to handle the args and return values
556 # and store the informations for the generation
557 #
558 try:
559 args = node.xpathEval("arg")
560 except:
561 args = []
562 t_args = []
Daniel Veillarda03e3652004-11-02 18:45:30 +0000563 n = 0
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000564 for arg in args:
Daniel Veillarda03e3652004-11-02 18:45:30 +0000565 n = n + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000566 rtype = arg.xpathEval("string(@type)")
567 if rtype == 'void':
568 break;
569 info = arg.xpathEval("string(@info)")
570 nam = arg.xpathEval("string(@name)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000571 type = type_convert(rtype, nam, info, module, name, n)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000572 if is_known_param_type(type) == 0:
573 add_missing_type(type, name);
574 no_gen = 1
575 t_args.append((nam, type, rtype, info))
576
577 try:
578 rets = node.xpathEval("return")
579 except:
580 rets = []
581 t_ret = None
582 for ret in rets:
583 rtype = ret.xpathEval("string(@type)")
584 info = ret.xpathEval("string(@info)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000585 type = type_convert(rtype, 'return', info, module, name, 0)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000586 if rtype == 'void':
587 break
588 if is_known_return_type(type) == 0:
589 add_missing_type(type, name);
590 no_gen = 1
591 t_ret = (type, rtype, info)
592 break
593
594 if no_gen == 1:
595 test.write("""
596 /* missing type support */
597 return(ret);
598}
599
600""")
601 return
602
603 try:
604 conds = node.xpathEval("cond")
605 for cond in conds:
606 test.write("#ifdef %s\n" % (cond.get_content()))
607 nb_cond = nb_cond + 1
608 except:
609 pass
610
611 # Declare the memory usage counter
612 no_mem = is_skipped_memcheck(name)
613 if no_mem == 0:
614 test.write(" int mem_base;\n");
615
616 # Declare the return value
617 if t_ret != None:
618 test.write(" %s ret_val;\n" % (t_ret[1]))
619
620 # Declare the arguments
621 for arg in t_args:
622 (nam, type, rtype, info) = arg;
623 # add declaration
624 test.write(" %s %s; /* %s */\n" % (rtype, nam, info))
625 test.write(" int n_%s;\n" % (nam))
626 test.write("\n")
627
628 # Cascade loop on of each argument list of values
629 for arg in t_args:
630 (nam, type, rtype, info) = arg;
631 #
632 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
633 nam, nam, type, nam))
634
635 # log the memory usage
636 if no_mem == 0:
637 test.write(" mem_base = xmlMemBlocks();\n");
638
639 # prepare the call
640 for arg in t_args:
641 (nam, type, rtype, info) = arg;
642 #
643 test.write(" %s = gen_%s(n_%s);\n" % (nam, type, nam))
644
645 # do the call, and clanup the result
646 if t_ret != None:
647 test.write("\n ret_val = %s(" % (name))
648 need = 0
649 for arg in t_args:
650 (nam, type, rtype, info) = arg
651 if need:
652 test.write(", ")
653 else:
654 need = 1
655 test.write("%s" % nam);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000656 test.write(");\n")
657 if extra_post_call.has_key(name):
658 test.write(" %s\n"% (extra_post_call[name]))
659 test.write(" desret_%s(ret_val);\n" % t_ret[0])
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000660 else:
661 test.write("\n %s(" % (name));
662 need = 0;
663 for arg in t_args:
664 (nam, type, rtype, info) = arg;
665 if need:
666 test.write(", ")
667 else:
668 need = 1
669 test.write("%s" % nam)
670 test.write(");\n")
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000671 if extra_post_call.has_key(name):
672 test.write(" %s\n"% (extra_post_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000673
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000674 test.write(" call_tests++;\n");
Daniel Veillarda03e3652004-11-02 18:45:30 +0000675
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000676 # Free the arguments
677 for arg in t_args:
678 (nam, type, rtype, info) = arg;
679 #
680 test.write(" des_%s(n_%s, %s);\n" % (type, nam, nam))
681
682 test.write(" xmlResetLastError();\n");
683 # Check the memory usage
684 if no_mem == 0:
685 test.write(""" if (mem_base != xmlMemBlocks()) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000686 printf("Leak of %%d blocks found in %s",
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000687 xmlMemBlocks() - mem_base);
688 ret++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000689""" % (name));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000690 for arg in t_args:
691 (nam, type, rtype, info) = arg;
692 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
693 test.write(""" printf("\\n");\n""")
694 test.write(" }\n")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000695
696 for arg in t_args:
697 test.write(" }\n")
698
699 #
700 # end of conditional
701 #
702 while nb_cond > 0:
703 test.write("#endif\n")
704 nb_cond = nb_cond -1
705
706 nb_tests = nb_tests + 1;
707
708 test.write("""
709 return(ret);
710}
711
712""")
713
714#
715# Generate all module callers
716#
717for module in modules:
718 # gather all the functions exported by that module
719 try:
720 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
721 except:
722 print "Failed to gather functions from module %s" % (module)
723 continue;
724
725 # iterate over all functions in the module generating the test
726 for function in functions:
727 generate_test(module, function);
728
729 # header
730 test.write("""static int
731test_%s(void) {
732 int ret = 0;
733
734 printf("Testing %s ...\\n");
735""" % (module, module))
736
737 # iterate over all functions in the module generating the call
738 for function in functions:
739 name = function.xpathEval('string(@name)')
740 if is_skipped_function(name):
741 continue
742 test.write(" ret += test_%s();\n" % (name))
743
744 # footer
745 test.write("""
746 if (ret != 0)
747 printf("Module %s: %%d errors\\n", ret);
748 return(ret);
749}
750""" % (module))
751
752print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000753nr1 = 0
754miss1 = 'none'
755nr2 = 0
756miss2 = 'none'
757nr3 = 0
758miss3 = 'none'
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000759for missing in missing_types.keys():
760 n = len(missing_types[missing])
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000761 if n > nr1:
762 miss3 = miss2
763 nr3 = nr2
764 miss2 = miss1
765 nr2 = nr1
766 miss1 = missing
767 nr1 = n
768 elif n > nr2:
769 miss3 = miss2
770 nr3 = nr2
771 miss2 = missing
772 nr2 = n
773 elif n > nr3:
774 miss3 = missing
775 nr3 = n
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000776
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000777if nr1 > 0:
778 print "most needed type support: %s %d times, %s %d and %s %d" % (
779 miss1, nr1, miss2, nr2, miss3, nr3)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000780
781