Annotation of embedaddon/libxml2/gentest.py, revision 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>