VirtualBox

source: vbox/trunk/src/libs/libxml2-2.6.30/gentest.py@ 25275

Last change on this file since 25275 was 6076, checked in by vboxsync, 17 years ago

Merged dmik/s2 branch (r25959:26751) to the trunk.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 28.6 KB
Line 
1#!/usr/bin/python -u
2#
3# generate a tester program for the API
4#
5import sys
6import os
7import string
8try:
9 import libxml2
10except:
11 print "libxml2 python bindings not available, skipping testapi.c generation"
12 sys.exit(0)
13
14if len(sys.argv) > 1:
15 srcPref = sys.argv[1] + '/'
16else:
17 srcPref = ''
18
19#
20# Modules we want to skip in API test
21#
22skipped_modules = [ "SAX", "xlink", "threads", "globals",
23 "xmlmemory", "xmlversion", "xmlexports",
24 #deprecated
25 "DOCBparser",
26]
27
28#
29# defines for each module
30#
31modules_defines = {
32 "HTMLparser": "LIBXML_HTML_ENABLED",
33 "catalog": "LIBXML_CATALOG_ENABLED",
34 "xmlreader": "LIBXML_READER_ENABLED",
35 "relaxng": "LIBXML_SCHEMAS_ENABLED",
36 "schemasInternals": "LIBXML_SCHEMAS_ENABLED",
37 "xmlschemas": "LIBXML_SCHEMAS_ENABLED",
38 "xmlschemastypes": "LIBXML_SCHEMAS_ENABLED",
39 "xpath": "LIBXML_XPATH_ENABLED",
40 "xpathInternals": "LIBXML_XPATH_ENABLED",
41 "xinclude": "LIBXML_XINCLUDE_ENABLED",
42 "xpointer": "LIBXML_XPTR_ENABLED",
43 "xmlregexp" : "LIBXML_REGEXP_ENABLED",
44 "xmlautomata" : "LIBXML_AUTOMATA_ENABLED",
45 "xmlsave" : "LIBXML_OUTPUT_ENABLED",
46 "DOCBparser" : "LIBXML_DOCB_ENABLED",
47 "xmlmodule" : "LIBXML_MODULES_ENABLED",
48 "pattern" : "LIBXML_PATTERN_ENABLED",
49 "schematron" : "LIBXML_SCHEMATRON_ENABLED",
50}
51
52#
53# defines for specific functions
54#
55function_defines = {
56 "htmlDefaultSAXHandlerInit": "LIBXML_HTML_ENABLED",
57 "xmlSAX2EndElement" : "LIBXML_SAX1_ENABLED",
58 "xmlSAX2StartElement" : "LIBXML_SAX1_ENABLED",
59 "xmlSAXDefaultVersion" : "LIBXML_SAX1_ENABLED",
60 "UTF8Toisolat1" : "LIBXML_OUTPUT_ENABLED",
61 "xmlCleanupPredefinedEntities": "LIBXML_LEGACY_ENABLED",
62 "xmlInitializePredefinedEntities": "LIBXML_LEGACY_ENABLED",
63 "xmlSetFeature": "LIBXML_LEGACY_ENABLED",
64 "xmlGetFeature": "LIBXML_LEGACY_ENABLED",
65 "xmlGetFeaturesList": "LIBXML_LEGACY_ENABLED",
66 "xmlIOParseDTD": "LIBXML_VALID_ENABLED",
67 "xmlParseDTD": "LIBXML_VALID_ENABLED",
68 "xmlParseDoc": "LIBXML_SAX1_ENABLED",
69 "xmlParseMemory": "LIBXML_SAX1_ENABLED",
70 "xmlRecoverDoc": "LIBXML_SAX1_ENABLED",
71 "xmlParseFile": "LIBXML_SAX1_ENABLED",
72 "xmlRecoverFile": "LIBXML_SAX1_ENABLED",
73 "xmlRecoverMemory": "LIBXML_SAX1_ENABLED",
74 "xmlSAXParseFileWithData": "LIBXML_SAX1_ENABLED",
75 "xmlSAXParseMemory": "LIBXML_SAX1_ENABLED",
76 "xmlSAXUserParseMemory": "LIBXML_SAX1_ENABLED",
77 "xmlSAXParseDoc": "LIBXML_SAX1_ENABLED",
78 "xmlSAXParseDTD": "LIBXML_SAX1_ENABLED",
79 "xmlSAXUserParseFile": "LIBXML_SAX1_ENABLED",
80 "xmlParseEntity": "LIBXML_SAX1_ENABLED",
81 "xmlParseExternalEntity": "LIBXML_SAX1_ENABLED",
82 "xmlSAXParseMemoryWithData": "LIBXML_SAX1_ENABLED",
83 "xmlParseBalancedChunkMemory": "LIBXML_SAX1_ENABLED",
84 "xmlParseBalancedChunkMemoryRecover": "LIBXML_SAX1_ENABLED",
85 "xmlSetupParserForBuffer": "LIBXML_SAX1_ENABLED",
86 "xmlStopParser": "LIBXML_PUSH_ENABLED",
87 "xmlAttrSerializeTxtContent": "LIBXML_OUTPUT_ENABLED",
88 "xmlSAXParseFile": "LIBXML_SAX1_ENABLED",
89 "xmlSAXParseEntity": "LIBXML_SAX1_ENABLED",
90 "xmlNewTextChild": "LIBXML_TREE_ENABLED",
91 "xmlNewDocRawNode": "LIBXML_TREE_ENABLED",
92 "xmlNewProp": "LIBXML_TREE_ENABLED",
93 "xmlReconciliateNs": "LIBXML_TREE_ENABLED",
94 "xmlValidateNCName": "LIBXML_TREE_ENABLED",
95 "xmlValidateNMToken": "LIBXML_TREE_ENABLED",
96 "xmlValidateName": "LIBXML_TREE_ENABLED",
97 "xmlNewChild": "LIBXML_TREE_ENABLED",
98 "xmlValidateQName": "LIBXML_TREE_ENABLED",
99 "xmlSprintfElementContent": "LIBXML_OUTPUT_ENABLED",
100 "xmlValidGetPotentialChildren" : "LIBXML_VALID_ENABLED",
101 "xmlValidGetValidElements" : "LIBXML_VALID_ENABLED",
102 "docbDefaultSAXHandlerInit" : "LIBXML_DOCB_ENABLED",
103 "xmlTextReaderPreservePattern" : "LIBXML_PATTERN_ENABLED",
104}
105
106#
107# Some functions really need to be skipped for the tests.
108#
109skipped_functions = [
110# block on I/O
111"xmlFdRead", "xmlReadFd", "xmlCtxtReadFd",
112"htmlFdRead", "htmlReadFd", "htmlCtxtReadFd",
113"xmlReaderNewFd", "xmlReaderForFd",
114"xmlIORead", "xmlReadIO", "xmlCtxtReadIO",
115"htmlIORead", "htmlReadIO", "htmlCtxtReadIO",
116"xmlReaderNewIO", "xmlBufferDump", "xmlNanoFTPConnect",
117"xmlNanoFTPConnectTo", "xmlNanoHTTPMethod", "xmlNanoHTTPMethodRedir",
118# Complex I/O APIs
119"xmlCreateIOParserCtxt", "xmlParserInputBufferCreateIO",
120"xmlRegisterInputCallbacks", "xmlReaderForIO",
121"xmlOutputBufferCreateIO", "xmlRegisterOutputCallbacks",
122"xmlSaveToIO", "xmlIOHTTPOpenW",
123# library state cleanup, generate false leak informations and other
124# troubles, heavillyb tested otherwise.
125"xmlCleanupParser", "xmlRelaxNGCleanupTypes", "xmlSetListDoc",
126"xmlSetTreeDoc", "xmlUnlinkNode",
127# hard to avoid leaks in the tests
128"xmlStrcat", "xmlStrncat", "xmlCatalogAddLocal", "xmlNewTextWriterDoc",
129"xmlXPathNewValueTree", "xmlXPathWrapString",
130# unimplemented
131"xmlTextReaderReadInnerXml", "xmlTextReaderReadOuterXml",
132"xmlTextReaderReadString",
133# destructor
134"xmlListDelete", "xmlOutputBufferClose", "xmlNanoFTPClose", "xmlNanoHTTPClose",
135# deprecated
136"xmlCatalogGetPublic", "xmlCatalogGetSystem", "xmlEncodeEntities",
137"xmlNewGlobalNs", "xmlHandleEntity", "xmlNamespaceParseNCName",
138"xmlNamespaceParseNSDef", "xmlNamespaceParseQName",
139"xmlParseNamespace", "xmlParseQuotedString", "xmlParserHandleReference",
140"xmlScanName",
141"xmlDecodeEntities",
142# allocators
143"xmlMemFree",
144# verbosity
145"xmlCatalogSetDebug", "xmlShellPrintXPathError", "xmlShellPrintNode",
146# Internal functions, no user space should really call them
147"xmlParseAttribute", "xmlParseAttributeListDecl", "xmlParseName",
148"xmlParseNmtoken", "xmlParseEntityValue", "xmlParseAttValue",
149"xmlParseSystemLiteral", "xmlParsePubidLiteral", "xmlParseCharData",
150"xmlParseExternalID", "xmlParseComment", "xmlParsePITarget", "xmlParsePI",
151"xmlParseNotationDecl", "xmlParseEntityDecl", "xmlParseDefaultDecl",
152"xmlParseNotationType", "xmlParseEnumerationType", "xmlParseEnumeratedType",
153"xmlParseAttributeType", "xmlParseAttributeListDecl",
154"xmlParseElementMixedContentDecl", "xmlParseElementChildrenContentDecl",
155"xmlParseElementContentDecl", "xmlParseElementDecl", "xmlParseMarkupDecl",
156"xmlParseCharRef", "xmlParseEntityRef", "xmlParseReference",
157"xmlParsePEReference", "xmlParseDocTypeDecl", "xmlParseAttribute",
158"xmlParseStartTag", "xmlParseEndTag", "xmlParseCDSect", "xmlParseContent",
159"xmlParseElement", "xmlParseVersionNum", "xmlParseVersionInfo",
160"xmlParseEncName", "xmlParseEncodingDecl", "xmlParseSDDecl",
161"xmlParseXMLDecl", "xmlParseTextDecl", "xmlParseMisc",
162"xmlParseExternalSubset", "xmlParserHandlePEReference",
163"xmlSkipBlankChars",
164]
165
166#
167# These functions have side effects on the global state
168# and hence generate errors on memory allocation tests
169#
170skipped_memcheck = [ "xmlLoadCatalog", "xmlAddEncodingAlias",
171 "xmlSchemaInitTypes", "xmlNanoFTPProxy", "xmlNanoFTPScanProxy",
172 "xmlNanoHTTPScanProxy", "xmlResetLastError", "xmlCatalogConvert",
173 "xmlCatalogRemove", "xmlLoadCatalogs", "xmlCleanupCharEncodingHandlers",
174 "xmlInitCharEncodingHandlers", "xmlCatalogCleanup",
175 "xmlSchemaGetBuiltInType",
176 "htmlParseFile", "htmlCtxtReadFile", # loads the catalogs
177 "xmlTextReaderSchemaValidate", "xmlSchemaCleanupTypes" # initialize the schemas type system
178]
179
180#
181# Extra code needed for some test cases
182#
183extra_pre_call = {
184 "xmlSAXUserParseFile": """
185#ifdef LIBXML_SAX1_ENABLED
186 if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
187#endif
188""",
189 "xmlSAXUserParseMemory": """
190#ifdef LIBXML_SAX1_ENABLED
191 if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
192#endif
193""",
194 "xmlParseBalancedChunkMemory": """
195#ifdef LIBXML_SAX1_ENABLED
196 if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
197#endif
198""",
199 "xmlParseBalancedChunkMemoryRecover": """
200#ifdef LIBXML_SAX1_ENABLED
201 if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
202#endif
203""",
204 "xmlParserInputBufferCreateFd":
205 "if (fd >= 0) fd = -1;",
206}
207extra_post_call = {
208 "xmlAddChild":
209 "if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; }",
210 "xmlAddChildList":
211 "if (ret_val == NULL) { xmlFreeNodeList(cur) ; cur = NULL ; }",
212 "xmlAddSibling":
213 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
214 "xmlAddNextSibling":
215 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
216 "xmlAddPrevSibling":
217 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
218 "xmlDocSetRootElement":
219 "if (doc == NULL) { xmlFreeNode(root) ; root = NULL ; }",
220 "xmlReplaceNode":
221 """if (cur != NULL) {
222 xmlUnlinkNode(cur);
223 xmlFreeNode(cur) ; cur = NULL ; }
224 if (old != NULL) {
225 xmlUnlinkNode(old);
226 xmlFreeNode(old) ; old = NULL ; }
227 ret_val = NULL;""",
228 "xmlTextMerge":
229 """if ((first != NULL) && (first->type != XML_TEXT_NODE)) {
230 xmlUnlinkNode(second);
231 xmlFreeNode(second) ; second = NULL ; }""",
232 "xmlBuildQName":
233 """if ((ret_val != NULL) && (ret_val != ncname) &&
234 (ret_val != prefix) && (ret_val != memory))
235 xmlFree(ret_val);
236 ret_val = NULL;""",
237 "xmlNewDocElementContent":
238 """xmlFreeDocElementContent(doc, ret_val); ret_val = NULL;""",
239 "xmlDictReference": "xmlDictFree(dict);",
240 # Functions which deallocates one of their parameters
241 "xmlXPathConvertBoolean": """val = NULL;""",
242 "xmlXPathConvertNumber": """val = NULL;""",
243 "xmlXPathConvertString": """val = NULL;""",
244 "xmlSaveFileTo": """buf = NULL;""",
245 "xmlSaveFormatFileTo": """buf = NULL;""",
246 "xmlIOParseDTD": "input = NULL;",
247 "xmlRemoveProp": "cur = NULL;",
248 "xmlNewNs": "if ((node == NULL) && (ret_val != NULL)) xmlFreeNs(ret_val);",
249 "xmlCopyNamespace": "if (ret_val != NULL) xmlFreeNs(ret_val);",
250 "xmlCopyNamespaceList": "if (ret_val != NULL) xmlFreeNsList(ret_val);",
251 "xmlNewTextWriter": "if (ret_val != NULL) out = NULL;",
252 "xmlNewTextWriterPushParser": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;} if (ret_val != NULL) ctxt = NULL;",
253 "xmlNewIOInputStream": "if (ret_val != NULL) input = NULL;",
254 "htmlParseChunk": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
255 "htmlParseDocument": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
256 "xmlParseDocument": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
257 "xmlParseChunk": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
258 "xmlParseExtParsedEnt": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
259 "xmlDOMWrapAdoptNode": "if ((node != NULL) && (node->parent == NULL)) {xmlUnlinkNode(node);xmlFreeNode(node);node = NULL;}",
260}
261
262modules = []
263
264def is_skipped_module(name):
265 for mod in skipped_modules:
266 if mod == name:
267 return 1
268 return 0
269
270def is_skipped_function(name):
271 for fun in skipped_functions:
272 if fun == name:
273 return 1
274 # Do not test destructors
275 if string.find(name, 'Free') != -1:
276 return 1
277 return 0
278
279def is_skipped_memcheck(name):
280 for fun in skipped_memcheck:
281 if fun == name:
282 return 1
283 return 0
284
285missing_types = {}
286def add_missing_type(name, func):
287 try:
288 list = missing_types[name]
289 list.append(func)
290 except:
291 missing_types[name] = [func]
292
293generated_param_types = []
294def add_generated_param_type(name):
295 generated_param_types.append(name)
296
297generated_return_types = []
298def add_generated_return_type(name):
299 generated_return_types.append(name)
300
301missing_functions = {}
302missing_functions_nr = 0
303def add_missing_functions(name, module):
304 global missing_functions_nr
305
306 missing_functions_nr = missing_functions_nr + 1
307 try:
308 list = missing_functions[module]
309 list.append(name)
310 except:
311 missing_functions[module] = [name]
312
313#
314# Provide the type generators and destructors for the parameters
315#
316
317def type_convert(str, name, info, module, function, pos):
318# res = string.replace(str, " ", " ")
319# res = string.replace(str, " ", " ")
320# res = string.replace(str, " ", " ")
321 res = string.replace(str, " *", "_ptr")
322# res = string.replace(str, "*", "_ptr")
323 res = string.replace(res, " ", "_")
324 if res == 'const_char_ptr':
325 if string.find(name, "file") != -1 or \
326 string.find(name, "uri") != -1 or \
327 string.find(name, "URI") != -1 or \
328 string.find(info, "filename") != -1 or \
329 string.find(info, "URI") != -1 or \
330 string.find(info, "URL") != -1:
331 if string.find(function, "Save") != -1 or \
332 string.find(function, "Create") != -1 or \
333 string.find(function, "Write") != -1 or \
334 string.find(function, "Fetch") != -1:
335 return('fileoutput')
336 return('filepath')
337 if res == 'void_ptr':
338 if module == 'nanoftp' and name == 'ctx':
339 return('xmlNanoFTPCtxtPtr')
340 if function == 'xmlNanoFTPNewCtxt' or \
341 function == 'xmlNanoFTPConnectTo' or \
342 function == 'xmlNanoFTPOpen':
343 return('xmlNanoFTPCtxtPtr')
344 if module == 'nanohttp' and name == 'ctx':
345 return('xmlNanoHTTPCtxtPtr')
346 if function == 'xmlNanoHTTPMethod' or \
347 function == 'xmlNanoHTTPMethodRedir' or \
348 function == 'xmlNanoHTTPOpen' or \
349 function == 'xmlNanoHTTPOpenRedir':
350 return('xmlNanoHTTPCtxtPtr');
351 if function == 'xmlIOHTTPOpen':
352 return('xmlNanoHTTPCtxtPtr')
353 if string.find(name, "data") != -1:
354 return('userdata')
355 if string.find(name, "user") != -1:
356 return('userdata')
357 if res == 'xmlDoc_ptr':
358 res = 'xmlDocPtr'
359 if res == 'xmlNode_ptr':
360 res = 'xmlNodePtr'
361 if res == 'xmlDict_ptr':
362 res = 'xmlDictPtr'
363 if res == 'xmlNodePtr' and pos != 0:
364 if (function == 'xmlAddChild' and pos == 2) or \
365 (function == 'xmlAddChildList' and pos == 2) or \
366 (function == 'xmlAddNextSibling' and pos == 2) or \
367 (function == 'xmlAddSibling' and pos == 2) or \
368 (function == 'xmlDocSetRootElement' and pos == 2) or \
369 (function == 'xmlReplaceNode' and pos == 2) or \
370 (function == 'xmlTextMerge') or \
371 (function == 'xmlAddPrevSibling' and pos == 2):
372 return('xmlNodePtr_in');
373 if res == 'const xmlBufferPtr':
374 res = 'xmlBufferPtr'
375 if res == 'xmlChar_ptr' and name == 'name' and \
376 string.find(function, "EatName") != -1:
377 return('eaten_name')
378 if res == 'void_ptr*':
379 res = 'void_ptr_ptr'
380 if res == 'char_ptr*':
381 res = 'char_ptr_ptr'
382 if res == 'xmlChar_ptr*':
383 res = 'xmlChar_ptr_ptr'
384 if res == 'const_xmlChar_ptr*':
385 res = 'const_xmlChar_ptr_ptr'
386 if res == 'const_char_ptr*':
387 res = 'const_char_ptr_ptr'
388 if res == 'FILE_ptr' and module == 'debugXML':
389 res = 'debug_FILE_ptr';
390 if res == 'int' and name == 'options':
391 if module == 'parser' or module == 'xmlreader':
392 res = 'parseroptions'
393
394 return res
395
396known_param_types = []
397
398def is_known_param_type(name, rtype):
399 global test
400 for type in known_param_types:
401 if type == name:
402 return 1
403 for type in generated_param_types:
404 if type == name:
405 return 1
406
407 if name[-3:] == 'Ptr' or name[-4:] == '_ptr':
408 if rtype[0:6] == 'const ':
409 crtype = rtype[6:]
410 else:
411 crtype = rtype
412
413 define = 0
414 if modules_defines.has_key(module):
415 test.write("#ifdef %s\n" % (modules_defines[module]))
416 define = 1
417 test.write("""
418#define gen_nb_%s 1
419static %s gen_%s(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
420 return(NULL);
421}
422static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
423}
424""" % (name, crtype, name, name, rtype))
425 if define == 1:
426 test.write("#endif\n\n")
427 add_generated_param_type(name)
428 return 1
429
430 return 0
431
432#
433# Provide the type destructors for the return values
434#
435
436known_return_types = []
437
438def is_known_return_type(name):
439 for type in known_return_types:
440 if type == name:
441 return 1
442 return 0
443
444#
445# Copy the beginning of the C test program result
446#
447
448try:
449 input = open("testapi.c", "r")
450except:
451 input = open(srcPref + "testapi.c", "r")
452test = open('testapi.c.new', 'w')
453
454def compare_and_save():
455 global test
456
457 test.close()
458 try:
459 input = open("testapi.c", "r").read()
460 except:
461 input = ''
462 test = open('testapi.c.new', "r").read()
463 if input != test:
464 try:
465 os.system("rm testapi.c; mv testapi.c.new testapi.c")
466 except:
467 os.system("mv testapi.c.new testapi.c")
468 print("Updated testapi.c")
469 else:
470 print("Generated testapi.c is identical")
471
472line = input.readline()
473while line != "":
474 if line == "/* CUT HERE: everything below that line is generated */\n":
475 break;
476 if line[0:15] == "#define gen_nb_":
477 type = string.split(line[15:])[0]
478 known_param_types.append(type)
479 if line[0:19] == "static void desret_":
480 type = string.split(line[19:], '(')[0]
481 known_return_types.append(type)
482 test.write(line)
483 line = input.readline()
484input.close()
485
486if line == "":
487 print "Could not find the CUT marker in testapi.c skipping generation"
488 test.close()
489 sys.exit(0)
490
491print("Scanned testapi.c: found %d parameters types and %d return types\n" % (
492 len(known_param_types), len(known_return_types)))
493test.write("/* CUT HERE: everything below that line is generated */\n")
494
495
496#
497# Open the input API description
498#
499doc = libxml2.readFile(srcPref + 'doc/libxml2-api.xml', None, 0)
500if doc == None:
501 print "Failed to load doc/libxml2-api.xml"
502 sys.exit(1)
503ctxt = doc.xpathNewContext()
504
505#
506# Generate a list of all function parameters and select only
507# those used in the api tests
508#
509argtypes = {}
510args = ctxt.xpathEval("/api/symbols/function/arg")
511for arg in args:
512 mod = arg.xpathEval('string(../@file)')
513 func = arg.xpathEval('string(../@name)')
514 if (mod not in skipped_modules) and (func not in skipped_functions):
515 type = arg.xpathEval('string(@type)')
516 if not argtypes.has_key(type):
517 argtypes[type] = func
518
519# similarly for return types
520rettypes = {}
521rets = ctxt.xpathEval("/api/symbols/function/return")
522for ret in rets:
523 mod = ret.xpathEval('string(../@file)')
524 func = ret.xpathEval('string(../@name)')
525 if (mod not in skipped_modules) and (func not in skipped_functions):
526 type = ret.xpathEval('string(@type)')
527 if not rettypes.has_key(type):
528 rettypes[type] = func
529
530#
531# Generate constructors and return type handling for all enums
532# which are used as function parameters
533#
534enums = ctxt.xpathEval("/api/symbols/typedef[@type='enum']")
535for enum in enums:
536 module = enum.xpathEval('string(@file)')
537 name = enum.xpathEval('string(@name)')
538 #
539 # Skip any enums which are not in our filtered lists
540 #
541 if (name == None) or ((name not in argtypes) and (name not in rettypes)):
542 continue;
543 define = 0
544
545 if argtypes.has_key(name) and is_known_param_type(name, name) == 0:
546 values = ctxt.xpathEval("/api/symbols/enum[@type='%s']" % name)
547 i = 0
548 vals = []
549 for value in values:
550 vname = value.xpathEval('string(@name)')
551 if vname == None:
552 continue;
553 i = i + 1
554 if i >= 5:
555 break;
556 vals.append(vname)
557 if vals == []:
558 print "Didn't find any value for enum %s" % (name)
559 continue
560 if modules_defines.has_key(module):
561 test.write("#ifdef %s\n" % (modules_defines[module]))
562 define = 1
563 test.write("#define gen_nb_%s %d\n" % (name, len(vals)))
564 test.write("""static %s gen_%s(int no, int nr ATTRIBUTE_UNUSED) {\n""" %
565 (name, name))
566 i = 1
567 for value in vals:
568 test.write(" if (no == %d) return(%s);\n" % (i, value))
569 i = i + 1
570 test.write(""" return(0);
571}
572
573static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
574}
575
576""" % (name, name));
577 known_param_types.append(name)
578
579 if (is_known_return_type(name) == 0) and (name in rettypes):
580 if define == 0 and modules_defines.has_key(module):
581 test.write("#ifdef %s\n" % (modules_defines[module]))
582 define = 1
583 test.write("""static void desret_%s(%s val ATTRIBUTE_UNUSED) {
584}
585
586""" % (name, name))
587 known_return_types.append(name)
588 if define == 1:
589 test.write("#endif\n\n")
590
591#
592# Load the interfaces
593#
594headers = ctxt.xpathEval("/api/files/file")
595for file in headers:
596 name = file.xpathEval('string(@name)')
597 if (name == None) or (name == ''):
598 continue
599
600 #
601 # Some module may be skipped because they don't really consists
602 # of user callable APIs
603 #
604 if is_skipped_module(name):
605 continue
606
607 #
608 # do not test deprecated APIs
609 #
610 desc = file.xpathEval('string(description)')
611 if string.find(desc, 'DEPRECATED') != -1:
612 print "Skipping deprecated interface %s" % name
613 continue;
614
615 test.write("#include <libxml/%s.h>\n" % name)
616 modules.append(name)
617
618#
619# Generate the callers signatures
620#
621for module in modules:
622 test.write("static int test_%s(void);\n" % module);
623
624#
625# Generate the top caller
626#
627
628test.write("""
629/**
630 * testlibxml2:
631 *
632 * Main entry point of the tester for the full libxml2 module,
633 * it calls all the tester entry point for each module.
634 *
635 * Returns the number of error found
636 */
637static int
638testlibxml2(void)
639{
640 int test_ret = 0;
641
642""")
643
644for module in modules:
645 test.write(" test_ret += test_%s();\n" % module)
646
647test.write("""
648 printf("Total: %d functions, %d tests, %d errors\\n",
649 function_tests, call_tests, test_ret);
650 return(test_ret);
651}
652
653""")
654
655#
656# How to handle a function
657#
658nb_tests = 0
659
660def generate_test(module, node):
661 global test
662 global nb_tests
663 nb_cond = 0
664 no_gen = 0
665
666 name = node.xpathEval('string(@name)')
667 if is_skipped_function(name):
668 return
669
670 #
671 # check we know how to handle the args and return values
672 # and store the informations for the generation
673 #
674 try:
675 args = node.xpathEval("arg")
676 except:
677 args = []
678 t_args = []
679 n = 0
680 for arg in args:
681 n = n + 1
682 rtype = arg.xpathEval("string(@type)")
683 if rtype == 'void':
684 break;
685 info = arg.xpathEval("string(@info)")
686 nam = arg.xpathEval("string(@name)")
687 type = type_convert(rtype, nam, info, module, name, n)
688 if is_known_param_type(type, rtype) == 0:
689 add_missing_type(type, name);
690 no_gen = 1
691 if (type[-3:] == 'Ptr' or type[-4:] == '_ptr') and \
692 rtype[0:6] == 'const ':
693 crtype = rtype[6:]
694 else:
695 crtype = rtype
696 t_args.append((nam, type, rtype, crtype, info))
697
698 try:
699 rets = node.xpathEval("return")
700 except:
701 rets = []
702 t_ret = None
703 for ret in rets:
704 rtype = ret.xpathEval("string(@type)")
705 info = ret.xpathEval("string(@info)")
706 type = type_convert(rtype, 'return', info, module, name, 0)
707 if rtype == 'void':
708 break
709 if is_known_return_type(type) == 0:
710 add_missing_type(type, name);
711 no_gen = 1
712 t_ret = (type, rtype, info)
713 break
714
715 test.write("""
716static int
717test_%s(void) {
718 int test_ret = 0;
719
720""" % (name))
721
722 if no_gen == 1:
723 add_missing_functions(name, module)
724 test.write("""
725 /* missing type support */
726 return(test_ret);
727}
728
729""")
730 return
731
732 try:
733 conds = node.xpathEval("cond")
734 for cond in conds:
735 test.write("#if %s\n" % (cond.get_content()))
736 nb_cond = nb_cond + 1
737 except:
738 pass
739
740 define = 0
741 if function_defines.has_key(name):
742 test.write("#ifdef %s\n" % (function_defines[name]))
743 define = 1
744
745 # Declare the memory usage counter
746 no_mem = is_skipped_memcheck(name)
747 if no_mem == 0:
748 test.write(" int mem_base;\n");
749
750 # Declare the return value
751 if t_ret != None:
752 test.write(" %s ret_val;\n" % (t_ret[1]))
753
754 # Declare the arguments
755 for arg in t_args:
756 (nam, type, rtype, crtype, info) = arg;
757 # add declaration
758 test.write(" %s %s; /* %s */\n" % (crtype, nam, info))
759 test.write(" int n_%s;\n" % (nam))
760 test.write("\n")
761
762 # Cascade loop on of each argument list of values
763 for arg in t_args:
764 (nam, type, rtype, crtype, info) = arg;
765 #
766 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
767 nam, nam, type, nam))
768
769 # log the memory usage
770 if no_mem == 0:
771 test.write(" mem_base = xmlMemBlocks();\n");
772
773 # prepare the call
774 i = 0;
775 for arg in t_args:
776 (nam, type, rtype, crtype, info) = arg;
777 #
778 test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
779 i = i + 1;
780
781 # do the call, and clanup the result
782 if extra_pre_call.has_key(name):
783 test.write(" %s\n"% (extra_pre_call[name]))
784 if t_ret != None:
785 test.write("\n ret_val = %s(" % (name))
786 need = 0
787 for arg in t_args:
788 (nam, type, rtype, crtype, info) = arg
789 if need:
790 test.write(", ")
791 else:
792 need = 1
793 if rtype != crtype:
794 test.write("(%s)" % rtype)
795 test.write("%s" % nam);
796 test.write(");\n")
797 if extra_post_call.has_key(name):
798 test.write(" %s\n"% (extra_post_call[name]))
799 test.write(" desret_%s(ret_val);\n" % t_ret[0])
800 else:
801 test.write("\n %s(" % (name));
802 need = 0;
803 for arg in t_args:
804 (nam, type, rtype, crtype, info) = arg;
805 if need:
806 test.write(", ")
807 else:
808 need = 1
809 if rtype != crtype:
810 test.write("(%s)" % rtype)
811 test.write("%s" % nam)
812 test.write(");\n")
813 if extra_post_call.has_key(name):
814 test.write(" %s\n"% (extra_post_call[name]))
815
816 test.write(" call_tests++;\n");
817
818 # Free the arguments
819 i = 0;
820 for arg in t_args:
821 (nam, type, rtype, crtype, info) = arg;
822 # This is a hack to prevent generating a destructor for the
823 # 'input' argument in xmlTextReaderSetup. There should be
824 # a better, more generic way to do this!
825 if string.find(info, 'destroy') == -1:
826 test.write(" des_%s(n_%s, " % (type, nam))
827 if rtype != crtype:
828 test.write("(%s)" % rtype)
829 test.write("%s, %d);\n" % (nam, i))
830 i = i + 1;
831
832 test.write(" xmlResetLastError();\n");
833 # Check the memory usage
834 if no_mem == 0:
835 test.write(""" if (mem_base != xmlMemBlocks()) {
836 printf("Leak of %%d blocks found in %s",
837 xmlMemBlocks() - mem_base);
838 test_ret++;
839""" % (name));
840 for arg in t_args:
841 (nam, type, rtype, crtype, info) = arg;
842 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
843 test.write(""" printf("\\n");\n""")
844 test.write(" }\n")
845
846 for arg in t_args:
847 test.write(" }\n")
848
849 test.write(" function_tests++;\n")
850 #
851 # end of conditional
852 #
853 while nb_cond > 0:
854 test.write("#endif\n")
855 nb_cond = nb_cond -1
856 if define == 1:
857 test.write("#endif\n")
858
859 nb_tests = nb_tests + 1;
860
861 test.write("""
862 return(test_ret);
863}
864
865""")
866
867#
868# Generate all module callers
869#
870for module in modules:
871 # gather all the functions exported by that module
872 try:
873 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
874 except:
875 print "Failed to gather functions from module %s" % (module)
876 continue;
877
878 # iterate over all functions in the module generating the test
879 i = 0
880 nb_tests_old = nb_tests
881 for function in functions:
882 i = i + 1
883 generate_test(module, function);
884
885 # header
886 test.write("""static int
887test_%s(void) {
888 int test_ret = 0;
889
890 if (quiet == 0) printf("Testing %s : %d of %d functions ...\\n");
891""" % (module, module, nb_tests - nb_tests_old, i))
892
893 # iterate over all functions in the module generating the call
894 for function in functions:
895 name = function.xpathEval('string(@name)')
896 if is_skipped_function(name):
897 continue
898 test.write(" test_ret += test_%s();\n" % (name))
899
900 # footer
901 test.write("""
902 if (test_ret != 0)
903 printf("Module %s: %%d errors\\n", test_ret);
904 return(test_ret);
905}
906""" % (module))
907
908#
909# Generate direct module caller
910#
911test.write("""static int
912test_module(const char *module) {
913""");
914for module in modules:
915 test.write(""" if (!strcmp(module, "%s")) return(test_%s());\n""" % (
916 module, module))
917test.write(""" return(0);
918}
919""");
920
921print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
922
923compare_and_save()
924
925missing_list = []
926for missing in missing_types.keys():
927 if missing == 'va_list' or missing == '...':
928 continue;
929
930 n = len(missing_types[missing])
931 missing_list.append((n, missing))
932
933def compare_missing(a, b):
934 return b[0] - a[0]
935
936missing_list.sort(compare_missing)
937print "Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list))
938lst = open("missing.lst", "w")
939lst.write("Missing support for %d types" % (len(missing_list)))
940lst.write("\n")
941for miss in missing_list:
942 lst.write("%s: %d :" % (miss[1], miss[0]))
943 i = 0
944 for n in missing_types[miss[1]]:
945 i = i + 1
946 if i > 5:
947 lst.write(" ...")
948 break
949 lst.write(" %s" % (n))
950 lst.write("\n")
951lst.write("\n")
952lst.write("\n")
953lst.write("Missing support per module");
954for module in missing_functions.keys():
955 lst.write("module %s:\n %s\n" % (module, missing_functions[module]))
956
957lst.close()
958
959
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use