1
0
mirror of https://github.com/GNOME/libxml2.git synced 2025-05-08 21:07:54 +08:00

test: Make gentest.py use Doxygen XML

This adds Python code to look up the required feature macros for a
symbol in tools/xmlmod.py.
This commit is contained in:
Nick Wellnhofer 2025-04-28 19:05:38 +02:00
parent bbe5827c94
commit 97f3ec7708
4 changed files with 61 additions and 78 deletions

View File

@ -153,10 +153,8 @@ testdso_la_SOURCES = testdso.c
testdso_la_LDFLAGS = $(AM_LDFLAGS) \ testdso_la_LDFLAGS = $(AM_LDFLAGS) \
-module -no-undefined -avoid-version -rpath $(libdir) -module -no-undefined -avoid-version -rpath $(libdir)
# that one forces the rebuild when "make rebuild" is run on doc/
rebuild_testapi: rebuild_testapi:
-@(if [ "$(PYTHON)" != "" ] ; then \ cd $(srcdir) && python3 tools/gentest.py $(abs_builddir)
$(PYTHON) $(srcdir)/tools/gentest.py $(srcdir) ; fi )
testapi_SOURCES=testapi.c testapi_SOURCES=testapi.c
testapi_DEPENDENCIES = $(DEPS) testapi_DEPENDENCIES = $(DEPS)
@ -204,7 +202,7 @@ CLEANFILES = missing.lst runsuite.log runxmlconf.log test.out \
EXTRA_DIST = Copyright libxml2-config.cmake.in autogen.sh \ EXTRA_DIST = Copyright libxml2-config.cmake.in autogen.sh \
libxml.h \ libxml.h \
html5ent.inc iso8859x.inc \ html5ent.inc iso8859x.inc \
tools/gentest.py \ tools/gentest.py tools/xmlmod.py \
tools/genChRanges.py tools/genEscape.py tools/genUnicode.py \ tools/genChRanges.py tools/genEscape.py tools/genUnicode.py \
timsort.h \ timsort.h \
README.zOS README.md \ README.zOS README.md \

View File

@ -1,7 +1,7 @@
/* /*
* testapi.c: libxml2 API tester program. * testapi.c: libxml2 API tester program.
* *
* Automatically generated by gentest.py from libxml2-api.xml * Automatically generated by gentest.py
* *
* See Copyright for the status of this software. * See Copyright for the status of this software.
*/ */
@ -41,6 +41,7 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
xmlInitParser(); xmlInitParser();
xmlSetStructuredErrorFunc(NULL, ignoreError); xmlSetStructuredErrorFunc(NULL, ignoreError);
xmlFreeParserInputBuffer(__xmlParserInputBufferCreateFilename(NULL, 0));
xmlAddAttributeDecl(NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL); xmlAddAttributeDecl(NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL);
xmlFreeNode(xmlAddChild(NULL, NULL)); xmlFreeNode(xmlAddChild(NULL, NULL));
xmlFreeNode(xmlAddChildList(NULL, NULL)); xmlFreeNode(xmlAddChildList(NULL, NULL));
@ -728,34 +729,6 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
#endif /* LIBXML_PUSH_ENABLED */ #endif /* LIBXML_PUSH_ENABLED */
#endif /* LIBXML_HTML_ENABLED */ #endif /* LIBXML_HTML_ENABLED */
#ifdef LIBXML_HTTP_ENABLED
xmlIOHTTPClose(NULL);
xmlIOHTTPMatch(NULL);
xmlIOHTTPOpen(NULL);
xmlIOHTTPRead(NULL, NULL, 0);
xmlNanoHTTPAuthHeader(NULL);
xmlNanoHTTPCleanup();
xmlNanoHTTPClose(NULL);
xmlNanoHTTPContentLength(NULL);
xmlNanoHTTPEncoding(NULL);
xmlNanoHTTPFetch(NULL, NULL, NULL);
xmlNanoHTTPInit();
xmlNanoHTTPMethod(NULL, NULL, NULL, NULL, NULL, 0);
xmlNanoHTTPMethodRedir(NULL, NULL, NULL, NULL, NULL, NULL, 0);
xmlNanoHTTPMimeType(NULL);
xmlNanoHTTPOpen(NULL, NULL);
xmlNanoHTTPOpenRedir(NULL, NULL, NULL);
xmlNanoHTTPRead(NULL, NULL, 0);
xmlNanoHTTPRedir(NULL);
xmlNanoHTTPReturnCode(NULL);
xmlNanoHTTPScanProxy(NULL);
#ifdef LIBXML_OUTPUT_ENABLED
xmlIOHTTPOpenW(NULL, 0);
xmlNanoHTTPSave(NULL, NULL);
xmlRegisterHTTPPostCallbacks();
#endif /* LIBXML_OUTPUT_ENABLED */
#endif /* LIBXML_HTTP_ENABLED */
#ifdef LIBXML_MODULES_ENABLED #ifdef LIBXML_MODULES_ENABLED
xmlModuleClose(NULL); xmlModuleClose(NULL);
xmlModuleFree(NULL); xmlModuleFree(NULL);
@ -764,6 +737,7 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
#endif /* LIBXML_MODULES_ENABLED */ #endif /* LIBXML_MODULES_ENABLED */
#ifdef LIBXML_OUTPUT_ENABLED #ifdef LIBXML_OUTPUT_ENABLED
xmlOutputBufferClose(__xmlOutputBufferCreateFilename(NULL, NULL, 0));
xmlOutputBufferClose(xmlAllocOutputBuffer(NULL)); xmlOutputBufferClose(xmlAllocOutputBuffer(NULL));
xmlAttrSerializeTxtContent(NULL, NULL, NULL, NULL); xmlAttrSerializeTxtContent(NULL, NULL, NULL, NULL);
xmlBufNodeDump(NULL, NULL, NULL, 0, 0); xmlBufNodeDump(NULL, NULL, NULL, 0, 0);

View File

@ -4,6 +4,7 @@
# #
import xml.etree.ElementTree as etree import xml.etree.ElementTree as etree
import os
import re import re
import sys import sys
@ -133,70 +134,79 @@ blockList = {
# Parse document # Parse document
if len(sys.argv) > 1: if len(sys.argv) > 1:
srcPref = sys.argv[1] + '/' buildDir = sys.argv[1]
else: else:
srcPref = '' buildDir = '.'
doc = etree.parse(srcPref + 'doc/libxml2-api.xml') xmlDocDir = buildDir + '/doc/xml'
# Create map of symbols to filenames
filenames = {} filenames = {}
for file in doc.find('files').findall('file'):
filename = file.get('name')
for export in file.findall('exports'):
filenames[export.get('symbol')] = filename
# Process functions
functions = {} functions = {}
for func in doc.find('symbols').findall('function'): for file in os.listdir(xmlDocDir):
name = func.get('name') if not file.endswith('_8h.xml'):
if name in blockList:
continue continue
module1, module2 = xmlmod.findModules(filenames[name], name) doc = etree.parse(xmlDocDir + '/' + file)
cargs = [] compound = doc.find('compounddef')
for arg in func.findall('arg'): module = compound.find('compoundname').text
atype = arg.get('type') if not module.endswith('.h'):
if re.search(r'(Ptr|\*)$', atype): continue
cargs.append('NULL') module = module[:-2]
else:
cargs.append('0')
mfunc = functions.get(module1) for section in compound.findall('sectiondef'):
if mfunc is None: if section.get('kind') != 'func':
mfunc = {} continue
functions[module1] = mfunc
mmfunc = mfunc.get(module2) for func in section.findall('memberdef'):
if mmfunc is None: name = func.find('name').text
mmfunc = [] if name in blockList:
mfunc[module2] = mmfunc continue
code = f'{name}({', '.join(cargs)})' module1, module2 = xmlmod.findModules(module, name)
rtype = func.find('return').get('type') cargs = []
dtor = dtors.get(rtype) for arg in func.findall('param'):
if dtor is not None: atype = etree.tostring(arg.find('type'),
code = f'{dtor}({code})' method='text', encoding='unicode').rstrip()
elif rtype == 'xmlHashTablePtr': if atype == 'void':
code = f'xmlHashFree({code}, NULL)' continue
if re.search(r'(Ptr|\*)$', atype):
cargs.append('NULL')
else:
cargs.append('0')
mmfunc.append(f' {code};') mfunc = functions.get(module1)
if mfunc is None:
mfunc = {}
functions[module1] = mfunc
mmfunc = mfunc.get(module2)
if mmfunc is None:
mmfunc = {}
mfunc[module2] = mmfunc
code = f'{name}({', '.join(cargs)})'
rtype = etree.tostring(func.find('type'),
method='text', encoding='unicode').rstrip()
dtor = dtors.get(rtype)
if dtor is not None:
code = f'{dtor}({code})'
elif rtype == 'xmlHashTablePtr':
code = f'xmlHashFree({code}, NULL)'
mmfunc[name] = f' {code};\n'
# Write output # Write output
test = open(srcPref + 'testapi.c', 'w') test = open('testapi.c', 'w')
test.write("""/* test.write("""/*
* testapi.c: libxml2 API tester program. * testapi.c: libxml2 API tester program.
* *
* Automatically generated by gentest.py from libxml2-api.xml * Automatically generated by gentest.py
* *
* See Copyright for the status of this software. * See Copyright for the status of this software.
*/ */
@ -250,8 +260,8 @@ for module1 in sorted(functions.keys()):
if module2 != '': if module2 != '':
test.write(f'#ifdef LIBXML_{module2}_ENABLED\n') test.write(f'#ifdef LIBXML_{module2}_ENABLED\n')
for code in mmfunc: for name in sorted(mmfunc.keys()):
test.write(code + '\n') test.write(mmfunc[name])
if module2 != '': if module2 != '':
test.write(f'#endif /* LIBXML_{module2}_ENABLED */\n') test.write(f'#endif /* LIBXML_{module2}_ENABLED */\n')

View File

@ -42,6 +42,7 @@ symbolMap1 = {
'xmlRegisterHTTPPostCallbacks': 'HTTP', 'xmlRegisterHTTPPostCallbacks': 'HTTP',
'__xmlOutputBufferCreateFilename': 'OUTPUT',
'xmlAttrSerializeTxtContent': 'OUTPUT', 'xmlAttrSerializeTxtContent': 'OUTPUT',
'xmlUTF8ToIsolat1': 'OUTPUT', 'xmlUTF8ToIsolat1': 'OUTPUT',
'xmlSprintfElementContent': 'OUTPUT', 'xmlSprintfElementContent': 'OUTPUT',