VirtualBox

source: vbox/trunk/src/libs/libxml2-2.9.14/gentest.py@ 102340

Last change on this file since 102340 was 95312, checked in by vboxsync, 2 years ago

libs/{curl,libxml2}: OSE export fixes, bugref:8515

  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 30.0 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 information 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 "xmlCatalogResolve", "xmlIOParseDTD" # loads the catalogs
179]
180
181#
182# Extra code needed for some test cases
183#
184extra_pre_call = {
185 "xmlSAXUserParseFile": """
186#ifdef LIBXML_SAX1_ENABLED
187 if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
188#endif
189""",
190 "xmlSAXUserParseMemory": """
191#ifdef LIBXML_SAX1_ENABLED
192 if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
193#endif
194""",
195 "xmlParseBalancedChunkMemory": """
196#ifdef LIBXML_SAX1_ENABLED
197 if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
198#endif
199""",
200 "xmlParseBalancedChunkMemoryRecover": """
201#ifdef LIBXML_SAX1_ENABLED
202 if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
203#endif
204""",
205 "xmlParserInputBufferCreateFd":
206 "if (fd >= 0) fd = -1;",
207}
208extra_post_call = {
209 "xmlAddChild":
210 "if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; }",
211 "xmlAddEntity":
212 "if (ret_val != NULL) { xmlFreeNode(ret_val) ; ret_val = NULL; }",
213 "xmlAddChildList":
214 "if (ret_val == NULL) { xmlFreeNodeList(cur) ; cur = NULL ; }",
215 "xmlAddSibling":
216 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
217 "xmlAddNextSibling":
218 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
219 "xmlAddPrevSibling":
220 "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
221 "xmlDocSetRootElement":
222 "if (doc == NULL) { xmlFreeNode(root) ; root = NULL ; }",
223 "xmlReplaceNode":
224 """if (cur != NULL) {
225 xmlUnlinkNode(cur);
226 xmlFreeNode(cur) ; cur = NULL ; }
227 if (old != NULL) {
228 xmlUnlinkNode(old);
229 xmlFreeNode(old) ; old = NULL ; }
230 ret_val = NULL;""",
231 "xmlTextMerge":
232 """if ((first != NULL) && (first->type != XML_TEXT_NODE)) {
233 xmlUnlinkNode(second);
234 xmlFreeNode(second) ; second = NULL ; }""",
235 "xmlBuildQName":
236 """if ((ret_val != NULL) && (ret_val != ncname) &&
237 (ret_val != prefix) && (ret_val != memory))
238 xmlFree(ret_val);
239 ret_val = NULL;""",
240 "xmlNewDocElementContent":
241 """xmlFreeDocElementContent(doc, ret_val); ret_val = NULL;""",
242 "xmlDictReference": "xmlDictFree(dict);",
243 # Functions which deallocates one of their parameters
244 "xmlXPathConvertBoolean": """val = NULL;""",
245 "xmlXPathConvertNumber": """val = NULL;""",
246 "xmlXPathConvertString": """val = NULL;""",
247 "xmlSaveFileTo": """buf = NULL;""",
248 "xmlSaveFormatFileTo": """buf = NULL;""",
249 "xmlIOParseDTD": "input = NULL;",
250 "xmlRemoveProp": "cur = NULL;",
251 "xmlNewNs": "if ((node == NULL) && (ret_val != NULL)) xmlFreeNs(ret_val);",
252 "xmlCopyNamespace": "if (ret_val != NULL) xmlFreeNs(ret_val);",
253 "xmlCopyNamespaceList": "if (ret_val != NULL) xmlFreeNsList(ret_val);",
254 "xmlNewTextWriter": "if (ret_val != NULL) out = NULL;",
255 "xmlNewTextWriterPushParser": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;} if (ret_val != NULL) ctxt = NULL;",
256 "xmlNewIOInputStream": "if (ret_val != NULL) input = NULL;",
257 "htmlParseChunk": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
258 "htmlParseDocument": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
259 "xmlParseDocument": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
260 "xmlParseChunk": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
261 "xmlParseExtParsedEnt": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
262 "xmlDOMWrapAdoptNode": "if ((node != NULL) && (node->parent == NULL)) {xmlUnlinkNode(node);xmlFreeNode(node);node = NULL;}",
263 "xmlBufferSetAllocationScheme": "if ((buf != NULL) && (scheme == XML_BUFFER_ALLOC_IMMUTABLE) && (buf->content != NULL) && (buf->content != static_buf_content)) { xmlFree(buf->content); buf->content = NULL;}"
264}
265
266modules = []
267
268def is_skipped_module(name):
269 for mod in skipped_modules:
270 if mod == name:
271 return 1
272 return 0
273
274def is_skipped_function(name):
275 for fun in skipped_functions:
276 if fun == name:
277 return 1
278 # Do not test destructors
279 if string.find(name, 'Free') != -1:
280 return 1
281 return 0
282
283def is_skipped_memcheck(name):
284 for fun in skipped_memcheck:
285 if fun == name:
286 return 1
287 return 0
288
289missing_types = {}
290def add_missing_type(name, func):
291 try:
292 list = missing_types[name]
293 list.append(func)
294 except:
295 missing_types[name] = [func]
296
297generated_param_types = []
298def add_generated_param_type(name):
299 generated_param_types.append(name)
300
301generated_return_types = []
302def add_generated_return_type(name):
303 generated_return_types.append(name)
304
305missing_functions = {}
306missing_functions_nr = 0
307def add_missing_functions(name, module):
308 global missing_functions_nr
309
310 missing_functions_nr = missing_functions_nr + 1
311 try:
312 list = missing_functions[module]
313 list.append(name)
314 except:
315 missing_functions[module] = [name]
316
317#
318# Provide the type generators and destructors for the parameters
319#
320
321def type_convert(str, name, info, module, function, pos):
322# res = string.replace(str, " ", " ")
323# res = string.replace(str, " ", " ")
324# res = string.replace(str, " ", " ")
325 res = string.replace(str, " *", "_ptr")
326# res = string.replace(str, "*", "_ptr")
327 res = string.replace(res, " ", "_")
328 if res == 'const_char_ptr':
329 if string.find(name, "file") != -1 or \
330 string.find(name, "uri") != -1 or \
331 string.find(name, "URI") != -1 or \
332 string.find(info, "filename") != -1 or \
333 string.find(info, "URI") != -1 or \
334 string.find(info, "URL") != -1:
335 if string.find(function, "Save") != -1 or \
336 string.find(function, "Create") != -1 or \
337 string.find(function, "Write") != -1 or \
338 string.find(function, "Fetch") != -1:
339 return('fileoutput')
340 return('filepath')
341 if res == 'void_ptr':
342 if module == 'nanoftp' and name == 'ctx':
343 return('xmlNanoFTPCtxtPtr')
344 if function == 'xmlNanoFTPNewCtxt' or \
345 function == 'xmlNanoFTPConnectTo' or \
346 function == 'xmlNanoFTPOpen':
347 return('xmlNanoFTPCtxtPtr')
348 if module == 'nanohttp' and name == 'ctx':
349 return('xmlNanoHTTPCtxtPtr')
350 if function == 'xmlNanoHTTPMethod' or \
351 function == 'xmlNanoHTTPMethodRedir' or \
352 function == 'xmlNanoHTTPOpen' or \
353 function == 'xmlNanoHTTPOpenRedir':
354 return('xmlNanoHTTPCtxtPtr');
355 if function == 'xmlIOHTTPOpen':
356 return('xmlNanoHTTPCtxtPtr')
357 if string.find(name, "data") != -1:
358 return('userdata')
359 if string.find(name, "user") != -1:
360 return('userdata')
361 if res == 'xmlDoc_ptr':
362 res = 'xmlDocPtr'
363 if res == 'xmlNode_ptr':
364 res = 'xmlNodePtr'
365 if res == 'xmlDict_ptr':
366 res = 'xmlDictPtr'
367 if res == 'xmlNodePtr' and pos != 0:
368 if (function == 'xmlAddChild' and pos == 2) or \
369 (function == 'xmlAddChildList' and pos == 2) or \
370 (function == 'xmlAddNextSibling' and pos == 2) or \
371 (function == 'xmlAddSibling' and pos == 2) or \
372 (function == 'xmlDocSetRootElement' and pos == 2) or \
373 (function == 'xmlReplaceNode' and pos == 2) or \
374 (function == 'xmlTextMerge') or \
375 (function == 'xmlAddPrevSibling' and pos == 2):
376 return('xmlNodePtr_in');
377 if res == 'const xmlBufferPtr':
378 res = 'xmlBufferPtr'
379 if res == 'xmlChar_ptr' and name == 'name' and \
380 string.find(function, "EatName") != -1:
381 return('eaten_name')
382 if res == 'void_ptr*':
383 res = 'void_ptr_ptr'
384 if res == 'char_ptr*':
385 res = 'char_ptr_ptr'
386 if res == 'xmlChar_ptr*':
387 res = 'xmlChar_ptr_ptr'
388 if res == 'const_xmlChar_ptr*':
389 res = 'const_xmlChar_ptr_ptr'
390 if res == 'const_char_ptr*':
391 res = 'const_char_ptr_ptr'
392 if res == 'FILE_ptr' and module == 'debugXML':
393 res = 'debug_FILE_ptr';
394 if res == 'int' and name == 'options':
395 if module == 'parser' or module == 'xmlreader':
396 res = 'parseroptions'
397
398 return res
399
400known_param_types = []
401
402def is_known_param_type(name):
403 for type in known_param_types:
404 if type == name:
405 return 1
406 return name[-3:] == 'Ptr' or name[-4:] == '_ptr'
407
408def generate_param_type(name, rtype):
409 global test
410 for type in known_param_types:
411 if type == name:
412 return
413 for type in generated_param_types:
414 if type == name:
415 return
416
417 if name[-3:] == 'Ptr' or name[-4:] == '_ptr':
418 if rtype[0:6] == 'const ':
419 crtype = rtype[6:]
420 else:
421 crtype = rtype
422
423 define = 0
424 if modules_defines.has_key(module):
425 test.write("#ifdef %s\n" % (modules_defines[module]))
426 define = 1
427 test.write("""
428#define gen_nb_%s 1
429static %s gen_%s(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
430 return(NULL);
431}
432static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
433}
434""" % (name, crtype, name, name, rtype))
435 if define == 1:
436 test.write("#endif\n\n")
437 add_generated_param_type(name)
438
439#
440# Provide the type destructors for the return values
441#
442
443known_return_types = []
444
445def is_known_return_type(name):
446 for type in known_return_types:
447 if type == name:
448 return 1
449 return 0
450
451#
452# Copy the beginning of the C test program result
453#
454
455try:
456 input = open("testapi.c", "r")
457except:
458 input = open(srcPref + "testapi.c", "r")
459test = open('testapi.c.new', 'w')
460
461def compare_and_save():
462 global test
463
464 test.close()
465 try:
466 input = open("testapi.c", "r").read()
467 except:
468 input = ''
469 test = open('testapi.c.new', "r").read()
470 if input != test:
471 try:
472 os.system("rm testapi.c; mv testapi.c.new testapi.c")
473 except:
474 os.system("mv testapi.c.new testapi.c")
475 print("Updated testapi.c")
476 else:
477 print("Generated testapi.c is identical")
478
479line = input.readline()
480while line != "":
481 if line == "/* CUT HERE: everything below that line is generated */\n":
482 break;
483 if line[0:15] == "#define gen_nb_":
484 type = string.split(line[15:])[0]
485 known_param_types.append(type)
486 if line[0:19] == "static void desret_":
487 type = string.split(line[19:], '(')[0]
488 known_return_types.append(type)
489 test.write(line)
490 line = input.readline()
491input.close()
492
493if line == "":
494 print "Could not find the CUT marker in testapi.c skipping generation"
495 test.close()
496 sys.exit(0)
497
498print("Scanned testapi.c: found %d parameters types and %d return types\n" % (
499 len(known_param_types), len(known_return_types)))
500test.write("/* CUT HERE: everything below that line is generated */\n")
501
502
503#
504# Open the input API description
505#
506doc = libxml2.readFile(srcPref + 'doc/libxml2-api.xml', None, 0)
507if doc == None:
508 print "Failed to load doc/libxml2-api.xml"
509 sys.exit(1)
510ctxt = doc.xpathNewContext()
511
512#
513# Generate a list of all function parameters and select only
514# those used in the api tests
515#
516argtypes = {}
517args = ctxt.xpathEval("/api/symbols/function/arg")
518for arg in args:
519 mod = arg.xpathEval('string(../@file)')
520 func = arg.xpathEval('string(../@name)')
521 if (mod not in skipped_modules) and (func not in skipped_functions):
522 type = arg.xpathEval('string(@type)')
523 if not argtypes.has_key(type):
524 argtypes[type] = func
525
526# similarly for return types
527rettypes = {}
528rets = ctxt.xpathEval("/api/symbols/function/return")
529for ret in rets:
530 mod = ret.xpathEval('string(../@file)')
531 func = ret.xpathEval('string(../@name)')
532 if (mod not in skipped_modules) and (func not in skipped_functions):
533 type = ret.xpathEval('string(@type)')
534 if not rettypes.has_key(type):
535 rettypes[type] = func
536
537#
538# Generate constructors and return type handling for all enums
539# which are used as function parameters
540#
541enums = ctxt.xpathEval("/api/symbols/typedef[@type='enum']")
542for enum in enums:
543 module = enum.xpathEval('string(@file)')
544 name = enum.xpathEval('string(@name)')
545 #
546 # Skip any enums which are not in our filtered lists
547 #
548 if (name == None) or ((name not in argtypes) and (name not in rettypes)):
549 continue;
550 define = 0
551
552 if argtypes.has_key(name) and is_known_param_type(name) == 0:
553 values = ctxt.xpathEval("/api/symbols/enum[@type='%s']" % name)
554 i = 0
555 vals = []
556 for value in values:
557 vname = value.xpathEval('string(@name)')
558 if vname == None:
559 continue;
560 i = i + 1
561 if i >= 5:
562 break;
563 vals.append(vname)
564 if vals == []:
565 print "Didn't find any value for enum %s" % (name)
566 continue
567 if modules_defines.has_key(module):
568 test.write("#ifdef %s\n" % (modules_defines[module]))
569 define = 1
570 test.write("#define gen_nb_%s %d\n" % (name, len(vals)))
571 test.write("""static %s gen_%s(int no, int nr ATTRIBUTE_UNUSED) {\n""" %
572 (name, name))
573 i = 1
574 for value in vals:
575 test.write(" if (no == %d) return(%s);\n" % (i, value))
576 i = i + 1
577 test.write(""" return(0);
578}
579
580static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
581}
582
583""" % (name, name));
584 known_param_types.append(name)
585
586 if (is_known_return_type(name) == 0) and (name in rettypes):
587 if define == 0 and modules_defines.has_key(module):
588 test.write("#ifdef %s\n" % (modules_defines[module]))
589 define = 1
590 test.write("""static void desret_%s(%s val ATTRIBUTE_UNUSED) {
591}
592
593""" % (name, name))
594 known_return_types.append(name)
595 if define == 1:
596 test.write("#endif\n\n")
597
598#
599# Load the interfaces
600#
601headers = ctxt.xpathEval("/api/files/file")
602for file in headers:
603 name = file.xpathEval('string(@name)')
604 if (name == None) or (name == ''):
605 continue
606
607 #
608 # Some module may be skipped because they don't really consists
609 # of user callable APIs
610 #
611 if is_skipped_module(name):
612 continue
613
614 #
615 # do not test deprecated APIs
616 #
617 desc = file.xpathEval('string(description)')
618 if string.find(desc, 'DEPRECATED') != -1:
619 print "Skipping deprecated interface %s" % name
620 continue;
621
622 test.write("#include <libxml/%s.h>\n" % name)
623 modules.append(name)
624
625#
626# Generate the callers signatures
627#
628for module in modules:
629 test.write("static int test_%s(void);\n" % module);
630
631#
632# Generate the top caller
633#
634
635test.write("""
636/**
637 * testlibxml2:
638 *
639 * Main entry point of the tester for the full libxml2 module,
640 * it calls all the tester entry point for each module.
641 *
642 * Returns the number of error found
643 */
644static int
645testlibxml2(void)
646{
647 int test_ret = 0;
648
649""")
650
651for module in modules:
652 test.write(" test_ret += test_%s();\n" % module)
653
654test.write("""
655 printf("Total: %d functions, %d tests, %d errors\\n",
656 function_tests, call_tests, test_ret);
657 return(test_ret);
658}
659
660""")
661
662#
663# How to handle a function
664#
665nb_tests = 0
666
667def generate_test(module, node):
668 global test
669 global nb_tests
670 nb_cond = 0
671 no_gen = 0
672
673 name = node.xpathEval('string(@name)')
674 if is_skipped_function(name):
675 return
676
677 #
678 # check we know how to handle the args and return values
679 # and store the information for the generation
680 #
681 try:
682 args = node.xpathEval("arg")
683 except:
684 args = []
685 t_args = []
686 n = 0
687 for arg in args:
688 n = n + 1
689 rtype = arg.xpathEval("string(@type)")
690 if rtype == 'void':
691 break;
692 info = arg.xpathEval("string(@info)")
693 nam = arg.xpathEval("string(@name)")
694 type = type_convert(rtype, nam, info, module, name, n)
695 if is_known_param_type(type) == 0:
696 add_missing_type(type, name);
697 no_gen = 1
698 if (type[-3:] == 'Ptr' or type[-4:] == '_ptr') and \
699 rtype[0:6] == 'const ':
700 crtype = rtype[6:]
701 else:
702 crtype = rtype
703 t_args.append((nam, type, rtype, crtype, info))
704
705 try:
706 rets = node.xpathEval("return")
707 except:
708 rets = []
709 t_ret = None
710 for ret in rets:
711 rtype = ret.xpathEval("string(@type)")
712 info = ret.xpathEval("string(@info)")
713 type = type_convert(rtype, 'return', info, module, name, 0)
714 if rtype == 'void':
715 break
716 if is_known_return_type(type) == 0:
717 add_missing_type(type, name);
718 no_gen = 1
719 t_ret = (type, rtype, info)
720 break
721
722 if no_gen == 0:
723 for t_arg in t_args:
724 (nam, type, rtype, crtype, info) = t_arg
725 generate_param_type(type, rtype)
726
727 test.write("""
728static int
729test_%s(void) {
730 int test_ret = 0;
731
732""" % (name))
733
734 if no_gen == 1:
735 add_missing_functions(name, module)
736 test.write("""
737 /* missing type support */
738 return(test_ret);
739}
740
741""")
742 return
743
744 try:
745 conds = node.xpathEval("cond")
746 for cond in conds:
747 test.write("#if %s\n" % (cond.get_content()))
748 nb_cond = nb_cond + 1
749 except:
750 pass
751
752 define = 0
753 if function_defines.has_key(name):
754 test.write("#ifdef %s\n" % (function_defines[name]))
755 define = 1
756
757 # Declare the memory usage counter
758 no_mem = is_skipped_memcheck(name)
759 if no_mem == 0:
760 test.write(" int mem_base;\n");
761
762 # Declare the return value
763 if t_ret != None:
764 test.write(" %s ret_val;\n" % (t_ret[1]))
765
766 # Declare the arguments
767 for arg in t_args:
768 (nam, type, rtype, crtype, info) = arg;
769 # add declaration
770 test.write(" %s %s; /* %s */\n" % (crtype, nam, info))
771 test.write(" int n_%s;\n" % (nam))
772 test.write("\n")
773
774 # Cascade loop on of each argument list of values
775 for arg in t_args:
776 (nam, type, rtype, crtype, info) = arg;
777 #
778 test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
779 nam, nam, type, nam))
780
781 # log the memory usage
782 if no_mem == 0:
783 test.write(" mem_base = xmlMemBlocks();\n");
784
785 # prepare the call
786 i = 0;
787 for arg in t_args:
788 (nam, type, rtype, crtype, info) = arg;
789 #
790 test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
791 i = i + 1;
792
793 # add checks to avoid out-of-bounds array access
794 i = 0;
795 for arg in t_args:
796 (nam, type, rtype, crtype, info) = arg;
797 # assume that "size", "len", and "start" parameters apply to either
798 # the nearest preceding or following char pointer
799 if type == "int" and (nam == "size" or nam == "len" or nam == "start"):
800 for j in range(i - 1, -1, -1) + range(i + 1, len(t_args)):
801 (bnam, btype) = t_args[j][:2]
802 if btype == "const_char_ptr" or btype == "const_xmlChar_ptr":
803 test.write(
804 " if ((%s != NULL) &&\n"
805 " (%s > (int) strlen((const char *) %s) + 1))\n"
806 " continue;\n"
807 % (bnam, nam, bnam))
808 break
809 i = i + 1;
810
811 # do the call, and clanup the result
812 if extra_pre_call.has_key(name):
813 test.write(" %s\n"% (extra_pre_call[name]))
814 if t_ret != None:
815 test.write("\n ret_val = %s(" % (name))
816 need = 0
817 for arg in t_args:
818 (nam, type, rtype, crtype, info) = arg
819 if need:
820 test.write(", ")
821 else:
822 need = 1
823 if rtype != crtype:
824 test.write("(%s)" % rtype)
825 test.write("%s" % nam);
826 test.write(");\n")
827 if extra_post_call.has_key(name):
828 test.write(" %s\n"% (extra_post_call[name]))
829 test.write(" desret_%s(ret_val);\n" % t_ret[0])
830 else:
831 test.write("\n %s(" % (name));
832 need = 0;
833 for arg in t_args:
834 (nam, type, rtype, crtype, info) = arg;
835 if need:
836 test.write(", ")
837 else:
838 need = 1
839 if rtype != crtype:
840 test.write("(%s)" % rtype)
841 test.write("%s" % nam)
842 test.write(");\n")
843 if extra_post_call.has_key(name):
844 test.write(" %s\n"% (extra_post_call[name]))
845
846 test.write(" call_tests++;\n");
847
848 # Free the arguments
849 i = 0;
850 for arg in t_args:
851 (nam, type, rtype, crtype, info) = arg;
852 # This is a hack to prevent generating a destructor for the
853 # 'input' argument in xmlTextReaderSetup. There should be
854 # a better, more generic way to do this!
855 if string.find(info, 'destroy') == -1:
856 test.write(" des_%s(n_%s, " % (type, nam))
857 if rtype != crtype:
858 test.write("(%s)" % rtype)
859 test.write("%s, %d);\n" % (nam, i))
860 i = i + 1;
861
862 test.write(" xmlResetLastError();\n");
863 # Check the memory usage
864 if no_mem == 0:
865 test.write(""" if (mem_base != xmlMemBlocks()) {
866 printf("Leak of %%d blocks found in %s",
867 xmlMemBlocks() - mem_base);
868 test_ret++;
869""" % (name));
870 for arg in t_args:
871 (nam, type, rtype, crtype, info) = arg;
872 test.write(""" printf(" %%d", n_%s);\n""" % (nam))
873 test.write(""" printf("\\n");\n""")
874 test.write(" }\n")
875
876 for arg in t_args:
877 test.write(" }\n")
878
879 test.write(" function_tests++;\n")
880 #
881 # end of conditional
882 #
883 while nb_cond > 0:
884 test.write("#endif\n")
885 nb_cond = nb_cond -1
886 if define == 1:
887 test.write("#endif\n")
888
889 nb_tests = nb_tests + 1;
890
891 test.write("""
892 return(test_ret);
893}
894
895""")
896
897#
898# Generate all module callers
899#
900for module in modules:
901 # gather all the functions exported by that module
902 try:
903 functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
904 except:
905 print "Failed to gather functions from module %s" % (module)
906 continue;
907
908 # iterate over all functions in the module generating the test
909 i = 0
910 nb_tests_old = nb_tests
911 for function in functions:
912 i = i + 1
913 generate_test(module, function);
914
915 # header
916 test.write("""static int
917test_%s(void) {
918 int test_ret = 0;
919
920 if (quiet == 0) printf("Testing %s : %d of %d functions ...\\n");
921""" % (module, module, nb_tests - nb_tests_old, i))
922
923 # iterate over all functions in the module generating the call
924 for function in functions:
925 name = function.xpathEval('string(@name)')
926 if is_skipped_function(name):
927 continue
928 test.write(" test_ret += test_%s();\n" % (name))
929
930 # footer
931 test.write("""
932 if (test_ret != 0)
933 printf("Module %s: %%d errors\\n", test_ret);
934 return(test_ret);
935}
936""" % (module))
937
938#
939# Generate direct module caller
940#
941test.write("""static int
942test_module(const char *module) {
943""");
944for module in modules:
945 test.write(""" if (!strcmp(module, "%s")) return(test_%s());\n""" % (
946 module, module))
947test.write(""" return(0);
948}
949""");
950
951print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
952
953compare_and_save()
954
955missing_list = []
956for missing in missing_types.keys():
957 if missing == 'va_list' or missing == '...':
958 continue;
959
960 n = len(missing_types[missing])
961 missing_list.append((n, missing))
962
963def compare_missing(a, b):
964 return b[0] - a[0]
965
966missing_list.sort(compare_missing)
967print "Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list))
968lst = open("missing.lst", "w")
969lst.write("Missing support for %d types" % (len(missing_list)))
970lst.write("\n")
971for miss in missing_list:
972 lst.write("%s: %d :" % (miss[1], miss[0]))
973 i = 0
974 for n in missing_types[miss[1]]:
975 i = i + 1
976 if i > 5:
977 lst.write(" ...")
978 break
979 lst.write(" %s" % (n))
980 lst.write("\n")
981lst.write("\n")
982lst.write("\n")
983lst.write("Missing support per module");
984for module in missing_functions.keys():
985 lst.write("module %s:\n %s\n" % (module, missing_functions[module]))
986
987lst.close()
988
989
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use