2022-12-07 00:40:01 +03:00
#!/usr/bin/env python3
2004-11-02 17:52:23 +03:00
#
# generate a tester program for the API
#
import sys
2004-11-04 20:34:35 +03:00
import os
2004-11-02 17:52:23 +03:00
import string
try :
import libxml2
except :
2022-04-21 01:45:58 +03:00
print ( " libxml2 python bindings not available, skipping testapi.c generation " )
2004-11-02 17:52:23 +03:00
sys . exit ( 0 )
2004-12-23 18:56:12 +03:00
if len ( sys . argv ) > 1 :
srcPref = sys . argv [ 1 ] + ' / '
else :
srcPref = ' '
2004-11-02 17:52:23 +03:00
#
2004-11-14 17:28:34 +03:00
# Modules we want to skip in API test
2004-11-02 17:52:23 +03:00
#
2004-11-08 17:02:18 +03:00
skipped_modules = [ " SAX " , " xlink " , " threads " , " globals " ,
2004-11-08 19:24:57 +03:00
" xmlmemory " , " xmlversion " , " xmlexports " ,
2004-11-03 20:07:05 +03:00
]
2004-11-02 17:52:23 +03:00
2004-11-09 17:59:59 +03:00
#
# 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 " ,
2005-01-09 20:48:02 +03:00
" xmlmodule " : " LIBXML_MODULES_ENABLED " ,
2005-03-25 06:05:46 +03:00
" pattern " : " LIBXML_PATTERN_ENABLED " ,
2005-10-22 06:04:26 +04:00
" schematron " : " LIBXML_SCHEMATRON_ENABLED " ,
2004-11-09 17:59:59 +03:00
}
#
# 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 " ,
" 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 " ,
2004-11-09 19:17:02 +03:00
" xmlTextReaderPreservePattern " : " LIBXML_PATTERN_ENABLED " ,
2004-11-09 17:59:59 +03:00
}
2004-11-02 17:52:23 +03:00
#
2004-11-14 17:28:34 +03:00
# Some functions really need to be skipped for the tests.
2004-11-02 17:52:23 +03:00
#
2004-11-03 17:20:29 +03:00
skipped_functions = [
# block on I/O
" xmlFdRead " , " xmlReadFd " , " xmlCtxtReadFd " ,
" htmlFdRead " , " htmlReadFd " , " htmlCtxtReadFd " ,
2004-11-04 15:32:18 +03:00
" xmlReaderNewFd " , " xmlReaderForFd " ,
2004-11-04 02:25:47 +03:00
" xmlIORead " , " xmlReadIO " , " xmlCtxtReadIO " ,
" htmlIORead " , " htmlReadIO " , " htmlCtxtReadIO " ,
2004-11-05 14:50:11 +03:00
" xmlReaderNewIO " , " xmlBufferDump " , " xmlNanoFTPConnect " ,
2005-02-13 11:18:52 +03:00
" xmlNanoFTPConnectTo " , " xmlNanoHTTPMethod " , " xmlNanoHTTPMethodRedir " ,
2004-11-08 13:52:06 +03:00
# Complex I/O APIs
" xmlCreateIOParserCtxt " , " xmlParserInputBufferCreateIO " ,
" xmlRegisterInputCallbacks " , " xmlReaderForIO " ,
" xmlOutputBufferCreateIO " , " xmlRegisterOutputCallbacks " ,
2005-02-13 11:18:52 +03:00
" xmlSaveToIO " , " xmlIOHTTPOpenW " ,
2020-03-08 19:19:42 +03:00
# library state cleanup, generate false leak information and other
2004-11-03 17:20:29 +03:00
# troubles, heavillyb tested otherwise.
2004-11-05 13:03:46 +03:00
" xmlCleanupParser " , " xmlRelaxNGCleanupTypes " , " xmlSetListDoc " ,
" xmlSetTreeDoc " , " xmlUnlinkNode " ,
2004-11-03 17:20:29 +03:00
# hard to avoid leaks in the tests
2004-11-06 22:24:28 +03:00
" xmlStrcat " , " xmlStrncat " , " xmlCatalogAddLocal " , " xmlNewTextWriterDoc " ,
2004-11-08 19:24:57 +03:00
" xmlXPathNewValueTree " , " xmlXPathWrapString " ,
2004-11-03 17:20:29 +03:00
# unimplemented
" xmlTextReaderReadInnerXml " , " xmlTextReaderReadOuterXml " ,
2004-11-03 20:07:05 +03:00
" xmlTextReaderReadString " ,
# destructor
2005-02-13 11:18:52 +03:00
" xmlListDelete " , " xmlOutputBufferClose " , " xmlNanoFTPClose " , " xmlNanoHTTPClose " ,
2004-11-03 20:07:05 +03:00
# deprecated
" xmlCatalogGetPublic " , " xmlCatalogGetSystem " , " xmlEncodeEntities " ,
2004-11-08 17:02:18 +03:00
" xmlNewGlobalNs " , " xmlHandleEntity " , " xmlNamespaceParseNCName " ,
" xmlNamespaceParseNSDef " , " xmlNamespaceParseQName " ,
" xmlParseNamespace " , " xmlParseQuotedString " , " xmlParserHandleReference " ,
" xmlScanName " ,
2004-11-08 19:24:57 +03:00
" xmlDecodeEntities " ,
2004-11-04 02:25:47 +03:00
# allocators
" xmlMemFree " ,
2004-11-07 15:17:35 +03:00
# verbosity
2004-11-08 19:24:57 +03:00
" xmlCatalogSetDebug " , " xmlShellPrintXPathError " , " xmlShellPrintNode " ,
2004-11-08 17:02:18 +03:00
# 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 " ,
2022-02-20 19:36:28 +03:00
# Legacy
" xmlCleanupPredefinedEntities " , " xmlInitializePredefinedEntities " ,
" xmlSetFeature " , " xmlGetFeature " , " xmlGetFeaturesList " ,
2022-04-21 00:17:14 +03:00
# location sets
" xmlXPtrLocationSetAdd " ,
" xmlXPtrLocationSetCreate " ,
" xmlXPtrLocationSetDel " ,
" xmlXPtrLocationSetMerge " ,
" xmlXPtrLocationSetRemove " ,
" xmlXPtrWrapLocationSet " ,
2004-11-03 17:20:29 +03:00
]
2004-11-02 17:52:23 +03:00
#
2004-11-14 17:28:34 +03:00
# These functions have side effects on the global state
2004-11-02 17:52:23 +03:00
# and hence generate errors on memory allocation tests
#
skipped_memcheck = [ " xmlLoadCatalog " , " xmlAddEncodingAlias " ,
" xmlSchemaInitTypes " , " xmlNanoFTPProxy " , " xmlNanoFTPScanProxy " ,
" xmlNanoHTTPScanProxy " , " xmlResetLastError " , " xmlCatalogConvert " ,
" xmlCatalogRemove " , " xmlLoadCatalogs " , " xmlCleanupCharEncodingHandlers " ,
2004-11-02 21:45:30 +03:00
" xmlInitCharEncodingHandlers " , " xmlCatalogCleanup " ,
2004-11-08 13:52:06 +03:00
" xmlSchemaGetBuiltInType " ,
2005-07-11 01:38:31 +04:00
" htmlParseFile " , " htmlCtxtReadFile " , # loads the catalogs
2008-07-29 13:02:27 +04:00
" xmlTextReaderSchemaValidate " , " xmlSchemaCleanupTypes " , # initialize the schemas type system
" xmlCatalogResolve " , " xmlIOParseDTD " # loads the catalogs
2004-11-02 21:45:30 +03:00
]
#
# Extra code needed for some test cases
#
2004-11-04 20:34:35 +03:00
extra_pre_call = {
2004-11-09 17:59:59 +03:00
" 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
""" ,
2004-11-06 22:24:28 +03:00
" xmlParserInputBufferCreateFd " :
" if (fd >= 0) fd = -1; " ,
2023-06-10 20:50:02 +03:00
" xmlSAXDefaultVersion " : """
{
int original_version = xmlSAXDefaultVersion ( 2 ) ;
""" ,
2004-11-04 20:34:35 +03:00
}
2004-11-02 21:45:30 +03:00
extra_post_call = {
" xmlAddChild " :
" if (ret_val == NULL) { xmlFreeNode(cur) ; cur = NULL ; } " ,
2008-08-27 15:45:41 +04:00
" xmlAddEntity " :
" if (ret_val != NULL) { xmlFreeNode(ret_val) ; ret_val = NULL; } " ,
2004-11-02 21:45:30 +03:00
" 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 " :
2004-11-05 13:03:46 +03:00
""" if (cur != NULL) {
xmlUnlinkNode ( cur ) ;
xmlFreeNode ( cur ) ; cur = NULL ; }
if ( old != NULL ) {
xmlUnlinkNode ( old ) ;
xmlFreeNode ( old ) ; old = NULL ; }
2022-04-21 01:45:58 +03:00
\t ret_val = NULL ; """ ,
2004-11-02 21:45:30 +03:00
" xmlTextMerge " :
""" if ((first != NULL) && (first->type != XML_TEXT_NODE)) {
2004-11-05 13:03:46 +03:00
xmlUnlinkNode ( second ) ;
2004-11-02 21:45:30 +03:00
xmlFreeNode ( second ) ; second = NULL ; } """ ,
2004-11-03 01:10:16 +03:00
" xmlBuildQName " :
""" if ((ret_val != NULL) && (ret_val != ncname) &&
( ret_val != prefix ) & & ( ret_val != memory ) )
xmlFree ( ret_val ) ;
2022-04-21 01:45:58 +03:00
\t ret_val = NULL ; """ ,
2005-01-26 03:04:52 +03:00
" xmlNewDocElementContent " :
""" xmlFreeDocElementContent(doc, ret_val); ret_val = NULL; """ ,
2004-11-04 15:32:18 +03:00
" xmlDictReference " : " xmlDictFree(dict); " ,
2004-11-04 13:49:00 +03:00
# Functions which deallocates one of their parameters
" xmlXPathConvertBoolean " : """ val = NULL; """ ,
" xmlXPathConvertNumber " : """ val = NULL; """ ,
" xmlXPathConvertString " : """ val = NULL; """ ,
" xmlSaveFileTo " : """ buf = NULL; """ ,
2004-11-04 20:34:35 +03:00
" xmlSaveFormatFileTo " : """ buf = NULL; """ ,
" xmlIOParseDTD " : " input = NULL; " ,
2004-11-05 13:03:46 +03:00
" xmlRemoveProp " : " cur = NULL; " ,
2004-11-06 22:24:28 +03:00
" 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; " ,
2004-11-09 17:59:59 +03:00
" xmlNewTextWriterPushParser " : " if (ctxt != NULL) { xmlFreeDoc(ctxt->myDoc); ctxt->myDoc = NULL;} if (ret_val != NULL) ctxt = NULL; " ,
2004-11-08 13:52:06 +03:00
" xmlNewIOInputStream " : " if (ret_val != NULL) input = NULL; " ,
2004-11-09 17:59:59 +03:00
" 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;} " ,
2005-07-04 02:40:26 +04:00
" xmlDOMWrapAdoptNode " : " if ((node != NULL) && (node->parent == NULL)) { xmlUnlinkNode(node);xmlFreeNode(node);node = NULL;} " ,
2023-06-10 20:50:02 +03:00
" xmlSAXDefaultVersion " : """
( void ) xmlSAXDefaultVersion ( original_version ) ;
}
""" ,
2004-11-02 21:45:30 +03:00
}
2004-11-02 17:52:23 +03:00
modules = [ ]
def is_skipped_module ( name ) :
for mod in skipped_modules :
if mod == name :
2022-04-21 01:45:58 +03:00
return 1
2004-11-02 17:52:23 +03:00
return 0
def is_skipped_function ( name ) :
for fun in skipped_functions :
if fun == name :
2022-04-21 01:45:58 +03:00
return 1
2004-11-02 17:52:23 +03:00
# Do not test destructors
2022-04-21 01:45:58 +03:00
if name . find ( ' Free ' ) != - 1 :
2004-11-02 17:52:23 +03:00
return 1
return 0
def is_skipped_memcheck ( name ) :
for fun in skipped_memcheck :
if fun == name :
2022-04-21 01:45:58 +03:00
return 1
2004-11-02 17:52:23 +03:00
return 0
missing_types = { }
def add_missing_type ( name , func ) :
try :
list = missing_types [ name ]
2022-04-21 01:45:58 +03:00
list . append ( func )
2004-11-02 17:52:23 +03:00
except :
missing_types [ name ] = [ func ]
2004-11-05 20:22:25 +03:00
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 )
2004-11-04 20:34:35 +03:00
missing_functions = { }
2004-11-05 17:30:41 +03:00
missing_functions_nr = 0
2004-11-04 20:34:35 +03:00
def add_missing_functions ( name , module ) :
2004-11-05 17:30:41 +03:00
global missing_functions_nr
missing_functions_nr = missing_functions_nr + 1
2004-11-04 20:34:35 +03:00
try :
list = missing_functions [ module ]
2022-04-21 01:45:58 +03:00
list . append ( name )
2004-11-04 20:34:35 +03:00
except :
missing_functions [ module ] = [ name ]
2004-11-02 17:52:23 +03:00
#
# Provide the type generators and destructors for the parameters
#
2004-11-02 21:45:30 +03:00
def type_convert ( str , name , info , module , function , pos ) :
2022-04-21 01:45:58 +03:00
# res = str.replace(" ", " ")
# res = str.replace(" ", " ")
# res = str.replace(" ", " ")
res = str . replace ( " * " , " _ptr " )
# res = str.replace("*", "_ptr")
res = res . replace ( " " , " _ " )
2004-11-02 17:52:23 +03:00
if res == ' const_char_ptr ' :
2022-04-21 01:45:58 +03:00
if name . find ( " file " ) != - 1 or \
name . find ( " uri " ) != - 1 or \
name . find ( " URI " ) != - 1 or \
info . find ( " filename " ) != - 1 or \
info . find ( " URI " ) != - 1 or \
info . find ( " URL " ) != - 1 :
if function . find ( " Save " ) != - 1 or \
function . find ( " Create " ) != - 1 or \
function . find ( " Write " ) != - 1 or \
function . find ( " Fetch " ) != - 1 :
return ( ' fileoutput ' )
return ( ' filepath ' )
2004-11-02 17:52:23 +03:00
if res == ' void_ptr ' :
if module == ' nanoftp ' and name == ' ctx ' :
2022-04-21 01:45:58 +03:00
return ( ' xmlNanoFTPCtxtPtr ' )
2005-02-13 11:18:52 +03:00
if function == ' xmlNanoFTPNewCtxt ' or \
2022-04-21 01:45:58 +03:00
function == ' xmlNanoFTPConnectTo ' or \
function == ' xmlNanoFTPOpen ' :
return ( ' xmlNanoFTPCtxtPtr ' )
2004-11-02 17:52:23 +03:00
if module == ' nanohttp ' and name == ' ctx ' :
2022-04-21 01:45:58 +03:00
return ( ' xmlNanoHTTPCtxtPtr ' )
if function == ' xmlNanoHTTPMethod ' or \
function == ' xmlNanoHTTPMethodRedir ' or \
function == ' xmlNanoHTTPOpen ' or \
function == ' xmlNanoHTTPOpenRedir ' :
return ( ' xmlNanoHTTPCtxtPtr ' ) ;
2005-02-13 11:18:52 +03:00
if function == ' xmlIOHTTPOpen ' :
2022-04-21 01:45:58 +03:00
return ( ' xmlNanoHTTPCtxtPtr ' )
if name . find ( " data " ) != - 1 :
return ( ' userdata ' )
if name . find ( " user " ) != - 1 :
return ( ' userdata ' )
2004-11-04 13:49:00 +03:00
if res == ' xmlDoc_ptr ' :
2004-11-14 17:28:34 +03:00
res = ' xmlDocPtr '
2004-11-04 13:49:00 +03:00
if res == ' xmlNode_ptr ' :
2004-11-14 17:28:34 +03:00
res = ' xmlNodePtr '
2004-11-04 13:49:00 +03:00
if res == ' xmlDict_ptr ' :
2004-11-14 17:28:34 +03:00
res = ' xmlDictPtr '
2004-11-02 21:45:30 +03:00
if res == ' xmlNodePtr ' and pos != 0 :
if ( function == ' xmlAddChild ' and pos == 2 ) or \
2022-04-21 01:45:58 +03:00
( function == ' xmlAddChildList ' and pos == 2 ) or \
2004-11-02 21:45:30 +03:00
( 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 \
2022-04-21 01:45:58 +03:00
( function == ' xmlAddPrevSibling ' and pos == 2 ) :
return ( ' xmlNodePtr_in ' ) ;
2004-11-04 20:34:35 +03:00
if res == ' const xmlBufferPtr ' :
2004-11-14 17:28:34 +03:00
res = ' xmlBufferPtr '
2004-11-05 14:50:11 +03:00
if res == ' xmlChar_ptr ' and name == ' name ' and \
2022-04-21 01:45:58 +03:00
function . find ( " EatName " ) != - 1 :
2004-11-05 14:50:11 +03:00
return ( ' eaten_name ' )
2004-11-06 22:24:28 +03:00
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 '
2004-11-08 19:24:57 +03:00
if res == ' FILE_ptr ' and module == ' debugXML ' :
res = ' debug_FILE_ptr ' ;
2004-11-08 20:16:15 +03:00
if res == ' int ' and name == ' options ' :
if module == ' parser ' or module == ' xmlreader ' :
2022-04-21 01:45:58 +03:00
res = ' parseroptions '
2004-11-14 17:28:34 +03:00
2004-11-02 17:52:23 +03:00
return res
2004-11-04 20:34:35 +03:00
known_param_types = [ ]
2004-11-02 17:52:23 +03:00
2019-01-01 21:20:22 +03:00
def is_known_param_type ( name ) :
2004-11-02 17:52:23 +03:00
for type in known_param_types :
if type == name :
2022-04-21 01:45:58 +03:00
return 1
2019-01-01 21:20:22 +03:00
return name [ - 3 : ] == ' Ptr ' or name [ - 4 : ] == ' _ptr '
def generate_param_type ( name , rtype ) :
global test
for type in known_param_types :
if type == name :
2022-04-21 01:45:58 +03:00
return
2004-11-05 20:22:25 +03:00
for type in generated_param_types :
if type == name :
2022-04-21 01:45:58 +03:00
return
2004-11-05 20:22:25 +03:00
if name [ - 3 : ] == ' Ptr ' or name [ - 4 : ] == ' _ptr ' :
2004-11-09 17:59:59 +03:00
define = 0
2022-04-21 01:45:58 +03:00
if module in modules_defines :
test . write ( " #ifdef %s \n " % ( modules_defines [ module ] ) )
define = 1
2004-11-05 20:22:25 +03:00
test . write ( """
#define gen_nb_%s 1
2022-04-21 07:03:22 +03:00
#define gen_%s(no, nr) NULL
#define des_%s(no, val, nr)
""" % (name, name, name))
2004-11-09 17:59:59 +03:00
if define == 1 :
2022-04-21 01:45:58 +03:00
test . write ( " #endif \n \n " )
2004-11-05 20:22:25 +03:00
add_generated_param_type ( name )
2004-11-02 17:52:23 +03:00
2004-11-04 20:34:35 +03:00
#
# Provide the type destructors for the return values
#
2004-11-03 14:50:29 +03:00
2004-11-04 20:34:35 +03:00
known_return_types = [ ]
2004-11-03 17:20:29 +03:00
2004-11-04 20:34:35 +03:00
def is_known_return_type ( name ) :
for type in known_return_types :
if type == name :
2022-04-21 01:45:58 +03:00
return 1
2004-11-04 20:34:35 +03:00
return 0
2004-11-03 20:07:05 +03:00
2004-11-04 20:34:35 +03:00
#
# Copy the beginning of the C test program result
#
2004-11-03 20:07:05 +03:00
2004-12-23 18:56:12 +03:00
try :
input = open ( " testapi.c " , " r " )
except :
input = open ( srcPref + " testapi.c " , " r " )
2004-11-04 20:34:35 +03:00
test = open ( ' testapi.c.new ' , ' w ' )
2004-11-03 20:07:05 +03:00
2004-11-04 20:34:35 +03:00
def compare_and_save ( ) :
global test
2004-11-03 20:07:05 +03:00
2004-11-04 20:34:35 +03:00
test . close ( )
2004-12-23 18:56:12 +03:00
try :
input = open ( " testapi.c " , " r " ) . read ( )
except :
input = ' '
2004-11-04 20:34:35 +03:00
test = open ( ' testapi.c.new ' , " r " ) . read ( )
if input != test :
2004-12-23 18:56:12 +03:00
try :
os . system ( " rm testapi.c; mv testapi.c.new testapi.c " )
except :
2022-04-21 01:45:58 +03:00
os . system ( " mv testapi.c.new testapi.c " )
2004-11-04 20:34:35 +03:00
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_ " :
2022-04-21 01:45:58 +03:00
type = line [ 15 : ] . split ( ) [ 0 ]
known_param_types . append ( type )
2004-11-04 20:34:35 +03:00
if line [ 0 : 19 ] == " static void desret_ " :
2022-04-21 01:45:58 +03:00
type = line [ 19 : ] . split ( ' ( ' ) [ 0 ]
known_return_types . append ( type )
2004-11-04 20:34:35 +03:00
test . write ( line )
line = input . readline ( )
input . close ( )
if line == " " :
2022-04-21 01:45:58 +03:00
print ( " Could not find the CUT marker in testapi.c skipping generation " )
2004-11-04 20:34:35 +03:00
test . close ( )
sys . exit ( 0 )
2004-11-03 20:07:05 +03:00
2004-11-04 20:34:35 +03:00
print ( " Scanned testapi.c: found %d parameters types and %d return types \n " % (
len ( known_param_types ) , len ( known_return_types ) ) )
test . write ( " /* CUT HERE: everything below that line is generated */ \n " )
2004-11-04 13:49:00 +03:00
2004-11-02 17:52:23 +03:00
#
2004-11-04 20:34:35 +03:00
# Open the input API description
2004-11-02 17:52:23 +03:00
#
2004-12-23 18:56:12 +03:00
doc = libxml2 . readFile ( srcPref + ' doc/libxml2-api.xml ' , None , 0 )
2004-11-04 20:34:35 +03:00
if doc == None :
2022-04-21 01:45:58 +03:00
print ( " Failed to load doc/libxml2-api.xml " )
2004-11-04 20:34:35 +03:00
sys . exit ( 1 )
ctxt = doc . xpathNewContext ( )
2004-11-06 17:50:18 +03:00
2004-11-14 17:28:34 +03:00
#
# Generate a list of all function parameters and select only
# those used in the api tests
#
argtypes = { }
args = ctxt . xpathEval ( " /api/symbols/function/arg " )
for arg in args :
mod = arg . xpathEval ( ' string(../@file) ' )
func = arg . xpathEval ( ' string(../@name) ' )
if ( mod not in skipped_modules ) and ( func not in skipped_functions ) :
2022-04-21 01:45:58 +03:00
type = arg . xpathEval ( ' string(@type) ' )
if type not in argtypes :
argtypes [ type ] = func
2004-11-14 17:28:34 +03:00
# similarly for return types
rettypes = { }
rets = ctxt . xpathEval ( " /api/symbols/function/return " )
for ret in rets :
mod = ret . xpathEval ( ' string(../@file) ' )
func = ret . xpathEval ( ' string(../@name) ' )
if ( mod not in skipped_modules ) and ( func not in skipped_functions ) :
type = ret . xpathEval ( ' string(@type) ' )
2022-04-21 01:45:58 +03:00
if type not in rettypes :
rettypes [ type ] = func
2004-11-14 17:28:34 +03:00
2004-11-06 17:50:18 +03:00
#
# Generate constructors and return type handling for all enums
2004-11-14 17:28:34 +03:00
# which are used as function parameters
2004-11-06 17:50:18 +03:00
#
enums = ctxt . xpathEval ( " /api/symbols/typedef[@type= ' enum ' ] " )
for enum in enums :
2004-11-14 17:28:34 +03:00
module = enum . xpathEval ( ' string(@file) ' )
2004-11-06 17:50:18 +03:00
name = enum . xpathEval ( ' string(@name) ' )
2004-11-14 17:28:34 +03:00
#
# Skip any enums which are not in our filtered lists
#
if ( name == None ) or ( ( name not in argtypes ) and ( name not in rettypes ) ) :
2004-11-06 17:50:18 +03:00
continue ;
2004-11-09 17:59:59 +03:00
define = 0
2004-11-06 17:50:18 +03:00
2022-04-21 01:45:58 +03:00
if ( name in argtypes ) and is_known_param_type ( name ) == 0 :
values = ctxt . xpathEval ( " /api/symbols/enum[@type= ' %s ' ] " % name )
i = 0
vals = [ ]
for value in values :
vname = value . xpathEval ( ' string(@name) ' )
if vname == None :
continue ;
i = i + 1
if i > = 5 :
break ;
vals . append ( vname )
if vals == [ ] :
print ( " Didn ' t find any value for enum %s " % ( name ) )
continue
if module in modules_defines :
test . write ( " #ifdef %s \n " % ( modules_defines [ module ] ) )
define = 1
test . write ( " #define gen_nb_ %s %d \n " % ( name , len ( vals ) ) )
test . write ( """ static %s gen_ %s (int no, int nr ATTRIBUTE_UNUSED) { \n """ %
( name , name ) )
i = 1
for value in vals :
test . write ( " if (no == %d ) return( %s ); \n " % ( i , value ) )
i = i + 1
test . write ( """ return(0);
2004-11-06 17:50:18 +03:00
}
2004-11-14 17:28:34 +03:00
static void des_ % s ( int no ATTRIBUTE_UNUSED , % s val ATTRIBUTE_UNUSED , int nr ATTRIBUTE_UNUSED ) {
}
""" % (name, name));
2022-04-21 01:45:58 +03:00
known_param_types . append ( name )
2004-11-06 17:50:18 +03:00
2004-11-14 17:28:34 +03:00
if ( is_known_return_type ( name ) == 0 ) and ( name in rettypes ) :
2022-04-21 01:45:58 +03:00
if define == 0 and ( module in modules_defines ) :
test . write ( " #ifdef %s \n " % ( modules_defines [ module ] ) )
define = 1
2004-11-14 17:28:34 +03:00
test . write ( """ static void desret_ %s ( %s val ATTRIBUTE_UNUSED) {
2004-11-06 17:50:18 +03:00
}
2004-11-14 17:28:34 +03:00
""" % (name, name))
2022-04-21 01:45:58 +03:00
known_return_types . append ( name )
2004-11-09 17:59:59 +03:00
if define == 1 :
test . write ( " #endif \n \n " )
2004-11-02 17:52:23 +03:00
2004-11-04 20:34:35 +03:00
#
# Load the interfaces
#
2004-11-06 17:50:18 +03:00
headers = ctxt . xpathEval ( " /api/files/file " )
2004-11-04 20:34:35 +03:00
for file in headers :
name = file . xpathEval ( ' string(@name) ' )
if ( name == None ) or ( name == ' ' ) :
continue
2004-11-02 17:52:23 +03:00
2004-11-04 20:34:35 +03:00
#
# Some module may be skipped because they don't really consists
# of user callable APIs
#
if is_skipped_module ( name ) :
continue
2004-11-02 17:52:23 +03:00
2004-11-04 20:34:35 +03:00
#
# do not test deprecated APIs
#
desc = file . xpathEval ( ' string(description) ' )
2022-04-21 01:45:58 +03:00
if desc . find ( ' DEPRECATED ' ) != - 1 :
print ( " Skipping deprecated interface %s " % name )
continue ;
2004-11-04 20:34:35 +03:00
test . write ( " #include <libxml/ %s .h> \n " % name )
modules . append ( name )
#
# Generate the callers signatures
#
for module in modules :
test . write ( " static int test_ %s (void); \n " % module ) ;
2004-11-02 17:52:23 +03:00
#
# Generate the top caller
#
test . write ( """
/ * *
* testlibxml2 :
*
* Main entry point of the tester for the full libxml2 module ,
* it calls all the tester entry point for each module .
*
* Returns the number of error found
* /
static int
testlibxml2 ( void )
{
2004-11-08 13:52:06 +03:00
int test_ret = 0 ;
2004-11-02 17:52:23 +03:00
""" )
for module in modules :
2004-11-08 13:52:06 +03:00
test . write ( " test_ret += test_ %s (); \n " % module )
2004-11-02 17:52:23 +03:00
test . write ( """
2004-11-04 13:49:00 +03:00
printf ( " Total: %d functions, %d tests, %d errors \\ n " ,
2004-11-08 13:52:06 +03:00
function_tests , call_tests , test_ret ) ;
return ( test_ret ) ;
2004-11-02 17:52:23 +03:00
}
""" )
#
# How to handle a function
#
nb_tests = 0
def generate_test ( module , node ) :
global test
global nb_tests
nb_cond = 0
no_gen = 0
name = node . xpathEval ( ' string(@name) ' )
if is_skipped_function ( name ) :
return
#
# check we know how to handle the args and return values
2020-03-08 19:19:42 +03:00
# and store the information for the generation
2004-11-02 17:52:23 +03:00
#
try :
2022-04-21 01:45:58 +03:00
args = node . xpathEval ( " arg " )
2004-11-02 17:52:23 +03:00
except :
args = [ ]
t_args = [ ]
2004-11-02 21:45:30 +03:00
n = 0
2004-11-02 17:52:23 +03:00
for arg in args :
2004-11-02 21:45:30 +03:00
n = n + 1
2004-11-02 17:52:23 +03:00
rtype = arg . xpathEval ( " string(@type) " )
2022-04-21 01:45:58 +03:00
if rtype == ' void ' :
break ;
info = arg . xpathEval ( " string(@info) " )
nam = arg . xpathEval ( " string(@name) " )
2004-11-02 21:45:30 +03:00
type = type_convert ( rtype , nam , info , module , name , n )
2022-04-21 01:45:58 +03:00
if is_known_param_type ( type ) == 0 :
add_missing_type ( type , name ) ;
no_gen = 1
2023-11-23 17:25:04 +03:00
t_args . append ( ( nam , type , rtype , info ) )
2004-11-02 17:52:23 +03:00
try :
2022-04-21 01:45:58 +03:00
rets = node . xpathEval ( " return " )
2004-11-02 17:52:23 +03:00
except :
rets = [ ]
t_ret = None
for ret in rets :
rtype = ret . xpathEval ( " string(@type) " )
2022-04-21 01:45:58 +03:00
info = ret . xpathEval ( " string(@info) " )
2004-11-02 21:45:30 +03:00
type = type_convert ( rtype , ' return ' , info , module , name , 0 )
2022-04-21 01:45:58 +03:00
if rtype == ' void ' :
break
if is_known_return_type ( type ) == 0 :
add_missing_type ( type , name ) ;
no_gen = 1
t_ret = ( type , rtype , info )
break
2004-11-02 17:52:23 +03:00
2019-01-01 21:20:22 +03:00
if no_gen == 0 :
for t_arg in t_args :
2023-11-23 17:25:04 +03:00
( nam , type , rtype , info ) = t_arg
2019-01-01 21:20:22 +03:00
generate_param_type ( type , rtype )
2004-11-05 17:30:41 +03:00
test . write ( """
static int
test_ % s ( void ) {
2004-11-08 13:52:06 +03:00
int test_ret = 0 ;
2004-11-05 17:30:41 +03:00
""" % (name))
2004-11-02 17:52:23 +03:00
if no_gen == 1 :
2004-11-04 20:34:35 +03:00
add_missing_functions ( name , module )
2022-04-21 01:45:58 +03:00
test . write ( """
2004-11-02 17:52:23 +03:00
/ * missing type support * /
2004-11-08 13:52:06 +03:00
return ( test_ret ) ;
2004-11-02 17:52:23 +03:00
}
""" )
return
try :
2022-04-21 01:45:58 +03:00
conds = node . xpathEval ( " cond " )
for cond in conds :
test . write ( " #if %s \n " % ( cond . get_content ( ) ) )
nb_cond = nb_cond + 1
2004-11-02 17:52:23 +03:00
except :
pass
2004-11-09 17:59:59 +03:00
define = 0
2022-04-21 01:45:58 +03:00
if name in function_defines :
2004-11-09 17:59:59 +03:00
test . write ( " #ifdef %s \n " % ( function_defines [ name ] ) )
2022-04-21 01:45:58 +03:00
define = 1
2004-11-02 17:52:23 +03:00
# Declare the memory usage counter
no_mem = is_skipped_memcheck ( name )
if no_mem == 0 :
2022-04-21 01:45:58 +03:00
test . write ( " int mem_base; \n " ) ;
2004-11-02 17:52:23 +03:00
# Declare the return value
if t_ret != None :
test . write ( " %s ret_val; \n " % ( t_ret [ 1 ] ) )
# Declare the arguments
for arg in t_args :
2023-11-23 17:25:04 +03:00
( nam , type , rtype , info ) = arg ;
2022-04-21 01:45:58 +03:00
# add declaration
2023-11-23 17:25:04 +03:00
test . write ( " %s %s ; /* %s */ \n " % ( rtype , nam , info ) )
2022-04-21 01:45:58 +03:00
test . write ( " int n_ %s ; \n " % ( nam ) )
2004-11-02 17:52:23 +03:00
test . write ( " \n " )
# Cascade loop on of each argument list of values
for arg in t_args :
2023-11-23 17:25:04 +03:00
( nam , type , rtype , info ) = arg ;
2022-04-21 01:45:58 +03:00
#
test . write ( " for (n_ %s = 0;n_ %s < gen_nb_ %s ;n_ %s ++) { \n " % (
nam , nam , type , nam ) )
2004-11-02 17:52:23 +03:00
# log the memory usage
if no_mem == 0 :
2022-04-21 01:45:58 +03:00
test . write ( " mem_base = xmlMemBlocks(); \n " ) ;
2004-11-02 17:52:23 +03:00
# prepare the call
2004-11-04 13:49:00 +03:00
i = 0 ;
2004-11-02 17:52:23 +03:00
for arg in t_args :
2023-11-23 17:25:04 +03:00
( nam , type , rtype , info ) = arg ;
2022-04-21 01:45:58 +03:00
#
test . write ( " %s = gen_ %s (n_ %s , %d ); \n " % ( nam , type , nam , i ) )
i = i + 1 ;
2004-11-02 17:52:23 +03:00
2017-05-31 19:53:45 +03:00
# add checks to avoid out-of-bounds array access
i = 0 ;
for arg in t_args :
2023-11-23 17:25:04 +03:00
( nam , type , rtype , info ) = arg ;
2017-05-31 19:53:45 +03:00
# assume that "size", "len", and "start" parameters apply to either
# the nearest preceding or following char pointer
if type == " int " and ( nam == " size " or nam == " len " or nam == " start " ) :
2022-08-17 12:22:38 +03:00
for j in ( list ( range ( i - 1 , - 1 , - 1 ) ) + list ( range ( i + 1 , len ( t_args ) ) ) ) :
2017-05-31 19:53:45 +03:00
( bnam , btype ) = t_args [ j ] [ : 2 ]
if btype == " const_char_ptr " or btype == " const_xmlChar_ptr " :
test . write (
" if (( %s != NULL) && \n "
2022-12-08 20:38:45 +03:00
" ( %s > xmlStrlen(BAD_CAST %s ))) \n "
" %s = 0; \n "
% ( bnam , nam , bnam , nam ) )
2017-05-31 19:53:45 +03:00
break
2022-04-21 01:45:58 +03:00
i = i + 1 ;
2017-05-31 19:53:45 +03:00
2004-11-02 17:52:23 +03:00
# do the call, and clanup the result
2022-04-21 01:45:58 +03:00
if name in extra_pre_call :
test . write ( " %s \n " % ( extra_pre_call [ name ] ) )
2004-11-02 17:52:23 +03:00
if t_ret != None :
2022-04-21 01:45:58 +03:00
test . write ( " \n ret_val = %s ( " % ( name ) )
need = 0
for arg in t_args :
2023-11-23 17:25:04 +03:00
( nam , type , rtype , info ) = arg
2022-04-21 01:45:58 +03:00
if need :
test . write ( " , " )
else :
need = 1
test . write ( " %s " % nam ) ;
test . write ( " ); \n " )
if name in extra_post_call :
test . write ( " %s \n " % ( extra_post_call [ name ] ) )
test . write ( " desret_ %s (ret_val); \n " % t_ret [ 0 ] )
2004-11-02 17:52:23 +03:00
else :
2022-04-21 01:45:58 +03:00
test . write ( " \n %s ( " % ( name ) ) ;
need = 0 ;
for arg in t_args :
2023-11-23 17:25:04 +03:00
( nam , type , rtype , info ) = arg ;
2022-04-21 01:45:58 +03:00
if need :
test . write ( " , " )
else :
need = 1
test . write ( " %s " % nam )
test . write ( " ); \n " )
if name in extra_post_call :
test . write ( " %s \n " % ( extra_post_call [ name ] ) )
2004-11-02 17:52:23 +03:00
2004-11-03 01:10:16 +03:00
test . write ( " call_tests++; \n " ) ;
2004-11-02 21:45:30 +03:00
2004-11-02 17:52:23 +03:00
# Free the arguments
2004-11-04 13:49:00 +03:00
i = 0 ;
2004-11-02 17:52:23 +03:00
for arg in t_args :
2023-11-23 17:25:04 +03:00
( nam , type , rtype , info ) = arg ;
2022-04-21 01:45:58 +03:00
# This is a hack to prevent generating a destructor for the
# 'input' argument in xmlTextReaderSetup. There should be
# a better, more generic way to do this!
if info . find ( ' destroy ' ) == - 1 :
test . write ( " des_ %s (n_ %s , " % ( type , nam ) )
test . write ( " %s , %d ); \n " % ( nam , i ) )
i = i + 1 ;
2004-11-02 17:52:23 +03:00
test . write ( " xmlResetLastError(); \n " ) ;
# Check the memory usage
if no_mem == 0 :
2022-04-21 01:45:58 +03:00
test . write ( """ if (mem_base != xmlMemBlocks()) {
2004-11-02 21:45:30 +03:00
printf ( " Leak of %% d blocks found in %s " ,
2022-04-21 01:45:58 +03:00
\t xmlMemBlocks ( ) - mem_base ) ;
\t test_ret + + ;
2004-11-02 17:52:23 +03:00
""" % (name));
2022-04-21 01:45:58 +03:00
for arg in t_args :
2023-11-23 17:25:04 +03:00
( nam , type , rtype , info ) = arg ;
2022-04-21 01:45:58 +03:00
test . write ( """ printf( " %% d " , n_ %s ); \n """ % ( nam ) )
test . write ( """ printf( " \\ n " ); \n """ )
test . write ( " } \n " )
2004-11-02 17:52:23 +03:00
for arg in t_args :
2022-04-21 01:45:58 +03:00
test . write ( " } \n " )
2004-11-02 17:52:23 +03:00
2004-11-09 19:17:02 +03:00
test . write ( " function_tests++; \n " )
2004-11-02 17:52:23 +03:00
#
# end of conditional
#
while nb_cond > 0 :
test . write ( " #endif \n " )
2022-04-21 01:45:58 +03:00
nb_cond = nb_cond - 1
2004-11-09 17:59:59 +03:00
if define == 1 :
test . write ( " #endif \n " )
2004-11-02 17:52:23 +03:00
nb_tests = nb_tests + 1 ;
test . write ( """
2004-11-08 13:52:06 +03:00
return ( test_ret ) ;
2004-11-02 17:52:23 +03:00
}
""" )
#
# Generate all module callers
#
for module in modules :
# gather all the functions exported by that module
try :
2022-04-21 01:45:58 +03:00
functions = ctxt . xpathEval ( " /api/symbols/function[@file= ' %s ' ] " % ( module ) )
2004-11-02 17:52:23 +03:00
except :
2022-04-21 01:45:58 +03:00
print ( " Failed to gather functions from module %s " % ( module ) )
continue ;
2004-11-02 17:52:23 +03:00
# iterate over all functions in the module generating the test
2004-11-04 15:32:18 +03:00
i = 0
nb_tests_old = nb_tests
2004-11-02 17:52:23 +03:00
for function in functions :
2004-11-04 15:32:18 +03:00
i = i + 1
2004-11-02 17:52:23 +03:00
generate_test ( module , function ) ;
# header
test . write ( """ static int
test_ % s ( void ) {
2004-11-08 13:52:06 +03:00
int test_ret = 0 ;
2004-11-02 17:52:23 +03:00
2004-11-09 19:17:02 +03:00
if ( quiet == 0 ) printf ( " Testing %s : %d of %d functions ... \\ n " ) ;
2004-11-04 15:32:18 +03:00
""" % (module, module, nb_tests - nb_tests_old, i))
2004-11-02 17:52:23 +03:00
# iterate over all functions in the module generating the call
for function in functions :
name = function . xpathEval ( ' string(@name) ' )
2022-04-21 01:45:58 +03:00
if is_skipped_function ( name ) :
continue
test . write ( " test_ret += test_ %s (); \n " % ( name ) )
2004-11-02 17:52:23 +03:00
# footer
test . write ( """
2004-11-08 13:52:06 +03:00
if ( test_ret != 0 )
2022-04-21 01:45:58 +03:00
\tprintf ( " Module %s : %% d errors \\ n " , test_ret ) ;
2004-11-08 13:52:06 +03:00
return ( test_ret ) ;
2004-11-02 17:52:23 +03:00
}
""" % (module))
2004-11-05 13:03:46 +03:00
#
# Generate direct module caller
#
test . write ( """ static int
test_module ( const char * module ) {
""" );
for module in modules :
test . write ( """ if (!strcmp(module, " %s " )) return(test_ %s ()); \n """ % (
module , module ) )
test . write ( """ return(0);
}
""" );
2022-04-21 01:45:58 +03:00
print ( " Generated test for %d modules and %d functions " % ( len ( modules ) , nb_tests ) )
2004-11-04 15:32:18 +03:00
2004-11-04 20:34:35 +03:00
compare_and_save ( )
2004-11-04 15:32:18 +03:00
missing_list = [ ]
2004-11-02 17:52:23 +03:00
for missing in missing_types . keys ( ) :
2004-11-04 15:32:18 +03:00
if missing == ' va_list ' or missing == ' ... ' :
2004-11-04 02:25:47 +03:00
continue ;
2004-11-04 15:32:18 +03:00
2004-11-02 17:52:23 +03:00
n = len ( missing_types [ missing ] )
2004-11-04 15:32:18 +03:00
missing_list . append ( ( n , missing ) )
2022-04-21 01:45:58 +03:00
missing_list . sort ( key = lambda a : a [ 0 ] )
print ( " Missing support for %d functions and %d types see missing.lst " % ( missing_functions_nr , len ( missing_list ) ) )
2004-11-04 15:32:18 +03:00
lst = open ( " missing.lst " , " w " )
2004-11-04 20:34:35 +03:00
lst . write ( " Missing support for %d types " % ( len ( missing_list ) ) )
lst . write ( " \n " )
2004-11-04 15:32:18 +03:00
for miss in missing_list :
lst . write ( " %s : %d : " % ( miss [ 1 ] , miss [ 0 ] ) )
i = 0
for n in missing_types [ miss [ 1 ] ] :
i = i + 1
if i > 5 :
2022-04-21 01:45:58 +03:00
lst . write ( " ... " )
break
lst . write ( " %s " % ( n ) )
2004-11-04 15:32:18 +03:00
lst . write ( " \n " )
2004-11-04 20:34:35 +03:00
lst . write ( " \n " )
lst . write ( " \n " )
lst . write ( " Missing support per module " ) ;
for module in missing_functions . keys ( ) :
lst . write ( " module %s : \n %s \n " % ( module , missing_functions [ module ] ) )
2004-11-04 15:32:18 +03:00
lst . close ( )
2004-11-04 02:25:47 +03:00
2004-11-02 17:52:23 +03:00