blob: d02a17b46c42d6ec4032fd8872cc43cf9ee88775 [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
Daniel Veillard3d97e662004-11-04 10:49:00 +000021 "xmlautomata", "xmlregexp", "c14n",
Daniel Veillardd005b9e2004-11-03 17:07:05 +000022
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
Daniel Veillard3d97e662004-11-04 10:49:00 +000045"xmlListDelete", "xmlOutputBufferClose",
Daniel Veillardd005b9e2004-11-03 17:07:05 +000046# 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 Veillard3d97e662004-11-04 10:49:00 +000091 # Functions which deallocates one of their parameters
92 "xmlXPathConvertBoolean": """val = NULL;""",
93 "xmlXPathConvertNumber": """val = NULL;""",
94 "xmlXPathConvertString": """val = NULL;""",
95 "xmlSaveFileTo": """buf = NULL;""",
96 "xmlSaveFormatFileTo": """buf = NULL;"""
Daniel Veillarda03e3652004-11-02 18:45:30 +000097}
Daniel Veillard36e5cd52004-11-02 14:52:23 +000098
99modules = []
100
101def is_skipped_module(name):
102 for mod in skipped_modules:
103 if mod == name:
104 return 1
105 return 0
106
107def is_skipped_function(name):
108 for fun in skipped_functions:
109 if fun == name:
110 return 1
111 # Do not test destructors
112 if string.find(name, 'Free') != -1:
113 return 1
114 return 0
115
116def is_skipped_memcheck(name):
117 for fun in skipped_memcheck:
118 if fun == name:
119 return 1
120 return 0
121
122missing_types = {}
123def add_missing_type(name, func):
124 try:
125 list = missing_types[name]
126 list.append(func)
127 except:
128 missing_types[name] = [func]
129
130#
131# Open the input API description and the C test program result
132#
133doc = libxml2.readFile('doc/libxml2-api.xml', None, 0)
134if doc == None:
135 print "Failed to load doc/libxml2-api.xml"
136 sys.exit(1)
137test = open('testapi.c', 'w')
138ctxt = doc.xpathNewContext()
139headers = ctxt.xpathEval("/api/files/file")
140
141#
142# Generate the test header
143#
144test.write("""/*
145 * testapi.c: libxml2 API tester program.
146 *
147 * Automatically generated by gentest.py from libxml2-api.xml
148 *
149 * See Copyright for the status of this software.
150 *
151 * daniel@veillard.com
152 */
153
154#include <stdio.h>
155#include <libxml/xmlerror.h>
Daniel Veillard3d97e662004-11-04 10:49:00 +0000156#include <libxml/relaxng.h>
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000157
158static int testlibxml2(void);
159
160static int generic_errors = 0;
161static int call_tests = 0;
Daniel Veillard3d97e662004-11-04 10:49:00 +0000162static int function_tests = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000163
Daniel Veillard348636d2004-11-02 22:34:52 +0000164static xmlChar chartab[1024] = " chartab\\n";
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000165
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000166static void
167structured_errors(void *userData ATTRIBUTE_UNUSED,
168 xmlErrorPtr error ATTRIBUTE_UNUSED) {
169 generic_errors++;
170}
171
172int main(void) {
173 int ret;
174 int blocks, mem;
175
Daniel Veillarda03e3652004-11-02 18:45:30 +0000176 xmlInitParser();
Daniel Veillard3d97e662004-11-04 10:49:00 +0000177#ifdef LIBXML_SCHEMAS_ENABLED
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000178 xmlRelaxNGInitTypes();
Daniel Veillard3d97e662004-11-04 10:49:00 +0000179#endif
Daniel Veillarda03e3652004-11-02 18:45:30 +0000180
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000181 LIBXML_TEST_VERSION
182
183 xmlSetStructuredErrorFunc(NULL, structured_errors);
184
185 ret = testlibxml2();
186
187 xmlCleanupParser();
188 blocks = xmlMemBlocks();
189 mem = xmlMemUsed();
190 if ((blocks != 0) || (mem != 0)) {
191 printf("testapi leaked %d bytes in %d blocks\\n", mem, blocks);
192 }
193 xmlMemoryDump();
194
195 return (ret != 0);
196}
197
198""");
199
200#
201# Load the interfaces
202#
203for file in headers:
204 name = file.xpathEval('string(@name)')
205 if (name == None) or (name == ''):
206 continue
207
208 #
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000209 # Some module may be skipped because they don't really consists
210 # of user callable APIs
211 #
212 if is_skipped_module(name):
213 continue
214
215 #
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000216 # do not test deprecated APIs
217 #
218 desc = file.xpathEval('string(description)')
219 if string.find(desc, 'DEPRECATED') != -1:
220 print "Skipping deprecated interface %s" % name
221 continue;
222
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000223 test.write("#include <libxml/%s.h>\n" % name)
224 modules.append(name)
225
226#
227# Generate the callers signatures
228#
229for module in modules:
230 test.write("static int test_%s(void);\n" % module);
231
232#
233# Provide the type generators and destructors for the parameters
234#
235
Daniel Veillarda03e3652004-11-02 18:45:30 +0000236def type_convert(str, name, info, module, function, pos):
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000237 res = string.replace(str, " *", "_ptr")
238 res = string.replace(res, " ", "_")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000239 res = string.replace(res, "htmlNode", "xmlNode")
240 res = string.replace(res, "htmlDoc", "xmlDoc")
241 res = string.replace(res, "htmlParser", "xmlParser")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000242 if res == 'const_char_ptr':
243 if string.find(name, "file") != -1 or \
244 string.find(name, "uri") != -1 or \
245 string.find(name, "URI") != -1 or \
246 string.find(info, "filename") != -1 or \
247 string.find(info, "URI") != -1 or \
248 string.find(info, "URL") != -1:
249 if string.find(function, "Save") != -1:
250 return('fileoutput')
251 return('filepath')
252 if res == 'void_ptr':
253 if module == 'nanoftp' and name == 'ctx':
254 return('xmlNanoFTPCtxtPtr')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000255 if function == 'xmlNanoFTPNewCtxt':
256 return('xmlNanoFTPCtxtPtr')
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000257 if module == 'nanohttp' and name == 'ctx':
258 return('xmlNanoHTTPCtxtPtr')
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000259 if function == 'xmlIOHTTPOpenW':
260 return('xmlNanoHTTPCtxtPtr')
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000261 if string.find(name, "data") != -1:
262 return('userdata');
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000263 if string.find(name, "user") != -1:
264 return('userdata');
Daniel Veillard3d97e662004-11-04 10:49:00 +0000265 if res == 'xmlDoc_ptr':
266 res = 'xmlDocPtr';
267 if res == 'xmlNode_ptr':
268 res = 'xmlNodePtr';
269 if res == 'xmlDict_ptr':
270 res = 'xmlDictPtr';
Daniel Veillarda03e3652004-11-02 18:45:30 +0000271 if res == 'xmlNodePtr' and pos != 0:
272 if (function == 'xmlAddChild' and pos == 2) or \
273 (function == 'xmlAddChildList' and pos == 2) or \
274 (function == 'xmlAddNextSibling' and pos == 2) or \
275 (function == 'xmlAddSibling' and pos == 2) or \
276 (function == 'xmlDocSetRootElement' and pos == 2) or \
277 (function == 'xmlReplaceNode' and pos == 2) or \
278 (function == 'xmlTextMerge') or \
279 (function == 'xmlAddPrevSibling' and pos == 2):
280 return('xmlNodePtr_in');
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000281
282 return res
283
284known_param_types = [ "int", "const_char_ptr", "const_xmlChar_ptr",
Daniel Veillarde43cc572004-11-03 11:50:29 +0000285 "xmlParserCtxtPtr", "xmlDocPtr", "filepath", "fileoutput",
286 "xmlNodePtr", "xmlNodePtr_in", "userdata", "xmlChar_ptr",
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000287 "xmlTextWriterPtr", "xmlTextReaderPtr", "xmlBufferPtr",
Daniel Veillardc0be74b2004-11-03 19:16:55 +0000288 "xmlListPtr", "xmlXPathObjectPtr", "xmlHashTablePtr", "xmlValidCtxtPtr",
Daniel Veillard3d97e662004-11-04 10:49:00 +0000289 "void_ptr", "xmlOutputBufferPtr", "xmlCharEncoding",
290 "unsigned_int"
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000291]
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000292
293def is_known_param_type(name):
294 for type in known_param_types:
295 if type == name:
296 return 1
297 return 0
298
299test.write("""
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000300#define gen_nb_void_ptr 1
301
Daniel Veillard3d97e662004-11-04 10:49:00 +0000302static void *gen_void_ptr(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000303 return(NULL);
304}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000305static void des_void_ptr(int no ATTRIBUTE_UNUSED, void *val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000306}
307
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000308#define gen_nb_userdata 3
309
Daniel Veillard3d97e662004-11-04 10:49:00 +0000310static void *gen_userdata(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000311 if (no == 0) return((void *) &call_tests);
312 if (no == 1) return((void *) -1);
313 return(NULL);
314}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000315static void des_userdata(int no ATTRIBUTE_UNUSED, void *val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000316}
317
318
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000319#define gen_nb_int 4
320
Daniel Veillard3d97e662004-11-04 10:49:00 +0000321static int gen_int(int no, int nr ATTRIBUTE_UNUSED) {
322 if (no == 0) return(0);
323 if (no == 1) return(1);
324 if (no == 1) return(-1);
325 if (no == 2) return(122);
326 return(-1);
327}
328
329static void des_int(int no ATTRIBUTE_UNUSED, int val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
330}
331
332#define gen_nb_unsigned_int 3
333
334static unsigned int gen_unsigned_int(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000335 if (no == 0) return(0);
336 if (no == 1) return(1);
337 if (no == 2) return(122);
338 return(-1);
339}
340
Daniel Veillard3d97e662004-11-04 10:49:00 +0000341static void des_unsigned_int(int no ATTRIBUTE_UNUSED, unsigned int val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000342}
343
344#define gen_nb_const_char_ptr 4
345
Daniel Veillard3d97e662004-11-04 10:49:00 +0000346static const char *gen_const_char_ptr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000347 if (no == 0) return("foo");
348 if (no == 1) return("<foo/>");
349 if (no == 2) return("test/ent2");
350 return(NULL);
351}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000352static void des_const_char_ptr(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000353}
354
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000355#define gen_nb_xmlChar_ptr 2
356
Daniel Veillard3d97e662004-11-04 10:49:00 +0000357static xmlChar *gen_xmlChar_ptr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000358 if (no == 0) return(&chartab[0]);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000359 return(NULL);
360}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000361static void des_xmlChar_ptr(int no ATTRIBUTE_UNUSED, xmlChar *val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000362}
363
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000364#define gen_nb_const_xmlChar_ptr 5
365
Daniel Veillard3d97e662004-11-04 10:49:00 +0000366static const xmlChar *gen_const_xmlChar_ptr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000367 if (no == 0) return((const xmlChar *) "foo");
368 if (no == 1) return((const xmlChar *) "<foo/>");
369 if (no == 2) return((const xmlChar *) "nøne");
370 if (no == 3) return((const xmlChar *) " 2ab ");
371 return(NULL);
372}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000373static void des_const_xmlChar_ptr(int no ATTRIBUTE_UNUSED, const xmlChar *val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000374}
375
376#define gen_nb_filepath 8
377
Daniel Veillard3d97e662004-11-04 10:49:00 +0000378static const char *gen_filepath(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000379 if (no == 0) return("missing.xml");
380 if (no == 1) return("<foo/>");
381 if (no == 2) return("test/ent2");
382 if (no == 3) return("test/valid/REC-xml-19980210.xml");
383 if (no == 4) return("test/valid/xhtml1-strict.dtd");
384 if (no == 5) return("http://missing.example.org/");
385 if (no == 6) return("http://missing. example.org/");
386 return(NULL);
387}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000388static void des_filepath(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000389}
390
391#define gen_nb_fileoutput 6
392
Daniel Veillard3d97e662004-11-04 10:49:00 +0000393static const char *gen_fileoutput(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000394 if (no == 0) return("/missing.xml");
395 if (no == 1) return("<foo/>");
396 if (no == 2) return("ftp://missing.example.org/foo");
397 if (no == 3) return("http://missing.example.org/");
398 if (no == 4) return("http://missing. example.org/");
399 return(NULL);
400}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000401static void des_fileoutput(int no ATTRIBUTE_UNUSED, const char *val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000402}
403
404#define gen_nb_xmlParserCtxtPtr 2
Daniel Veillard3d97e662004-11-04 10:49:00 +0000405static xmlParserCtxtPtr gen_xmlParserCtxtPtr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000406 if (no == 0) return(xmlNewParserCtxt());
407 return(NULL);
408}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000409static void des_xmlParserCtxtPtr(int no ATTRIBUTE_UNUSED, xmlParserCtxtPtr val, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000410 if (val != NULL)
411 xmlFreeParserCtxt(val);
412}
413
Daniel Veillardc0be74b2004-11-03 19:16:55 +0000414#define gen_nb_xmlValidCtxtPtr 2
Daniel Veillard3d97e662004-11-04 10:49:00 +0000415static xmlValidCtxtPtr gen_xmlValidCtxtPtr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardc0be74b2004-11-03 19:16:55 +0000416 if (no == 0) return(xmlNewValidCtxt());
417 return(NULL);
418}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000419static void des_xmlValidCtxtPtr(int no ATTRIBUTE_UNUSED, xmlValidCtxtPtr val, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardc0be74b2004-11-03 19:16:55 +0000420 if (val != NULL)
421 xmlFreeValidCtxt(val);
422}
423
Daniel Veillarda03e3652004-11-02 18:45:30 +0000424#define gen_nb_xmlDocPtr 3
Daniel Veillard3d97e662004-11-04 10:49:00 +0000425static xmlDocPtr gen_xmlDocPtr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000426 if (no == 0) return(xmlNewDoc(BAD_CAST "1.0"));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000427 if (no == 1) return(xmlReadMemory("<foo/>", 6, "test", NULL, 0));
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000428 return(NULL);
429}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000430static void des_xmlDocPtr(int no ATTRIBUTE_UNUSED, xmlDocPtr val, int nr ATTRIBUTE_UNUSED) {
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000431 if (val != NULL)
432 xmlFreeDoc(val);
433}
434
Daniel Veillarda03e3652004-11-02 18:45:30 +0000435#define gen_nb_xmlNodePtr 2
Daniel Veillard3d97e662004-11-04 10:49:00 +0000436static xmlNodePtr gen_xmlNodePtr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000437 if (no == 0) return(xmlNewPI(BAD_CAST "test", NULL));
438 return(NULL);
439}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000440static void des_xmlNodePtr(int no ATTRIBUTE_UNUSED, xmlNodePtr val, int nr ATTRIBUTE_UNUSED) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000441 if (val != NULL) {
442 xmlUnlinkNode(val);
443 xmlFreeNode(val);
444 }
445}
446
447#define gen_nb_xmlNodePtr_in 3
Daniel Veillard3d97e662004-11-04 10:49:00 +0000448static xmlNodePtr gen_xmlNodePtr_in(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000449 if (no == 0) return(xmlNewPI(BAD_CAST "test", NULL));
450 if (no == 0) return(xmlNewText(BAD_CAST "text"));
451 return(NULL);
452}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000453static void des_xmlNodePtr_in(int no ATTRIBUTE_UNUSED, xmlNodePtr val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000454}
455
Daniel Veillarde43cc572004-11-03 11:50:29 +0000456#define gen_nb_xmlTextWriterPtr 2
Daniel Veillard3d97e662004-11-04 10:49:00 +0000457static xmlTextWriterPtr gen_xmlTextWriterPtr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillarde43cc572004-11-03 11:50:29 +0000458 if (no == 0) return(xmlNewTextWriterFilename("test.out", 0));
459 return(NULL);
460}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000461static void des_xmlTextWriterPtr(int no ATTRIBUTE_UNUSED, xmlTextWriterPtr val, int nr ATTRIBUTE_UNUSED) {
Daniel Veillarde43cc572004-11-03 11:50:29 +0000462 if (val != NULL) xmlFreeTextWriter(val);
463}
464
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000465#define gen_nb_xmlTextReaderPtr 4
Daniel Veillard3d97e662004-11-04 10:49:00 +0000466static xmlTextReaderPtr gen_xmlTextReaderPtr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000467 if (no == 0) return(xmlNewTextReaderFilename("test/ent2"));
468 if (no == 1) return(xmlNewTextReaderFilename("test/valid/REC-xml-19980210.xml"));
469 if (no == 2) return(xmlNewTextReaderFilename("test/valid/dtds/xhtml1-strict.dtd"));
470 return(NULL);
471}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000472static void des_xmlTextReaderPtr(int no ATTRIBUTE_UNUSED, xmlTextReaderPtr val, int nr ATTRIBUTE_UNUSED) {
Daniel Veillarddd6d3002004-11-03 14:20:29 +0000473 if (val != NULL) xmlFreeTextReader(val);
474}
475
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000476#define gen_nb_xmlBufferPtr 2
Daniel Veillard3d97e662004-11-04 10:49:00 +0000477static xmlBufferPtr gen_xmlBufferPtr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000478 if (no == 0) return(xmlBufferCreate());
479 return(NULL);
480}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000481static void des_xmlBufferPtr(int no ATTRIBUTE_UNUSED, xmlBufferPtr val, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000482 if (val != NULL) {
483 xmlBufferFree(val);
484 }
485}
486
487#define gen_nb_xmlListPtr 2
Daniel Veillard3d97e662004-11-04 10:49:00 +0000488static xmlListPtr gen_xmlListPtr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000489 if (no == 0) return(xmlListCreate(NULL, NULL));
490 return(NULL);
491}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000492static void des_xmlListPtr(int no ATTRIBUTE_UNUSED, xmlListPtr val, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000493 if (val != NULL) {
494 xmlListDelete(val);
495 }
496}
497
498#define gen_nb_xmlHashTablePtr 2
Daniel Veillard3d97e662004-11-04 10:49:00 +0000499static xmlHashTablePtr gen_xmlHashTablePtr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000500 if (no == 0) return(xmlHashCreate(10));
501 return(NULL);
502}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000503static void des_xmlHashTablePtr(int no ATTRIBUTE_UNUSED, xmlHashTablePtr val, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000504 if (val != NULL) {
505 xmlHashFree(val, NULL);
506 }
507}
508
509#include <libxml/xpathInternals.h>
510
511#define gen_nb_xmlXPathObjectPtr 5
Daniel Veillard3d97e662004-11-04 10:49:00 +0000512static xmlXPathObjectPtr gen_xmlXPathObjectPtr(int no, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000513 if (no == 0) return(xmlXPathNewString(BAD_CAST "string object"));
514 if (no == 1) return(xmlXPathNewFloat(1.1));
515 if (no == 2) return(xmlXPathNewBoolean(1));
516 if (no == 3) return(xmlXPathNewNodeSet(NULL));
517 return(NULL);
518}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000519static void des_xmlXPathObjectPtr(int no ATTRIBUTE_UNUSED, xmlXPathObjectPtr val, int nr ATTRIBUTE_UNUSED) {
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000520 if (val != NULL) {
521 xmlXPathFreeObject(val);
522 }
523}
524
Daniel Veillard3d97e662004-11-04 10:49:00 +0000525#define gen_nb_xmlOutputBufferPtr 2
526static xmlOutputBufferPtr gen_xmlOutputBufferPtr(int no, int nr ATTRIBUTE_UNUSED) {
527 if (no == 0) return(xmlOutputBufferCreateFilename("test.out", NULL, 0));
528 return(NULL);
529}
530static void des_xmlOutputBufferPtr(int no ATTRIBUTE_UNUSED, xmlOutputBufferPtr val, int nr ATTRIBUTE_UNUSED) {
531 if (val != NULL) {
532 xmlOutputBufferClose(val);
533 }
534}
535
536#define gen_nb_xmlCharEncoding 4
537static xmlCharEncoding gen_xmlCharEncoding(int no, int nr ATTRIBUTE_UNUSED) {
538 if (no == 0) return(XML_CHAR_ENCODING_UTF8);
539 if (no == 1) return(XML_CHAR_ENCODING_NONE);
540 if (no == 0) return(XML_CHAR_ENCODING_8859_1);
541 return(XML_CHAR_ENCODING_ERROR);
542}
543static void des_xmlCharEncoding(int no ATTRIBUTE_UNUSED, xmlCharEncoding val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
544}
545
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000546""");
547
548#
549# Provide the type destructors for the return values
550#
551
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000552known_return_types = [ "int", "const_char_ptr", "xmlDocPtr", "xmlNodePtr",
Daniel Veillard3d97e662004-11-04 10:49:00 +0000553 "xmlChar_ptr", "const_xmlChar_ptr", "void_ptr",
554 "xmlXPathObjectPtr", "xmlCharEncoding" ];
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000555
556def is_known_return_type(name):
557 for type in known_return_types:
558 if type == name:
559 return 1
560 return 0
561
562test.write("""
563static void desret_int(int val ATTRIBUTE_UNUSED) {
564}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000565static void desret_xmlCharEncoding(xmlCharEncoding val ATTRIBUTE_UNUSED) {
566}
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000567static void desret_void_ptr(void *val ATTRIBUTE_UNUSED) {
568}
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000569static void desret_const_char_ptr(const char *val ATTRIBUTE_UNUSED) {
570}
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000571static void desret_const_xmlChar_ptr(const xmlChar *val ATTRIBUTE_UNUSED) {
572}
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000573static void desret_xmlChar_ptr(xmlChar *val) {
574 if (val != NULL)
575 xmlFree(val);
576}
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000577static void desret_xmlDocPtr(xmlDocPtr val) {
578 xmlFreeDoc(val);
579}
580static void desret_xmlNodePtr(xmlNodePtr val) {
581 xmlUnlinkNode(val);
582 xmlFreeNode(val);
583}
Daniel Veillard3d97e662004-11-04 10:49:00 +0000584static void desret_xmlXPathObjectPtr(xmlXPathObjectPtr val) {
585 if (val != NULL) {
586 xmlXPathFreeObject(val);
587 }
588}
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000589""");
590
591#
592# Generate the top caller
593#
594
595test.write("""
596/**
597 * testlibxml2:
598 *
599 * Main entry point of the tester for the full libxml2 module,
600 * it calls all the tester entry point for each module.
601 *
602 * Returns the number of error found
603 */
604static int
605testlibxml2(void)
606{
607 int ret = 0;
608
609""")
610
611for module in modules:
612 test.write(" ret += test_%s();\n" % module)
613
614test.write("""
Daniel Veillard3d97e662004-11-04 10:49:00 +0000615 printf("Total: %d functions, %d tests, %d errors\\n",
616 function_tests, call_tests, ret);
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000617 return(ret);
618}
619
620""")
621
622#
623# How to handle a function
624#
625nb_tests = 0
626
627def generate_test(module, node):
628 global test
629 global nb_tests
630 nb_cond = 0
631 no_gen = 0
632
633 name = node.xpathEval('string(@name)')
634 if is_skipped_function(name):
635 return
636
637 test.write("""
638static int
639test_%s(void) {
640 int ret = 0;
641
642""" % (name))
643
644 #
645 # check we know how to handle the args and return values
646 # and store the informations for the generation
647 #
648 try:
649 args = node.xpathEval("arg")
650 except:
651 args = []
652 t_args = []
Daniel Veillarda03e3652004-11-02 18:45:30 +0000653 n = 0
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000654 for arg in args:
Daniel Veillarda03e3652004-11-02 18:45:30 +0000655 n = n + 1
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000656 rtype = arg.xpathEval("string(@type)")
657 if rtype == 'void':
658 break;
659 info = arg.xpathEval("string(@info)")
660 nam = arg.xpathEval("string(@name)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000661 type = type_convert(rtype, nam, info, module, name, n)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000662 if is_known_param_type(type) == 0:
663 add_missing_type(type, name);
664 no_gen = 1
665 t_args.append((nam, type, rtype, info))
666
667 try:
668 rets = node.xpathEval("return")
669 except:
670 rets = []
671 t_ret = None
672 for ret in rets:
673 rtype = ret.xpathEval("string(@type)")
674 info = ret.xpathEval("string(@info)")
Daniel Veillarda03e3652004-11-02 18:45:30 +0000675 type = type_convert(rtype, 'return', info, module, name, 0)
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000676 if rtype == 'void':
677 break
678 if is_known_return_type(type) == 0:
679 add_missing_type(type, name);
680 no_gen = 1
681 t_ret = (type, rtype, info)
682 break
683
684 if no_gen == 1:
685 test.write("""
686 /* missing type support */
687 return(ret);
688}
689
690""")
691 return
692
693 try:
694 conds = node.xpathEval("cond")
695 for cond in conds:
696 test.write("#ifdef %s\n" % (cond.get_content()))
697 nb_cond = nb_cond + 1
698 except:
699 pass
700
701 # Declare the memory usage counter
702 no_mem = is_skipped_memcheck(name)
703 if no_mem == 0:
704 test.write(" int mem_base;\n");
705
706 # Declare the return value
707 if t_ret != None:
708 test.write(" %s ret_val;\n" % (t_ret[1]))
709
710 # Declare the arguments
711 for arg in t_args:
712 (nam, type, rtype, info) = arg;
713 # add declaration
714 test.write(" %s %s; /* %s */\n" % (rtype, nam, info))
715 test.write(" int n_%s;\n" % (nam))
716 test.write("\n")
717
718 # Cascade loop on of each argument list of values
719 for arg in t_args:
720 (nam, type, rtype, info) = arg;
721 #
722 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
723 nam, nam, type, nam))
724
725 # log the memory usage
726 if no_mem == 0:
727 test.write(" mem_base = xmlMemBlocks();\n");
728
729 # prepare the call
Daniel Veillard3d97e662004-11-04 10:49:00 +0000730 i = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000731 for arg in t_args:
732 (nam, type, rtype, info) = arg;
733 #
Daniel Veillard3d97e662004-11-04 10:49:00 +0000734 test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
735 i = i + 1;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000736
737 # do the call, and clanup the result
738 if t_ret != None:
739 test.write("\n ret_val = %s(" % (name))
740 need = 0
741 for arg in t_args:
742 (nam, type, rtype, info) = arg
743 if need:
744 test.write(", ")
745 else:
746 need = 1
747 test.write("%s" % nam);
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000748 test.write(");\n")
749 if extra_post_call.has_key(name):
750 test.write(" %s\n"% (extra_post_call[name]))
751 test.write(" desret_%s(ret_val);\n" % t_ret[0])
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000752 else:
753 test.write("\n %s(" % (name));
754 need = 0;
755 for arg in t_args:
756 (nam, type, rtype, info) = arg;
757 if need:
758 test.write(", ")
759 else:
760 need = 1
761 test.write("%s" % nam)
762 test.write(");\n")
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000763 if extra_post_call.has_key(name):
764 test.write(" %s\n"% (extra_post_call[name]))
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000765
Daniel Veillard8a32fe42004-11-02 22:10:16 +0000766 test.write(" call_tests++;\n");
Daniel Veillarda03e3652004-11-02 18:45:30 +0000767
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000768 # Free the arguments
Daniel Veillard3d97e662004-11-04 10:49:00 +0000769 i = 0;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000770 for arg in t_args:
771 (nam, type, rtype, info) = arg;
772 #
Daniel Veillard3d97e662004-11-04 10:49:00 +0000773 test.write(" des_%s(n_%s, %s, %d);\n" % (type, nam, nam, i))
774 i = i + 1;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000775
776 test.write(" xmlResetLastError();\n");
777 # Check the memory usage
778 if no_mem == 0:
779 test.write(""" if (mem_base != xmlMemBlocks()) {
Daniel Veillarda03e3652004-11-02 18:45:30 +0000780 printf("Leak of %%d blocks found in %s",
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000781 xmlMemBlocks() - mem_base);
782 ret++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000783""" % (name));
Daniel Veillarda03e3652004-11-02 18:45:30 +0000784 for arg in t_args:
785 (nam, type, rtype, info) = arg;
786 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
787 test.write(""" printf("\\n");\n""")
788 test.write(" }\n")
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000789
790 for arg in t_args:
791 test.write(" }\n")
792
793 #
794 # end of conditional
795 #
796 while nb_cond > 0:
797 test.write("#endif\n")
798 nb_cond = nb_cond -1
799
800 nb_tests = nb_tests + 1;
801
802 test.write("""
Daniel Veillard3d97e662004-11-04 10:49:00 +0000803 function_tests++;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000804 return(ret);
805}
806
807""")
808
809#
810# Generate all module callers
811#
812for module in modules:
813 # gather all the functions exported by that module
814 try:
815 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
816 except:
817 print "Failed to gather functions from module %s" % (module)
818 continue;
819
820 # iterate over all functions in the module generating the test
821 for function in functions:
822 generate_test(module, function);
823
824 # header
825 test.write("""static int
826test_%s(void) {
827 int ret = 0;
828
829 printf("Testing %s ...\\n");
830""" % (module, module))
831
832 # iterate over all functions in the module generating the call
833 for function in functions:
834 name = function.xpathEval('string(@name)')
835 if is_skipped_function(name):
836 continue
837 test.write(" ret += test_%s();\n" % (name))
838
839 # footer
840 test.write("""
841 if (ret != 0)
842 printf("Module %s: %%d errors\\n", ret);
843 return(ret);
844}
845""" % (module))
846
847print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000848nr1 = 0
849miss1 = 'none'
850nr2 = 0
851miss2 = 'none'
852nr3 = 0
853miss3 = 'none'
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000854for missing in missing_types.keys():
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000855 if missing == 'xmlAttrPtr' or missing == 'xmlNsPtr' or missing == '...':
856 continue;
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000857 n = len(missing_types[missing])
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000858 if n > nr1:
859 miss3 = miss2
860 nr3 = nr2
861 miss2 = miss1
862 nr2 = nr1
863 miss1 = missing
864 nr1 = n
865 elif n > nr2:
866 miss3 = miss2
867 nr3 = nr2
868 miss2 = missing
869 nr2 = n
870 elif n > nr3:
871 miss3 = missing
872 nr3 = n
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000873
Daniel Veillardd005b9e2004-11-03 17:07:05 +0000874if nr1 > 0:
875 print "most needed type support: %s %d times, %s %d and %s %d" % (
876 miss1, nr1, miss2, nr2, miss3, nr3)
Daniel Veillard3d97e662004-11-04 10:49:00 +0000877 print "%d missing types: %s" % (len(missing_types.keys()),
878 missing_types.keys())
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000879
Daniel Veillardb1b3a3e2004-11-03 23:25:47 +0000880print missing_types[miss1]
881
Daniel Veillard36e5cd52004-11-02 14:52:23 +0000882