blob: 9446a21453472ca2d6623b32b591d992b4072990 [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 Veillardb1b3a3e2004-11-03 23:25:47 +000018 "xmlversion", "debugXML", "xmlexports", "DOCBparser",
Daniel Veillardd005b9e2004-11-03 17:07:05 +000019
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",
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +000033"xmlIORead", "xmlReadIO", "xmlCtxtReadIO",
34"htmlIORead", "htmlReadIO", "htmlCtxtReadIO",
35"xmlReaderNewIO",
Daniel Veillarddd6d3002004-11-03 14:20:29 +000036# library state cleanup, generate false leak informations and other
37# troubles, heavillyb tested otherwise.
38"xmlCleanupParser", "xmlRelaxNGCleanupTypes",
39# hard to avoid leaks in the tests
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +000040"xmlStrcat", "xmlStrncat", "xmlCatalogAddLocal",
Daniel Veillarddd6d3002004-11-03 14:20:29 +000041# unimplemented
42"xmlTextReaderReadInnerXml", "xmlTextReaderReadOuterXml",
Daniel Veillardd005b9e2004-11-03 17:07:05 +000043"xmlTextReaderReadString",
44# destructor
45"xmlListDelete",
46# deprecated
47"xmlCatalogGetPublic", "xmlCatalogGetSystem", "xmlEncodeEntities",
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +000048# allocators
49"xmlMemFree",
Daniel Veillarddd6d3002004-11-03 14:20:29 +000050]
Daniel Veillard36e5cd52004-11-02 14:52:23 +000051
52#
53# Those functions have side effect on the global state
54# and hence generate errors on memory allocation tests
55#
56skipped_memcheck = [ "xmlLoadCatalog", "xmlAddEncodingAlias",
57 "xmlSchemaInitTypes", "xmlNanoFTPProxy", "xmlNanoFTPScanProxy",
58 "xmlNanoHTTPScanProxy", "xmlResetLastError", "xmlCatalogConvert",
59 "xmlCatalogRemove", "xmlLoadCatalogs", "xmlCleanupCharEncodingHandlers",
Daniel Veillarda03e3652004-11-02 18:45:30 +000060 "xmlInitCharEncodingHandlers", "xmlCatalogCleanup",
61 "htmlParseFile" # loads the catalogs
62]
63
64#
65# Extra code needed for some test cases
66#
67extra_post_call = {
68 "xmlAddChild":
69 "if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; }",
70 "xmlAddChildList":
71 "if (ret_val == NULL) { xmlFreeNodeList(cur) ; cur = NULL ; }",
72 "xmlAddSibling":
73 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
74 "xmlAddNextSibling":
75 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
76 "xmlAddPrevSibling":
77 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
78 "xmlDocSetRootElement":
79 "if (doc == NULL) { xmlFreeNode(root) ; root = NULL ; }",
80 "xmlReplaceNode":
81 """if ((old == NULL) || (old->parent == NULL)) {
82 xmlFreeNode(cur) ; cur = NULL ; }""",
83 "xmlTextMerge":
84 """if ((first != NULL) && (first->type != XML_TEXT_NODE)) {
85 xmlFreeNode(second) ; second = NULL ; }""",
Daniel Veillard8a32fe42004-11-02 22:10:16 +000086 "xmlBuildQName":
87 """if ((ret_val != NULL) && (ret_val != ncname) &&
88 (ret_val != prefix) && (ret_val != memory))
89 xmlFree(ret_val);
90 ret_val = NULL;""",
Daniel Veillarda03e3652004-11-02 18:45:30 +000091}
Daniel Veillard36e5cd52004-11-02 14:52:23 +000092
93modules = []
94
95def is_skipped_module(name):
96 for mod in skipped_modules:
97 if mod == name:
98 return 1
99 return 0
100
101def is_skipped_function(name):
102 for fun in skipped_functions:
103 if fun == name:
104 return 1
105 # Do not test destructors
106 if string.find(name, 'Free') != -1:
107 return 1
108 return 0
109
110def is_skipped_memcheck(name):
111 for fun in skipped_memcheck:
112 if fun == name:
113 return 1
114 return 0
115
116missing_types = {}
117def add_missing_type(name, func):
118 try:
119 list = missing_types[name]
120 list.append(func)
121 except:
122 missing_types[name] = [func]
123
124#
125# Open the input API description and the C test program result
126#
127doc = libxml2.readFile('doc/libxml2-api.xml', None, 0)
128if doc == None:
129 print "Failed to load doc/libxml2-api.xml"
130 sys.exit(1)
131test = open('testapi.c', 'w')
132ctxt = doc.xpathNewContext()
133headers = ctxt.xpathEval("/api/files/file")
134
135#
136# Generate the test header
137#
138test.write("""/*
139 * testapi.c: libxml2 API tester program.
140 *
141 * Automatically generated by gentest.py from libxml2-api.xml
142 *
143 * See Copyright for the status of this software.
144 *
145 * daniel@veillard.com
146 */
147
148#include <stdio.h>
149#include <libxml/xmlerror.h>
150
151static int testlibxml2(void);
152
153static int generic_errors = 0;
154static int call_tests = 0;
155
Daniel Veillard348636d2004-11-02 22:34:52 +0000156static xmlChar chartab[1024] = " chartab\\n";
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000157
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000158static void
159structured_errors(void *userData ATTRIBUTE_UNUSED,
160 xmlErrorPtr error ATTRIBUTE_UNUSED) {
161 generic_errors++;
162}
163
164int main(void) {
165 int ret;
166 int blocks, mem;
167
Daniel Veillarda03e3652004-11-02 18:45:30 +0000168 xmlInitParser();
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000169 xmlRelaxNGInitTypes();
Daniel Veillarda03e3652004-11-02 18:45:30 +0000170
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000171 LIBXML_TEST_VERSION
172
173 xmlSetStructuredErrorFunc(NULL, structured_errors);
174
175 ret = testlibxml2();
176
177 xmlCleanupParser();
178 blocks = xmlMemBlocks();
179 mem = xmlMemUsed();
180 if ((blocks != 0) || (mem != 0)) {
181 printf("testapi leaked %d bytes in %d blocks\\n", mem, blocks);
182 }
183 xmlMemoryDump();
184
185 return (ret != 0);
186}
187
188""");
189
190#
191# Load the interfaces
192#
193for file in headers:
194 name = file.xpathEval('string(@name)')
195 if (name == None) or (name == ''):
196 continue
197
198 #
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000199 # Some module may be skipped because they don't really consists
200 # of user callable APIs
201 #
202 if is_skipped_module(name):
203 continue
204
205 #
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000206 # do not test deprecated APIs
207 #
208 desc = file.xpathEval('string(description)')
209 if string.find(desc, 'DEPRECATED') != -1:
210 print "Skipping deprecated interface %s" % name
211 continue;
212
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000213 test.write("#include <libxml/%s.h>\n" % name)
214 modules.append(name)
215
216#
217# Generate the callers signatures
218#
219for module in modules:
220 test.write("static int test_%s(void);\n" % module);
221
222#
223# Provide the type generators and destructors for the parameters
224#
225
Daniel Veillarda03e3652004-11-02 18:45:30 +0000226def type_convert(str, name, info, module, function, pos):
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000227 res = string.replace(str, " *", "_ptr")
228 res = string.replace(res, " ", "_")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000229 res = string.replace(res, "htmlNode", "xmlNode")
230 res = string.replace(res, "htmlDoc", "xmlDoc")
231 res = string.replace(res, "htmlParser", "xmlParser")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000232 if res == 'const_char_ptr':
233 if string.find(name, "file") != -1 or \
234 string.find(name, "uri") != -1 or \
235 string.find(name, "URI") != -1 or \
236 string.find(info, "filename") != -1 or \
237 string.find(info, "URI") != -1 or \
238 string.find(info, "URL") != -1:
239 if string.find(function, "Save") != -1:
240 return('fileoutput')
241 return('filepath')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000242 if function == 'xmlIOHTTPOpenW':
243 print function, name, res, pos
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000244 if res == 'void_ptr':
245 if module == 'nanoftp' and name == 'ctx':
246 return('xmlNanoFTPCtxtPtr')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000247 if function == 'xmlNanoFTPNewCtxt':
248 return('xmlNanoFTPCtxtPtr')
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000249 if module == 'nanohttp' and name == 'ctx':
250 return('xmlNanoHTTPCtxtPtr')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000251 if function == 'xmlIOHTTPOpenW':
252 return('xmlNanoHTTPCtxtPtr')
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000253 if string.find(name, "data") != -1:
254 return('userdata');
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000255 if string.find(name, "user") != -1:
256 return('userdata');
Daniel Veillarda03e3652004-11-02 18:45:30 +0000257 if res == 'xmlNodePtr' and pos != 0:
258 if (function == 'xmlAddChild' and pos == 2) or \
259 (function == 'xmlAddChildList' and pos == 2) or \
260 (function == 'xmlAddNextSibling' and pos == 2) or \
261 (function == 'xmlAddSibling' and pos == 2) or \
262 (function == 'xmlDocSetRootElement' and pos == 2) or \
263 (function == 'xmlReplaceNode' and pos == 2) or \
264 (function == 'xmlTextMerge') or \
265 (function == 'xmlAddPrevSibling' and pos == 2):
266 return('xmlNodePtr_in');
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000267
268 return res
269
270known_param_types = [ "int", "const_char_ptr", "const_xmlChar_ptr",
Daniel Veillarde43cc572004-11-03 11:50:29 +0000271 "xmlParserCtxtPtr", "xmlDocPtr", "filepath", "fileoutput",
272 "xmlNodePtr", "xmlNodePtr_in", "userdata", "xmlChar_ptr",
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000273 "xmlTextWriterPtr", "xmlTextReaderPtr", "xmlBufferPtr",
Daniel Veillardc0be74b2004-11-03 19:16:55 +0000274 "xmlListPtr", "xmlXPathObjectPtr", "xmlHashTablePtr", "xmlValidCtxtPtr",
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000275 "void_ptr",
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000276]
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000277
278def is_known_param_type(name):
279 for type in known_param_types:
280 if type == name:
281 return 1
282 return 0
283
284test.write("""
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000285#define gen_nb_void_ptr 1
286
287static void *gen_void_ptr(int no ATTRIBUTE_UNUSED) {
288 return(NULL);
289}
290static void des_void_ptr(int no ATTRIBUTE_UNUSED, void *val ATTRIBUTE_UNUSED) {
291}
292
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000293#define gen_nb_userdata 3
294
295static void *gen_userdata(int no) {
296 if (no == 0) return((void *) &call_tests);
297 if (no == 1) return((void *) -1);
298 return(NULL);
299}
300static void des_userdata(int no ATTRIBUTE_UNUSED, void *val ATTRIBUTE_UNUSED) {
301}
302
303
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000304#define gen_nb_int 4
305
306static int gen_int(int no) {
307 if (no == 0) return(0);
308 if (no == 1) return(1);
309 if (no == 2) return(122);
310 return(-1);
311}
312
313static void des_int(int no ATTRIBUTE_UNUSED, int val ATTRIBUTE_UNUSED) {
314}
315
316#define gen_nb_const_char_ptr 4
317
318static const char *gen_const_char_ptr(int no) {
319 if (no == 0) return("foo");
320 if (no == 1) return("<foo/>");
321 if (no == 2) return("test/ent2");
322 return(NULL);
323}
324static void des_const_char_ptr(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED) {
325}
326
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000327#define gen_nb_xmlChar_ptr 2
328
329static xmlChar *gen_xmlChar_ptr(int no) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000330 if (no == 0) return(&chartab[0]);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000331 return(NULL);
332}
333static void des_xmlChar_ptr(int no ATTRIBUTE_UNUSED, xmlChar *val ATTRIBUTE_UNUSED) {
334}
335
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000336#define gen_nb_const_xmlChar_ptr 5
337
338static const xmlChar *gen_const_xmlChar_ptr(int no) {
339 if (no == 0) return((const xmlChar *) "foo");
340 if (no == 1) return((const xmlChar *) "<foo/>");
341 if (no == 2) return((const xmlChar *) "nøne");
342 if (no == 3) return((const xmlChar *) " 2ab ");
343 return(NULL);
344}
345static void des_const_xmlChar_ptr(int no ATTRIBUTE_UNUSED, const xmlChar *val ATTRIBUTE_UNUSED) {
346}
347
348#define gen_nb_filepath 8
349
350static const char *gen_filepath(int no) {
351 if (no == 0) return("missing.xml");
352 if (no == 1) return("<foo/>");
353 if (no == 2) return("test/ent2");
354 if (no == 3) return("test/valid/REC-xml-19980210.xml");
355 if (no == 4) return("test/valid/xhtml1-strict.dtd");
356 if (no == 5) return("http://missing.example.org/");
357 if (no == 6) return("http://missing. example.org/");
358 return(NULL);
359}
360static void des_filepath(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED) {
361}
362
363#define gen_nb_fileoutput 6
364
365static const char *gen_fileoutput(int no) {
366 if (no == 0) return("/missing.xml");
367 if (no == 1) return("<foo/>");
368 if (no == 2) return("ftp://missing.example.org/foo");
369 if (no == 3) return("http://missing.example.org/");
370 if (no == 4) return("http://missing. example.org/");
371 return(NULL);
372}
373static void des_fileoutput(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED) {
374}
375
376#define gen_nb_xmlParserCtxtPtr 2
377static xmlParserCtxtPtr gen_xmlParserCtxtPtr(int no) {
378 if (no == 0) return(xmlNewParserCtxt());
379 return(NULL);
380}
381static void des_xmlParserCtxtPtr(int no ATTRIBUTE_UNUSED, xmlParserCtxtPtr val) {
382 if (val != NULL)
383 xmlFreeParserCtxt(val);
384}
385
Daniel Veillardc0be74b2004-11-03 19:16:55 +0000386#define gen_nb_xmlValidCtxtPtr 2
387static xmlValidCtxtPtr gen_xmlValidCtxtPtr(int no) {
388 if (no == 0) return(xmlNewValidCtxt());
389 return(NULL);
390}
391static void des_xmlValidCtxtPtr(int no ATTRIBUTE_UNUSED, xmlValidCtxtPtr val) {
392 if (val != NULL)
393 xmlFreeValidCtxt(val);
394}
395
Daniel Veillarda03e3652004-11-02 18:45:30 +0000396#define gen_nb_xmlDocPtr 3
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000397static xmlDocPtr gen_xmlDocPtr(int no) {
398 if (no == 0) return(xmlNewDoc(BAD_CAST "1.0"));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000399 if (no == 1) return(xmlReadMemory("<foo/>", 6, "test", NULL, 0));
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000400 return(NULL);
401}
402static void des_xmlDocPtr(int no ATTRIBUTE_UNUSED, xmlDocPtr val) {
403 if (val != NULL)
404 xmlFreeDoc(val);
405}
406
Daniel Veillarda03e3652004-11-02 18:45:30 +0000407#define gen_nb_xmlNodePtr 2
408static xmlNodePtr gen_xmlNodePtr(int no) {
409 if (no == 0) return(xmlNewPI(BAD_CAST "test", NULL));
410 return(NULL);
411}
412static void des_xmlNodePtr(int no ATTRIBUTE_UNUSED, xmlNodePtr val) {
413 if (val != NULL) {
414 xmlUnlinkNode(val);
415 xmlFreeNode(val);
416 }
417}
418
419#define gen_nb_xmlNodePtr_in 3
420static xmlNodePtr gen_xmlNodePtr_in(int no) {
421 if (no == 0) return(xmlNewPI(BAD_CAST "test", NULL));
422 if (no == 0) return(xmlNewText(BAD_CAST "text"));
423 return(NULL);
424}
425static void des_xmlNodePtr_in(int no ATTRIBUTE_UNUSED, xmlNodePtr val ATTRIBUTE_UNUSED) {
426}
427
Daniel Veillarde43cc572004-11-03 11:50:29 +0000428#define gen_nb_xmlTextWriterPtr 2
429static xmlTextWriterPtr gen_xmlTextWriterPtr(int no) {
430 if (no == 0) return(xmlNewTextWriterFilename("test.out", 0));
431 return(NULL);
432}
433static void des_xmlTextWriterPtr(int no ATTRIBUTE_UNUSED, xmlTextWriterPtr val) {
434 if (val != NULL) xmlFreeTextWriter(val);
435}
436
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000437#define gen_nb_xmlTextReaderPtr 4
438static xmlTextReaderPtr gen_xmlTextReaderPtr(int no) {
439 if (no == 0) return(xmlNewTextReaderFilename("test/ent2"));
440 if (no == 1) return(xmlNewTextReaderFilename("test/valid/REC-xml-19980210.xml"));
441 if (no == 2) return(xmlNewTextReaderFilename("test/valid/dtds/xhtml1-strict.dtd"));
442 return(NULL);
443}
444static void des_xmlTextReaderPtr(int no ATTRIBUTE_UNUSED, xmlTextReaderPtr val) {
445 if (val != NULL) xmlFreeTextReader(val);
446}
447
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000448#define gen_nb_xmlBufferPtr 2
449static xmlBufferPtr gen_xmlBufferPtr(int no) {
450 if (no == 0) return(xmlBufferCreate());
451 return(NULL);
452}
453static void des_xmlBufferPtr(int no ATTRIBUTE_UNUSED, xmlBufferPtr val) {
454 if (val != NULL) {
455 xmlBufferFree(val);
456 }
457}
458
459#define gen_nb_xmlListPtr 2
460static xmlListPtr gen_xmlListPtr(int no) {
461 if (no == 0) return(xmlListCreate(NULL, NULL));
462 return(NULL);
463}
464static void des_xmlListPtr(int no ATTRIBUTE_UNUSED, xmlListPtr val) {
465 if (val != NULL) {
466 xmlListDelete(val);
467 }
468}
469
470#define gen_nb_xmlHashTablePtr 2
471static xmlHashTablePtr gen_xmlHashTablePtr(int no) {
472 if (no == 0) return(xmlHashCreate(10));
473 return(NULL);
474}
475static void des_xmlHashTablePtr(int no ATTRIBUTE_UNUSED, xmlHashTablePtr val) {
476 if (val != NULL) {
477 xmlHashFree(val, NULL);
478 }
479}
480
481#include <libxml/xpathInternals.h>
482
483#define gen_nb_xmlXPathObjectPtr 5
484static xmlXPathObjectPtr gen_xmlXPathObjectPtr(int no) {
485 if (no == 0) return(xmlXPathNewString(BAD_CAST "string object"));
486 if (no == 1) return(xmlXPathNewFloat(1.1));
487 if (no == 2) return(xmlXPathNewBoolean(1));
488 if (no == 3) return(xmlXPathNewNodeSet(NULL));
489 return(NULL);
490}
491static void des_xmlXPathObjectPtr(int no ATTRIBUTE_UNUSED, xmlXPathObjectPtr val) {
492 if (val != NULL) {
493 xmlXPathFreeObject(val);
494 }
495}
496
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000497""");
498
499#
500# Provide the type destructors for the return values
501#
502
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000503known_return_types = [ "int", "const_char_ptr", "xmlDocPtr", "xmlNodePtr",
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000504 "xmlChar_ptr", "const_xmlChar_ptr", "void_ptr" ];
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000505
506def is_known_return_type(name):
507 for type in known_return_types:
508 if type == name:
509 return 1
510 return 0
511
512test.write("""
513static void desret_int(int val ATTRIBUTE_UNUSED) {
514}
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000515static void desret_void_ptr(void *val ATTRIBUTE_UNUSED) {
516}
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000517static void desret_const_char_ptr(const char *val ATTRIBUTE_UNUSED) {
518}
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000519static void desret_const_xmlChar_ptr(const xmlChar *val ATTRIBUTE_UNUSED) {
520}
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000521static void desret_xmlChar_ptr(xmlChar *val) {
522 if (val != NULL)
523 xmlFree(val);
524}
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000525static void desret_xmlDocPtr(xmlDocPtr val) {
526 xmlFreeDoc(val);
527}
528static void desret_xmlNodePtr(xmlNodePtr val) {
529 xmlUnlinkNode(val);
530 xmlFreeNode(val);
531}
532""");
533
534#
535# Generate the top caller
536#
537
538test.write("""
539/**
540 * testlibxml2:
541 *
542 * Main entry point of the tester for the full libxml2 module,
543 * it calls all the tester entry point for each module.
544 *
545 * Returns the number of error found
546 */
547static int
548testlibxml2(void)
549{
550 int ret = 0;
551
552""")
553
554for module in modules:
555 test.write(" ret += test_%s();\n" % module)
556
557test.write("""
558 printf("Total: %d tests, %d errors\\n", call_tests, ret);
559 return(ret);
560}
561
562""")
563
564#
565# How to handle a function
566#
567nb_tests = 0
568
569def generate_test(module, node):
570 global test
571 global nb_tests
572 nb_cond = 0
573 no_gen = 0
574
575 name = node.xpathEval('string(@name)')
576 if is_skipped_function(name):
577 return
578
579 test.write("""
580static int
581test_%s(void) {
582 int ret = 0;
583
584""" % (name))
585
586 #
587 # check we know how to handle the args and return values
588 # and store the informations for the generation
589 #
590 try:
591 args = node.xpathEval("arg")
592 except:
593 args = []
594 t_args = []
Daniel Veillarda03e3652004-11-02 18:45:30 +0000595 n = 0
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000596 for arg in args:
Daniel Veillarda03e3652004-11-02 18:45:30 +0000597 n = n + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000598 rtype = arg.xpathEval("string(@type)")
599 if rtype == 'void':
600 break;
601 info = arg.xpathEval("string(@info)")
602 nam = arg.xpathEval("string(@name)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000603 type = type_convert(rtype, nam, info, module, name, n)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000604 if is_known_param_type(type) == 0:
605 add_missing_type(type, name);
606 no_gen = 1
607 t_args.append((nam, type, rtype, info))
608
609 try:
610 rets = node.xpathEval("return")
611 except:
612 rets = []
613 t_ret = None
614 for ret in rets:
615 rtype = ret.xpathEval("string(@type)")
616 info = ret.xpathEval("string(@info)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000617 type = type_convert(rtype, 'return', info, module, name, 0)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000618 if rtype == 'void':
619 break
620 if is_known_return_type(type) == 0:
621 add_missing_type(type, name);
622 no_gen = 1
623 t_ret = (type, rtype, info)
624 break
625
626 if no_gen == 1:
627 test.write("""
628 /* missing type support */
629 return(ret);
630}
631
632""")
633 return
634
635 try:
636 conds = node.xpathEval("cond")
637 for cond in conds:
638 test.write("#ifdef %s\n" % (cond.get_content()))
639 nb_cond = nb_cond + 1
640 except:
641 pass
642
643 # Declare the memory usage counter
644 no_mem = is_skipped_memcheck(name)
645 if no_mem == 0:
646 test.write(" int mem_base;\n");
647
648 # Declare the return value
649 if t_ret != None:
650 test.write(" %s ret_val;\n" % (t_ret[1]))
651
652 # Declare the arguments
653 for arg in t_args:
654 (nam, type, rtype, info) = arg;
655 # add declaration
656 test.write(" %s %s; /* %s */\n" % (rtype, nam, info))
657 test.write(" int n_%s;\n" % (nam))
658 test.write("\n")
659
660 # Cascade loop on of each argument list of values
661 for arg in t_args:
662 (nam, type, rtype, info) = arg;
663 #
664 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
665 nam, nam, type, nam))
666
667 # log the memory usage
668 if no_mem == 0:
669 test.write(" mem_base = xmlMemBlocks();\n");
670
671 # prepare the call
672 for arg in t_args:
673 (nam, type, rtype, info) = arg;
674 #
675 test.write(" %s = gen_%s(n_%s);\n" % (nam, type, nam))
676
677 # do the call, and clanup the result
678 if t_ret != None:
679 test.write("\n ret_val = %s(" % (name))
680 need = 0
681 for arg in t_args:
682 (nam, type, rtype, info) = arg
683 if need:
684 test.write(", ")
685 else:
686 need = 1
687 test.write("%s" % nam);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000688 test.write(");\n")
689 if extra_post_call.has_key(name):
690 test.write(" %s\n"% (extra_post_call[name]))
691 test.write(" desret_%s(ret_val);\n" % t_ret[0])
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000692 else:
693 test.write("\n %s(" % (name));
694 need = 0;
695 for arg in t_args:
696 (nam, type, rtype, info) = arg;
697 if need:
698 test.write(", ")
699 else:
700 need = 1
701 test.write("%s" % nam)
702 test.write(");\n")
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000703 if extra_post_call.has_key(name):
704 test.write(" %s\n"% (extra_post_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000705
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000706 test.write(" call_tests++;\n");
Daniel Veillarda03e3652004-11-02 18:45:30 +0000707
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000708 # Free the arguments
709 for arg in t_args:
710 (nam, type, rtype, info) = arg;
711 #
712 test.write(" des_%s(n_%s, %s);\n" % (type, nam, nam))
713
714 test.write(" xmlResetLastError();\n");
715 # Check the memory usage
716 if no_mem == 0:
717 test.write(""" if (mem_base != xmlMemBlocks()) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000718 printf("Leak of %%d blocks found in %s",
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000719 xmlMemBlocks() - mem_base);
720 ret++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000721""" % (name));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000722 for arg in t_args:
723 (nam, type, rtype, info) = arg;
724 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
725 test.write(""" printf("\\n");\n""")
726 test.write(" }\n")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000727
728 for arg in t_args:
729 test.write(" }\n")
730
731 #
732 # end of conditional
733 #
734 while nb_cond > 0:
735 test.write("#endif\n")
736 nb_cond = nb_cond -1
737
738 nb_tests = nb_tests + 1;
739
740 test.write("""
741 return(ret);
742}
743
744""")
745
746#
747# Generate all module callers
748#
749for module in modules:
750 # gather all the functions exported by that module
751 try:
752 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
753 except:
754 print "Failed to gather functions from module %s" % (module)
755 continue;
756
757 # iterate over all functions in the module generating the test
758 for function in functions:
759 generate_test(module, function);
760
761 # header
762 test.write("""static int
763test_%s(void) {
764 int ret = 0;
765
766 printf("Testing %s ...\\n");
767""" % (module, module))
768
769 # iterate over all functions in the module generating the call
770 for function in functions:
771 name = function.xpathEval('string(@name)')
772 if is_skipped_function(name):
773 continue
774 test.write(" ret += test_%s();\n" % (name))
775
776 # footer
777 test.write("""
778 if (ret != 0)
779 printf("Module %s: %%d errors\\n", ret);
780 return(ret);
781}
782""" % (module))
783
784print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000785nr1 = 0
786miss1 = 'none'
787nr2 = 0
788miss2 = 'none'
789nr3 = 0
790miss3 = 'none'
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000791for missing in missing_types.keys():
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000792 if missing == 'xmlAttrPtr' or missing == 'xmlNsPtr' or missing == '...':
793 continue;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000794 n = len(missing_types[missing])
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000795 if n > nr1:
796 miss3 = miss2
797 nr3 = nr2
798 miss2 = miss1
799 nr2 = nr1
800 miss1 = missing
801 nr1 = n
802 elif n > nr2:
803 miss3 = miss2
804 nr3 = nr2
805 miss2 = missing
806 nr2 = n
807 elif n > nr3:
808 miss3 = missing
809 nr3 = n
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000810
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000811if nr1 > 0:
812 print "most needed type support: %s %d times, %s %d and %s %d" % (
813 miss1, nr1, miss2, nr2, miss3, nr3)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000814
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000815print missing_types[miss1]
816
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000817