blob: 28247c82b944806f6b67f8fad83310e071bd979f [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",
Daniel Veillardc0be74b2004-11-03 19:16:55 +0000263 "xmlListPtr", "xmlXPathObjectPtr", "xmlHashTablePtr", "xmlValidCtxtPtr",
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000264]
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 Veillardc0be74b2004-11-03 19:16:55 +0000366#define gen_nb_xmlValidCtxtPtr 2
367static xmlValidCtxtPtr gen_xmlValidCtxtPtr(int no) {
368 if (no == 0) return(xmlNewValidCtxt());
369 return(NULL);
370}
371static void des_xmlValidCtxtPtr(int no ATTRIBUTE_UNUSED, xmlValidCtxtPtr val) {
372 if (val != NULL)
373 xmlFreeValidCtxt(val);
374}
375
Daniel Veillarda03e3652004-11-02 18:45:30 +0000376#define gen_nb_xmlDocPtr 3
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000377static xmlDocPtr gen_xmlDocPtr(int no) {
378 if (no == 0) return(xmlNewDoc(BAD_CAST "1.0"));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000379 if (no == 1) return(xmlReadMemory("<foo/>", 6, "test", NULL, 0));
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000380 return(NULL);
381}
382static void des_xmlDocPtr(int no ATTRIBUTE_UNUSED, xmlDocPtr val) {
383 if (val != NULL)
384 xmlFreeDoc(val);
385}
386
Daniel Veillarda03e3652004-11-02 18:45:30 +0000387#define gen_nb_xmlNodePtr 2
388static xmlNodePtr gen_xmlNodePtr(int no) {
389 if (no == 0) return(xmlNewPI(BAD_CAST "test", NULL));
390 return(NULL);
391}
392static void des_xmlNodePtr(int no ATTRIBUTE_UNUSED, xmlNodePtr val) {
393 if (val != NULL) {
394 xmlUnlinkNode(val);
395 xmlFreeNode(val);
396 }
397}
398
399#define gen_nb_xmlNodePtr_in 3
400static xmlNodePtr gen_xmlNodePtr_in(int no) {
401 if (no == 0) return(xmlNewPI(BAD_CAST "test", NULL));
402 if (no == 0) return(xmlNewText(BAD_CAST "text"));
403 return(NULL);
404}
405static void des_xmlNodePtr_in(int no ATTRIBUTE_UNUSED, xmlNodePtr val ATTRIBUTE_UNUSED) {
406}
407
Daniel Veillarde43cc572004-11-03 11:50:29 +0000408#define gen_nb_xmlTextWriterPtr 2
409static xmlTextWriterPtr gen_xmlTextWriterPtr(int no) {
410 if (no == 0) return(xmlNewTextWriterFilename("test.out", 0));
411 return(NULL);
412}
413static void des_xmlTextWriterPtr(int no ATTRIBUTE_UNUSED, xmlTextWriterPtr val) {
414 if (val != NULL) xmlFreeTextWriter(val);
415}
416
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000417#define gen_nb_xmlTextReaderPtr 4
418static xmlTextReaderPtr gen_xmlTextReaderPtr(int no) {
419 if (no == 0) return(xmlNewTextReaderFilename("test/ent2"));
420 if (no == 1) return(xmlNewTextReaderFilename("test/valid/REC-xml-19980210.xml"));
421 if (no == 2) return(xmlNewTextReaderFilename("test/valid/dtds/xhtml1-strict.dtd"));
422 return(NULL);
423}
424static void des_xmlTextReaderPtr(int no ATTRIBUTE_UNUSED, xmlTextReaderPtr val) {
425 if (val != NULL) xmlFreeTextReader(val);
426}
427
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000428#define gen_nb_xmlBufferPtr 2
429static xmlBufferPtr gen_xmlBufferPtr(int no) {
430 if (no == 0) return(xmlBufferCreate());
431 return(NULL);
432}
433static void des_xmlBufferPtr(int no ATTRIBUTE_UNUSED, xmlBufferPtr val) {
434 if (val != NULL) {
435 xmlBufferFree(val);
436 }
437}
438
439#define gen_nb_xmlListPtr 2
440static xmlListPtr gen_xmlListPtr(int no) {
441 if (no == 0) return(xmlListCreate(NULL, NULL));
442 return(NULL);
443}
444static void des_xmlListPtr(int no ATTRIBUTE_UNUSED, xmlListPtr val) {
445 if (val != NULL) {
446 xmlListDelete(val);
447 }
448}
449
450#define gen_nb_xmlHashTablePtr 2
451static xmlHashTablePtr gen_xmlHashTablePtr(int no) {
452 if (no == 0) return(xmlHashCreate(10));
453 return(NULL);
454}
455static void des_xmlHashTablePtr(int no ATTRIBUTE_UNUSED, xmlHashTablePtr val) {
456 if (val != NULL) {
457 xmlHashFree(val, NULL);
458 }
459}
460
461#include <libxml/xpathInternals.h>
462
463#define gen_nb_xmlXPathObjectPtr 5
464static xmlXPathObjectPtr gen_xmlXPathObjectPtr(int no) {
465 if (no == 0) return(xmlXPathNewString(BAD_CAST "string object"));
466 if (no == 1) return(xmlXPathNewFloat(1.1));
467 if (no == 2) return(xmlXPathNewBoolean(1));
468 if (no == 3) return(xmlXPathNewNodeSet(NULL));
469 return(NULL);
470}
471static void des_xmlXPathObjectPtr(int no ATTRIBUTE_UNUSED, xmlXPathObjectPtr val) {
472 if (val != NULL) {
473 xmlXPathFreeObject(val);
474 }
475}
476
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000477""");
478
479#
480# Provide the type destructors for the return values
481#
482
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000483known_return_types = [ "int", "const_char_ptr", "xmlDocPtr", "xmlNodePtr",
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000484 "xmlChar_ptr", "const_xmlChar_ptr" ];
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000485
486def is_known_return_type(name):
487 for type in known_return_types:
488 if type == name:
489 return 1
490 return 0
491
492test.write("""
493static void desret_int(int val ATTRIBUTE_UNUSED) {
494}
495static void desret_const_char_ptr(const char *val ATTRIBUTE_UNUSED) {
496}
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000497static void desret_const_xmlChar_ptr(const xmlChar *val ATTRIBUTE_UNUSED) {
498}
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000499static void desret_xmlChar_ptr(xmlChar *val) {
500 if (val != NULL)
501 xmlFree(val);
502}
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000503static void desret_xmlDocPtr(xmlDocPtr val) {
504 xmlFreeDoc(val);
505}
506static void desret_xmlNodePtr(xmlNodePtr val) {
507 xmlUnlinkNode(val);
508 xmlFreeNode(val);
509}
510""");
511
512#
513# Generate the top caller
514#
515
516test.write("""
517/**
518 * testlibxml2:
519 *
520 * Main entry point of the tester for the full libxml2 module,
521 * it calls all the tester entry point for each module.
522 *
523 * Returns the number of error found
524 */
525static int
526testlibxml2(void)
527{
528 int ret = 0;
529
530""")
531
532for module in modules:
533 test.write(" ret += test_%s();\n" % module)
534
535test.write("""
536 printf("Total: %d tests, %d errors\\n", call_tests, ret);
537 return(ret);
538}
539
540""")
541
542#
543# How to handle a function
544#
545nb_tests = 0
546
547def generate_test(module, node):
548 global test
549 global nb_tests
550 nb_cond = 0
551 no_gen = 0
552
553 name = node.xpathEval('string(@name)')
554 if is_skipped_function(name):
555 return
556
557 test.write("""
558static int
559test_%s(void) {
560 int ret = 0;
561
562""" % (name))
563
564 #
565 # check we know how to handle the args and return values
566 # and store the informations for the generation
567 #
568 try:
569 args = node.xpathEval("arg")
570 except:
571 args = []
572 t_args = []
Daniel Veillarda03e3652004-11-02 18:45:30 +0000573 n = 0
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000574 for arg in args:
Daniel Veillarda03e3652004-11-02 18:45:30 +0000575 n = n + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000576 rtype = arg.xpathEval("string(@type)")
577 if rtype == 'void':
578 break;
579 info = arg.xpathEval("string(@info)")
580 nam = arg.xpathEval("string(@name)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000581 type = type_convert(rtype, nam, info, module, name, n)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000582 if is_known_param_type(type) == 0:
583 add_missing_type(type, name);
584 no_gen = 1
585 t_args.append((nam, type, rtype, info))
586
587 try:
588 rets = node.xpathEval("return")
589 except:
590 rets = []
591 t_ret = None
592 for ret in rets:
593 rtype = ret.xpathEval("string(@type)")
594 info = ret.xpathEval("string(@info)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000595 type = type_convert(rtype, 'return', info, module, name, 0)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000596 if rtype == 'void':
597 break
598 if is_known_return_type(type) == 0:
599 add_missing_type(type, name);
600 no_gen = 1
601 t_ret = (type, rtype, info)
602 break
603
604 if no_gen == 1:
605 test.write("""
606 /* missing type support */
607 return(ret);
608}
609
610""")
611 return
612
613 try:
614 conds = node.xpathEval("cond")
615 for cond in conds:
616 test.write("#ifdef %s\n" % (cond.get_content()))
617 nb_cond = nb_cond + 1
618 except:
619 pass
620
621 # Declare the memory usage counter
622 no_mem = is_skipped_memcheck(name)
623 if no_mem == 0:
624 test.write(" int mem_base;\n");
625
626 # Declare the return value
627 if t_ret != None:
628 test.write(" %s ret_val;\n" % (t_ret[1]))
629
630 # Declare the arguments
631 for arg in t_args:
632 (nam, type, rtype, info) = arg;
633 # add declaration
634 test.write(" %s %s; /* %s */\n" % (rtype, nam, info))
635 test.write(" int n_%s;\n" % (nam))
636 test.write("\n")
637
638 # Cascade loop on of each argument list of values
639 for arg in t_args:
640 (nam, type, rtype, info) = arg;
641 #
642 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
643 nam, nam, type, nam))
644
645 # log the memory usage
646 if no_mem == 0:
647 test.write(" mem_base = xmlMemBlocks();\n");
648
649 # prepare the call
650 for arg in t_args:
651 (nam, type, rtype, info) = arg;
652 #
653 test.write(" %s = gen_%s(n_%s);\n" % (nam, type, nam))
654
655 # do the call, and clanup the result
656 if t_ret != None:
657 test.write("\n ret_val = %s(" % (name))
658 need = 0
659 for arg in t_args:
660 (nam, type, rtype, info) = arg
661 if need:
662 test.write(", ")
663 else:
664 need = 1
665 test.write("%s" % nam);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000666 test.write(");\n")
667 if extra_post_call.has_key(name):
668 test.write(" %s\n"% (extra_post_call[name]))
669 test.write(" desret_%s(ret_val);\n" % t_ret[0])
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000670 else:
671 test.write("\n %s(" % (name));
672 need = 0;
673 for arg in t_args:
674 (nam, type, rtype, info) = arg;
675 if need:
676 test.write(", ")
677 else:
678 need = 1
679 test.write("%s" % nam)
680 test.write(");\n")
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000681 if extra_post_call.has_key(name):
682 test.write(" %s\n"% (extra_post_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000683
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000684 test.write(" call_tests++;\n");
Daniel Veillarda03e3652004-11-02 18:45:30 +0000685
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000686 # Free the arguments
687 for arg in t_args:
688 (nam, type, rtype, info) = arg;
689 #
690 test.write(" des_%s(n_%s, %s);\n" % (type, nam, nam))
691
692 test.write(" xmlResetLastError();\n");
693 # Check the memory usage
694 if no_mem == 0:
695 test.write(""" if (mem_base != xmlMemBlocks()) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000696 printf("Leak of %%d blocks found in %s",
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000697 xmlMemBlocks() - mem_base);
698 ret++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000699""" % (name));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000700 for arg in t_args:
701 (nam, type, rtype, info) = arg;
702 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
703 test.write(""" printf("\\n");\n""")
704 test.write(" }\n")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000705
706 for arg in t_args:
707 test.write(" }\n")
708
709 #
710 # end of conditional
711 #
712 while nb_cond > 0:
713 test.write("#endif\n")
714 nb_cond = nb_cond -1
715
716 nb_tests = nb_tests + 1;
717
718 test.write("""
719 return(ret);
720}
721
722""")
723
724#
725# Generate all module callers
726#
727for module in modules:
728 # gather all the functions exported by that module
729 try:
730 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
731 except:
732 print "Failed to gather functions from module %s" % (module)
733 continue;
734
735 # iterate over all functions in the module generating the test
736 for function in functions:
737 generate_test(module, function);
738
739 # header
740 test.write("""static int
741test_%s(void) {
742 int ret = 0;
743
744 printf("Testing %s ...\\n");
745""" % (module, module))
746
747 # iterate over all functions in the module generating the call
748 for function in functions:
749 name = function.xpathEval('string(@name)')
750 if is_skipped_function(name):
751 continue
752 test.write(" ret += test_%s();\n" % (name))
753
754 # footer
755 test.write("""
756 if (ret != 0)
757 printf("Module %s: %%d errors\\n", ret);
758 return(ret);
759}
760""" % (module))
761
762print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000763nr1 = 0
764miss1 = 'none'
765nr2 = 0
766miss2 = 'none'
767nr3 = 0
768miss3 = 'none'
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000769for missing in missing_types.keys():
770 n = len(missing_types[missing])
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000771 if n > nr1:
772 miss3 = miss2
773 nr3 = nr2
774 miss2 = miss1
775 nr2 = nr1
776 miss1 = missing
777 nr1 = n
778 elif n > nr2:
779 miss3 = miss2
780 nr3 = nr2
781 miss2 = missing
782 nr2 = n
783 elif n > nr3:
784 miss3 = missing
785 nr3 = n
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000786
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000787if nr1 > 0:
788 print "most needed type support: %s %d times, %s %d and %s %d" % (
789 miss1, nr1, miss2, nr2, miss3, nr3)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000790
791