Annotation of embedaddon/libxml2/gentest.py, revision 1.1.1.1
1.1 misho 1: #!/usr/bin/python -u
2: #
3: # generate a tester program for the API
4: #
5: import sys
6: import os
7: import string
8: try:
9: import libxml2
10: except:
11: print "libxml2 python bindings not available, skipping testapi.c generation"
12: sys.exit(0)
13:
14: if len(sys.argv) > 1:
15: srcPref = sys.argv[1] + '/'
16: else:
17: srcPref = ''
18:
19: #
20: # Modules we want to skip in API test
21: #
22: skipped_modules = [ "SAX", "xlink", "threads", "globals",
23: "xmlmemory", "xmlversion", "xmlexports",
24: #deprecated
25: "DOCBparser",
26: ]
27:
28: #
29: # defines for each module
30: #
31: modules_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: #
55: function_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: #
109: skipped_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: #
170: skipped_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: #
184: extra_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: }
208: extra_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:
266: modules = []
267:
268: def is_skipped_module(name):
269: for mod in skipped_modules:
270: if mod == name:
271: return 1
272: return 0
273:
274: def 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:
283: def is_skipped_memcheck(name):
284: for fun in skipped_memcheck:
285: if fun == name:
286: return 1
287: return 0
288:
289: missing_types = {}
290: def add_missing_type(name, func):
291: try:
292: list = missing_types[name]
293: list.append(func)
294: except:
295: missing_types[name] = [func]
296:
297: generated_param_types = []
298: def add_generated_param_type(name):
299: generated_param_types.append(name)
300:
301: generated_return_types = []
302: def add_generated_return_type(name):
303: generated_return_types.append(name)
304:
305: missing_functions = {}
306: missing_functions_nr = 0
307: def 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:
321: def 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:
400: known_param_types = []
401:
402: def is_known_param_type(name, rtype):
403: global test
404: for type in known_param_types:
405: if type == name:
406: return 1
407: for type in generated_param_types:
408: if type == name:
409: return 1
410:
411: if name[-3:] == 'Ptr' or name[-4:] == '_ptr':
412: if rtype[0:6] == 'const ':
413: crtype = rtype[6:]
414: else:
415: crtype = rtype
416:
417: define = 0
418: if modules_defines.has_key(module):
419: test.write("#ifdef %s\n" % (modules_defines[module]))
420: define = 1
421: test.write("""
422: #define gen_nb_%s 1
423: static %s gen_%s(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
424: return(NULL);
425: }
426: static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
427: }
428: """ % (name, crtype, name, name, rtype))
429: if define == 1:
430: test.write("#endif\n\n")
431: add_generated_param_type(name)
432: return 1
433:
434: return 0
435:
436: #
437: # Provide the type destructors for the return values
438: #
439:
440: known_return_types = []
441:
442: def is_known_return_type(name):
443: for type in known_return_types:
444: if type == name:
445: return 1
446: return 0
447:
448: #
449: # Copy the beginning of the C test program result
450: #
451:
452: try:
453: input = open("testapi.c", "r")
454: except:
455: input = open(srcPref + "testapi.c", "r")
456: test = open('testapi.c.new', 'w')
457:
458: def compare_and_save():
459: global test
460:
461: test.close()
462: try:
463: input = open("testapi.c", "r").read()
464: except:
465: input = ''
466: test = open('testapi.c.new', "r").read()
467: if input != test:
468: try:
469: os.system("rm testapi.c; mv testapi.c.new testapi.c")
470: except:
471: os.system("mv testapi.c.new testapi.c")
472: print("Updated testapi.c")
473: else:
474: print("Generated testapi.c is identical")
475:
476: line = input.readline()
477: while line != "":
478: if line == "/* CUT HERE: everything below that line is generated */\n":
479: break;
480: if line[0:15] == "#define gen_nb_":
481: type = string.split(line[15:])[0]
482: known_param_types.append(type)
483: if line[0:19] == "static void desret_":
484: type = string.split(line[19:], '(')[0]
485: known_return_types.append(type)
486: test.write(line)
487: line = input.readline()
488: input.close()
489:
490: if line == "":
491: print "Could not find the CUT marker in testapi.c skipping generation"
492: test.close()
493: sys.exit(0)
494:
495: print("Scanned testapi.c: found %d parameters types and %d return types\n" % (
496: len(known_param_types), len(known_return_types)))
497: test.write("/* CUT HERE: everything below that line is generated */\n")
498:
499:
500: #
501: # Open the input API description
502: #
503: doc = libxml2.readFile(srcPref + 'doc/libxml2-api.xml', None, 0)
504: if doc == None:
505: print "Failed to load doc/libxml2-api.xml"
506: sys.exit(1)
507: ctxt = doc.xpathNewContext()
508:
509: #
510: # Generate a list of all function parameters and select only
511: # those used in the api tests
512: #
513: argtypes = {}
514: args = ctxt.xpathEval("/api/symbols/function/arg")
515: for arg in args:
516: mod = arg.xpathEval('string(../@file)')
517: func = arg.xpathEval('string(../@name)')
518: if (mod not in skipped_modules) and (func not in skipped_functions):
519: type = arg.xpathEval('string(@type)')
520: if not argtypes.has_key(type):
521: argtypes[type] = func
522:
523: # similarly for return types
524: rettypes = {}
525: rets = ctxt.xpathEval("/api/symbols/function/return")
526: for ret in rets:
527: mod = ret.xpathEval('string(../@file)')
528: func = ret.xpathEval('string(../@name)')
529: if (mod not in skipped_modules) and (func not in skipped_functions):
530: type = ret.xpathEval('string(@type)')
531: if not rettypes.has_key(type):
532: rettypes[type] = func
533:
534: #
535: # Generate constructors and return type handling for all enums
536: # which are used as function parameters
537: #
538: enums = ctxt.xpathEval("/api/symbols/typedef[@type='enum']")
539: for enum in enums:
540: module = enum.xpathEval('string(@file)')
541: name = enum.xpathEval('string(@name)')
542: #
543: # Skip any enums which are not in our filtered lists
544: #
545: if (name == None) or ((name not in argtypes) and (name not in rettypes)):
546: continue;
547: define = 0
548:
549: if argtypes.has_key(name) and is_known_param_type(name, name) == 0:
550: values = ctxt.xpathEval("/api/symbols/enum[@type='%s']" % name)
551: i = 0
552: vals = []
553: for value in values:
554: vname = value.xpathEval('string(@name)')
555: if vname == None:
556: continue;
557: i = i + 1
558: if i >= 5:
559: break;
560: vals.append(vname)
561: if vals == []:
562: print "Didn't find any value for enum %s" % (name)
563: continue
564: if modules_defines.has_key(module):
565: test.write("#ifdef %s\n" % (modules_defines[module]))
566: define = 1
567: test.write("#define gen_nb_%s %d\n" % (name, len(vals)))
568: test.write("""static %s gen_%s(int no, int nr ATTRIBUTE_UNUSED) {\n""" %
569: (name, name))
570: i = 1
571: for value in vals:
572: test.write(" if (no == %d) return(%s);\n" % (i, value))
573: i = i + 1
574: test.write(""" return(0);
575: }
576:
577: static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
578: }
579:
580: """ % (name, name));
581: known_param_types.append(name)
582:
583: if (is_known_return_type(name) == 0) and (name in rettypes):
584: if define == 0 and modules_defines.has_key(module):
585: test.write("#ifdef %s\n" % (modules_defines[module]))
586: define = 1
587: test.write("""static void desret_%s(%s val ATTRIBUTE_UNUSED) {
588: }
589:
590: """ % (name, name))
591: known_return_types.append(name)
592: if define == 1:
593: test.write("#endif\n\n")
594:
595: #
596: # Load the interfaces
597: #
598: headers = ctxt.xpathEval("/api/files/file")
599: for file in headers:
600: name = file.xpathEval('string(@name)')
601: if (name == None) or (name == ''):
602: continue
603:
604: #
605: # Some module may be skipped because they don't really consists
606: # of user callable APIs
607: #
608: if is_skipped_module(name):
609: continue
610:
611: #
612: # do not test deprecated APIs
613: #
614: desc = file.xpathEval('string(description)')
615: if string.find(desc, 'DEPRECATED') != -1:
616: print "Skipping deprecated interface %s" % name
617: continue;
618:
619: test.write("#include <libxml/%s.h>\n" % name)
620: modules.append(name)
621:
622: #
623: # Generate the callers signatures
624: #
625: for module in modules:
626: test.write("static int test_%s(void);\n" % module);
627:
628: #
629: # Generate the top caller
630: #
631:
632: test.write("""
633: /**
634: * testlibxml2:
635: *
636: * Main entry point of the tester for the full libxml2 module,
637: * it calls all the tester entry point for each module.
638: *
639: * Returns the number of error found
640: */
641: static int
642: testlibxml2(void)
643: {
644: int test_ret = 0;
645:
646: """)
647:
648: for module in modules:
649: test.write(" test_ret += test_%s();\n" % module)
650:
651: test.write("""
652: printf("Total: %d functions, %d tests, %d errors\\n",
653: function_tests, call_tests, test_ret);
654: return(test_ret);
655: }
656:
657: """)
658:
659: #
660: # How to handle a function
661: #
662: nb_tests = 0
663:
664: def generate_test(module, node):
665: global test
666: global nb_tests
667: nb_cond = 0
668: no_gen = 0
669:
670: name = node.xpathEval('string(@name)')
671: if is_skipped_function(name):
672: return
673:
674: #
675: # check we know how to handle the args and return values
676: # and store the informations for the generation
677: #
678: try:
679: args = node.xpathEval("arg")
680: except:
681: args = []
682: t_args = []
683: n = 0
684: for arg in args:
685: n = n + 1
686: rtype = arg.xpathEval("string(@type)")
687: if rtype == 'void':
688: break;
689: info = arg.xpathEval("string(@info)")
690: nam = arg.xpathEval("string(@name)")
691: type = type_convert(rtype, nam, info, module, name, n)
692: if is_known_param_type(type, rtype) == 0:
693: add_missing_type(type, name);
694: no_gen = 1
695: if (type[-3:] == 'Ptr' or type[-4:] == '_ptr') and \
696: rtype[0:6] == 'const ':
697: crtype = rtype[6:]
698: else:
699: crtype = rtype
700: t_args.append((nam, type, rtype, crtype, info))
701:
702: try:
703: rets = node.xpathEval("return")
704: except:
705: rets = []
706: t_ret = None
707: for ret in rets:
708: rtype = ret.xpathEval("string(@type)")
709: info = ret.xpathEval("string(@info)")
710: type = type_convert(rtype, 'return', info, module, name, 0)
711: if rtype == 'void':
712: break
713: if is_known_return_type(type) == 0:
714: add_missing_type(type, name);
715: no_gen = 1
716: t_ret = (type, rtype, info)
717: break
718:
719: test.write("""
720: static int
721: test_%s(void) {
722: int test_ret = 0;
723:
724: """ % (name))
725:
726: if no_gen == 1:
727: add_missing_functions(name, module)
728: test.write("""
729: /* missing type support */
730: return(test_ret);
731: }
732:
733: """)
734: return
735:
736: try:
737: conds = node.xpathEval("cond")
738: for cond in conds:
739: test.write("#if %s\n" % (cond.get_content()))
740: nb_cond = nb_cond + 1
741: except:
742: pass
743:
744: define = 0
745: if function_defines.has_key(name):
746: test.write("#ifdef %s\n" % (function_defines[name]))
747: define = 1
748:
749: # Declare the memory usage counter
750: no_mem = is_skipped_memcheck(name)
751: if no_mem == 0:
752: test.write(" int mem_base;\n");
753:
754: # Declare the return value
755: if t_ret != None:
756: test.write(" %s ret_val;\n" % (t_ret[1]))
757:
758: # Declare the arguments
759: for arg in t_args:
760: (nam, type, rtype, crtype, info) = arg;
761: # add declaration
762: test.write(" %s %s; /* %s */\n" % (crtype, nam, info))
763: test.write(" int n_%s;\n" % (nam))
764: test.write("\n")
765:
766: # Cascade loop on of each argument list of values
767: for arg in t_args:
768: (nam, type, rtype, crtype, info) = arg;
769: #
770: test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
771: nam, nam, type, nam))
772:
773: # log the memory usage
774: if no_mem == 0:
775: test.write(" mem_base = xmlMemBlocks();\n");
776:
777: # prepare the call
778: i = 0;
779: for arg in t_args:
780: (nam, type, rtype, crtype, info) = arg;
781: #
782: test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
783: i = i + 1;
784:
785: # do the call, and clanup the result
786: if extra_pre_call.has_key(name):
787: test.write(" %s\n"% (extra_pre_call[name]))
788: if t_ret != None:
789: test.write("\n ret_val = %s(" % (name))
790: need = 0
791: for arg in t_args:
792: (nam, type, rtype, crtype, info) = arg
793: if need:
794: test.write(", ")
795: else:
796: need = 1
797: if rtype != crtype:
798: test.write("(%s)" % rtype)
799: test.write("%s" % nam);
800: test.write(");\n")
801: if extra_post_call.has_key(name):
802: test.write(" %s\n"% (extra_post_call[name]))
803: test.write(" desret_%s(ret_val);\n" % t_ret[0])
804: else:
805: test.write("\n %s(" % (name));
806: need = 0;
807: for arg in t_args:
808: (nam, type, rtype, crtype, info) = arg;
809: if need:
810: test.write(", ")
811: else:
812: need = 1
813: if rtype != crtype:
814: test.write("(%s)" % rtype)
815: test.write("%s" % nam)
816: test.write(");\n")
817: if extra_post_call.has_key(name):
818: test.write(" %s\n"% (extra_post_call[name]))
819:
820: test.write(" call_tests++;\n");
821:
822: # Free the arguments
823: i = 0;
824: for arg in t_args:
825: (nam, type, rtype, crtype, info) = arg;
826: # This is a hack to prevent generating a destructor for the
827: # 'input' argument in xmlTextReaderSetup. There should be
828: # a better, more generic way to do this!
829: if string.find(info, 'destroy') == -1:
830: test.write(" des_%s(n_%s, " % (type, nam))
831: if rtype != crtype:
832: test.write("(%s)" % rtype)
833: test.write("%s, %d);\n" % (nam, i))
834: i = i + 1;
835:
836: test.write(" xmlResetLastError();\n");
837: # Check the memory usage
838: if no_mem == 0:
839: test.write(""" if (mem_base != xmlMemBlocks()) {
840: printf("Leak of %%d blocks found in %s",
841: xmlMemBlocks() - mem_base);
842: test_ret++;
843: """ % (name));
844: for arg in t_args:
845: (nam, type, rtype, crtype, info) = arg;
846: test.write(""" printf(" %%d", n_%s);\n""" % (nam))
847: test.write(""" printf("\\n");\n""")
848: test.write(" }\n")
849:
850: for arg in t_args:
851: test.write(" }\n")
852:
853: test.write(" function_tests++;\n")
854: #
855: # end of conditional
856: #
857: while nb_cond > 0:
858: test.write("#endif\n")
859: nb_cond = nb_cond -1
860: if define == 1:
861: test.write("#endif\n")
862:
863: nb_tests = nb_tests + 1;
864:
865: test.write("""
866: return(test_ret);
867: }
868:
869: """)
870:
871: #
872: # Generate all module callers
873: #
874: for module in modules:
875: # gather all the functions exported by that module
876: try:
877: functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
878: except:
879: print "Failed to gather functions from module %s" % (module)
880: continue;
881:
882: # iterate over all functions in the module generating the test
883: i = 0
884: nb_tests_old = nb_tests
885: for function in functions:
886: i = i + 1
887: generate_test(module, function);
888:
889: # header
890: test.write("""static int
891: test_%s(void) {
892: int test_ret = 0;
893:
894: if (quiet == 0) printf("Testing %s : %d of %d functions ...\\n");
895: """ % (module, module, nb_tests - nb_tests_old, i))
896:
897: # iterate over all functions in the module generating the call
898: for function in functions:
899: name = function.xpathEval('string(@name)')
900: if is_skipped_function(name):
901: continue
902: test.write(" test_ret += test_%s();\n" % (name))
903:
904: # footer
905: test.write("""
906: if (test_ret != 0)
907: printf("Module %s: %%d errors\\n", test_ret);
908: return(test_ret);
909: }
910: """ % (module))
911:
912: #
913: # Generate direct module caller
914: #
915: test.write("""static int
916: test_module(const char *module) {
917: """);
918: for module in modules:
919: test.write(""" if (!strcmp(module, "%s")) return(test_%s());\n""" % (
920: module, module))
921: test.write(""" return(0);
922: }
923: """);
924:
925: print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
926:
927: compare_and_save()
928:
929: missing_list = []
930: for missing in missing_types.keys():
931: if missing == 'va_list' or missing == '...':
932: continue;
933:
934: n = len(missing_types[missing])
935: missing_list.append((n, missing))
936:
937: def compare_missing(a, b):
938: return b[0] - a[0]
939:
940: missing_list.sort(compare_missing)
941: print "Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list))
942: lst = open("missing.lst", "w")
943: lst.write("Missing support for %d types" % (len(missing_list)))
944: lst.write("\n")
945: for miss in missing_list:
946: lst.write("%s: %d :" % (miss[1], miss[0]))
947: i = 0
948: for n in missing_types[miss[1]]:
949: i = i + 1
950: if i > 5:
951: lst.write(" ...")
952: break
953: lst.write(" %s" % (n))
954: lst.write("\n")
955: lst.write("\n")
956: lst.write("\n")
957: lst.write("Missing support per module");
958: for module in missing_functions.keys():
959: lst.write("module %s:\n %s\n" % (module, missing_functions[module]))
960:
961: lst.close()
962:
963:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>