gentest.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  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. if len(sys.argv) > 1:
  14. srcPref = sys.argv[1] + '/'
  15. else:
  16. srcPref = ''
  17. #
  18. # Modules we want to skip in API test
  19. #
  20. skipped_modules = [ "SAX", "xlink", "threads", "globals",
  21. "xmlmemory", "xmlversion", "xmlexports",
  22. #deprecated
  23. "DOCBparser",
  24. ]
  25. #
  26. # defines for each module
  27. #
  28. modules_defines = {
  29. "HTMLparser": "LIBXML_HTML_ENABLED",
  30. "catalog": "LIBXML_CATALOG_ENABLED",
  31. "xmlreader": "LIBXML_READER_ENABLED",
  32. "relaxng": "LIBXML_SCHEMAS_ENABLED",
  33. "schemasInternals": "LIBXML_SCHEMAS_ENABLED",
  34. "xmlschemas": "LIBXML_SCHEMAS_ENABLED",
  35. "xmlschemastypes": "LIBXML_SCHEMAS_ENABLED",
  36. "xpath": "LIBXML_XPATH_ENABLED",
  37. "xpathInternals": "LIBXML_XPATH_ENABLED",
  38. "xinclude": "LIBXML_XINCLUDE_ENABLED",
  39. "xpointer": "LIBXML_XPTR_ENABLED",
  40. "xmlregexp" : "LIBXML_REGEXP_ENABLED",
  41. "xmlautomata" : "LIBXML_AUTOMATA_ENABLED",
  42. "xmlsave" : "LIBXML_OUTPUT_ENABLED",
  43. "DOCBparser" : "LIBXML_DOCB_ENABLED",
  44. "xmlmodule" : "LIBXML_MODULES_ENABLED",
  45. "pattern" : "LIBXML_PATTERN_ENABLED",
  46. "schematron" : "LIBXML_SCHEMATRON_ENABLED",
  47. }
  48. #
  49. # defines for specific functions
  50. #
  51. function_defines = {
  52. "htmlDefaultSAXHandlerInit": "LIBXML_HTML_ENABLED",
  53. "xmlSAX2EndElement" : "LIBXML_SAX1_ENABLED",
  54. "xmlSAX2StartElement" : "LIBXML_SAX1_ENABLED",
  55. "xmlSAXDefaultVersion" : "LIBXML_SAX1_ENABLED",
  56. "UTF8Toisolat1" : "LIBXML_OUTPUT_ENABLED",
  57. "xmlCleanupPredefinedEntities": "LIBXML_LEGACY_ENABLED",
  58. "xmlInitializePredefinedEntities": "LIBXML_LEGACY_ENABLED",
  59. "xmlSetFeature": "LIBXML_LEGACY_ENABLED",
  60. "xmlGetFeature": "LIBXML_LEGACY_ENABLED",
  61. "xmlGetFeaturesList": "LIBXML_LEGACY_ENABLED",
  62. "xmlIOParseDTD": "LIBXML_VALID_ENABLED",
  63. "xmlParseDTD": "LIBXML_VALID_ENABLED",
  64. "xmlParseDoc": "LIBXML_SAX1_ENABLED",
  65. "xmlParseMemory": "LIBXML_SAX1_ENABLED",
  66. "xmlRecoverDoc": "LIBXML_SAX1_ENABLED",
  67. "xmlParseFile": "LIBXML_SAX1_ENABLED",
  68. "xmlRecoverFile": "LIBXML_SAX1_ENABLED",
  69. "xmlRecoverMemory": "LIBXML_SAX1_ENABLED",
  70. "xmlSAXParseFileWithData": "LIBXML_SAX1_ENABLED",
  71. "xmlSAXParseMemory": "LIBXML_SAX1_ENABLED",
  72. "xmlSAXUserParseMemory": "LIBXML_SAX1_ENABLED",
  73. "xmlSAXParseDoc": "LIBXML_SAX1_ENABLED",
  74. "xmlSAXParseDTD": "LIBXML_SAX1_ENABLED",
  75. "xmlSAXUserParseFile": "LIBXML_SAX1_ENABLED",
  76. "xmlParseEntity": "LIBXML_SAX1_ENABLED",
  77. "xmlParseExternalEntity": "LIBXML_SAX1_ENABLED",
  78. "xmlSAXParseMemoryWithData": "LIBXML_SAX1_ENABLED",
  79. "xmlParseBalancedChunkMemory": "LIBXML_SAX1_ENABLED",
  80. "xmlParseBalancedChunkMemoryRecover": "LIBXML_SAX1_ENABLED",
  81. "xmlSetupParserForBuffer": "LIBXML_SAX1_ENABLED",
  82. "xmlStopParser": "LIBXML_PUSH_ENABLED",
  83. "xmlAttrSerializeTxtContent": "LIBXML_OUTPUT_ENABLED",
  84. "xmlSAXParseFile": "LIBXML_SAX1_ENABLED",
  85. "xmlSAXParseEntity": "LIBXML_SAX1_ENABLED",
  86. "xmlNewTextChild": "LIBXML_TREE_ENABLED",
  87. "xmlNewDocRawNode": "LIBXML_TREE_ENABLED",
  88. "xmlNewProp": "LIBXML_TREE_ENABLED",
  89. "xmlReconciliateNs": "LIBXML_TREE_ENABLED",
  90. "xmlValidateNCName": "LIBXML_TREE_ENABLED",
  91. "xmlValidateNMToken": "LIBXML_TREE_ENABLED",
  92. "xmlValidateName": "LIBXML_TREE_ENABLED",
  93. "xmlNewChild": "LIBXML_TREE_ENABLED",
  94. "xmlValidateQName": "LIBXML_TREE_ENABLED",
  95. "xmlSprintfElementContent": "LIBXML_OUTPUT_ENABLED",
  96. "xmlValidGetPotentialChildren" : "LIBXML_VALID_ENABLED",
  97. "xmlValidGetValidElements" : "LIBXML_VALID_ENABLED",
  98. "docbDefaultSAXHandlerInit" : "LIBXML_DOCB_ENABLED",
  99. "xmlTextReaderPreservePattern" : "LIBXML_PATTERN_ENABLED",
  100. }
  101. #
  102. # Some functions really need to be skipped for the tests.
  103. #
  104. skipped_functions = [
  105. # block on I/O
  106. "xmlFdRead", "xmlReadFd", "xmlCtxtReadFd",
  107. "htmlFdRead", "htmlReadFd", "htmlCtxtReadFd",
  108. "xmlReaderNewFd", "xmlReaderForFd",
  109. "xmlIORead", "xmlReadIO", "xmlCtxtReadIO",
  110. "htmlIORead", "htmlReadIO", "htmlCtxtReadIO",
  111. "xmlReaderNewIO", "xmlBufferDump", "xmlNanoFTPConnect",
  112. "xmlNanoFTPConnectTo", "xmlNanoHTTPMethod", "xmlNanoHTTPMethodRedir",
  113. # Complex I/O APIs
  114. "xmlCreateIOParserCtxt", "xmlParserInputBufferCreateIO",
  115. "xmlRegisterInputCallbacks", "xmlReaderForIO",
  116. "xmlOutputBufferCreateIO", "xmlRegisterOutputCallbacks",
  117. "xmlSaveToIO", "xmlIOHTTPOpenW",
  118. # library state cleanup, generate false leak informations and other
  119. # troubles, heavillyb tested otherwise.
  120. "xmlCleanupParser", "xmlRelaxNGCleanupTypes", "xmlSetListDoc",
  121. "xmlSetTreeDoc", "xmlUnlinkNode",
  122. # hard to avoid leaks in the tests
  123. "xmlStrcat", "xmlStrncat", "xmlCatalogAddLocal", "xmlNewTextWriterDoc",
  124. "xmlXPathNewValueTree", "xmlXPathWrapString",
  125. # unimplemented
  126. "xmlTextReaderReadInnerXml", "xmlTextReaderReadOuterXml",
  127. "xmlTextReaderReadString",
  128. # destructor
  129. "xmlListDelete", "xmlOutputBufferClose", "xmlNanoFTPClose", "xmlNanoHTTPClose",
  130. # deprecated
  131. "xmlCatalogGetPublic", "xmlCatalogGetSystem", "xmlEncodeEntities",
  132. "xmlNewGlobalNs", "xmlHandleEntity", "xmlNamespaceParseNCName",
  133. "xmlNamespaceParseNSDef", "xmlNamespaceParseQName",
  134. "xmlParseNamespace", "xmlParseQuotedString", "xmlParserHandleReference",
  135. "xmlScanName",
  136. "xmlDecodeEntities",
  137. # allocators
  138. "xmlMemFree",
  139. # verbosity
  140. "xmlCatalogSetDebug", "xmlShellPrintXPathError", "xmlShellPrintNode",
  141. # Internal functions, no user space should really call them
  142. "xmlParseAttribute", "xmlParseAttributeListDecl", "xmlParseName",
  143. "xmlParseNmtoken", "xmlParseEntityValue", "xmlParseAttValue",
  144. "xmlParseSystemLiteral", "xmlParsePubidLiteral", "xmlParseCharData",
  145. "xmlParseExternalID", "xmlParseComment", "xmlParsePITarget", "xmlParsePI",
  146. "xmlParseNotationDecl", "xmlParseEntityDecl", "xmlParseDefaultDecl",
  147. "xmlParseNotationType", "xmlParseEnumerationType", "xmlParseEnumeratedType",
  148. "xmlParseAttributeType", "xmlParseAttributeListDecl",
  149. "xmlParseElementMixedContentDecl", "xmlParseElementChildrenContentDecl",
  150. "xmlParseElementContentDecl", "xmlParseElementDecl", "xmlParseMarkupDecl",
  151. "xmlParseCharRef", "xmlParseEntityRef", "xmlParseReference",
  152. "xmlParsePEReference", "xmlParseDocTypeDecl", "xmlParseAttribute",
  153. "xmlParseStartTag", "xmlParseEndTag", "xmlParseCDSect", "xmlParseContent",
  154. "xmlParseElement", "xmlParseVersionNum", "xmlParseVersionInfo",
  155. "xmlParseEncName", "xmlParseEncodingDecl", "xmlParseSDDecl",
  156. "xmlParseXMLDecl", "xmlParseTextDecl", "xmlParseMisc",
  157. "xmlParseExternalSubset", "xmlParserHandlePEReference",
  158. "xmlSkipBlankChars",
  159. ]
  160. #
  161. # These functions have side effects on the global state
  162. # and hence generate errors on memory allocation tests
  163. #
  164. skipped_memcheck = [ "xmlLoadCatalog", "xmlAddEncodingAlias",
  165. "xmlSchemaInitTypes", "xmlNanoFTPProxy", "xmlNanoFTPScanProxy",
  166. "xmlNanoHTTPScanProxy", "xmlResetLastError", "xmlCatalogConvert",
  167. "xmlCatalogRemove", "xmlLoadCatalogs", "xmlCleanupCharEncodingHandlers",
  168. "xmlInitCharEncodingHandlers", "xmlCatalogCleanup",
  169. "xmlSchemaGetBuiltInType",
  170. "htmlParseFile", "htmlCtxtReadFile", # loads the catalogs
  171. "xmlTextReaderSchemaValidate", "xmlSchemaCleanupTypes", # initialize the schemas type system
  172. "xmlCatalogResolve", "xmlIOParseDTD" # loads the catalogs
  173. ]
  174. #
  175. # Extra code needed for some test cases
  176. #
  177. extra_pre_call = {
  178. "xmlSAXUserParseFile": """
  179. #ifdef LIBXML_SAX1_ENABLED
  180. if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
  181. #endif
  182. """,
  183. "xmlSAXUserParseMemory": """
  184. #ifdef LIBXML_SAX1_ENABLED
  185. if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
  186. #endif
  187. """,
  188. "xmlParseBalancedChunkMemory": """
  189. #ifdef LIBXML_SAX1_ENABLED
  190. if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
  191. #endif
  192. """,
  193. "xmlParseBalancedChunkMemoryRecover": """
  194. #ifdef LIBXML_SAX1_ENABLED
  195. if (sax == (xmlSAXHandlerPtr)&xmlDefaultSAXHandler) user_data = NULL;
  196. #endif
  197. """,
  198. "xmlParserInputBufferCreateFd":
  199. "if (fd >= 0) fd = -1;",
  200. }
  201. extra_post_call = {
  202. "xmlAddChild":
  203. "if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; }",
  204. "xmlAddEntity":
  205. "if (ret_val != NULL) { xmlFreeNode(ret_val) ; ret_val = NULL; }",
  206. "xmlAddChildList":
  207. "if (ret_val == NULL) { xmlFreeNodeList(cur) ; cur = NULL ; }",
  208. "xmlAddSibling":
  209. "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
  210. "xmlAddNextSibling":
  211. "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
  212. "xmlAddPrevSibling":
  213. "if (ret_val == NULL) { xmlFreeNode(elem) ; elem = NULL ; }",
  214. "xmlDocSetRootElement":
  215. "if (doc == NULL) { xmlFreeNode(root) ; root = NULL ; }",
  216. "xmlReplaceNode":
  217. """if (cur != NULL) {
  218. xmlUnlinkNode(cur);
  219. xmlFreeNode(cur) ; cur = NULL ; }
  220. if (old != NULL) {
  221. xmlUnlinkNode(old);
  222. xmlFreeNode(old) ; old = NULL ; }
  223. ret_val = NULL;""",
  224. "xmlTextMerge":
  225. """if ((first != NULL) && (first->type != XML_TEXT_NODE)) {
  226. xmlUnlinkNode(second);
  227. xmlFreeNode(second) ; second = NULL ; }""",
  228. "xmlBuildQName":
  229. """if ((ret_val != NULL) && (ret_val != ncname) &&
  230. (ret_val != prefix) && (ret_val != memory))
  231. xmlFree(ret_val);
  232. ret_val = NULL;""",
  233. "xmlNewDocElementContent":
  234. """xmlFreeDocElementContent(doc, ret_val); ret_val = NULL;""",
  235. "xmlDictReference": "xmlDictFree(dict);",
  236. # Functions which deallocates one of their parameters
  237. "xmlXPathConvertBoolean": """val = NULL;""",
  238. "xmlXPathConvertNumber": """val = NULL;""",
  239. "xmlXPathConvertString": """val = NULL;""",
  240. "xmlSaveFileTo": """buf = NULL;""",
  241. "xmlSaveFormatFileTo": """buf = NULL;""",
  242. "xmlIOParseDTD": "input = NULL;",
  243. "xmlRemoveProp": "cur = NULL;",
  244. "xmlNewNs": "if ((node == NULL) && (ret_val != NULL)) xmlFreeNs(ret_val);",
  245. "xmlCopyNamespace": "if (ret_val != NULL) xmlFreeNs(ret_val);",
  246. "xmlCopyNamespaceList": "if (ret_val != NULL) xmlFreeNsList(ret_val);",
  247. "xmlNewTextWriter": "if (ret_val != NULL) out = NULL;",
  248. "xmlNewTextWriterPushParser": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;} if (ret_val != NULL) ctxt = NULL;",
  249. "xmlNewIOInputStream": "if (ret_val != NULL) input = NULL;",
  250. "htmlParseChunk": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
  251. "htmlParseDocument": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
  252. "xmlParseDocument": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
  253. "xmlParseChunk": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
  254. "xmlParseExtParsedEnt": "if (ctxt != NULL) {xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;}",
  255. "xmlDOMWrapAdoptNode": "if ((node != NULL) && (node->parent == NULL)) {xmlUnlinkNode(node);xmlFreeNode(node);node = NULL;}",
  256. "xmlBufferSetAllocationScheme": "if ((buf != NULL) && (scheme == XML_BUFFER_ALLOC_IMMUTABLE) && (buf->content != NULL) && (buf->content != static_buf_content)) { xmlFree(buf->content); buf->content = NULL;}"
  257. }
  258. modules = []
  259. def is_skipped_module(name):
  260. for mod in skipped_modules:
  261. if mod == name:
  262. return 1
  263. return 0
  264. def is_skipped_function(name):
  265. for fun in skipped_functions:
  266. if fun == name:
  267. return 1
  268. # Do not test destructors
  269. if string.find(name, 'Free') != -1:
  270. return 1
  271. return 0
  272. def is_skipped_memcheck(name):
  273. for fun in skipped_memcheck:
  274. if fun == name:
  275. return 1
  276. return 0
  277. missing_types = {}
  278. def add_missing_type(name, func):
  279. try:
  280. list = missing_types[name]
  281. list.append(func)
  282. except:
  283. missing_types[name] = [func]
  284. generated_param_types = []
  285. def add_generated_param_type(name):
  286. generated_param_types.append(name)
  287. generated_return_types = []
  288. def add_generated_return_type(name):
  289. generated_return_types.append(name)
  290. missing_functions = {}
  291. missing_functions_nr = 0
  292. def add_missing_functions(name, module):
  293. global missing_functions_nr
  294. missing_functions_nr = missing_functions_nr + 1
  295. try:
  296. list = missing_functions[module]
  297. list.append(name)
  298. except:
  299. missing_functions[module] = [name]
  300. #
  301. # Provide the type generators and destructors for the parameters
  302. #
  303. def type_convert(str, name, info, module, function, pos):
  304. # res = string.replace(str, " ", " ")
  305. # res = string.replace(str, " ", " ")
  306. # res = string.replace(str, " ", " ")
  307. res = string.replace(str, " *", "_ptr")
  308. # res = string.replace(str, "*", "_ptr")
  309. res = string.replace(res, " ", "_")
  310. if res == 'const_char_ptr':
  311. if string.find(name, "file") != -1 or \
  312. string.find(name, "uri") != -1 or \
  313. string.find(name, "URI") != -1 or \
  314. string.find(info, "filename") != -1 or \
  315. string.find(info, "URI") != -1 or \
  316. string.find(info, "URL") != -1:
  317. if string.find(function, "Save") != -1 or \
  318. string.find(function, "Create") != -1 or \
  319. string.find(function, "Write") != -1 or \
  320. string.find(function, "Fetch") != -1:
  321. return('fileoutput')
  322. return('filepath')
  323. if res == 'void_ptr':
  324. if module == 'nanoftp' and name == 'ctx':
  325. return('xmlNanoFTPCtxtPtr')
  326. if function == 'xmlNanoFTPNewCtxt' or \
  327. function == 'xmlNanoFTPConnectTo' or \
  328. function == 'xmlNanoFTPOpen':
  329. return('xmlNanoFTPCtxtPtr')
  330. if module == 'nanohttp' and name == 'ctx':
  331. return('xmlNanoHTTPCtxtPtr')
  332. if function == 'xmlNanoHTTPMethod' or \
  333. function == 'xmlNanoHTTPMethodRedir' or \
  334. function == 'xmlNanoHTTPOpen' or \
  335. function == 'xmlNanoHTTPOpenRedir':
  336. return('xmlNanoHTTPCtxtPtr');
  337. if function == 'xmlIOHTTPOpen':
  338. return('xmlNanoHTTPCtxtPtr')
  339. if string.find(name, "data") != -1:
  340. return('userdata')
  341. if string.find(name, "user") != -1:
  342. return('userdata')
  343. if res == 'xmlDoc_ptr':
  344. res = 'xmlDocPtr'
  345. if res == 'xmlNode_ptr':
  346. res = 'xmlNodePtr'
  347. if res == 'xmlDict_ptr':
  348. res = 'xmlDictPtr'
  349. if res == 'xmlNodePtr' and pos != 0:
  350. if (function == 'xmlAddChild' and pos == 2) or \
  351. (function == 'xmlAddChildList' and pos == 2) or \
  352. (function == 'xmlAddNextSibling' and pos == 2) or \
  353. (function == 'xmlAddSibling' and pos == 2) or \
  354. (function == 'xmlDocSetRootElement' and pos == 2) or \
  355. (function == 'xmlReplaceNode' and pos == 2) or \
  356. (function == 'xmlTextMerge') or \
  357. (function == 'xmlAddPrevSibling' and pos == 2):
  358. return('xmlNodePtr_in');
  359. if res == 'const xmlBufferPtr':
  360. res = 'xmlBufferPtr'
  361. if res == 'xmlChar_ptr' and name == 'name' and \
  362. string.find(function, "EatName") != -1:
  363. return('eaten_name')
  364. if res == 'void_ptr*':
  365. res = 'void_ptr_ptr'
  366. if res == 'char_ptr*':
  367. res = 'char_ptr_ptr'
  368. if res == 'xmlChar_ptr*':
  369. res = 'xmlChar_ptr_ptr'
  370. if res == 'const_xmlChar_ptr*':
  371. res = 'const_xmlChar_ptr_ptr'
  372. if res == 'const_char_ptr*':
  373. res = 'const_char_ptr_ptr'
  374. if res == 'FILE_ptr' and module == 'debugXML':
  375. res = 'debug_FILE_ptr';
  376. if res == 'int' and name == 'options':
  377. if module == 'parser' or module == 'xmlreader':
  378. res = 'parseroptions'
  379. return res
  380. known_param_types = []
  381. def is_known_param_type(name, rtype):
  382. global test
  383. for type in known_param_types:
  384. if type == name:
  385. return 1
  386. for type in generated_param_types:
  387. if type == name:
  388. return 1
  389. if name[-3:] == 'Ptr' or name[-4:] == '_ptr':
  390. if rtype[0:6] == 'const ':
  391. crtype = rtype[6:]
  392. else:
  393. crtype = rtype
  394. define = 0
  395. if modules_defines.has_key(module):
  396. test.write("#ifdef %s\n" % (modules_defines[module]))
  397. define = 1
  398. test.write("""
  399. #define gen_nb_%s 1
  400. static %s gen_%s(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
  401. return(NULL);
  402. }
  403. static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
  404. }
  405. """ % (name, crtype, name, name, rtype))
  406. if define == 1:
  407. test.write("#endif\n\n")
  408. add_generated_param_type(name)
  409. return 1
  410. return 0
  411. #
  412. # Provide the type destructors for the return values
  413. #
  414. known_return_types = []
  415. def is_known_return_type(name):
  416. for type in known_return_types:
  417. if type == name:
  418. return 1
  419. return 0
  420. #
  421. # Copy the beginning of the C test program result
  422. #
  423. try:
  424. input = open("testapi.c", "r")
  425. except:
  426. input = open(srcPref + "testapi.c", "r")
  427. test = open('testapi.c.new', 'w')
  428. def compare_and_save():
  429. global test
  430. test.close()
  431. try:
  432. input = open("testapi.c", "r").read()
  433. except:
  434. input = ''
  435. test = open('testapi.c.new', "r").read()
  436. if input != test:
  437. try:
  438. os.system("rm testapi.c; mv testapi.c.new testapi.c")
  439. except:
  440. os.system("mv testapi.c.new testapi.c")
  441. print("Updated testapi.c")
  442. else:
  443. print("Generated testapi.c is identical")
  444. line = input.readline()
  445. while line != "":
  446. if line == "/* CUT HERE: everything below that line is generated */\n":
  447. break;
  448. if line[0:15] == "#define gen_nb_":
  449. type = string.split(line[15:])[0]
  450. known_param_types.append(type)
  451. if line[0:19] == "static void desret_":
  452. type = string.split(line[19:], '(')[0]
  453. known_return_types.append(type)
  454. test.write(line)
  455. line = input.readline()
  456. input.close()
  457. if line == "":
  458. print "Could not find the CUT marker in testapi.c skipping generation"
  459. test.close()
  460. sys.exit(0)
  461. print("Scanned testapi.c: found %d parameters types and %d return types\n" % (
  462. len(known_param_types), len(known_return_types)))
  463. test.write("/* CUT HERE: everything below that line is generated */\n")
  464. #
  465. # Open the input API description
  466. #
  467. doc = libxml2.readFile(srcPref + 'doc/libxml2-api.xml', None, 0)
  468. if doc == None:
  469. print "Failed to load doc/libxml2-api.xml"
  470. sys.exit(1)
  471. ctxt = doc.xpathNewContext()
  472. #
  473. # Generate a list of all function parameters and select only
  474. # those used in the api tests
  475. #
  476. argtypes = {}
  477. args = ctxt.xpathEval("/api/symbols/function/arg")
  478. for arg in args:
  479. mod = arg.xpathEval('string(../@file)')
  480. func = arg.xpathEval('string(../@name)')
  481. if (mod not in skipped_modules) and (func not in skipped_functions):
  482. type = arg.xpathEval('string(@type)')
  483. if not argtypes.has_key(type):
  484. argtypes[type] = func
  485. # similarly for return types
  486. rettypes = {}
  487. rets = ctxt.xpathEval("/api/symbols/function/return")
  488. for ret in rets:
  489. mod = ret.xpathEval('string(../@file)')
  490. func = ret.xpathEval('string(../@name)')
  491. if (mod not in skipped_modules) and (func not in skipped_functions):
  492. type = ret.xpathEval('string(@type)')
  493. if not rettypes.has_key(type):
  494. rettypes[type] = func
  495. #
  496. # Generate constructors and return type handling for all enums
  497. # which are used as function parameters
  498. #
  499. enums = ctxt.xpathEval("/api/symbols/typedef[@type='enum']")
  500. for enum in enums:
  501. module = enum.xpathEval('string(@file)')
  502. name = enum.xpathEval('string(@name)')
  503. #
  504. # Skip any enums which are not in our filtered lists
  505. #
  506. if (name == None) or ((name not in argtypes) and (name not in rettypes)):
  507. continue;
  508. define = 0
  509. if argtypes.has_key(name) and is_known_param_type(name, name) == 0:
  510. values = ctxt.xpathEval("/api/symbols/enum[@type='%s']" % name)
  511. i = 0
  512. vals = []
  513. for value in values:
  514. vname = value.xpathEval('string(@name)')
  515. if vname == None:
  516. continue;
  517. i = i + 1
  518. if i >= 5:
  519. break;
  520. vals.append(vname)
  521. if vals == []:
  522. print "Didn't find any value for enum %s" % (name)
  523. continue
  524. if modules_defines.has_key(module):
  525. test.write("#ifdef %s\n" % (modules_defines[module]))
  526. define = 1
  527. test.write("#define gen_nb_%s %d\n" % (name, len(vals)))
  528. test.write("""static %s gen_%s(int no, int nr ATTRIBUTE_UNUSED) {\n""" %
  529. (name, name))
  530. i = 1
  531. for value in vals:
  532. test.write(" if (no == %d) return(%s);\n" % (i, value))
  533. i = i + 1
  534. test.write(""" return(0);
  535. }
  536. static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
  537. }
  538. """ % (name, name));
  539. known_param_types.append(name)
  540. if (is_known_return_type(name) == 0) and (name in rettypes):
  541. if define == 0 and modules_defines.has_key(module):
  542. test.write("#ifdef %s\n" % (modules_defines[module]))
  543. define = 1
  544. test.write("""static void desret_%s(%s val ATTRIBUTE_UNUSED) {
  545. }
  546. """ % (name, name))
  547. known_return_types.append(name)
  548. if define == 1:
  549. test.write("#endif\n\n")
  550. #
  551. # Load the interfaces
  552. #
  553. headers = ctxt.xpathEval("/api/files/file")
  554. for file in headers:
  555. name = file.xpathEval('string(@name)')
  556. if (name == None) or (name == ''):
  557. continue
  558. #
  559. # Some module may be skipped because they don't really consists
  560. # of user callable APIs
  561. #
  562. if is_skipped_module(name):
  563. continue
  564. #
  565. # do not test deprecated APIs
  566. #
  567. desc = file.xpathEval('string(description)')
  568. if string.find(desc, 'DEPRECATED') != -1:
  569. print "Skipping deprecated interface %s" % name
  570. continue;
  571. test.write("#include <libxml/%s.h>\n" % name)
  572. modules.append(name)
  573. #
  574. # Generate the callers signatures
  575. #
  576. for module in modules:
  577. test.write("static int test_%s(void);\n" % module);
  578. #
  579. # Generate the top caller
  580. #
  581. test.write("""
  582. /**
  583. * testlibxml2:
  584. *
  585. * Main entry point of the tester for the full libxml2 module,
  586. * it calls all the tester entry point for each module.
  587. *
  588. * Returns the number of error found
  589. */
  590. static int
  591. testlibxml2(void)
  592. {
  593. int test_ret = 0;
  594. """)
  595. for module in modules:
  596. test.write(" test_ret += test_%s();\n" % module)
  597. test.write("""
  598. printf("Total: %d functions, %d tests, %d errors\\n",
  599. function_tests, call_tests, test_ret);
  600. return(test_ret);
  601. }
  602. """)
  603. #
  604. # How to handle a function
  605. #
  606. nb_tests = 0
  607. def generate_test(module, node):
  608. global test
  609. global nb_tests
  610. nb_cond = 0
  611. no_gen = 0
  612. name = node.xpathEval('string(@name)')
  613. if is_skipped_function(name):
  614. return
  615. #
  616. # check we know how to handle the args and return values
  617. # and store the informations for the generation
  618. #
  619. try:
  620. args = node.xpathEval("arg")
  621. except:
  622. args = []
  623. t_args = []
  624. n = 0
  625. for arg in args:
  626. n = n + 1
  627. rtype = arg.xpathEval("string(@type)")
  628. if rtype == 'void':
  629. break;
  630. info = arg.xpathEval("string(@info)")
  631. nam = arg.xpathEval("string(@name)")
  632. type = type_convert(rtype, nam, info, module, name, n)
  633. if is_known_param_type(type, rtype) == 0:
  634. add_missing_type(type, name);
  635. no_gen = 1
  636. if (type[-3:] == 'Ptr' or type[-4:] == '_ptr') and \
  637. rtype[0:6] == 'const ':
  638. crtype = rtype[6:]
  639. else:
  640. crtype = rtype
  641. t_args.append((nam, type, rtype, crtype, info))
  642. try:
  643. rets = node.xpathEval("return")
  644. except:
  645. rets = []
  646. t_ret = None
  647. for ret in rets:
  648. rtype = ret.xpathEval("string(@type)")
  649. info = ret.xpathEval("string(@info)")
  650. type = type_convert(rtype, 'return', info, module, name, 0)
  651. if rtype == 'void':
  652. break
  653. if is_known_return_type(type) == 0:
  654. add_missing_type(type, name);
  655. no_gen = 1
  656. t_ret = (type, rtype, info)
  657. break
  658. test.write("""
  659. static int
  660. test_%s(void) {
  661. int test_ret = 0;
  662. """ % (name))
  663. if no_gen == 1:
  664. add_missing_functions(name, module)
  665. test.write("""
  666. /* missing type support */
  667. return(test_ret);
  668. }
  669. """)
  670. return
  671. try:
  672. conds = node.xpathEval("cond")
  673. for cond in conds:
  674. test.write("#if %s\n" % (cond.get_content()))
  675. nb_cond = nb_cond + 1
  676. except:
  677. pass
  678. define = 0
  679. if function_defines.has_key(name):
  680. test.write("#ifdef %s\n" % (function_defines[name]))
  681. define = 1
  682. # Declare the memory usage counter
  683. no_mem = is_skipped_memcheck(name)
  684. if no_mem == 0:
  685. test.write(" int mem_base;\n");
  686. # Declare the return value
  687. if t_ret != None:
  688. test.write(" %s ret_val;\n" % (t_ret[1]))
  689. # Declare the arguments
  690. for arg in t_args:
  691. (nam, type, rtype, crtype, info) = arg;
  692. # add declaration
  693. test.write(" %s %s; /* %s */\n" % (crtype, nam, info))
  694. test.write(" int n_%s;\n" % (nam))
  695. test.write("\n")
  696. # Cascade loop on of each argument list of values
  697. for arg in t_args:
  698. (nam, type, rtype, crtype, info) = arg;
  699. #
  700. test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
  701. nam, nam, type, nam))
  702. # log the memory usage
  703. if no_mem == 0:
  704. test.write(" mem_base = xmlMemBlocks();\n");
  705. # prepare the call
  706. i = 0;
  707. for arg in t_args:
  708. (nam, type, rtype, crtype, info) = arg;
  709. #
  710. test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
  711. i = i + 1;
  712. # do the call, and clanup the result
  713. if extra_pre_call.has_key(name):
  714. test.write(" %s\n"% (extra_pre_call[name]))
  715. if t_ret != None:
  716. test.write("\n ret_val = %s(" % (name))
  717. need = 0
  718. for arg in t_args:
  719. (nam, type, rtype, crtype, info) = arg
  720. if need:
  721. test.write(", ")
  722. else:
  723. need = 1
  724. if rtype != crtype:
  725. test.write("(%s)" % rtype)
  726. test.write("%s" % nam);
  727. test.write(");\n")
  728. if extra_post_call.has_key(name):
  729. test.write(" %s\n"% (extra_post_call[name]))
  730. test.write(" desret_%s(ret_val);\n" % t_ret[0])
  731. else:
  732. test.write("\n %s(" % (name));
  733. need = 0;
  734. for arg in t_args:
  735. (nam, type, rtype, crtype, info) = arg;
  736. if need:
  737. test.write(", ")
  738. else:
  739. need = 1
  740. if rtype != crtype:
  741. test.write("(%s)" % rtype)
  742. test.write("%s" % nam)
  743. test.write(");\n")
  744. if extra_post_call.has_key(name):
  745. test.write(" %s\n"% (extra_post_call[name]))
  746. test.write(" call_tests++;\n");
  747. # Free the arguments
  748. i = 0;
  749. for arg in t_args:
  750. (nam, type, rtype, crtype, info) = arg;
  751. # This is a hack to prevent generating a destructor for the
  752. # 'input' argument in xmlTextReaderSetup. There should be
  753. # a better, more generic way to do this!
  754. if string.find(info, 'destroy') == -1:
  755. test.write(" des_%s(n_%s, " % (type, nam))
  756. if rtype != crtype:
  757. test.write("(%s)" % rtype)
  758. test.write("%s, %d);\n" % (nam, i))
  759. i = i + 1;
  760. test.write(" xmlResetLastError();\n");
  761. # Check the memory usage
  762. if no_mem == 0:
  763. test.write(""" if (mem_base != xmlMemBlocks()) {
  764. printf("Leak of %%d blocks found in %s",
  765. xmlMemBlocks() - mem_base);
  766. test_ret++;
  767. """ % (name));
  768. for arg in t_args:
  769. (nam, type, rtype, crtype, info) = arg;
  770. test.write(""" printf(" %%d", n_%s);\n""" % (nam))
  771. test.write(""" printf("\\n");\n""")
  772. test.write(" }\n")
  773. for arg in t_args:
  774. test.write(" }\n")
  775. test.write(" function_tests++;\n")
  776. #
  777. # end of conditional
  778. #
  779. while nb_cond > 0:
  780. test.write("#endif\n")
  781. nb_cond = nb_cond -1
  782. if define == 1:
  783. test.write("#endif\n")
  784. nb_tests = nb_tests + 1;
  785. test.write("""
  786. return(test_ret);
  787. }
  788. """)
  789. #
  790. # Generate all module callers
  791. #
  792. for module in modules:
  793. # gather all the functions exported by that module
  794. try:
  795. functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
  796. except:
  797. print "Failed to gather functions from module %s" % (module)
  798. continue;
  799. # iterate over all functions in the module generating the test
  800. i = 0
  801. nb_tests_old = nb_tests
  802. for function in functions:
  803. i = i + 1
  804. generate_test(module, function);
  805. # header
  806. test.write("""static int
  807. test_%s(void) {
  808. int test_ret = 0;
  809. if (quiet == 0) printf("Testing %s : %d of %d functions ...\\n");
  810. """ % (module, module, nb_tests - nb_tests_old, i))
  811. # iterate over all functions in the module generating the call
  812. for function in functions:
  813. name = function.xpathEval('string(@name)')
  814. if is_skipped_function(name):
  815. continue
  816. test.write(" test_ret += test_%s();\n" % (name))
  817. # footer
  818. test.write("""
  819. if (test_ret != 0)
  820. printf("Module %s: %%d errors\\n", test_ret);
  821. return(test_ret);
  822. }
  823. """ % (module))
  824. #
  825. # Generate direct module caller
  826. #
  827. test.write("""static int
  828. test_module(const char *module) {
  829. """);
  830. for module in modules:
  831. test.write(""" if (!strcmp(module, "%s")) return(test_%s());\n""" % (
  832. module, module))
  833. test.write(""" return(0);
  834. }
  835. """);
  836. print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
  837. compare_and_save()
  838. missing_list = []
  839. for missing in missing_types.keys():
  840. if missing == 'va_list' or missing == '...':
  841. continue;
  842. n = len(missing_types[missing])
  843. missing_list.append((n, missing))
  844. def compare_missing(a, b):
  845. return b[0] - a[0]
  846. missing_list.sort(compare_missing)
  847. print "Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list))
  848. lst = open("missing.lst", "w")
  849. lst.write("Missing support for %d types" % (len(missing_list)))
  850. lst.write("\n")
  851. for miss in missing_list:
  852. lst.write("%s: %d :" % (miss[1], miss[0]))
  853. i = 0
  854. for n in missing_types[miss[1]]:
  855. i = i + 1
  856. if i > 5:
  857. lst.write(" ...")
  858. break
  859. lst.write(" %s" % (n))
  860. lst.write("\n")
  861. lst.write("\n")
  862. lst.write("\n")
  863. lst.write("Missing support per module");
  864. for module in missing_functions.keys():
  865. lst.write("module %s:\n %s\n" % (module, missing_functions[module]))
  866. lst.close()