📄 gentest.py
字号:
#!/usr/bin/python -u## generate a tester program for the API#import sysimport osimport stringtry: import libxml2except: print "libxml2 python bindings not available, skipping testapi.c generation" sys.exit(0)if len(sys.argv) > 1: srcPref = sys.argv[1] + '/'else: srcPref = ''## Modules we want to skip in API test#skipped_modules = [ "SAX", "xlink", "threads", "globals", "xmlmemory", "xmlversion", "xmlexports", #deprecated "DOCBparser",]## defines for each module#modules_defines = { "HTMLparser": "LIBXML_HTML_ENABLED", "catalog": "LIBXML_CATALOG_ENABLED", "xmlreader": "LIBXML_READER_ENABLED", "relaxng": "LIBXML_SCHEMAS_ENABLED", "schemasInternals": "LIBXML_SCHEMAS_ENABLED", "xmlschemas": "LIBXML_SCHEMAS_ENABLED", "xmlschemastypes": "LIBXML_SCHEMAS_ENABLED", "xpath": "LIBXML_XPATH_ENABLED", "xpathInternals": "LIBXML_XPATH_ENABLED", "xinclude": "LIBXML_XINCLUDE_ENABLED", "xpointer": "LIBXML_XPTR_ENABLED", "xmlregexp" : "LIBXML_REGEXP_ENABLED", "xmlautomata" : "LIBXML_AUTOMATA_ENABLED", "xmlsave" : "LIBXML_OUTPUT_ENABLED", "DOCBparser" : "LIBXML_DOCB_ENABLED", "xmlmodule" : "LIBXML_MODULES_ENABLED", "pattern" : "LIBXML_PATTERN_ENABLED",}## defines for specific functions#function_defines = { "htmlDefaultSAXHandlerInit": "LIBXML_HTML_ENABLED", "xmlSAX2EndElement" : "LIBXML_SAX1_ENABLED", "xmlSAX2StartElement" : "LIBXML_SAX1_ENABLED", "xmlSAXDefaultVersion" : "LIBXML_SAX1_ENABLED", "UTF8Toisolat1" : "LIBXML_OUTPUT_ENABLED", "xmlCleanupPredefinedEntities": "LIBXML_LEGACY_ENABLED", "xmlInitializePredefinedEntities": "LIBXML_LEGACY_ENABLED", "xmlSetFeature": "LIBXML_LEGACY_ENABLED", "xmlGetFeature": "LIBXML_LEGACY_ENABLED", "xmlGetFeaturesList": "LIBXML_LEGACY_ENABLED", "xmlIOParseDTD": "LIBXML_VALID_ENABLED", "xmlParseDTD": "LIBXML_VALID_ENABLED", "xmlParseDoc": "LIBXML_SAX1_ENABLED", "xmlParseMemory": "LIBXML_SAX1_ENABLED", "xmlRecoverDoc": "LIBXML_SAX1_ENABLED", "xmlParseFile": "LIBXML_SAX1_ENABLED", "xmlRecoverFile": "LIBXML_SAX1_ENABLED", "xmlRecoverMemory": "LIBXML_SAX1_ENABLED", "xmlSAXParseFileWithData": "LIBXML_SAX1_ENABLED", "xmlSAXParseMemory": "LIBXML_SAX1_ENABLED", "xmlSAXUserParseMemory": "LIBXML_SAX1_ENABLED", "xmlSAXParseDoc": "LIBXML_SAX1_ENABLED", "xmlSAXParseDTD": "LIBXML_SAX1_ENABLED", "xmlSAXUserParseFile": "LIBXML_SAX1_ENABLED", "xmlParseEntity": "LIBXML_SAX1_ENABLED", "xmlParseExternalEntity": "LIBXML_SAX1_ENABLED", "xmlSAXParseMemoryWithData": "LIBXML_SAX1_ENABLED", "xmlParseBalancedChunkMemory": "LIBXML_SAX1_ENABLED", "xmlParseBalancedChunkMemoryRecover": "LIBXML_SAX1_ENABLED", "xmlSetupParserForBuffer": "LIBXML_SAX1_ENABLED", "xmlStopParser": "LIBXML_PUSH_ENABLED", "xmlAttrSerializeTxtContent": "LIBXML_OUTPUT_ENABLED", "xmlSAXParseFile": "LIBXML_SAX1_ENABLED", "xmlSAXParseEntity": "LIBXML_SAX1_ENABLED", "xmlNewTextChild": "LIBXML_TREE_ENABLED", "xmlNewDocRawNode": "LIBXML_TREE_ENABLED", "xmlNewProp": "LIBXML_TREE_ENABLED", "xmlReconciliateNs": "LIBXML_TREE_ENABLED", "xmlValidateNCName": "LIBXML_TREE_ENABLED", "xmlValidateNMToken": "LIBXML_TREE_ENABLED", "xmlValidateName": "LIBXML_TREE_ENABLED", "xmlNewChild": "LIBXML_TREE_ENABLED", "xmlValidateQName": "LIBXML_TREE_ENABLED", "xmlSprintfElementContent": "LIBXML_OUTPUT_ENABLED", "xmlValidGetPotentialChildren" : "LIBXML_VALID_ENABLED", "xmlValidGetValidElements" : "LIBXML_VALID_ENABLED", "docbDefaultSAXHandlerInit" : "LIBXML_DOCB_ENABLED", "xmlTextReaderPreservePattern" : "LIBXML_PATTERN_ENABLED",}## Some functions really need to be skipped for the tests.#skipped_functions = [# block on I/O"xmlFdRead", "xmlReadFd", "xmlCtxtReadFd","htmlFdRead", "htmlReadFd", "htmlCtxtReadFd","xmlReaderNewFd", "xmlReaderForFd","xmlIORead", "xmlReadIO", "xmlCtxtReadIO","htmlIORead", "htmlReadIO", "htmlCtxtReadIO","xmlReaderNewIO", "xmlBufferDump", "xmlNanoFTPConnect","xmlNanoFTPConnectTo", "xmlNanoHTTPMethod", "xmlNanoHTTPMethodRedir",# Complex I/O APIs"xmlCreateIOParserCtxt", "xmlParserInputBufferCreateIO","xmlRegisterInputCallbacks", "xmlReaderForIO","xmlOutputBufferCreateIO", "xmlRegisterOutputCallbacks","xmlSaveToIO", "xmlIOHTTPOpenW",# library state cleanup, generate false leak informations and other# troubles, heavillyb tested otherwise."xmlCleanupParser", "xmlRelaxNGCleanupTypes", "xmlSetListDoc","xmlSetTreeDoc", "xmlUnlinkNode",# hard to avoid leaks in the tests"xmlStrcat", "xmlStrncat", "xmlCatalogAddLocal", "xmlNewTextWriterDoc","xmlXPathNewValueTree", "xmlXPathWrapString",# unimplemented"xmlTextReaderReadInnerXml", "xmlTextReaderReadOuterXml","xmlTextReaderReadString",# destructor"xmlListDelete", "xmlOutputBufferClose", "xmlNanoFTPClose", "xmlNanoHTTPClose",# deprecated"xmlCatalogGetPublic", "xmlCatalogGetSystem", "xmlEncodeEntities","xmlNewGlobalNs", "xmlHandleEntity", "xmlNamespaceParseNCName","xmlNamespaceParseNSDef", "xmlNamespaceParseQName","xmlParseNamespace", "xmlParseQuotedString", "xmlParserHandleReference","xmlScanName","xmlDecodeEntities", # allocators"xmlMemFree",# verbosity"xmlCatalogSetDebug", "xmlShellPrintXPathError", "xmlShellPrintNode",# Internal functions, no user space should really call them"xmlParseAttribute", "xmlParseAttributeListDecl", "xmlParseName","xmlParseNmtoken", "xmlParseEntityValue", "xmlParseAttValue","xmlParseSystemLiteral", "xmlParsePubidLiteral", "xmlParseCharData","xmlParseExternalID", "xmlParseComment", "xmlParsePITarget", "xmlParsePI","xmlParseNotationDecl", "xmlParseEntityDecl", "xmlParseDefaultDecl","xmlParseNotationType", "xmlParseEnumerationType", "xmlParseEnumeratedType","xmlParseAttributeType", "xmlParseAttributeListDecl","xmlParseElementMixedContentDecl", "xmlParseElementChildrenContentDecl","xmlParseElementContentDecl", "xmlParseElementDecl", "xmlParseMarkupDecl","xmlParseCharRef", "xmlParseEntityRef", "xmlParseReference","xmlParsePEReference", "xmlParseDocTypeDecl", "xmlParseAttribute","xmlParseStartTag", "xmlParseEndTag", "xmlParseCDSect", "xmlParseContent","xmlParseElement", "xmlParseVersionNum", "xmlParseVersionInfo","xmlParseEncName", "xmlParseEncodingDecl", "xmlParseSDDecl","xmlParseXMLDecl", "xmlParseTextDecl", "xmlParseMisc","xmlParseExternalSubset", "xmlParserHandlePEReference","xmlSkipBlankChars",]## These functions have side effects on the global state# and hence generate errors on memory allocation tests#skipped_memcheck = [ "xmlLoadCatalog", "xmlAddEncodingAlias", "xmlSchemaInitTypes", "xmlNanoFTPProxy", "xmlNanoFTPScanProxy", "xmlNanoHTTPScanProxy", "xmlResetLastError", "xmlCatalogConvert", "xmlCatalogRemove", "xmlLoadCatalogs", "xmlCleanupCharEncodingHandlers", "xmlInitCharEncodingHandlers", "xmlCatalogCleanup", "xmlSchemaGetBuiltInType", "htmlParseFile", "htmlCtxtReadFile" # loads the catalogs]## Extra code needed for some test cases#extra_pre_call = { "xmlSAXUserParseFile": """#ifdef LIBXML_SAX1_ENABLED if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;#endif""", "xmlSAXUserParseMemory": """#ifdef LIBXML_SAX1_ENABLED if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;#endif""", "xmlParseBalancedChunkMemory": """#ifdef LIBXML_SAX1_ENABLED if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;#endif""", "xmlParseBalancedChunkMemoryRecover": """#ifdef LIBXML_SAX1_ENABLED if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;#endif""", "xmlParserInputBufferCreateFd": "if (fd >= 0) fd = -1;",}extra_post_call = { "xmlAddChild": "if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; }", "xmlAddChildList": "if (ret_val == NULL) { xmlFreeNodeList(cur) ; cur = NULL ; }", "xmlAddSibling": "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }", "xmlAddNextSibling": "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }", "xmlAddPrevSibling": "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }", "xmlDocSetRootElement": "if (doc == NULL) { xmlFreeNode(root) ; root = NULL ; }", "xmlReplaceNode": """if (cur != NULL) { xmlUnlinkNode(cur); xmlFreeNode(cur) ; cur = NULL ; } if (old != NULL) { xmlUnlinkNode(old); xmlFreeNode(old) ; old = NULL ; } ret_val = NULL;""", "xmlTextMerge": """if ((first != NULL) && (first->type != XML_TEXT_NODE)) { xmlUnlinkNode(second); xmlFreeNode(second) ; second = NULL ; }""", "xmlBuildQName": """if ((ret_val != NULL) && (ret_val != ncname) && (ret_val != prefix) && (ret_val != memory)) xmlFree(ret_val); ret_val = NULL;""", "xmlNewDocElementContent": """xmlFreeDocElementContent(doc, ret_val); ret_val = NULL;""", "xmlDictReference": "xmlDictFree(dict);", # Functions which deallocates one of their parameters "xmlXPathConvertBoolean": """val = NULL;""", "xmlXPathConvertNumber": """val = NULL;""", "xmlXPathConvertString": """val = NULL;""", "xmlSaveFileTo": """buf = NULL;""", "xmlSaveFormatFileTo": """buf = NULL;""", "xmlIOParseDTD": "input = NULL;", "xmlRemoveProp": "cur = NULL;", "xmlNewNs": "if ((node == NULL) && (ret_val != NULL)) xmlFreeNs(ret_val);", "xmlCopyNamespace": "if (ret_val != NULL) xmlFreeNs(ret_val);", "xmlCopyNamespaceList": "if (ret_val != NULL) xmlFreeNsList(ret_val);", "xmlNewTextWriter": "if (ret_val != NULL) out = NULL;", "xmlNewTextWriterPushParser": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;} if (ret_val != NULL) ctxt = NULL;", "xmlNewIOInputStream": "if (ret_val != NULL) input = NULL;", "htmlParseChunk": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}", "htmlParseDocument": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}", "xmlParseDocument": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}", "xmlParseChunk": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}", "xmlParseExtParsedEnt": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",}modules = []def is_skipped_module(name): for mod in skipped_modules: if mod == name: return 1 return 0def is_skipped_function(name): for fun in skipped_functions: if fun == name: return 1 # Do not test destructors if string.find(name, 'Free') != -1: return 1 return 0def is_skipped_memcheck(name): for fun in skipped_memcheck: if fun == name: return 1 return 0missing_types = {}def add_missing_type(name, func): try: list = missing_types[name] list.append(func) except: missing_types[name] = [func]generated_param_types = []def add_generated_param_type(name): generated_param_types.append(name)generated_return_types = []def add_generated_return_type(name): generated_return_types.append(name)missing_functions = {}missing_functions_nr = 0def add_missing_functions(name, module): global missing_functions_nr missing_functions_nr = missing_functions_nr + 1 try: list = missing_functions[module] list.append(name) except: missing_functions[module] = [name]## Provide the type generators and destructors for the parameters#def type_convert(str, name, info, module, function, pos):# res = string.replace(str, " ", " ")# res = string.replace(str, " ", " ")# res = string.replace(str, " ", " ") res = string.replace(str, " *", "_ptr")# res = string.replace(str, "*", "_ptr") res = string.replace(res, " ", "_") if res == 'const_char_ptr': if string.find(name, "file") != -1 or \ string.find(name, "uri") != -1 or \ string.find(name, "URI") != -1 or \ string.find(info, "filename") != -1 or \ string.find(info, "URI") != -1 or \ string.find(info, "URL") != -1: if string.find(function, "Save") != -1 or \ string.find(function, "Create") != -1 or \ string.find(function, "Write") != -1 or \ string.find(function, "Fetch") != -1: return('fileoutput') return('filepath') if res == 'void_ptr': if module == 'nanoftp' and name == 'ctx': return('xmlNanoFTPCtxtPtr') if function == 'xmlNanoFTPNewCtxt' or \ function == 'xmlNanoFTPConnectTo' or \ function == 'xmlNanoFTPOpen': return('xmlNanoFTPCtxtPtr') if module == 'nanohttp' and name == 'ctx': return('xmlNanoHTTPCtxtPtr') if function == 'xmlNanoHTTPMethod' or \ function == 'xmlNanoHTTPMethodRedir' or \ function == 'xmlNanoHTTPOpen' or \ function == 'xmlNanoHTTPOpenRedir': return('xmlNanoHTTPCtxtPtr'); if function == 'xmlIOHTTPOpen': return('xmlNanoHTTPCtxtPtr') if string.find(name, "data") != -1: return('userdata') if string.find(name, "user") != -1: return('userdata') if res == 'xmlDoc_ptr': res = 'xmlDocPtr' if res == 'xmlNode_ptr': res = 'xmlNodePtr' if res == 'xmlDict_ptr': res = 'xmlDictPtr' if res == 'xmlNodePtr' and pos != 0: if (function == 'xmlAddChild' and pos == 2) or \ (function == 'xmlAddChildList' and pos == 2) or \ (function == 'xmlAddNextSibling' and pos == 2) or \ (function == 'xmlAddSibling' and pos == 2) or \ (function == 'xmlDocSetRootElement' and pos == 2) or \ (function == 'xmlReplaceNode' and pos == 2) or \ (function == 'xmlTextMerge') or \ (function == 'xmlAddPrevSibling' and pos == 2): return('xmlNodePtr_in'); if res == 'const xmlBufferPtr': res = 'xmlBufferPtr' if res == 'xmlChar_ptr' and name == 'name' and \ string.find(function, "EatName") != -1: return('eaten_name') if res == 'void_ptr*': res = 'void_ptr_ptr' if res == 'char_ptr*': res = 'char_ptr_ptr' if res == 'xmlChar_ptr*': res = 'xmlChar_ptr_ptr' if res == 'const_xmlChar_ptr*': res = 'const_xmlChar_ptr_ptr' if res == 'const_char_ptr*': res = 'const_char_ptr_ptr' if res == 'FILE_ptr' and module == 'debugXML': res = 'debug_FILE_ptr'; if res == 'int' and name == 'options': if module == 'parser' or module == 'xmlreader': res = 'parseroptions' return resknown_param_types = []def is_known_param_type(name, rtype): global test for type in known_param_types: if type == name: return 1 for type in generated_param_types: if type == name: return 1 if name[-3:] == 'Ptr' or name[-4:] == '_ptr': if rtype[0:6] == 'const ': crtype = rtype[6:] else: crtype = rtype define = 0 if modules_defines.has_key(module): test.write("#ifdef %s\n" % (modules_defines[module])) define = 1 test.write("""#define gen_nb_%s 1static %s gen_%s(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { return(NULL);}static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {}""" % (name, crtype, name, name, rtype)) if define == 1: test.write("#endif\n\n") add_generated_param_type(name) return 1 return 0## Provide the type destructors for the return values#known_return_types = []def is_known_return_type(name): for type in known_return_types: if type == name: return 1 return 0## Copy the beginning of the C test program result#try: input = open("testapi.c", "r")except: input = open(srcPref + "testapi.c", "r")test = open('testapi.c.new', 'w')def compare_and_save(): global test test.close() try: input = open("testapi.c", "r").read() except: input = '' test = open('testapi.c.new', "r").read() if input != test: try: os.system("rm testapi.c; mv testapi.c.new testapi.c") except: os.system("mv testapi.c.new testapi.c") print("Updated testapi.c") else: print("Generated testapi.c is identical")line = input.readline()while line != "": if line == "/* CUT HERE: everything below that line is generated */\n": break; if line[0:15] == "#define gen_nb_": type = string.split(line[15:])[0] known_param_types.append(type) if line[0:19] == "static void desret_": type = string.split(line[19:], '(')[0]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -