2 * runtest.c: C program to run libxml2 regression tests without
3 * requiring make or Python, and reducing platform dependancies
6 * To compile on Unixes:
7 * cc -o runtest `xml2-config --cflags` runtest.c `xml2-config --libs` -lpthread
9 * See Copyright for the status of this software.
17 #if !defined(_WIN32) || defined(__CYGWIN__)
21 #include <sys/types.h>
25 #include <libxml/parser.h>
26 #include <libxml/parserInternals.h>
27 #include <libxml/tree.h>
28 #include <libxml/uri.h>
30 #ifdef LIBXML_OUTPUT_ENABLED
31 #ifdef LIBXML_READER_ENABLED
32 #include <libxml/xmlreader.h>
35 #ifdef LIBXML_XINCLUDE_ENABLED
36 #include <libxml/xinclude.h>
39 #ifdef LIBXML_XPATH_ENABLED
40 #include <libxml/xpath.h>
41 #include <libxml/xpathInternals.h>
42 #ifdef LIBXML_XPTR_ENABLED
43 #include <libxml/xpointer.h>
47 #ifdef LIBXML_SCHEMAS_ENABLED
48 #include <libxml/relaxng.h>
49 #include <libxml/xmlschemas.h>
50 #include <libxml/xmlschemastypes.h>
53 #ifdef LIBXML_PATTERN_ENABLED
54 #include <libxml/pattern.h>
57 #ifdef LIBXML_C14N_ENABLED
58 #include <libxml/c14n.h>
61 #ifdef LIBXML_HTML_ENABLED
62 #include <libxml/HTMLparser.h>
63 #include <libxml/HTMLtree.h>
66 * pseudo flag for the unification of HTML and XML tests
68 #define XML_PARSE_HTML 1 << 24
71 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
72 #include <libxml/globals.h>
73 #include <libxml/threads.h>
74 #include <libxml/parser.h>
75 #include <libxml/catalog.h>
80 * O_BINARY is just for Windows compatibility - if it isn't defined
81 * on this system, avoid any compilation error
84 #define RD_FLAGS O_RDONLY | O_BINARY
85 #define WR_FLAGS O_WRONLY | O_CREAT | O_TRUNC | O_BINARY
87 #define RD_FLAGS O_RDONLY
88 #define WR_FLAGS O_WRONLY | O_CREAT | O_TRUNC
91 typedef int (*functest) (const char *filename, const char *result,
92 const char *error, int options);
94 typedef struct testDesc testDesc;
95 typedef testDesc *testDescPtr;
97 const char *desc; /* descripton of the test */
98 functest func; /* function implementing the test */
99 const char *in; /* glob to path for input files */
100 const char *out; /* output directory */
101 const char *suffix;/* suffix for output files */
102 const char *err; /* suffix for error output files */
103 int options; /* parser options for the test */
106 static int update_results = 0;
107 static int checkTestFile(const char *filename);
109 #if defined(_WIN32) && !defined(__CYGWIN__)
116 size_t gl_pathc; /* Count of paths matched so far */
117 char **gl_pathv; /* List of matched pathnames. */
118 size_t gl_offs; /* Slots to reserve in 'gl_pathv'. */
121 #define GLOB_DOOFFS 0
122 static int glob(const char *pattern, ATTRIBUTE_UNUSED int flags,
123 ATTRIBUTE_UNUSED int errfunc(const char *epath, int eerrno),
126 WIN32_FIND_DATA FindFileData;
128 unsigned int nb_paths = 0;
132 if ((pattern == NULL) || (pglob == NULL)) return(-1);
134 strncpy(directory, pattern, 499);
135 for (len = strlen(directory);len >= 0;len--) {
136 if (directory[len] == '/') {
147 memset(ret, 0, sizeof(glob_t));
149 hFind = FindFirstFileA(pattern, &FindFileData);
150 if (hFind == INVALID_HANDLE_VALUE)
153 ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
154 if (ret->gl_pathv == NULL) {
158 strncpy(directory + len, FindFileData.cFileName, 499 - len);
159 ret->gl_pathv[ret->gl_pathc] = strdup(directory);
160 if (ret->gl_pathv[ret->gl_pathc] == NULL)
163 while(FindNextFileA(hFind, &FindFileData)) {
164 if (FindFileData.cFileName[0] == '.')
166 if (ret->gl_pathc + 2 > nb_paths) {
167 char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
173 strncpy(directory + len, FindFileData.cFileName, 499 - len);
174 ret->gl_pathv[ret->gl_pathc] = strdup(directory);
175 if (ret->gl_pathv[ret->gl_pathc] == NULL)
179 ret->gl_pathv[ret->gl_pathc] = NULL;
188 static void globfree(glob_t *pglob) {
193 for (i = 0;i < pglob->gl_pathc;i++) {
194 if (pglob->gl_pathv[i] != NULL)
195 free(pglob->gl_pathv[i]);
203 /************************************************************************
205 * Libxml2 specific routines *
207 ************************************************************************/
209 static int nb_tests = 0;
210 static int nb_errors = 0;
211 static int nb_leaks = 0;
212 static int extraMemoryFromResolver = 0;
216 fprintf(stderr, "Exitting tests on fatal error\n");
221 * We need to trap calls to the resolver to not account memory for the catalog
222 * which is shared to the current running test. We also don't want to have
223 * network downloads modifying tests.
225 static xmlParserInputPtr
226 testExternalEntityLoader(const char *URL, const char *ID,
227 xmlParserCtxtPtr ctxt) {
228 xmlParserInputPtr ret;
230 if (checkTestFile(URL)) {
231 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
233 int memused = xmlMemUsed();
234 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
235 extraMemoryFromResolver += xmlMemUsed() - memused;
242 * Trapping the error messages at the generic level to grab the equivalent of
243 * stderr messages on CLI tools.
245 static char testErrors[32769];
246 static int testErrorsSize = 0;
249 testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
253 if (testErrorsSize >= 32768)
256 res = vsnprintf(&testErrors[testErrorsSize],
257 32768 - testErrorsSize,
260 if (testErrorsSize + res >= 32768) {
262 testErrorsSize = 32768;
263 testErrors[testErrorsSize] = 0;
265 testErrorsSize += res;
267 testErrors[testErrorsSize] = 0;
271 channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
275 if (testErrorsSize >= 32768)
278 res = vsnprintf(&testErrors[testErrorsSize],
279 32768 - testErrorsSize,
282 if (testErrorsSize + res >= 32768) {
284 testErrorsSize = 32768;
285 testErrors[testErrorsSize] = 0;
287 testErrorsSize += res;
289 testErrors[testErrorsSize] = 0;
293 * xmlParserPrintFileContext:
294 * @input: an xmlParserInputPtr input
296 * Displays current context within the input content for error tracking
300 xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
301 xmlGenericErrorFunc chanl, void *data ) {
302 const xmlChar *cur, *base;
303 unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
304 xmlChar content[81]; /* space for 80 chars + line terminator */
307 if (input == NULL) return;
310 /* skip backwards over any end-of-lines */
311 while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
315 /* search backwards for beginning-of-line (to max buff size) */
316 while ((n++ < (sizeof(content)-1)) && (cur > base) &&
317 (*(cur) != '\n') && (*(cur) != '\r'))
319 if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
320 /* calculate the error position in terms of the current position */
321 col = input->cur - cur;
322 /* search forward for end-of-line (to max buff size) */
325 /* copy selected text to our buffer */
326 while ((*cur != 0) && (*(cur) != '\n') &&
327 (*(cur) != '\r') && (n < sizeof(content)-1)) {
332 /* print out the selected text */
333 chanl(data ,"%s\n", content);
334 /* create blank line with problem pointer */
337 /* (leave buffer space for pointer + line terminator) */
338 while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
345 chanl(data ,"%s\n", content);
349 testStructuredErrorHandler(void *ctx ATTRIBUTE_UNUSED, xmlErrorPtr err) {
356 const xmlChar *name = NULL;
359 xmlParserInputPtr input = NULL;
360 xmlParserInputPtr cur = NULL;
361 xmlParserCtxtPtr ctxt = NULL;
369 domain = err->domain;
372 if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
373 (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
374 (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
379 if (code == XML_ERR_OK)
382 if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
386 * Maintain the compatibility with the legacy error handling
390 if ((input != NULL) && (input->filename == NULL) &&
391 (ctxt->inputNr > 1)) {
393 input = ctxt->inputTab[ctxt->inputNr - 2];
397 channel(data, "%s:%d: ", input->filename, input->line);
398 else if ((line != 0) && (domain == XML_FROM_PARSER))
399 channel(data, "Entity: line %d: ", input->line);
403 channel(data, "%s:%d: ", file, line);
404 else if ((line != 0) && (domain == XML_FROM_PARSER))
405 channel(data, "Entity: line %d: ", line);
408 channel(data, "element %s: ", name);
410 if (code == XML_ERR_OK)
413 case XML_FROM_PARSER:
414 channel(data, "parser ");
416 case XML_FROM_NAMESPACE:
417 channel(data, "namespace ");
421 channel(data, "validity ");
424 channel(data, "HTML parser ");
426 case XML_FROM_MEMORY:
427 channel(data, "memory ");
429 case XML_FROM_OUTPUT:
430 channel(data, "output ");
433 channel(data, "I/O ");
435 case XML_FROM_XINCLUDE:
436 channel(data, "XInclude ");
439 channel(data, "XPath ");
441 case XML_FROM_XPOINTER:
442 channel(data, "parser ");
444 case XML_FROM_REGEXP:
445 channel(data, "regexp ");
447 case XML_FROM_MODULE:
448 channel(data, "module ");
450 case XML_FROM_SCHEMASV:
451 channel(data, "Schemas validity ");
453 case XML_FROM_SCHEMASP:
454 channel(data, "Schemas parser ");
456 case XML_FROM_RELAXNGP:
457 channel(data, "Relax-NG parser ");
459 case XML_FROM_RELAXNGV:
460 channel(data, "Relax-NG validity ");
462 case XML_FROM_CATALOG:
463 channel(data, "Catalog ");
466 channel(data, "C14N ");
469 channel(data, "XSLT ");
474 if (code == XML_ERR_OK)
480 case XML_ERR_WARNING:
481 channel(data, "warning : ");
484 channel(data, "error : ");
487 channel(data, "error : ");
490 if (code == XML_ERR_OK)
494 len = xmlStrlen((const xmlChar *)str);
495 if ((len > 0) && (str[len - 1] != '\n'))
496 channel(data, "%s\n", str);
498 channel(data, "%s", str);
500 channel(data, "%s\n", "out of memory error");
502 if (code == XML_ERR_OK)
506 xmlParserPrintFileContextInternal(input, channel, data);
509 channel(data, "%s:%d: \n", cur->filename, cur->line);
510 else if ((line != 0) && (domain == XML_FROM_PARSER))
511 channel(data, "Entity: line %d: \n", cur->line);
512 xmlParserPrintFileContextInternal(cur, channel, data);
515 if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
517 (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
521 channel(data, "%s\n", err->str1);
522 for (i=0;i < err->int1;i++)
526 channel(data, "%s\n", buf);
531 initializeLibxml2(void) {
532 xmlGetWarningsDefaultValue = 0;
533 xmlPedanticParserDefault(0);
535 xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
537 xmlSetExternalEntityLoader(testExternalEntityLoader);
538 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
539 #ifdef LIBXML_SCHEMAS_ENABLED
540 xmlSchemaInitTypes();
541 xmlRelaxNGInitTypes();
546 /************************************************************************
548 * File name and path utilities *
550 ************************************************************************/
552 static const char *baseFilename(const char *filename) {
554 if (filename == NULL)
556 cur = &filename[strlen(filename)];
557 while ((cur > filename) && (*cur != '/'))
564 static char *resultFilename(const char *filename, const char *out,
565 const char *suffix) {
568 char suffixbuff[500];
571 if ((filename[0] == 't') && (filename[1] == 'e') &&
572 (filename[2] == 's') && (filename[3] == 't') &&
573 (filename[4] == '/'))
574 filename = &filename[5];
577 base = baseFilename(filename);
583 strncpy(suffixbuff,suffix,499);
585 if(strstr(base,".") && suffixbuff[0]=='.')
589 snprintf(res, 499, "%s%s%s", out, base, suffixbuff);
594 static int checkTestFile(const char *filename) {
597 if (stat(filename, &buf) == -1)
600 #if defined(_WIN32) && !defined(__CYGWIN__)
601 if (!(buf.st_mode & _S_IFREG))
604 if (!S_ISREG(buf.st_mode))
611 static int compareFiles(const char *r1 /* temp */, const char *r2 /* result */) {
617 if (update_results) {
618 fd1 = open(r1, RD_FLAGS);
621 fd2 = open(r2, WR_FLAGS, 0644);
627 res1 = read(fd1, bytes1, 4096);
630 res2 = write(fd2, bytes1, res1);
631 if (res2 <= 0 || res2 != res1)
639 fd1 = open(r1, RD_FLAGS);
642 fd2 = open(r2, RD_FLAGS);
648 res1 = read(fd1, bytes1, 4096);
649 res2 = read(fd2, bytes2, 4096);
650 if ((res1 != res2) || (res1 < 0)) {
657 if (memcmp(bytes1, bytes2, res1) != 0) {
668 static int compareFileMem(const char *filename, const char *mem, int size) {
675 if (update_results) {
676 fd = open(filename, WR_FLAGS, 0644);
678 fprintf(stderr, "failed to open %s for writing", filename);
681 res = write(fd, mem, size);
686 if (stat(filename, &info) < 0) {
687 fprintf(stderr, "failed to stat %s\n", filename);
690 if (info.st_size != size) {
691 fprintf(stderr, "file %s is %ld bytes, result is %d bytes\n",
692 filename, (long) info.st_size, size);
695 fd = open(filename, RD_FLAGS);
697 fprintf(stderr, "failed to open %s for reading", filename);
701 res = read(fd, bytes, 4096);
704 if (res + idx > size)
706 if (memcmp(bytes, &mem[idx], res) != 0) {
708 for (ix=0; ix<res; ix++)
709 if (bytes[ix] != mem[idx+ix])
711 fprintf(stderr,"Compare error at position %d\n", idx+ix);
719 fprintf(stderr,"Compare error index %d, size %d\n", idx, size);
724 static int loadMem(const char *filename, const char **mem, int *size) {
729 if (stat(filename, &info) < 0)
731 base = malloc(info.st_size + 1);
734 if ((fd = open(filename, RD_FLAGS)) < 0) {
738 while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
743 if (siz != info.st_size) {
754 static int unloadMem(const char *mem) {
759 /************************************************************************
761 * Tests implementations *
763 ************************************************************************/
765 /************************************************************************
767 * Parse to SAX based tests *
769 ************************************************************************/
771 static FILE *SAXdebug = NULL;
776 static xmlSAXHandler emptySAXHandlerStruct = {
777 NULL, /* internalSubset */
778 NULL, /* isStandalone */
779 NULL, /* hasInternalSubset */
780 NULL, /* hasExternalSubset */
781 NULL, /* resolveEntity */
782 NULL, /* getEntity */
783 NULL, /* entityDecl */
784 NULL, /* notationDecl */
785 NULL, /* attributeDecl */
786 NULL, /* elementDecl */
787 NULL, /* unparsedEntityDecl */
788 NULL, /* setDocumentLocator */
789 NULL, /* startDocument */
790 NULL, /* endDocument */
791 NULL, /* startElement */
792 NULL, /* endElement */
793 NULL, /* reference */
794 NULL, /* characters */
795 NULL, /* ignorableWhitespace */
796 NULL, /* processingInstruction */
798 NULL, /* xmlParserWarning */
799 NULL, /* xmlParserError */
800 NULL, /* xmlParserError */
801 NULL, /* getParameterEntity */
802 NULL, /* cdataBlock; */
803 NULL, /* externalSubset; */
806 NULL, /* startElementNs */
807 NULL, /* endElementNs */
808 NULL /* xmlStructuredErrorFunc */
811 static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
812 static int callbacks = 0;
813 static int quiet = 0;
817 * @ctxt: An XML parser context
819 * Is this document tagged standalone ?
824 isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
829 fprintf(SAXdebug, "SAX.isStandalone()\n");
834 * hasInternalSubsetDebug:
835 * @ctxt: An XML parser context
837 * Does this document has an internal subset
842 hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
847 fprintf(SAXdebug, "SAX.hasInternalSubset()\n");
852 * hasExternalSubsetDebug:
853 * @ctxt: An XML parser context
855 * Does this document has an external subset
860 hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
865 fprintf(SAXdebug, "SAX.hasExternalSubset()\n");
870 * internalSubsetDebug:
871 * @ctxt: An XML parser context
873 * Does this document has an internal subset
876 internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
877 const xmlChar *ExternalID, const xmlChar *SystemID)
882 fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
883 if (ExternalID == NULL)
884 fprintf(SAXdebug, " ,");
886 fprintf(SAXdebug, " %s,", ExternalID);
887 if (SystemID == NULL)
888 fprintf(SAXdebug, " )\n");
890 fprintf(SAXdebug, " %s)\n", SystemID);
894 * externalSubsetDebug:
895 * @ctxt: An XML parser context
897 * Does this document has an external subset
900 externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
901 const xmlChar *ExternalID, const xmlChar *SystemID)
906 fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
907 if (ExternalID == NULL)
908 fprintf(SAXdebug, " ,");
910 fprintf(SAXdebug, " %s,", ExternalID);
911 if (SystemID == NULL)
912 fprintf(SAXdebug, " )\n");
914 fprintf(SAXdebug, " %s)\n", SystemID);
918 * resolveEntityDebug:
919 * @ctxt: An XML parser context
920 * @publicId: The public ID of the entity
921 * @systemId: The system ID of the entity
923 * Special entity resolver, better left to the parser, it has
924 * more context than the application layer.
925 * The default behaviour is to NOT resolve the entities, in that case
926 * the ENTITY_REF nodes are built in the structure (and the parameter
929 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
931 static xmlParserInputPtr
932 resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
937 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
940 fprintf(SAXdebug, "SAX.resolveEntity(");
941 if (publicId != NULL)
942 fprintf(SAXdebug, "%s", (char *)publicId);
944 fprintf(SAXdebug, " ");
945 if (systemId != NULL)
946 fprintf(SAXdebug, ", %s)\n", (char *)systemId);
948 fprintf(SAXdebug, ", )\n");
950 if (systemId != NULL) {
951 return(xmlNewInputFromFile(ctxt, (char *) systemId));
959 * @ctxt: An XML parser context
960 * @name: The entity name
962 * Get an entity by name
964 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
967 getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
972 fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
977 * getParameterEntityDebug:
978 * @ctxt: An XML parser context
979 * @name: The entity name
981 * Get a parameter entity by name
983 * Returns the xmlParserInputPtr
986 getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
991 fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
998 * @ctxt: An XML parser context
999 * @name: the entity name
1000 * @type: the entity type
1001 * @publicId: The public ID of the entity
1002 * @systemId: The system ID of the entity
1003 * @content: the entity value (without processing).
1005 * An entity definition has been parsed
1008 entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1009 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
1011 const xmlChar *nullstr = BAD_CAST "(null)";
1012 /* not all libraries handle printing null pointers nicely */
1013 if (publicId == NULL)
1015 if (systemId == NULL)
1017 if (content == NULL)
1018 content = (xmlChar *)nullstr;
1022 fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
1023 name, type, publicId, systemId, content);
1027 * attributeDeclDebug:
1028 * @ctxt: An XML parser context
1029 * @name: the attribute name
1030 * @type: the attribute type
1032 * An attribute definition has been parsed
1035 attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
1036 const xmlChar * name, int type, int def,
1037 const xmlChar * defaultValue, xmlEnumerationPtr tree)
1042 if (defaultValue == NULL)
1043 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
1044 elem, name, type, def);
1046 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
1047 elem, name, type, def, defaultValue);
1048 xmlFreeEnumeration(tree);
1053 * @ctxt: An XML parser context
1054 * @name: the element name
1055 * @type: the element type
1056 * @content: the element value (without processing).
1058 * An element definition has been parsed
1061 elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1062 xmlElementContentPtr content ATTRIBUTE_UNUSED)
1067 fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n",
1072 * notationDeclDebug:
1073 * @ctxt: An XML parser context
1074 * @name: The name of the notation
1075 * @publicId: The public ID of the entity
1076 * @systemId: The system ID of the entity
1078 * What to do when a notation declaration has been parsed.
1081 notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1082 const xmlChar *publicId, const xmlChar *systemId)
1087 fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n",
1088 (char *) name, (char *) publicId, (char *) systemId);
1092 * unparsedEntityDeclDebug:
1093 * @ctxt: An XML parser context
1094 * @name: The name of the entity
1095 * @publicId: The public ID of the entity
1096 * @systemId: The system ID of the entity
1097 * @notationName: the name of the notation
1099 * What to do when an unparsed entity declaration is parsed
1102 unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1103 const xmlChar *publicId, const xmlChar *systemId,
1104 const xmlChar *notationName)
1106 const xmlChar *nullstr = BAD_CAST "(null)";
1108 if (publicId == NULL)
1110 if (systemId == NULL)
1112 if (notationName == NULL)
1113 notationName = nullstr;
1117 fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
1118 (char *) name, (char *) publicId, (char *) systemId,
1119 (char *) notationName);
1123 * setDocumentLocatorDebug:
1124 * @ctxt: An XML parser context
1125 * @loc: A SAX Locator
1127 * Receive the document locator at startup, actually xmlDefaultSAXLocator
1128 * Everything is available on the context, so this is useless in our case.
1131 setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
1136 fprintf(SAXdebug, "SAX.setDocumentLocator()\n");
1140 * startDocumentDebug:
1141 * @ctxt: An XML parser context
1143 * called when the document start being processed.
1146 startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1151 fprintf(SAXdebug, "SAX.startDocument()\n");
1156 * @ctxt: An XML parser context
1158 * called when the document end has been detected.
1161 endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1166 fprintf(SAXdebug, "SAX.endDocument()\n");
1170 * startElementDebug:
1171 * @ctxt: An XML parser context
1172 * @name: The element name
1174 * called when an opening tag has been processed.
1177 startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1184 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1186 for (i = 0;(atts[i] != NULL);i++) {
1187 fprintf(SAXdebug, ", %s='", atts[i++]);
1188 if (atts[i] != NULL)
1189 fprintf(SAXdebug, "%s'", atts[i]);
1192 fprintf(SAXdebug, ")\n");
1197 * @ctxt: An XML parser context
1198 * @name: The element name
1200 * called when the end of an element has been detected.
1203 endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1208 fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name);
1213 * @ctxt: An XML parser context
1214 * @ch: a xmlChar string
1215 * @len: the number of xmlChar
1217 * receiving some chars from the parser.
1218 * Question: how much at a time ???
1221 charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1229 for (i = 0;(i<len) && (i < 30);i++)
1233 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1238 * @ctxt: An XML parser context
1239 * @name: The entity name
1241 * called when an entity reference is detected.
1244 referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1249 fprintf(SAXdebug, "SAX.reference(%s)\n", name);
1253 * ignorableWhitespaceDebug:
1254 * @ctxt: An XML parser context
1255 * @ch: a xmlChar string
1256 * @start: the first char in the string
1257 * @len: the number of xmlChar
1259 * receiving some ignorable whitespaces from the parser.
1260 * Question: how much at a time ???
1263 ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1271 for (i = 0;(i<len) && (i < 30);i++)
1274 fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
1278 * processingInstructionDebug:
1279 * @ctxt: An XML parser context
1280 * @target: the target name
1281 * @data: the PI data's
1282 * @len: the number of xmlChar
1284 * A processing instruction has been parsed.
1287 processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
1288 const xmlChar *data)
1294 fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
1295 (char *) target, (char *) data);
1297 fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n",
1303 * @ctx: the user data (XML parser context)
1304 * @value: The pcdata content
1305 * @len: the block length
1307 * called when a pcdata block has been parsed
1310 cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
1315 fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n",
1316 (char *) value, len);
1321 * @ctxt: An XML parser context
1322 * @value: the comment content
1324 * A comment has been parsed.
1327 commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
1332 fprintf(SAXdebug, "SAX.comment(%s)\n", value);
1337 * @ctxt: An XML parser context
1338 * @msg: the message to display/transmit
1339 * @...: extra parameters for the message display
1341 * Display and format a warning messages, gives file, line, position and
1344 static void XMLCDECL
1345 warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1352 va_start(args, msg);
1353 fprintf(SAXdebug, "SAX.warning: ");
1354 vfprintf(SAXdebug, msg, args);
1360 * @ctxt: An XML parser context
1361 * @msg: the message to display/transmit
1362 * @...: extra parameters for the message display
1364 * Display and format a error messages, gives file, line, position and
1367 static void XMLCDECL
1368 errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1375 va_start(args, msg);
1376 fprintf(SAXdebug, "SAX.error: ");
1377 vfprintf(SAXdebug, msg, args);
1383 * @ctxt: An XML parser context
1384 * @msg: the message to display/transmit
1385 * @...: extra parameters for the message display
1387 * Display and format a fatalError messages, gives file, line, position and
1390 static void XMLCDECL
1391 fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1398 va_start(args, msg);
1399 fprintf(SAXdebug, "SAX.fatalError: ");
1400 vfprintf(SAXdebug, msg, args);
1404 static xmlSAXHandler debugSAXHandlerStruct = {
1405 internalSubsetDebug,
1407 hasInternalSubsetDebug,
1408 hasExternalSubsetDebug,
1415 unparsedEntityDeclDebug,
1416 setDocumentLocatorDebug,
1423 ignorableWhitespaceDebug,
1424 processingInstructionDebug,
1429 getParameterEntityDebug,
1431 externalSubsetDebug,
1439 static xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
1442 * SAX2 specific callbacks
1445 * startElementNsDebug:
1446 * @ctxt: An XML parser context
1447 * @name: The element name
1449 * called when an opening tag has been processed.
1452 startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1453 const xmlChar *localname,
1454 const xmlChar *prefix,
1457 const xmlChar **namespaces,
1460 const xmlChar **attributes)
1467 fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
1469 fprintf(SAXdebug, ", NULL");
1471 fprintf(SAXdebug, ", %s", (char *) prefix);
1473 fprintf(SAXdebug, ", NULL");
1475 fprintf(SAXdebug, ", '%s'", (char *) URI);
1476 fprintf(SAXdebug, ", %d", nb_namespaces);
1478 if (namespaces != NULL) {
1479 for (i = 0;i < nb_namespaces * 2;i++) {
1480 fprintf(SAXdebug, ", xmlns");
1481 if (namespaces[i] != NULL)
1482 fprintf(SAXdebug, ":%s", namespaces[i]);
1484 fprintf(SAXdebug, "='%s'", namespaces[i]);
1487 fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
1488 if (attributes != NULL) {
1489 for (i = 0;i < nb_attributes * 5;i += 5) {
1490 if (attributes[i + 1] != NULL)
1491 fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
1493 fprintf(SAXdebug, ", %s='", attributes[i]);
1494 fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
1495 (int)(attributes[i + 4] - attributes[i + 3]));
1498 fprintf(SAXdebug, ")\n");
1503 * @ctxt: An XML parser context
1504 * @name: The element name
1506 * called when the end of an element has been detected.
1509 endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1510 const xmlChar *localname,
1511 const xmlChar *prefix,
1517 fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
1519 fprintf(SAXdebug, ", NULL");
1521 fprintf(SAXdebug, ", %s", (char *) prefix);
1523 fprintf(SAXdebug, ", NULL)\n");
1525 fprintf(SAXdebug, ", '%s')\n", (char *) URI);
1528 static xmlSAXHandler debugSAX2HandlerStruct = {
1529 internalSubsetDebug,
1531 hasInternalSubsetDebug,
1532 hasExternalSubsetDebug,
1539 unparsedEntityDeclDebug,
1540 setDocumentLocatorDebug,
1547 ignorableWhitespaceDebug,
1548 processingInstructionDebug,
1553 getParameterEntityDebug,
1555 externalSubsetDebug,
1558 startElementNsDebug,
1563 static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
1565 #ifdef LIBXML_HTML_ENABLED
1567 * htmlstartElementDebug:
1568 * @ctxt: An XML parser context
1569 * @name: The element name
1571 * called when an opening tag has been processed.
1574 htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1578 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1580 for (i = 0;(atts[i] != NULL);i++) {
1581 fprintf(SAXdebug, ", %s", atts[i++]);
1582 if (atts[i] != NULL) {
1583 unsigned char output[40];
1584 const unsigned char *att = atts[i];
1586 fprintf(SAXdebug, "='");
1587 while ((attlen = strlen((char*)att)) > 0) {
1588 outlen = sizeof output - 1;
1589 htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
1591 fprintf(SAXdebug, "%s", (char *) output);
1594 fprintf(SAXdebug, "'");
1598 fprintf(SAXdebug, ")\n");
1602 * htmlcharactersDebug:
1603 * @ctxt: An XML parser context
1604 * @ch: a xmlChar string
1605 * @len: the number of xmlChar
1607 * receiving some chars from the parser.
1608 * Question: how much at a time ???
1611 htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1613 unsigned char output[40];
1614 int inlen = len, outlen = 30;
1616 htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1619 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1624 * @ctxt: An XML parser context
1625 * @ch: a xmlChar string
1626 * @len: the number of xmlChar
1628 * receiving some cdata chars from the parser.
1629 * Question: how much at a time ???
1632 htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1634 unsigned char output[40];
1635 int inlen = len, outlen = 30;
1637 htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1640 fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
1643 static xmlSAXHandler debugHTMLSAXHandlerStruct = {
1644 internalSubsetDebug,
1646 hasInternalSubsetDebug,
1647 hasExternalSubsetDebug,
1654 unparsedEntityDeclDebug,
1655 setDocumentLocatorDebug,
1658 htmlstartElementDebug,
1661 htmlcharactersDebug,
1662 ignorableWhitespaceDebug,
1663 processingInstructionDebug,
1668 getParameterEntityDebug,
1670 externalSubsetDebug,
1678 static xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
1679 #endif /* LIBXML_HTML_ENABLED */
1683 * @filename: the file to parse
1684 * @result: the file with expected result
1685 * @err: the file with error messages
1687 * Parse a file using the SAX API and check for errors.
1689 * Returns 0 in case of success, an error code otherwise
1692 saxParseTest(const char *filename, const char *result,
1693 const char *err ATTRIBUTE_UNUSED,
1699 temp = resultFilename(filename, "", ".res");
1701 fprintf(stderr, "out of memory\n");
1704 SAXdebug = fopen(temp, "wb");
1705 if (SAXdebug == NULL) {
1706 fprintf(stderr, "Failed to write to %s\n", temp);
1711 /* for SAX we really want the callbacks though the context handlers */
1712 xmlSetStructuredErrorFunc(NULL, NULL);
1713 xmlSetGenericErrorFunc(NULL, testErrorHandler);
1715 #ifdef LIBXML_HTML_ENABLED
1716 if (options & XML_PARSE_HTML) {
1717 htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);
1722 xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename);
1723 memcpy(ctxt->sax, emptySAXHandler, sizeof(xmlSAXHandler));
1724 xmlCtxtUseOptions(ctxt, options);
1725 xmlParseDocument(ctxt);
1726 ret = ctxt->wellFormed ? 0 : ctxt->errNo;
1727 xmlFreeDoc(ctxt->myDoc);
1728 xmlFreeParserCtxt(ctxt);
1730 if (ret == XML_WAR_UNDECLARED_ENTITY) {
1731 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1735 fprintf(stderr, "Failed to parse %s\n", filename);
1739 #ifdef LIBXML_HTML_ENABLED
1740 if (options & XML_PARSE_HTML) {
1741 htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
1746 xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename);
1747 if (options & XML_PARSE_SAX1) {
1748 memcpy(ctxt->sax, debugSAXHandler, sizeof(xmlSAXHandler));
1749 options -= XML_PARSE_SAX1;
1751 memcpy(ctxt->sax, debugSAX2Handler, sizeof(xmlSAXHandler));
1753 xmlCtxtUseOptions(ctxt, options);
1754 xmlParseDocument(ctxt);
1755 ret = ctxt->wellFormed ? 0 : ctxt->errNo;
1756 xmlFreeDoc(ctxt->myDoc);
1757 xmlFreeParserCtxt(ctxt);
1759 if (ret == XML_WAR_UNDECLARED_ENTITY) {
1760 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1764 if (compareFiles(temp, result)) {
1765 fprintf(stderr, "Got a difference for %s\n", filename);
1775 /* switch back to structured error handling */
1776 xmlSetGenericErrorFunc(NULL, NULL);
1777 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
1782 /************************************************************************
1784 * Parse to tree based tests *
1786 ************************************************************************/
1789 * @filename: the file to parse
1790 * @result: the file with expected result
1791 * @err: the file with error messages: unused
1793 * Parse a file using the old xmlParseFile API, then serialize back
1794 * reparse the result and serialize again, then check for deviation
1797 * Returns 0 in case of success, an error code otherwise
1800 oldParseTest(const char *filename, const char *result,
1801 const char *err ATTRIBUTE_UNUSED,
1802 int options ATTRIBUTE_UNUSED) {
1809 * base of the test, parse with the old API
1811 #ifdef LIBXML_SAX1_ENABLED
1812 doc = xmlParseFile(filename);
1814 doc = xmlReadFile(filename, NULL, 0);
1818 temp = resultFilename(filename, "", ".res");
1820 fprintf(stderr, "out of memory\n");
1823 xmlSaveFile(temp, doc);
1824 if (compareFiles(temp, result)) {
1830 * Parse the saved result to make sure the round trip is okay
1832 #ifdef LIBXML_SAX1_ENABLED
1833 doc = xmlParseFile(temp);
1835 doc = xmlReadFile(temp, NULL, 0);
1839 xmlSaveFile(temp, doc);
1840 if (compareFiles(temp, result)) {
1852 #ifdef LIBXML_PUSH_ENABLED
1855 * @filename: the file to parse
1856 * @result: the file with expected result
1857 * @err: the file with error messages: unused
1859 * Parse a file using the Push API, then serialize back
1860 * to check for content.
1862 * Returns 0 in case of success, an error code otherwise
1865 pushParseTest(const char *filename, const char *result,
1866 const char *err ATTRIBUTE_UNUSED,
1868 xmlParserCtxtPtr ctxt;
1877 * load the document in memory and work from there.
1879 if (loadMem(filename, &base, &size) != 0) {
1880 fprintf(stderr, "Failed to load %s\n", filename);
1884 if (chunkSize > size)
1887 #ifdef LIBXML_HTML_ENABLED
1888 if (options & XML_PARSE_HTML)
1889 ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, chunkSize, filename,
1890 XML_CHAR_ENCODING_NONE);
1893 ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, chunkSize, filename);
1894 xmlCtxtUseOptions(ctxt, options);
1898 if (cur + chunkSize >= size) {
1899 #ifdef LIBXML_HTML_ENABLED
1900 if (options & XML_PARSE_HTML)
1901 htmlParseChunk(ctxt, base + cur, size - cur, 1);
1904 xmlParseChunk(ctxt, base + cur, size - cur, 1);
1907 #ifdef LIBXML_HTML_ENABLED
1908 if (options & XML_PARSE_HTML)
1909 htmlParseChunk(ctxt, base + cur, chunkSize, 0);
1912 xmlParseChunk(ctxt, base + cur, chunkSize, 0);
1915 } while (cur < size);
1917 #ifdef LIBXML_HTML_ENABLED
1918 if (options & XML_PARSE_HTML)
1922 res = ctxt->wellFormed;
1923 xmlFreeParserCtxt(ctxt);
1927 fprintf(stderr, "Failed to parse %s\n", filename);
1930 #ifdef LIBXML_HTML_ENABLED
1931 if (options & XML_PARSE_HTML)
1932 htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1935 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1937 res = compareFileMem(result, base, size);
1938 if ((base == NULL) || (res != 0)) {
1940 xmlFree((char *)base);
1941 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
1944 xmlFree((char *)base);
1946 res = compareFileMem(err, testErrors, testErrorsSize);
1948 fprintf(stderr, "Error for %s failed\n", filename);
1958 * @filename: the file to parse
1959 * @result: the file with expected result
1960 * @err: the file with error messages: unused
1962 * Parse a file using the old xmlReadMemory API, then serialize back
1963 * reparse the result and serialize again, then check for deviation
1966 * Returns 0 in case of success, an error code otherwise
1969 memParseTest(const char *filename, const char *result,
1970 const char *err ATTRIBUTE_UNUSED,
1971 int options ATTRIBUTE_UNUSED) {
1978 * load and parse the memory
1980 if (loadMem(filename, &base, &size) != 0) {
1981 fprintf(stderr, "Failed to load %s\n", filename);
1985 doc = xmlReadMemory(base, size, filename, NULL, 0);
1990 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1992 res = compareFileMem(result, base, size);
1993 if ((base == NULL) || (res != 0)) {
1995 xmlFree((char *)base);
1996 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
1999 xmlFree((char *)base);
2005 * @filename: the file to parse
2006 * @result: the file with expected result
2007 * @err: the file with error messages: unused
2009 * Parse a file with entity resolution, then serialize back
2010 * reparse the result and serialize again, then check for deviation
2013 * Returns 0 in case of success, an error code otherwise
2016 noentParseTest(const char *filename, const char *result,
2017 const char *err ATTRIBUTE_UNUSED,
2025 * base of the test, parse with the old API
2027 doc = xmlReadFile(filename, NULL, options);
2030 temp = resultFilename(filename, "", ".res");
2032 fprintf(stderr, "Out of memory\n");
2035 xmlSaveFile(temp, doc);
2036 if (compareFiles(temp, result)) {
2042 * Parse the saved result to make sure the round trip is okay
2044 doc = xmlReadFile(filename, NULL, options);
2047 xmlSaveFile(temp, doc);
2048 if (compareFiles(temp, result)) {
2062 * @filename: the file to parse
2063 * @result: the file with expected result
2064 * @err: the file with error messages
2066 * Parse a file using the xmlReadFile API and check for errors.
2068 * Returns 0 in case of success, an error code otherwise
2071 errParseTest(const char *filename, const char *result, const char *err,
2074 const char *base = NULL;
2078 #ifdef LIBXML_HTML_ENABLED
2079 if (options & XML_PARSE_HTML) {
2080 doc = htmlReadFile(filename, NULL, options);
2083 #ifdef LIBXML_XINCLUDE_ENABLED
2084 if (options & XML_PARSE_XINCLUDE) {
2085 doc = xmlReadFile(filename, NULL, options);
2086 xmlXIncludeProcessFlags(doc, options);
2090 xmlGetWarningsDefaultValue = 1;
2091 doc = xmlReadFile(filename, NULL, options);
2093 xmlGetWarningsDefaultValue = 0;
2099 #ifdef LIBXML_HTML_ENABLED
2100 if (options & XML_PARSE_HTML) {
2101 htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2104 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2106 res = compareFileMem(result, base, size);
2108 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
2114 xmlFree((char *)base);
2118 res = compareFileMem(err, testErrors, testErrorsSize);
2120 fprintf(stderr, "Error for %s failed\n", filename);
2123 } else if (options & XML_PARSE_DTDVALID) {
2124 if (testErrorsSize != 0)
2125 fprintf(stderr, "Validation for %s failed\n", filename);
2131 #ifdef LIBXML_READER_ENABLED
2132 /************************************************************************
2134 * Reader based tests *
2136 ************************************************************************/
2138 static void processNode(FILE *out, xmlTextReaderPtr reader) {
2139 const xmlChar *name, *value;
2142 type = xmlTextReaderNodeType(reader);
2143 empty = xmlTextReaderIsEmptyElement(reader);
2145 name = xmlTextReaderConstName(reader);
2147 name = BAD_CAST "--";
2149 value = xmlTextReaderConstValue(reader);
2152 fprintf(out, "%d %d %s %d %d",
2153 xmlTextReaderDepth(reader),
2157 xmlTextReaderHasValue(reader));
2161 fprintf(out, " %s\n", value);
2165 streamProcessTest(const char *filename, const char *result, const char *err,
2166 xmlTextReaderPtr reader, const char *rng,
2167 int options ATTRIBUTE_UNUSED) {
2176 if (result != NULL) {
2177 temp = resultFilename(filename, "", ".res");
2179 fprintf(stderr, "Out of memory\n");
2182 t = fopen(temp, "wb");
2184 fprintf(stderr, "Can't open temp file %s\n", temp);
2189 #ifdef LIBXML_SCHEMAS_ENABLED
2191 ret = xmlTextReaderRelaxNGValidate(reader, rng);
2193 testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
2204 xmlGetWarningsDefaultValue = 1;
2205 ret = xmlTextReaderRead(reader);
2207 if ((t != NULL) && (rng == NULL))
2208 processNode(t, reader);
2209 ret = xmlTextReaderRead(reader);
2212 testErrorHandler(NULL, "%s : failed to parse\n", filename);
2215 if (xmlTextReaderIsValid(reader) != 1) {
2216 testErrorHandler(NULL, "%s fails to validate\n", filename);
2218 testErrorHandler(NULL, "%s validates\n", filename);
2221 xmlGetWarningsDefaultValue = 0;
2224 ret = compareFiles(temp, result);
2230 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
2235 ret = compareFileMem(err, testErrors, testErrorsSize);
2237 fprintf(stderr, "Error for %s failed\n", filename);
2238 printf("%s", testErrors);
2248 * @filename: the file to parse
2249 * @result: the file with expected result
2250 * @err: the file with error messages
2252 * Parse a file using the reader API and check for errors.
2254 * Returns 0 in case of success, an error code otherwise
2257 streamParseTest(const char *filename, const char *result, const char *err,
2259 xmlTextReaderPtr reader;
2262 reader = xmlReaderForFile(filename, NULL, options);
2263 ret = streamProcessTest(filename, result, err, reader, NULL, options);
2264 xmlFreeTextReader(reader);
2270 * @filename: the file to parse
2271 * @result: the file with expected result
2272 * @err: the file with error messages
2274 * Parse a file using the walker, i.e. a reader built from a atree.
2276 * Returns 0 in case of success, an error code otherwise
2279 walkerParseTest(const char *filename, const char *result, const char *err,
2282 xmlTextReaderPtr reader;
2285 doc = xmlReadFile(filename, NULL, options);
2287 fprintf(stderr, "Failed to parse %s\n", filename);
2290 reader = xmlReaderWalker(doc);
2291 ret = streamProcessTest(filename, result, err, reader, NULL, options);
2292 xmlFreeTextReader(reader);
2298 * streamMemParseTest:
2299 * @filename: the file to parse
2300 * @result: the file with expected result
2301 * @err: the file with error messages
2303 * Parse a file using the reader API from memory and check for errors.
2305 * Returns 0 in case of success, an error code otherwise
2308 streamMemParseTest(const char *filename, const char *result, const char *err,
2310 xmlTextReaderPtr reader;
2316 * load and parse the memory
2318 if (loadMem(filename, &base, &size) != 0) {
2319 fprintf(stderr, "Failed to load %s\n", filename);
2322 reader = xmlReaderForMemory(base, size, filename, NULL, options);
2323 ret = streamProcessTest(filename, result, err, reader, NULL, options);
2325 xmlFreeTextReader(reader);
2330 #ifdef LIBXML_XPATH_ENABLED
2331 #ifdef LIBXML_DEBUG_ENABLED
2332 /************************************************************************
2334 * XPath and XPointer based tests *
2336 ************************************************************************/
2338 static FILE *xpathOutput;
2339 static xmlDocPtr xpathDocument;
2342 ignoreGenericError(void *ctx ATTRIBUTE_UNUSED,
2343 const char *msg ATTRIBUTE_UNUSED, ...) {
2347 testXPath(const char *str, int xptr, int expr) {
2348 xmlGenericErrorFunc handler = ignoreGenericError;
2349 xmlXPathObjectPtr res;
2350 xmlXPathContextPtr ctxt;
2352 /* Don't print generic errors to stderr. */
2353 initGenericErrorDefaultFunc(&handler);
2356 #if defined(LIBXML_XPTR_ENABLED)
2358 ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
2359 res = xmlXPtrEval(BAD_CAST str, ctxt);
2362 ctxt = xmlXPathNewContext(xpathDocument);
2363 ctxt->node = xmlDocGetRootElement(xpathDocument);
2365 res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
2367 /* res = xmlXPathEval(BAD_CAST str, ctxt); */
2368 xmlXPathCompExprPtr comp;
2370 comp = xmlXPathCompile(BAD_CAST str);
2372 res = xmlXPathCompiledEval(comp, ctxt);
2373 xmlXPathFreeCompExpr(comp);
2377 #if defined(LIBXML_XPTR_ENABLED)
2380 xmlXPathDebugDumpObject(xpathOutput, res, 0);
2381 xmlXPathFreeObject(res);
2382 xmlXPathFreeContext(ctxt);
2384 /* Reset generic error handler. */
2385 initGenericErrorDefaultFunc(NULL);
2390 * @filename: the file to parse
2391 * @result: the file with expected result
2392 * @err: the file with error messages
2394 * Parse a file containing XPath standalone expressions and evaluate them
2396 * Returns 0 in case of success, an error code otherwise
2399 xpathCommonTest(const char *filename, const char *result,
2400 int xptr, int expr) {
2402 char expression[5000];
2406 temp = resultFilename(filename, "", ".res");
2408 fprintf(stderr, "Out of memory\n");
2411 xpathOutput = fopen(temp, "wb");
2412 if (xpathOutput == NULL) {
2413 fprintf(stderr, "failed to open output file %s\n", temp);
2418 input = fopen(filename, "rb");
2419 if (input == NULL) {
2420 xmlGenericError(xmlGenericErrorContext,
2421 "Cannot open %s for reading\n", filename);
2425 while (fgets(expression, 4500, input) != NULL) {
2426 len = strlen(expression);
2428 while ((len >= 0) &&
2429 ((expression[len] == '\n') || (expression[len] == '\t') ||
2430 (expression[len] == '\r') || (expression[len] == ' '))) len--;
2431 expression[len + 1] = 0;
2433 fprintf(xpathOutput,
2434 "\n========================\nExpression: %s\n",
2436 testXPath(expression, xptr, expr);
2441 fclose(xpathOutput);
2442 if (result != NULL) {
2443 ret = compareFiles(temp, result);
2445 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
2458 * @filename: the file to parse
2459 * @result: the file with expected result
2460 * @err: the file with error messages
2462 * Parse a file containing XPath standalone expressions and evaluate them
2464 * Returns 0 in case of success, an error code otherwise
2467 xpathExprTest(const char *filename, const char *result,
2468 const char *err ATTRIBUTE_UNUSED,
2469 int options ATTRIBUTE_UNUSED) {
2470 return(xpathCommonTest(filename, result, 0, 1));
2475 * @filename: the file to parse
2476 * @result: the file with expected result
2477 * @err: the file with error messages
2479 * Parse a file containing XPath expressions and evaluate them against
2480 * a set of corresponding documents.
2482 * Returns 0 in case of success, an error code otherwise
2485 xpathDocTest(const char *filename,
2486 const char *resul ATTRIBUTE_UNUSED,
2487 const char *err ATTRIBUTE_UNUSED,
2496 xpathDocument = xmlReadFile(filename, NULL,
2497 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2498 if (xpathDocument == NULL) {
2499 fprintf(stderr, "Failed to load %s\n", filename);
2503 snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
2505 globbuf.gl_offs = 0;
2506 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2507 for (i = 0;i < globbuf.gl_pathc;i++) {
2508 snprintf(result, 499, "result/XPath/tests/%s",
2509 baseFilename(globbuf.gl_pathv[i]));
2510 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
2516 xmlFreeDoc(xpathDocument);
2520 #ifdef LIBXML_XPTR_ENABLED
2523 * @filename: the file to parse
2524 * @result: the file with expected result
2525 * @err: the file with error messages
2527 * Parse a file containing XPath expressions and evaluate them against
2528 * a set of corresponding documents.
2530 * Returns 0 in case of success, an error code otherwise
2533 xptrDocTest(const char *filename,
2534 const char *resul ATTRIBUTE_UNUSED,
2535 const char *err ATTRIBUTE_UNUSED,
2544 xpathDocument = xmlReadFile(filename, NULL,
2545 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2546 if (xpathDocument == NULL) {
2547 fprintf(stderr, "Failed to load %s\n", filename);
2551 snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
2553 globbuf.gl_offs = 0;
2554 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2555 for (i = 0;i < globbuf.gl_pathc;i++) {
2556 snprintf(result, 499, "result/XPath/xptr/%s",
2557 baseFilename(globbuf.gl_pathv[i]));
2558 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
2564 xmlFreeDoc(xpathDocument);
2567 #endif /* LIBXML_XPTR_ENABLED */
2571 * @filename: the file to parse
2572 * @result: the file with expected result
2573 * @err: the file with error messages
2575 * Parse a file containing xml:id and check for errors and verify
2576 * that XPath queries will work on them as expected.
2578 * Returns 0 in case of success, an error code otherwise
2581 xmlidDocTest(const char *filename,
2590 xpathDocument = xmlReadFile(filename, NULL,
2591 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2592 if (xpathDocument == NULL) {
2593 fprintf(stderr, "Failed to load %s\n", filename);
2597 temp = resultFilename(filename, "", ".res");
2599 fprintf(stderr, "Out of memory\n");
2602 xpathOutput = fopen(temp, "wb");
2603 if (xpathOutput == NULL) {
2604 fprintf(stderr, "failed to open output file %s\n", temp);
2605 xmlFreeDoc(xpathDocument);
2610 testXPath("id('bar')", 0, 0);
2612 fclose(xpathOutput);
2613 if (result != NULL) {
2614 ret = compareFiles(temp, result);
2616 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
2625 xmlFreeDoc(xpathDocument);
2628 ret = compareFileMem(err, testErrors, testErrorsSize);
2630 fprintf(stderr, "Error for %s failed\n", filename);
2637 #endif /* LIBXML_DEBUG_ENABLED */
2639 /************************************************************************
2643 ************************************************************************/
2646 handleURI(const char *str, const char *base, FILE *o) {
2649 xmlChar *res = NULL;
2651 uri = xmlCreateURI();
2654 ret = xmlParseURIReference(uri, str);
2656 fprintf(o, "%s : error %d\n", str, ret);
2658 xmlNormalizeURIPath(uri->path);
2659 xmlPrintURI(o, uri);
2663 res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
2665 fprintf(o, "%s\n", (char *) res);
2668 fprintf(o, "::ERROR::\n");
2677 * @filename: the file to parse
2678 * @result: the file with expected result
2679 * @err: the file with error messages
2681 * Parse a file containing URI and check for errors
2683 * Returns 0 in case of success, an error code otherwise
2686 uriCommonTest(const char *filename,
2693 int res = 0, i, ret;
2695 temp = resultFilename(filename, "", ".res");
2697 fprintf(stderr, "Out of memory\n");
2700 o = fopen(temp, "wb");
2702 fprintf(stderr, "failed to open output file %s\n", temp);
2706 f = fopen(filename, "rb");
2708 fprintf(stderr, "failed to open input file %s\n", filename);
2719 * read one line in string buffer.
2721 if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
2725 * remove the ending spaces
2729 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
2730 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
2735 handleURI(str, base, o);
2741 if (result != NULL) {
2742 ret = compareFiles(temp, result);
2744 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
2749 ret = compareFileMem(err, testErrors, testErrorsSize);
2751 fprintf(stderr, "Error for %s failed\n", filename);
2765 * @filename: the file to parse
2766 * @result: the file with expected result
2767 * @err: the file with error messages
2769 * Parse a file containing URI and check for errors
2771 * Returns 0 in case of success, an error code otherwise
2774 uriParseTest(const char *filename,
2777 int options ATTRIBUTE_UNUSED) {
2778 return(uriCommonTest(filename, result, err, NULL));
2783 * @filename: the file to parse
2784 * @result: the file with expected result
2785 * @err: the file with error messages
2787 * Parse a file containing URI, compose them against a fixed base and
2790 * Returns 0 in case of success, an error code otherwise
2793 uriBaseTest(const char *filename,
2796 int options ATTRIBUTE_UNUSED) {
2797 return(uriCommonTest(filename, result, err,
2798 "http://foo.com/path/to/index.html?orig#help"));
2801 static int urip_success = 1;
2802 static int urip_current = 0;
2803 static const char *urip_testURLs[] = {
2804 "urip://example.com/a b.html",
2805 "urip://example.com/a%20b.html",
2806 "file:///path/to/a b.html",
2807 "file:///path/to/a%20b.html",
2808 "/path/to/a b.html",
2809 "/path/to/a%20b.html",
2810 "urip://example.com/r" "\xe9" "sum" "\xe9" ".html",
2811 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2814 static const char *urip_rcvsURLs[] = {
2815 /* it is an URI the strings must be escaped */
2816 "urip://example.com/a%20b.html",
2817 /* check that % escaping is not broken */
2818 "urip://example.com/a%20b.html",
2819 /* it's an URI path the strings must be escaped */
2820 "file:///path/to/a%20b.html",
2821 /* check that % escaping is not broken */
2822 "file:///path/to/a%20b.html",
2823 /* this is not an URI, this is a path, so this should not be escaped */
2824 "/path/to/a b.html",
2825 /* check that paths with % are not broken */
2826 "/path/to/a%20b.html",
2827 /* out of context the encoding can't be guessed byte by byte conversion */
2828 "urip://example.com/r%E9sum%E9.html",
2829 /* verify we don't destroy URIs especially the query part */
2830 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2833 static const char *urip_res = "<list/>";
2834 static const char *urip_cur = NULL;
2835 static int urip_rlen;
2839 * @URI: an URI to test
2841 * Check for an urip: query
2843 * Returns 1 if yes and 0 if another Input module should be used
2846 uripMatch(const char * URI) {
2847 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2849 /* Verify we received the escaped URL */
2850 if (strcmp(urip_rcvsURLs[urip_current], URI))
2857 * @URI: an URI to test
2859 * Return a pointer to the urip: query handler, in this example simply
2860 * the urip_current pointer...
2862 * Returns an Input context or NULL in case or error
2865 uripOpen(const char * URI) {
2866 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2868 /* Verify we received the escaped URL */
2869 if (strcmp(urip_rcvsURLs[urip_current], URI))
2871 urip_cur = urip_res;
2872 urip_rlen = strlen(urip_res);
2873 return((void *) urip_cur);
2878 * @context: the read context
2880 * Close the urip: query handler
2882 * Returns 0 or -1 in case of error
2885 uripClose(void * context) {
2886 if (context == NULL) return(-1);
2894 * @context: the read context
2895 * @buffer: where to store data
2896 * @len: number of bytes to read
2898 * Implement an urip: query read.
2900 * Returns the number of bytes read or -1 in case of error
2903 uripRead(void * context, char * buffer, int len) {
2904 const char *ptr = (const char *) context;
2906 if ((context == NULL) || (buffer == NULL) || (len < 0))
2909 if (len > urip_rlen) len = urip_rlen;
2910 memcpy(buffer, ptr, len);
2916 urip_checkURL(const char *URL) {
2919 doc = xmlReadFile(URL, NULL, 0);
2928 * @filename: ignored
2932 * Run a set of tests to check how Path and URI are handled before
2933 * being passed to the I/O layer
2935 * Returns 0 in case of success, an error code otherwise
2938 uriPathTest(const char *filename ATTRIBUTE_UNUSED,
2939 const char *result ATTRIBUTE_UNUSED,
2940 const char *err ATTRIBUTE_UNUSED,
2941 int options ATTRIBUTE_UNUSED) {
2946 * register the new I/O handlers
2948 if (xmlRegisterInputCallbacks(uripMatch, uripOpen, uripRead, uripClose) < 0)
2950 fprintf(stderr, "failed to register HTTP handler\n");
2954 for (urip_current = 0;urip_testURLs[urip_current] != NULL;urip_current++) {
2956 parsed = urip_checkURL(urip_testURLs[urip_current]);
2957 if (urip_success != 1) {
2958 fprintf(stderr, "failed the URL passing test for %s",
2959 urip_testURLs[urip_current]);
2961 } else if (parsed != 1) {
2962 fprintf(stderr, "failed the parsing test for %s",
2963 urip_testURLs[urip_current]);
2969 xmlPopInputCallbacks();
2973 #ifdef LIBXML_SCHEMAS_ENABLED
2974 /************************************************************************
2978 ************************************************************************/
2980 schemasOneTest(const char *sch,
2981 const char *filename,
2985 xmlSchemaPtr schemas) {
2987 xmlSchemaValidCtxtPtr ctxt;
2989 int validResult = 0;
2991 FILE *schemasOutput;
2993 doc = xmlReadFile(filename, NULL, options);
2995 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
2999 temp = resultFilename(result, "", ".res");
3001 fprintf(stderr, "Out of memory\n");
3004 schemasOutput = fopen(temp, "wb");
3005 if (schemasOutput == NULL) {
3006 fprintf(stderr, "failed to open output file %s\n", temp);
3012 ctxt = xmlSchemaNewValidCtxt(schemas);
3013 xmlSchemaSetValidErrors(ctxt,
3014 (xmlSchemaValidityErrorFunc) testErrorHandler,
3015 (xmlSchemaValidityWarningFunc) testErrorHandler,
3017 validResult = xmlSchemaValidateDoc(ctxt, doc);
3018 if (validResult == 0) {
3019 fprintf(schemasOutput, "%s validates\n", filename);
3020 } else if (validResult > 0) {
3021 fprintf(schemasOutput, "%s fails to validate\n", filename);
3023 fprintf(schemasOutput, "%s validation generated an internal error\n",
3026 fclose(schemasOutput);
3028 if (compareFiles(temp, result)) {
3029 fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
3038 if ((validResult != 0) && (err != NULL)) {
3039 if (compareFileMem(err, testErrors, testErrorsSize)) {
3040 fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
3045 xmlSchemaFreeValidCtxt(ctxt);
3051 * @filename: the schemas file
3052 * @result: the file with expected result
3053 * @err: the file with error messages
3055 * Parse a file containing URI, compose them against a fixed base and
3058 * Returns 0 in case of success, an error code otherwise
3061 schemasTest(const char *filename,
3062 const char *resul ATTRIBUTE_UNUSED,
3063 const char *errr ATTRIBUTE_UNUSED,
3065 const char *base = baseFilename(filename);
3067 const char *instance;
3068 xmlSchemaParserCtxtPtr ctxt;
3069 xmlSchemaPtr schemas;
3070 int res = 0, len, ret;
3079 /* first compile the schemas if possible */
3080 ctxt = xmlSchemaNewParserCtxt(filename);
3081 xmlSchemaSetParserErrors(ctxt,
3082 (xmlSchemaValidityErrorFunc) testErrorHandler,
3083 (xmlSchemaValidityWarningFunc) testErrorHandler,
3085 schemas = xmlSchemaParse(ctxt);
3086 xmlSchemaFreeParserCtxt(ctxt);
3089 * most of the mess is about the output filenames generated by the Makefile
3092 if ((len > 499) || (len < 5)) {
3093 xmlSchemaFree(schemas);
3096 len -= 4; /* remove trailing .xsd */
3097 if (base[len - 2] == '_') {
3098 len -= 2; /* remove subtest number */
3100 if (base[len - 2] == '_') {
3101 len -= 2; /* remove subtest number */
3103 memcpy(prefix, base, len);
3106 snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
3109 if (base[len] == '_') {
3111 memcpy(prefix, base, len);
3115 globbuf.gl_offs = 0;
3116 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3117 for (i = 0;i < globbuf.gl_pathc;i++) {
3120 instance = globbuf.gl_pathv[i];
3121 base2 = baseFilename(instance);
3122 len = strlen(base2);
3123 if ((len > 6) && (base2[len - 6] == '_')) {
3124 count = base2[len - 5];
3125 snprintf(result, 499, "result/schemas/%s_%c",
3128 snprintf(err, 499, "result/schemas/%s_%c.err",
3132 fprintf(stderr, "don't know how to process %s\n", instance);
3135 if (schemas == NULL) {
3138 ret = schemasOneTest(filename, instance, result, err,
3145 xmlSchemaFree(schemas);
3150 /************************************************************************
3154 ************************************************************************/
3156 rngOneTest(const char *sch,
3157 const char *filename,
3161 xmlRelaxNGPtr schemas) {
3163 xmlRelaxNGValidCtxtPtr ctxt;
3166 FILE *schemasOutput;
3168 doc = xmlReadFile(filename, NULL, options);
3170 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
3174 temp = resultFilename(result, "", ".res");
3176 fprintf(stderr, "Out of memory\n");
3179 schemasOutput = fopen(temp, "wb");
3180 if (schemasOutput == NULL) {
3181 fprintf(stderr, "failed to open output file %s\n", temp);
3187 ctxt = xmlRelaxNGNewValidCtxt(schemas);
3188 xmlRelaxNGSetValidErrors(ctxt,
3189 (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3190 (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3192 ret = xmlRelaxNGValidateDoc(ctxt, doc);
3194 testErrorHandler(NULL, "%s validates\n", filename);
3195 } else if (ret > 0) {
3196 testErrorHandler(NULL, "%s fails to validate\n", filename);
3198 testErrorHandler(NULL, "%s validation generated an internal error\n",
3201 fclose(schemasOutput);
3204 if (compareFiles(temp, result)) {
3205 fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
3215 if (compareFileMem(err, testErrors, testErrorsSize)) {
3216 fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
3218 printf("%s", testErrors);
3223 xmlRelaxNGFreeValidCtxt(ctxt);
3229 * @filename: the schemas file
3230 * @result: the file with expected result
3231 * @err: the file with error messages
3233 * Parse an RNG schemas and then apply it to the related .xml
3235 * Returns 0 in case of success, an error code otherwise
3238 rngTest(const char *filename,
3239 const char *resul ATTRIBUTE_UNUSED,
3240 const char *errr ATTRIBUTE_UNUSED,
3242 const char *base = baseFilename(filename);
3244 const char *instance;
3245 xmlRelaxNGParserCtxtPtr ctxt;
3246 xmlRelaxNGPtr schemas;
3247 int res = 0, len, ret = 0;
3256 /* first compile the schemas if possible */
3257 ctxt = xmlRelaxNGNewParserCtxt(filename);
3258 xmlRelaxNGSetParserErrors(ctxt,
3259 (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3260 (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3262 schemas = xmlRelaxNGParse(ctxt);
3263 xmlRelaxNGFreeParserCtxt(ctxt);
3266 * most of the mess is about the output filenames generated by the Makefile
3269 if ((len > 499) || (len < 5)) {
3270 xmlRelaxNGFree(schemas);
3273 len -= 4; /* remove trailing .rng */
3274 memcpy(prefix, base, len);
3277 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3280 globbuf.gl_offs = 0;
3281 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3282 for (i = 0;i < globbuf.gl_pathc;i++) {
3285 instance = globbuf.gl_pathv[i];
3286 base2 = baseFilename(instance);
3287 len = strlen(base2);
3288 if ((len > 6) && (base2[len - 6] == '_')) {
3289 count = base2[len - 5];
3290 snprintf(result, 499, "result/relaxng/%s_%c",
3293 snprintf(err, 499, "result/relaxng/%s_%c.err",
3297 fprintf(stderr, "don't know how to process %s\n", instance);
3300 if (schemas == NULL) {
3303 ret = rngOneTest(filename, instance, result, err,
3310 xmlRelaxNGFree(schemas);
3315 #ifdef LIBXML_READER_ENABLED
3318 * @filename: the schemas file
3319 * @result: the file with expected result
3320 * @err: the file with error messages
3322 * Parse a set of files with streaming, applying an RNG schemas
3324 * Returns 0 in case of success, an error code otherwise
3327 rngStreamTest(const char *filename,
3328 const char *resul ATTRIBUTE_UNUSED,
3329 const char *errr ATTRIBUTE_UNUSED,
3331 const char *base = baseFilename(filename);
3333 const char *instance;
3334 int res = 0, len, ret;
3342 xmlTextReaderPtr reader;
3343 int disable_err = 0;
3346 * most of the mess is about the output filenames generated by the Makefile
3349 if ((len > 499) || (len < 5)) {
3350 fprintf(stderr, "len(base) == %d !\n", len);
3353 len -= 4; /* remove trailing .rng */
3354 memcpy(prefix, base, len);
3358 * strictly unifying the error messages is nearly impossible this
3359 * hack is also done in the Makefile
3361 if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
3362 (!strcmp(prefix, "tutor3_2")) || (!strcmp(prefix, "307377")) ||
3363 (!strcmp(prefix, "tutor8_2")))
3366 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3369 globbuf.gl_offs = 0;
3370 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3371 for (i = 0;i < globbuf.gl_pathc;i++) {
3374 instance = globbuf.gl_pathv[i];
3375 base2 = baseFilename(instance);
3376 len = strlen(base2);
3377 if ((len > 6) && (base2[len - 6] == '_')) {
3378 count = base2[len - 5];
3379 snprintf(result, 499, "result/relaxng/%s_%c",
3382 snprintf(err, 499, "result/relaxng/%s_%c.err",
3386 fprintf(stderr, "don't know how to process %s\n", instance);
3389 reader = xmlReaderForFile(instance, NULL, options);
3390 if (reader == NULL) {
3391 fprintf(stderr, "Failed to build reder for %s\n", instance);
3393 if (disable_err == 1)
3394 ret = streamProcessTest(instance, result, NULL, reader, filename,
3397 ret = streamProcessTest(instance, result, err, reader, filename,
3399 xmlFreeTextReader(reader);
3401 fprintf(stderr, "instance %s failed\n", instance);
3413 #ifdef LIBXML_PATTERN_ENABLED
3414 #ifdef LIBXML_READER_ENABLED
3415 /************************************************************************
3419 ************************************************************************/
3420 static void patternNode(FILE *out, xmlTextReaderPtr reader,
3421 const char *pattern, xmlPatternPtr patternc,
3422 xmlStreamCtxtPtr patstream) {
3423 xmlChar *path = NULL;
3427 type = xmlTextReaderNodeType(reader);
3428 empty = xmlTextReaderIsEmptyElement(reader);
3430 if (type == XML_READER_TYPE_ELEMENT) {
3431 /* do the check only on element start */
3432 match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
3435 path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
3436 fprintf(out, "Node %s matches pattern %s\n", path, pattern);
3439 if (patstream != NULL) {
3442 if (type == XML_READER_TYPE_ELEMENT) {
3443 ret = xmlStreamPush(patstream,
3444 xmlTextReaderConstLocalName(reader),
3445 xmlTextReaderConstNamespaceUri(reader));
3447 fprintf(out, "xmlStreamPush() failure\n");
3448 xmlFreeStreamCtxt(patstream);
3450 } else if (ret != match) {
3452 path = xmlGetNodePath(
3453 xmlTextReaderCurrentNode(reader));
3456 "xmlPatternMatch and xmlStreamPush disagree\n");
3458 " pattern %s node %s\n",
3464 if ((type == XML_READER_TYPE_END_ELEMENT) ||
3465 ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
3466 ret = xmlStreamPop(patstream);
3468 fprintf(out, "xmlStreamPop() failure\n");
3469 xmlFreeStreamCtxt(patstream);
3480 * @filename: the schemas file
3481 * @result: the file with expected result
3482 * @err: the file with error messages
3484 * Parse a set of files with streaming, applying an RNG schemas
3486 * Returns 0 in case of success, an error code otherwise
3489 patternTest(const char *filename,
3490 const char *resul ATTRIBUTE_UNUSED,
3491 const char *err ATTRIBUTE_UNUSED,
3493 xmlPatternPtr patternc = NULL;
3494 xmlStreamCtxtPtr patstream = NULL;
3502 xmlTextReaderPtr reader;
3505 len = strlen(filename);
3507 memcpy(xml, filename, len);
3509 snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
3511 memcpy(xml + len, ".xml", 5);
3513 if (!checkTestFile(xml) && !update_results) {
3514 fprintf(stderr, "Missing xml file %s\n", xml);
3517 if (!checkTestFile(result) && !update_results) {
3518 fprintf(stderr, "Missing result file %s\n", result);
3521 f = fopen(filename, "rb");
3523 fprintf(stderr, "Failed to open %s\n", filename);
3526 temp = resultFilename(filename, "", ".res");
3528 fprintf(stderr, "Out of memory\n");
3531 o = fopen(temp, "wb");
3533 fprintf(stderr, "failed to open output file %s\n", temp);
3540 * read one line in string buffer.
3542 if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
3546 * remove the ending spaces
3550 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
3551 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
3555 doc = xmlReadFile(xml, NULL, options);
3557 fprintf(stderr, "Failed to parse %s\n", xml);
3561 const xmlChar *namespaces[22];
3565 root = xmlDocGetRootElement(doc);
3566 for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
3567 namespaces[j++] = ns->href;
3568 namespaces[j++] = ns->prefix;
3570 namespaces[j++] = NULL;
3571 namespaces[j] = NULL;
3573 patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
3575 if (patternc == NULL) {
3576 testErrorHandler(NULL,
3577 "Pattern %s failed to compile\n", str);
3582 patstream = xmlPatternGetStreamCtxt(patternc);
3583 if (patstream != NULL) {
3584 ret = xmlStreamPush(patstream, NULL, NULL);
3586 fprintf(stderr, "xmlStreamPush() failure\n");
3587 xmlFreeStreamCtxt(patstream);
3593 reader = xmlReaderWalker(doc);
3594 res = xmlTextReaderRead(reader);
3596 patternNode(o, reader, str, patternc, patstream);
3597 res = xmlTextReaderRead(reader);
3600 fprintf(o, "%s : failed to parse\n", filename);
3602 xmlFreeTextReader(reader);
3604 xmlFreeStreamCtxt(patstream);
3606 xmlFreePattern(patternc);
3614 ret = compareFiles(temp, result);
3616 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
3626 #endif /* PATTERN */
3627 #ifdef LIBXML_C14N_ENABLED
3628 /************************************************************************
3630 * Canonicalization tests *
3632 ************************************************************************/
3633 static xmlXPathObjectPtr
3634 load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
3635 xmlXPathObjectPtr xpath;
3638 xmlXPathContextPtr ctx;
3643 * load XPath expr as a file
3645 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3646 xmlSubstituteEntitiesDefault(1);
3648 doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3650 fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
3655 * Check the document is of the right kind
3657 if(xmlDocGetRootElement(doc) == NULL) {
3658 fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
3663 node = doc->children;
3664 while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
3669 fprintf(stderr,"Error: XPath element expected in the file \"%s\"\n", filename);
3674 expr = xmlNodeGetContent(node);
3676 fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
3681 ctx = xmlXPathNewContext(parent_doc);
3683 fprintf(stderr,"Error: unable to create new context\n");
3690 * Register namespaces
3694 if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
3695 fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
3697 xmlXPathFreeContext(ctx);
3707 xpath = xmlXPathEvalExpression(expr, ctx);
3709 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3711 xmlXPathFreeContext(ctx);
3716 /* print_xpath_nodes(xpath->nodesetval); */
3719 xmlXPathFreeContext(ctx);
3725 * Macro used to grow the current buffer.
3727 #define xxx_growBufferReentrant() { \
3729 buffer = (xmlChar **) \
3730 xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \
3731 if (buffer == NULL) { \
3732 perror("realloc failed"); \
3738 parse_list(xmlChar *str) {
3740 xmlChar **out = NULL;
3741 int buffer_size = 0;
3748 len = xmlStrlen(str);
3749 if((str[0] == '\'') && (str[len - 1] == '\'')) {
3750 str[len - 1] = '\0';
3754 * allocate an translation buffer.
3757 buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
3758 if (buffer == NULL) {
3759 perror("malloc failed");
3764 while(*str != '\0') {
3765 if (out - buffer > buffer_size - 10) {
3766 int indx = out - buffer;
3768 xxx_growBufferReentrant();
3769 out = &buffer[indx];
3772 while(*str != ',' && *str != '\0') ++str;
3773 if(*str == ',') *(str++) = '\0';
3780 c14nRunTest(const char* xml_filename, int with_comments, int mode,
3781 const char* xpath_filename, const char *ns_filename,
3782 const char* result_file) {
3784 xmlXPathObjectPtr xpath = NULL;
3785 xmlChar *result = NULL;
3787 xmlChar **inclusive_namespaces = NULL;
3788 const char *nslist = NULL;
3793 * build an XML tree from a the file; we need to add default
3794 * attributes and resolve all character and entities references
3796 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3797 xmlSubstituteEntitiesDefault(1);
3799 doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3801 fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
3806 * Check the document is of the right kind
3808 if(xmlDocGetRootElement(doc) == NULL) {
3809 fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
3815 * load xpath file if specified
3817 if(xpath_filename) {
3818 xpath = load_xpath_expr(doc, xpath_filename);
3820 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3826 if (ns_filename != NULL) {
3827 if (loadMem(ns_filename, &nslist, &nssize)) {
3828 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3829 if(xpath != NULL) xmlXPathFreeObject(xpath);
3833 inclusive_namespaces = parse_list((xmlChar *) nslist);
3839 /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
3840 ret = xmlC14NDocDumpMemory(doc,
3841 (xpath) ? xpath->nodesetval : NULL,
3842 mode, inclusive_namespaces,
3843 with_comments, &result);
3845 if(result != NULL) {
3846 if (compareFileMem(result_file, (const char *) result, ret)) {
3847 fprintf(stderr, "Result mismatch for %s\n", xml_filename);
3848 fprintf(stderr, "RESULT:\n%s\n", (const char*)result);
3853 fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
3860 if (result != NULL) xmlFree(result);
3861 if(xpath != NULL) xmlXPathFreeObject(xpath);
3862 if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
3863 if (nslist != NULL) free((char *) nslist);
3870 c14nCommonTest(const char *filename, int with_comments, int mode,
3871 const char *subdir) {
3876 char *result = NULL;
3881 base = baseFilename(filename);
3884 memcpy(prefix, base, len);
3887 snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
3888 if (!checkTestFile(buf) && !update_results) {
3889 fprintf(stderr, "Missing result file %s", buf);
3892 result = strdup(buf);
3893 snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
3894 if (checkTestFile(buf)) {
3895 xpath = strdup(buf);
3897 snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
3898 if (checkTestFile(buf)) {
3903 if (c14nRunTest(filename, with_comments, mode,
3904 xpath, ns, result) < 0)
3907 if (result != NULL) free(result);
3908 if (xpath != NULL) free(xpath);
3909 if (ns != NULL) free(ns);
3914 c14nWithCommentTest(const char *filename,
3915 const char *resul ATTRIBUTE_UNUSED,
3916 const char *err ATTRIBUTE_UNUSED,
3917 int options ATTRIBUTE_UNUSED) {
3918 return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments"));
3921 c14nWithoutCommentTest(const char *filename,
3922 const char *resul ATTRIBUTE_UNUSED,
3923 const char *err ATTRIBUTE_UNUSED,
3924 int options ATTRIBUTE_UNUSED) {
3925 return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments"));
3928 c14nExcWithoutCommentTest(const char *filename,
3929 const char *resul ATTRIBUTE_UNUSED,
3930 const char *err ATTRIBUTE_UNUSED,
3931 int options ATTRIBUTE_UNUSED) {
3932 return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments"));
3935 c14n11WithoutCommentTest(const char *filename,
3936 const char *resul ATTRIBUTE_UNUSED,
3937 const char *err ATTRIBUTE_UNUSED,
3938 int options ATTRIBUTE_UNUSED) {
3939 return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments"));
3942 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
3943 /************************************************************************
3945 * Catalog and threads test *
3947 ************************************************************************/
3950 * mostly a cut and paste from testThreads.c
3955 const char *filename;
3959 static const char *catalog = "test/threads/complex.xml";
3960 static xmlThreadParams threadParams[] = {
3961 { "test/threads/abc.xml", 0 },
3962 { "test/threads/acb.xml", 0 },
3963 { "test/threads/bac.xml", 0 },
3964 { "test/threads/bca.xml", 0 },
3965 { "test/threads/cab.xml", 0 },
3966 { "test/threads/cba.xml", 0 },
3967 { "test/threads/invalid.xml", 0 }
3969 static const unsigned int num_threads = sizeof(threadParams) /
3970 sizeof(threadParams[0]);
3972 #ifndef xmlDoValidityCheckingDefaultValue
3973 #error xmlDoValidityCheckingDefaultValue is not a macro
3975 #ifndef xmlGenericErrorContext
3976 #error xmlGenericErrorContext is not a macro
3980 thread_specific_data(void *private_data)
3983 xmlThreadParams *params = (xmlThreadParams *) private_data;
3984 const char *filename = params->filename;
3987 if (!strcmp(filename, "test/threads/invalid.xml")) {
3988 xmlDoValidityCheckingDefaultValue = 0;
3989 xmlGenericErrorContext = stdout;
3991 xmlDoValidityCheckingDefaultValue = 1;
3992 xmlGenericErrorContext = stderr;
3994 #ifdef LIBXML_SAX1_ENABLED
3995 myDoc = xmlParseFile(filename);
3997 myDoc = xmlReadFile(filename, NULL, XML_WITH_CATALOG);
4002 printf("parse failed\n");
4005 if (!strcmp(filename, "test/threads/invalid.xml")) {
4006 if (xmlDoValidityCheckingDefaultValue != 0) {
4007 printf("ValidityCheckingDefaultValue override failed\n");
4010 if (xmlGenericErrorContext != stdout) {
4011 printf("xmlGenericErrorContext override failed\n");
4015 if (xmlDoValidityCheckingDefaultValue != 1) {
4016 printf("ValidityCheckingDefaultValue override failed\n");
4019 if (xmlGenericErrorContext != stderr) {
4020 printf("xmlGenericErrorContext override failed\n");
4024 params->okay = okay;
4028 #if defined(_WIN32) && !defined(__CYGWIN__)
4029 #include <windows.h>
4032 #define TEST_REPEAT_COUNT 500
4034 static HANDLE tid[MAX_ARGC];
4037 win32_thread_specific_data(void *private_data)
4039 thread_specific_data(private_data);
4046 unsigned int i, repeat;
4051 for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
4052 xmlLoadCatalog(catalog);
4055 for (i = 0; i < num_threads; i++) {
4056 tid[i] = (HANDLE) - 1;
4059 for (i = 0; i < num_threads; i++) {
4062 tid[i] = CreateThread(NULL, 0,
4063 win32_thread_specific_data,
4064 (void *) &threadParams[i], 0,
4066 if (tid[i] == NULL) {
4067 fprintf(stderr, "CreateThread failed\n");
4072 if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
4074 fprintf(stderr, "WaitForMultipleObjects failed\n");
4078 for (i = 0; i < num_threads; i++) {
4080 ret = GetExitCodeThread(tid[i], &exitCode);
4082 fprintf(stderr, "GetExitCodeThread failed\n");
4085 CloseHandle(tid[i]);
4088 xmlCatalogCleanup();
4089 for (i = 0; i < num_threads; i++) {
4090 if (threadParams[i].okay == 0) {
4091 fprintf(stderr, "Thread %d handling %s failed\n",
4092 i, threadParams[i].filename);
4101 #elif defined __BEOS__
4104 static thread_id tid[MAX_ARGC];
4109 unsigned int i, repeat;
4114 for (repeat = 0; repeat < 500; repeat++) {
4115 xmlLoadCatalog(catalog);
4116 for (i = 0; i < num_threads; i++) {
4117 tid[i] = (thread_id) - 1;
4119 for (i = 0; i < num_threads; i++) {
4121 spawn_thread(thread_specific_data, "xmlTestThread",
4122 B_NORMAL_PRIORITY, (void *) &threadParams[i]);
4123 if (tid[i] < B_OK) {
4124 fprintf(stderr, "beos_thread_create failed\n");
4127 printf("beos_thread_create %d -> %d\n", i, tid[i]);
4129 for (i = 0; i < num_threads; i++) {
4131 ret = wait_for_thread(tid[i], &result);
4132 printf("beos_thread_wait %d -> %d\n", i, ret);
4134 fprintf(stderr, "beos_thread_wait failed\n");
4139 xmlCatalogCleanup();
4141 for (i = 0; i < num_threads; i++)
4142 if (threadParams[i].okay == 0) {
4143 printf("Thread %d handling %s failed\n", i,
4144 threadParams[i].filename);
4153 #elif defined HAVE_PTHREAD_H
4154 #include <pthread.h>
4156 static pthread_t tid[MAX_ARGC];
4161 unsigned int i, repeat;
4167 for (repeat = 0; repeat < 500; repeat++) {
4168 xmlLoadCatalog(catalog);
4171 for (i = 0; i < num_threads; i++) {
4172 tid[i] = (pthread_t) - 1;
4175 for (i = 0; i < num_threads; i++) {
4176 ret = pthread_create(&tid[i], 0, thread_specific_data,
4177 (void *) &threadParams[i]);
4179 fprintf(stderr, "pthread_create failed\n");
4183 for (i = 0; i < num_threads; i++) {
4185 ret = pthread_join(tid[i], &result);
4187 fprintf(stderr, "pthread_join failed\n");
4192 xmlCatalogCleanup();
4193 for (i = 0; i < num_threads; i++)
4194 if (threadParams[i].okay == 0) {
4195 fprintf(stderr, "Thread %d handling %s failed\n",
4196 i, threadParams[i].filename);
4208 "Specific platform thread support not detected\n");
4213 threadsTest(const char *filename ATTRIBUTE_UNUSED,
4214 const char *resul ATTRIBUTE_UNUSED,
4215 const char *err ATTRIBUTE_UNUSED,
4216 int options ATTRIBUTE_UNUSED) {
4217 return(testThread());
4220 /************************************************************************
4222 * Tests Descriptions *
4224 ************************************************************************/
4227 testDesc testDescriptions[] = {
4228 { "XML regression tests" ,
4229 oldParseTest, "./test/*", "result/", "", NULL,
4231 { "XML regression tests on memory" ,
4232 memParseTest, "./test/*", "result/", "", NULL,
4234 { "XML entity subst regression tests" ,
4235 noentParseTest, "./test/*", "result/noent/", "", NULL,
4237 { "XML Namespaces regression tests",
4238 errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
4240 { "Error cases regression tests",
4241 errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
4243 { "Error cases regression tests (old 1.0)",
4244 errParseTest, "./test/errors10/*.xml", "result/errors10/", "", ".err",
4246 #ifdef LIBXML_READER_ENABLED
4247 { "Error cases stream regression tests",
4248 streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
4250 { "Reader regression tests",
4251 streamParseTest, "./test/*", "result/", ".rdr", NULL,
4253 { "Reader entities substitution regression tests",
4254 streamParseTest, "./test/*", "result/", ".rde", NULL,
4256 { "Reader on memory regression tests",
4257 streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
4259 { "Walker regression tests",
4260 walkerParseTest, "./test/*", "result/", ".rdr", NULL,
4263 #ifdef LIBXML_SAX1_ENABLED
4264 { "SAX1 callbacks regression tests" ,
4265 saxParseTest, "./test/*", "result/", ".sax", NULL,
4268 { "SAX2 callbacks regression tests" ,
4269 saxParseTest, "./test/*", "result/", ".sax2", NULL,
4271 { "SAX2 callbacks regression tests with entity substitution" ,
4272 saxParseTest, "./test/*", "result/noent/", ".sax2", NULL,
4274 #ifdef LIBXML_PUSH_ENABLED
4275 { "XML push regression tests" ,
4276 pushParseTest, "./test/*", "result/", "", NULL,
4279 #ifdef LIBXML_HTML_ENABLED
4280 { "HTML regression tests" ,
4281 errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4283 #ifdef LIBXML_PUSH_ENABLED
4284 { "Push HTML regression tests" ,
4285 pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4288 { "HTML SAX regression tests" ,
4289 saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
4292 #ifdef LIBXML_VALID_ENABLED
4293 { "Valid documents regression tests" ,
4294 errParseTest, "./test/VCM/*", NULL, NULL, NULL,
4295 XML_PARSE_DTDVALID },
4296 { "Validity checking regression tests" ,
4297 errParseTest, "./test/VC/*", "result/VC/", NULL, "",
4298 XML_PARSE_DTDVALID },
4299 #ifdef LIBXML_READER_ENABLED
4300 { "Streaming validity checking regression tests" ,
4301 streamParseTest, "./test/valid/*.xml", "result/valid/", NULL, ".err.rdr",
4302 XML_PARSE_DTDVALID },
4303 { "Streaming validity error checking regression tests" ,
4304 streamParseTest, "./test/VC/*", "result/VC/", NULL, ".rdr",
4305 XML_PARSE_DTDVALID },
4307 { "General documents valid regression tests" ,
4308 errParseTest, "./test/valid/*", "result/valid/", "", ".err",
4309 XML_PARSE_DTDVALID },
4311 #ifdef LIBXML_XINCLUDE_ENABLED
4312 { "XInclude regression tests" ,
4313 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4314 /* Ignore errors at this point ".err", */
4315 XML_PARSE_XINCLUDE },
4316 #ifdef LIBXML_READER_ENABLED
4317 { "XInclude xmlReader regression tests",
4318 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4319 /* Ignore errors at this point ".err", */
4320 NULL, XML_PARSE_XINCLUDE },
4322 { "XInclude regression tests stripping include nodes" ,
4323 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4324 /* Ignore errors at this point ".err", */
4325 XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4326 #ifdef LIBXML_READER_ENABLED
4327 { "XInclude xmlReader regression tests stripping include nodes",
4328 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4329 /* Ignore errors at this point ".err", */
4330 NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4333 #ifdef LIBXML_XPATH_ENABLED
4334 #ifdef LIBXML_DEBUG_ENABLED
4335 { "XPath expressions regression tests" ,
4336 xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
4338 { "XPath document queries regression tests" ,
4339 xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4341 #ifdef LIBXML_XPTR_ENABLED
4342 { "XPointer document queries regression tests" ,
4343 xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4346 { "xml:id regression tests" ,
4347 xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
4351 { "URI parsing tests" ,
4352 uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
4354 { "URI base composition tests" ,
4355 uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
4357 { "Path URI conversion tests" ,
4358 uriPathTest, NULL, NULL, NULL, NULL,
4360 #ifdef LIBXML_SCHEMAS_ENABLED
4361 { "Schemas regression tests" ,
4362 schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
4364 { "Relax-NG regression tests" ,
4365 rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4366 XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4367 #ifdef LIBXML_READER_ENABLED
4368 { "Relax-NG streaming regression tests" ,
4369 rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4370 XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4373 #ifdef LIBXML_PATTERN_ENABLED
4374 #ifdef LIBXML_READER_ENABLED
4375 { "Pattern regression tests" ,
4376 patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
4380 #ifdef LIBXML_C14N_ENABLED
4381 { "C14N with comments regression tests" ,
4382 c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
4384 { "C14N without comments regression tests" ,
4385 c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
4387 { "C14N exclusive without comments regression tests" ,
4388 c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
4390 { "C14N 1.1 without comments regression tests" ,
4391 c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL,
4394 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
4395 { "Catalog and Threads regression tests" ,
4396 threadsTest, NULL, NULL, NULL, NULL,
4399 {NULL, NULL, NULL, NULL, NULL, NULL, 0}
4402 /************************************************************************
4404 * The main code driving the tests *
4406 ************************************************************************/
4409 launchTests(testDescPtr tst) {
4410 int res = 0, err = 0;
4416 if (tst == NULL) return(-1);
4417 if (tst->in != NULL) {
4420 globbuf.gl_offs = 0;
4421 glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
4422 for (i = 0;i < globbuf.gl_pathc;i++) {
4423 if (!checkTestFile(globbuf.gl_pathv[i]))
4425 if (tst->suffix != NULL) {
4426 result = resultFilename(globbuf.gl_pathv[i], tst->out,
4428 if (result == NULL) {
4429 fprintf(stderr, "Out of memory !\n");
4435 if (tst->err != NULL) {
4436 error = resultFilename(globbuf.gl_pathv[i], tst->out,
4438 if (error == NULL) {
4439 fprintf(stderr, "Out of memory !\n");
4445 if ((result) &&(!checkTestFile(result)) && !update_results) {
4446 fprintf(stderr, "Missing result file %s\n", result);
4447 } else if ((error) &&(!checkTestFile(error)) && !update_results) {
4448 fprintf(stderr, "Missing error file %s\n", error);
4451 extraMemoryFromResolver = 0;
4454 res = tst->func(globbuf.gl_pathv[i], result, error,
4455 tst->options | XML_PARSE_COMPACT);
4456 xmlResetLastError();
4458 fprintf(stderr, "File %s generated an error\n",
4459 globbuf.gl_pathv[i]);
4463 else if (xmlMemUsed() != mem) {
4464 if ((xmlMemUsed() != mem) &&
4465 (extraMemoryFromResolver == 0)) {
4466 fprintf(stderr, "File %s leaked %d bytes\n",
4467 globbuf.gl_pathv[i], xmlMemUsed() - mem);
4483 extraMemoryFromResolver = 0;
4484 res = tst->func(NULL, NULL, NULL, tst->options);
4493 static int verbose = 0;
4494 static int tests_quiet = 0;
4499 int old_errors, old_tests, old_leaks;
4501 old_errors = nb_errors;
4502 old_tests = nb_tests;
4503 old_leaks = nb_leaks;
4504 if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
4505 printf("## %s\n", testDescriptions[i].desc);
4506 res = launchTests(&testDescriptions[i]);
4510 if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
4511 printf("Ran %d tests, no errors\n", nb_tests - old_tests);
4513 printf("Ran %d tests, %d errors, %d leaks\n",
4514 nb_tests - old_tests,
4515 nb_errors - old_errors,
4516 nb_leaks - old_leaks);
4522 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4526 #if defined(_WIN32) && !defined(__CYGWIN__)
4527 setvbuf(stdout, NULL, _IONBF, 0);
4528 setvbuf(stderr, NULL, _IONBF, 0);
4531 initializeLibxml2();
4533 for (a = 1; a < argc;a++) {
4534 if (!strcmp(argv[a], "-v"))
4536 else if (!strcmp(argv[a], "-u"))
4538 else if (!strcmp(argv[a], "-quiet"))
4541 for (i = 0; testDescriptions[i].func != NULL; i++) {
4542 if (strstr(testDescriptions[i].desc, argv[a])) {
4550 for (i = 0; testDescriptions[i].func != NULL; i++) {
4554 if ((nb_errors == 0) && (nb_leaks == 0)) {
4556 printf("Total %d tests, no errors\n",
4560 printf("Total %d tests, %d errors, %d leaks\n",
4561 nb_tests, nb_errors, nb_leaks);
4569 #else /* ! LIBXML_OUTPUT_ENABLED */
4571 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4572 fprintf(stderr, "runtest requires output to be enabled in libxml2\n");