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>