python script to run regression tests against the XML Test suite of
* check-xml-test-suite.py: python script to run regression tests
against the XML Test suite of W3C/OASis
* SAX.c: fixed a validation bug
* parser.c: fixed 3 errors pointed by the test suite
* doc/buildDocBookCatalog: fixed a typo pointed by drake
* python/Makefile.am: fixed a dependendy
Daniel
diff --git a/ChangeLog b/ChangeLog
index 0fc8225..037d9ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Sun Feb 17 20:41:37 CET 2002 Daniel Veillard <daniel@veillard.com>
+
+ * check-xml-test-suite.py: python script to run regression tests
+ against the XML Test suite of W3C/OASis
+ * SAX.c: fixed a validation bug
+ * parser.c: fixed 3 errors pointed by the test suite
+ * doc/buildDocBookCatalog: fixed a typo pointed by drake
+ * python/Makefile.am: fixed a dependendy
+
Fri Feb 15 21:47:13 CET 2002 Daniel Veillard <daniel@veillard.com>
* xmlmemory.c: avoid a warning bug #71594
diff --git a/SAX.c b/SAX.c
index 399eed4..da13370 100644
--- a/SAX.c
+++ b/SAX.c
@@ -493,7 +493,7 @@
"SAX.attributeDecl(%s) called while not in subset\n", name);
return;
}
- if (attr == 0) ctxt->valid = 0;
+ /* if (attr == 0) ctxt->valid = 0; */
if (ctxt->validate && ctxt->wellFormed &&
ctxt->myDoc && ctxt->myDoc->intSubset)
ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
diff --git a/check-xml-test-suite.py b/check-xml-test-suite.py
new file mode 100755
index 0000000..3bf9f9e
--- /dev/null
+++ b/check-xml-test-suite.py
@@ -0,0 +1,330 @@
+#!/usr/bin/python
+import sys
+import os
+import string
+sys.path.append("python")
+import libxml2
+
+#
+# the testsuite description
+#
+CONF="xml-test-suite/xmlconf/xmlconf.xml"
+LOG="check-xml-test-suite.log"
+
+log = open(LOG, "w")
+
+#
+# Error and warning handlers
+#
+error_nr = 0
+def errorHandler(ctx, str):
+ global error_nr
+
+ error_nr = error_nr + 1
+
+libxml2.registerErrorHandler(errorHandler, None)
+
+#warning_nr = 0
+#warning = ''
+#def warningHandler(ctx, str):
+# global warning_nr
+# global warning
+#
+# warning_nr = warning_nr + 1
+# warning = warning + str
+#
+#libxml2.registerWarningHandler(warningHandler, None)
+
+#
+# Used to load the XML testsuite description
+#
+def loadNoentDoc(filename):
+ ctxt = libxml2.createFileParserCtxt(filename)
+ if ctxt == None:
+ return None
+ ctxt.replaceEntities(1)
+ ctxt.parseDocument()
+ doc = ctxt.doc()
+ if ctxt.wellFormed() != 1:
+ doc.freeDoc()
+ return None
+ return doc
+
+#
+# The conformance testing routines
+#
+
+def testNotWf(filename, id):
+ global error_nr
+ global log
+
+ error_nr = 0
+
+ ctxt = libxml2.createFileParserCtxt(filename)
+ if ctxt == None:
+ return -1
+ ctxt.parseDocument()
+
+ doc = ctxt.doc()
+ if error_nr == 0 or ctxt.wellFormed() != 0:
+ print "%s: error: Well Formedness error not detected" % (id)
+ log.write("%s: error: Well Formedness error not detected\n" % (id))
+ doc.freeDoc()
+ return 0
+ return 1
+
+def testNotWfEnt(filename, id):
+ global error_nr
+ global log
+
+ error_nr = 0
+
+ ctxt = libxml2.createFileParserCtxt(filename)
+ if ctxt == None:
+ return -1
+ ctxt.replaceEntities(1)
+ ctxt.parseDocument()
+
+ doc = ctxt.doc()
+ if error_nr == 0 or ctxt.wellFormed() != 0:
+ print "%s: error: Well Formedness error not detected" % (id)
+ log.write("%s: error: Well Formedness error not detected\n" % (id))
+ doc.freeDoc()
+ return 0
+ return 1
+
+def testNotWfEntDtd(filename, id):
+ global error_nr
+ global log
+
+ error = ''
+ error_nr = 0
+
+ ctxt = libxml2.createFileParserCtxt(filename)
+ if ctxt == None:
+ return -1
+ ctxt.replaceEntities(1)
+ ctxt.loadSubset(1)
+ ctxt.parseDocument()
+
+ doc = ctxt.doc()
+ if error_nr == 0 or ctxt.wellFormed() != 0:
+ print "%s: error: Well Formedness error not detected" % (id)
+ log.write("%s: error: Well Formedness error not detected\n" % (id))
+ doc.freeDoc()
+ return 0
+ return 1
+
+def testWfEntDtd(filename, id):
+ global error_nr
+ global log
+
+ error = ''
+ error_nr = 0
+
+ ctxt = libxml2.createFileParserCtxt(filename)
+ if ctxt == None:
+ return -1
+ ctxt.replaceEntities(1)
+ ctxt.loadSubset(1)
+ ctxt.parseDocument()
+
+ doc = ctxt.doc()
+ if ctxt.wellFormed() == 0:
+ print "%s: error: wrongly failed to parse the document" % (id)
+ log.write("%s: error: wrongly failed to parse the document\n" % (id))
+ return 0
+ if error_nr != 0:
+ print "%s: warning: WF document generated an error msg" % (id)
+ log.write("%s: error: WF document generated an error msg\n" % (id))
+ doc.freeDoc()
+ return 2
+ doc.freeDoc()
+ return 1
+
+def testInvalid(filename, id):
+ global error_nr
+ global log
+
+ error_nr = 0
+
+ ctxt = libxml2.createFileParserCtxt(filename)
+ if ctxt == None:
+ return -1
+ ctxt.validate(1)
+ ctxt.parseDocument()
+
+ doc = ctxt.doc()
+ valid = ctxt.isValid()
+ if doc == None:
+ print "%s: error: wrongly failed to parse the document" % (id)
+ log.write("%s: error: wrongly failed to parse the document\n" % (id))
+ return 0
+ if valid == 1:
+ print "%s: error: Validity error not detected" % (id)
+ log.write("%s: error: Validity error not detected\n" % (id))
+ doc.freeDoc()
+ return 0
+ if error_nr == 0:
+ print "%s: warning: Validity error not reported" % (id)
+ log.write("%s: warning: Validity error not reported\n" % (id))
+ doc.freeDoc()
+ return 2
+
+ doc.freeDoc()
+ return 1
+
+def testValid(filename, id):
+ global error_nr
+
+ error_nr = 0
+
+ ctxt = libxml2.createFileParserCtxt(filename)
+ if ctxt == None:
+ return -1
+ ctxt.validate(1)
+ ctxt.parseDocument()
+
+ doc = ctxt.doc()
+ valid = ctxt.isValid()
+ if doc == None:
+ print "%s: error: wrongly failed to parse the document" % (id)
+ log.write("%s: error: wrongly failed to parse the document\n" % (id))
+ return 0
+ if valid != 1:
+ print "%s: error: Validity check failed" % (id)
+ log.write("%s: error: Validity check failed\n" % (id))
+ doc.freeDoc()
+ return 0
+ if error_nr != 0 or valid != 1:
+ print "%s: warning: valid document reported an error" % (id)
+ log.write("%s: warning: valid document reported an error\n" % (id))
+ doc.freeDoc()
+ return 2
+ doc.freeDoc()
+ return 1
+
+test_nr = 0
+test_succeed = 0
+test_failed = 0
+test_error = 0
+def runTest(test):
+ global test_nr
+ global test_failed
+ global test_error
+ global test_succeed
+ global log
+
+ uri = test.prop('URI')
+ id = test.prop('ID')
+ if uri == None:
+ print "Test without ID:", uri
+ return -1
+ if id == None:
+ print "Test without URI:", id
+ return -1
+ base = test.getBase(None)
+ URI = libxml2.buildURI(uri, base)
+ if os.access(URI, os.R_OK) == 0:
+ print "Test %s missing: base %s uri %s" % (URI, base, uri)
+ return -1
+ type = test.prop('TYPE')
+ if type == None:
+ print "Test %s missing TYPE" % (id)
+ return -1
+
+ extra = None
+ if type == "invalid":
+ res = testInvalid(URI, id)
+ elif type == "valid":
+ res = testValid(URI, id)
+ elif type == "not-wf":
+ extra = test.prop('ENTITIES')
+ # print URI
+ #if extra == None:
+ # res = testNotWfEntDtd(URI, id)
+ #elif extra == 'none':
+ # res = testNotWf(URI, id)
+ #elif extra == 'general':
+ # res = testNotWfEnt(URI, id)
+ #elif extra == 'both' or extra == 'parameter':
+ res = testNotWfEntDtd(URI, id)
+ #else:
+ # print "Unknow value %s for an ENTITIES test value" % (extra)
+ # return -1
+ elif type == "error":
+ res = testWfEntDtd(URI, id)
+ else:
+ # TODO skipped for now
+ return -1
+
+ test_nr = test_nr + 1
+ if res > 0:
+ test_succeed = test_succeed + 1
+ elif res == 0:
+ test_failed = test_failed + 1
+ elif res < 0:
+ test_error = test_error + 1
+
+ # Log the ontext
+ if res != 1:
+ log.write(" File: %s\n" % (URI))
+ content = test.content
+ if extra != None:
+ log.write(" %s:%s:%s\n\n" % (type, extra, content))
+ else:
+ log.write(" %s:%s\n\n" % (type, content))
+
+ return 0
+
+
+def runTestCases(case):
+ profile = case.prop('PROFILE')
+ if profile != None and \
+ string.find(profile, "IBM XML Conformance Test Suite - Production") < 0:
+ print "=>", profile
+ test = case.children
+ while test != None:
+ if test.name == 'TEST':
+ runTest(test)
+ if test.name == 'TESTCASES':
+ runTestCases(test)
+ test = test.next
+
+conf = loadNoentDoc(CONF)
+if conf == None:
+ print "Unable to load %s" % CONF
+ sys.exit(1)
+
+testsuite = conf.getRootElement()
+if testsuite.name != 'TESTSUITE':
+ print "Expecting TESTSUITE root element: aborting"
+ sys.exit(1)
+
+profile = testsuite.prop('PROFILE')
+if profile != None:
+ print profile
+
+case = testsuite.children
+while case != None:
+ global test_nr
+ global test_succeed
+ global test_failed
+ global test_error
+
+ if case.name == 'TESTCASES':
+ old_test_nr = test_nr
+ old_test_succeed = test_succeed
+ old_test_failed = test_failed
+ old_test_error = test_error
+ runTestCases(case)
+ print " Ran %d tests: %d suceeded, %d failed and %d generated an error" % (
+ test_nr - old_test_nr, test_succeed - old_test_succeed,
+ test_failed - old_test_failed, test_error - old_test_error)
+ case = case.next
+
+conf.freeDoc()
+log.close()
+
+print "Ran %d tests: %d suceeded, %d failed and %d generated an error" % (
+ test_nr, test_succeed, test_failed, test_error)
diff --git a/doc/buildDocBookCatalog b/doc/buildDocBookCatalog
index 64cf931..513796a 100755
--- a/doc/buildDocBookCatalog
+++ b/doc/buildDocBookCatalog
@@ -51,7 +51,7 @@
found=`find /usr/share/sgml -name docbookx.dtd`
fi
if [ "$found" = "" ] ; then
- echo could not locate docbookx.dtd drom DocBook XML
+ echo could not locate docbookx.dtd for DocBook XML
exit 1
fi
diff --git a/parser.c b/parser.c
index 8a783ef..fcb9e85 100644
--- a/parser.c
+++ b/parser.c
@@ -469,7 +469,11 @@
SKIP(3);
GROW;
while (RAW != ';') { /* loop blocked by count */
- if ((RAW >= '0') && (RAW <= '9') && (count < 20))
+ if (count++ > 20) {
+ count = 0;
+ GROW;
+ }
+ if ((RAW >= '0') && (RAW <= '9'))
val = val * 16 + (CUR - '0');
else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
val = val * 16 + (CUR - 'a') + 10;
@@ -497,7 +501,11 @@
SKIP(2);
GROW;
while (RAW != ';') { /* loop blocked by count */
- if ((RAW >= '0') && (RAW <= '9') && (count < 20))
+ if (count++ > 20) {
+ count = 0;
+ GROW;
+ }
+ if ((RAW >= '0') && (RAW <= '9'))
val = val * 10 + (CUR - '0');
else {
ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
@@ -2555,7 +2563,7 @@
in = ctxt->input->cur;
do {
get_more:
- while (((*in >= 0x20) && (*in != '<') &&
+ while (((*in >= 0x20) && (*in != '<') && (*in != ']') &&
(*in != '&') && (*in <= 0x7F)) || (*in == 0x09))
in++;
if (*in == 0xA) {
@@ -2567,6 +2575,20 @@
}
goto get_more;
}
+ if (*in == ']') {
+ if ((in[1] == ']') && (in[2] == '>')) {
+ ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
+ if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+ ctxt->sax->error(ctxt->userData,
+ "Sequence ']]>' not allowed in content\n");
+ ctxt->input->cur = in;
+ ctxt->wellFormed = 0;
+ ctxt->disableSAX = 1;
+ return;
+ }
+ in++;
+ goto get_more;
+ }
nbchar = in - ctxt->input->cur;
if (nbchar > 0) {
if (IS_BLANK(*ctxt->input->cur)) {
@@ -2848,7 +2870,7 @@
while (IS_CHAR(cur) && /* checked */
((cur != '>') ||
(r != '-') || (q != '-'))) {
- if ((r == '-') && (q == '-') && (len > 1)) {
+ if ((r == '-') && (q == '-')) {
ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
@@ -4814,7 +4836,7 @@
ctxt->disableSAX = 1;
ctxt->instate = XML_PARSER_IGNORE;
- while (depth >= 0) {
+ while ((depth >= 0) && (RAW != 0)) {
if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
depth++;
SKIP(3);
@@ -5149,6 +5171,8 @@
} else {
ent = xmlParseEntityRef(ctxt);
if (ent == NULL) return;
+ if (!ctxt->wellFormed)
+ return;
if ((ent->name != NULL) &&
(ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
xmlNodePtr list = NULL;
@@ -5237,6 +5261,7 @@
"Detected entity reference loop\n");
ctxt->wellFormed = 0;
ctxt->disableSAX = 1;
+ return;
} else if ((ret == 0) && (list != NULL)) {
if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
(ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
diff --git a/python/Makefile.am b/python/Makefile.am
index a3fecfc..2978b70 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -38,7 +38,7 @@
noinst_LTLIBRARIES = libxmlmodule.la
libxmlmodule_la_SOURCES = libxml.c types.c libxml2-py.c
-libxml2mod.so: $(libxmlmodule_la_OBJECTS)
+libxml2mod.so: $(libxmlmodule_la_OBJECTS) $(mylibs)
$(LINK) -o $@ $(libxmlmodule_la_OBJECTS) $(libxml2mod_so_LDFLAGS)