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/tree.h>
27 #include <libxml/uri.h>
29 #ifdef LIBXML_OUTPUT_ENABLED
30 #ifdef LIBXML_READER_ENABLED
31 #include <libxml/xmlreader.h>
34 #ifdef LIBXML_XINCLUDE_ENABLED
35 #include <libxml/xinclude.h>
38 #ifdef LIBXML_XPATH_ENABLED
39 #include <libxml/xpath.h>
40 #include <libxml/xpathInternals.h>
41 #ifdef LIBXML_XPTR_ENABLED
42 #include <libxml/xpointer.h>
46 #ifdef LIBXML_SCHEMAS_ENABLED
47 #include <libxml/relaxng.h>
48 #include <libxml/xmlschemas.h>
49 #include <libxml/xmlschemastypes.h>
52 #ifdef LIBXML_PATTERN_ENABLED
53 #include <libxml/pattern.h>
56 #ifdef LIBXML_C14N_ENABLED
57 #include <libxml/c14n.h>
60 #ifdef LIBXML_HTML_ENABLED
61 #include <libxml/HTMLparser.h>
62 #include <libxml/HTMLtree.h>
65 * pseudo flag for the unification of HTML and XML tests
67 #define XML_PARSE_HTML 1 << 24
70 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
71 #include <libxml/globals.h>
72 #include <libxml/threads.h>
73 #include <libxml/parser.h>
74 #include <libxml/catalog.h>
79 * O_BINARY is just for Windows compatibility - if it isn't defined
80 * on this system, avoid any compilation error
83 #define RD_FLAGS O_RDONLY | O_BINARY
84 #define WR_FLAGS O_WRONLY | O_CREAT | O_TRUNC | O_BINARY
86 #define RD_FLAGS O_RDONLY
87 #define WR_FLAGS O_WRONLY | O_CREAT | O_TRUNC
90 typedef int (*functest) (const char *filename, const char *result,
91 const char *error, int options);
93 typedef struct testDesc testDesc;
94 typedef testDesc *testDescPtr;
96 const char *desc; /* descripton of the test */
97 functest func; /* function implementing the test */
98 const char *in; /* glob to path for input files */
99 const char *out; /* output directory */
100 const char *suffix;/* suffix for output files */
101 const char *err; /* suffix for error output files */
102 int options; /* parser options for the test */
105 static int update_results = 0;
106 static int checkTestFile(const char *filename);
108 #if defined(_WIN32) && !defined(__CYGWIN__)
115 size_t gl_pathc; /* Count of paths matched so far */
116 char **gl_pathv; /* List of matched pathnames. */
117 size_t gl_offs; /* Slots to reserve in 'gl_pathv'. */
120 #define GLOB_DOOFFS 0
121 static int glob(const char *pattern, int flags,
122 int errfunc(const char *epath, int eerrno),
125 WIN32_FIND_DATA FindFileData;
127 unsigned int nb_paths = 0;
131 if ((pattern == NULL) || (pglob == NULL)) return(-1);
133 strncpy(directory, pattern, 499);
134 for (len = strlen(directory);len >= 0;len--) {
135 if (directory[len] == '/') {
146 memset(ret, 0, sizeof(glob_t));
148 hFind = FindFirstFileA(pattern, &FindFileData);
149 if (hFind == INVALID_HANDLE_VALUE)
152 ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
153 if (ret->gl_pathv == NULL) {
157 strncpy(directory + len, FindFileData.cFileName, 499 - len);
158 ret->gl_pathv[ret->gl_pathc] = strdup(directory);
159 if (ret->gl_pathv[ret->gl_pathc] == NULL)
162 while(FindNextFileA(hFind, &FindFileData)) {
163 if (FindFileData.cFileName[0] == '.')
165 if (ret->gl_pathc + 2 > nb_paths) {
166 char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
172 strncpy(directory + len, FindFileData.cFileName, 499 - len);
173 ret->gl_pathv[ret->gl_pathc] = strdup(directory);
174 if (ret->gl_pathv[ret->gl_pathc] == NULL)
178 ret->gl_pathv[ret->gl_pathc] = NULL;
187 static void globfree(glob_t *pglob) {
192 for (i = 0;i < pglob->gl_pathc;i++) {
193 if (pglob->gl_pathv[i] != NULL)
194 free(pglob->gl_pathv[i]);
202 /************************************************************************
204 * Libxml2 specific routines *
206 ************************************************************************/
208 static int nb_tests = 0;
209 static int nb_errors = 0;
210 static int nb_leaks = 0;
211 static int extraMemoryFromResolver = 0;
215 fprintf(stderr, "Exitting tests on fatal error\n");
220 * We need to trap calls to the resolver to not account memory for the catalog
221 * which is shared to the current running test. We also don't want to have
222 * network downloads modifying tests.
224 static xmlParserInputPtr
225 testExternalEntityLoader(const char *URL, const char *ID,
226 xmlParserCtxtPtr ctxt) {
227 xmlParserInputPtr ret;
229 if (checkTestFile(URL)) {
230 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
232 int memused = xmlMemUsed();
233 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
234 extraMemoryFromResolver += xmlMemUsed() - memused;
241 * Trapping the error messages at the generic level to grab the equivalent of
242 * stderr messages on CLI tools.
244 static char testErrors[32769];
245 static int testErrorsSize = 0;
248 testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
252 if (testErrorsSize >= 32768)
255 res = vsnprintf(&testErrors[testErrorsSize],
256 32768 - testErrorsSize,
259 if (testErrorsSize + res >= 32768) {
261 testErrorsSize = 32768;
262 testErrors[testErrorsSize] = 0;
264 testErrorsSize += res;
266 testErrors[testErrorsSize] = 0;
270 channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
274 if (testErrorsSize >= 32768)
277 res = vsnprintf(&testErrors[testErrorsSize],
278 32768 - testErrorsSize,
281 if (testErrorsSize + res >= 32768) {
283 testErrorsSize = 32768;
284 testErrors[testErrorsSize] = 0;
286 testErrorsSize += res;
288 testErrors[testErrorsSize] = 0;
292 * xmlParserPrintFileContext:
293 * @input: an xmlParserInputPtr input
295 * Displays current context within the input content for error tracking
299 xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
300 xmlGenericErrorFunc chanl, void *data ) {
301 const xmlChar *cur, *base;
302 unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
303 xmlChar content[81]; /* space for 80 chars + line terminator */
306 if (input == NULL) return;
309 /* skip backwards over any end-of-lines */
310 while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
314 /* search backwards for beginning-of-line (to max buff size) */
315 while ((n++ < (sizeof(content)-1)) && (cur > base) &&
316 (*(cur) != '\n') && (*(cur) != '\r'))
318 if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
319 /* calculate the error position in terms of the current position */
320 col = input->cur - cur;
321 /* search forward for end-of-line (to max buff size) */
324 /* copy selected text to our buffer */
325 while ((*cur != 0) && (*(cur) != '\n') &&
326 (*(cur) != '\r') && (n < sizeof(content)-1)) {
331 /* print out the selected text */
332 chanl(data ,"%s\n", content);
333 /* create blank line with problem pointer */
336 /* (leave buffer space for pointer + line terminator) */
337 while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
344 chanl(data ,"%s\n", content);
348 testStructuredErrorHandler(void *ctx ATTRIBUTE_UNUSED, xmlErrorPtr err) {
355 const xmlChar *name = NULL;
358 xmlParserInputPtr input = NULL;
359 xmlParserInputPtr cur = NULL;
360 xmlParserCtxtPtr ctxt = NULL;
368 domain = err->domain;
371 if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
372 (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
373 (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
378 if (code == XML_ERR_OK)
381 if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
385 * Maintain the compatibility with the legacy error handling
389 if ((input != NULL) && (input->filename == NULL) &&
390 (ctxt->inputNr > 1)) {
392 input = ctxt->inputTab[ctxt->inputNr - 2];
396 channel(data, "%s:%d: ", input->filename, input->line);
397 else if ((line != 0) && (domain == XML_FROM_PARSER))
398 channel(data, "Entity: line %d: ", input->line);
402 channel(data, "%s:%d: ", file, line);
403 else if ((line != 0) && (domain == XML_FROM_PARSER))
404 channel(data, "Entity: line %d: ", line);
407 channel(data, "element %s: ", name);
409 if (code == XML_ERR_OK)
412 case XML_FROM_PARSER:
413 channel(data, "parser ");
415 case XML_FROM_NAMESPACE:
416 channel(data, "namespace ");
420 channel(data, "validity ");
423 channel(data, "HTML parser ");
425 case XML_FROM_MEMORY:
426 channel(data, "memory ");
428 case XML_FROM_OUTPUT:
429 channel(data, "output ");
432 channel(data, "I/O ");
434 case XML_FROM_XINCLUDE:
435 channel(data, "XInclude ");
438 channel(data, "XPath ");
440 case XML_FROM_XPOINTER:
441 channel(data, "parser ");
443 case XML_FROM_REGEXP:
444 channel(data, "regexp ");
446 case XML_FROM_MODULE:
447 channel(data, "module ");
449 case XML_FROM_SCHEMASV:
450 channel(data, "Schemas validity ");
452 case XML_FROM_SCHEMASP:
453 channel(data, "Schemas parser ");
455 case XML_FROM_RELAXNGP:
456 channel(data, "Relax-NG parser ");
458 case XML_FROM_RELAXNGV:
459 channel(data, "Relax-NG validity ");
461 case XML_FROM_CATALOG:
462 channel(data, "Catalog ");
465 channel(data, "C14N ");
468 channel(data, "XSLT ");
473 if (code == XML_ERR_OK)
479 case XML_ERR_WARNING:
480 channel(data, "warning : ");
483 channel(data, "error : ");
486 channel(data, "error : ");
489 if (code == XML_ERR_OK)
493 len = xmlStrlen((const xmlChar *)str);
494 if ((len > 0) && (str[len - 1] != '\n'))
495 channel(data, "%s\n", str);
497 channel(data, "%s", str);
499 channel(data, "%s\n", "out of memory error");
501 if (code == XML_ERR_OK)
505 xmlParserPrintFileContextInternal(input, channel, data);
508 channel(data, "%s:%d: \n", cur->filename, cur->line);
509 else if ((line != 0) && (domain == XML_FROM_PARSER))
510 channel(data, "Entity: line %d: \n", cur->line);
511 xmlParserPrintFileContextInternal(cur, channel, data);
514 if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
516 (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
520 channel(data, "%s\n", err->str1);
521 for (i=0;i < err->int1;i++)
525 channel(data, "%s\n", buf);
530 initializeLibxml2(void) {
531 xmlGetWarningsDefaultValue = 0;
532 xmlPedanticParserDefault(0);
534 xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
536 xmlSetExternalEntityLoader(testExternalEntityLoader);
537 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
538 #ifdef LIBXML_SCHEMAS_ENABLED
539 xmlSchemaInitTypes();
540 xmlRelaxNGInitTypes();
545 /************************************************************************
547 * File name and path utilities *
549 ************************************************************************/
551 static const char *baseFilename(const char *filename) {
553 if (filename == NULL)
555 cur = &filename[strlen(filename)];
556 while ((cur > filename) && (*cur != '/'))
563 static char *resultFilename(const char *filename, const char *out,
564 const char *suffix) {
567 char suffixbuff[500];
570 if ((filename[0] == 't') && (filename[1] == 'e') &&
571 (filename[2] == 's') && (filename[3] == 't') &&
572 (filename[4] == '/'))
573 filename = &filename[5];
576 base = baseFilename(filename);
582 strncpy(suffixbuff,suffix,499);
584 if(strstr(base,".") && suffixbuff[0]=='.')
588 snprintf(res, 499, "%s%s%s", out, base, suffixbuff);
593 static int checkTestFile(const char *filename) {
596 if (stat(filename, &buf) == -1)
599 #if defined(_WIN32) && !defined(__CYGWIN__)
600 if (!(buf.st_mode & _S_IFREG))
603 if (!S_ISREG(buf.st_mode))
610 static int compareFiles(const char *r1 /* temp */, const char *r2 /* result */) {
616 if (update_results) {
617 fd1 = open(r1, RD_FLAGS);
620 fd2 = open(r2, WR_FLAGS, 0644);
626 res1 = read(fd1, bytes1, 4096);
629 res2 = write(fd2, bytes1, res1);
630 if (res2 <= 0 || res2 != res1)
638 fd1 = open(r1, RD_FLAGS);
641 fd2 = open(r2, RD_FLAGS);
647 res1 = read(fd1, bytes1, 4096);
648 res2 = read(fd2, bytes2, 4096);
649 if ((res1 != res2) || (res1 < 0)) {
656 if (memcmp(bytes1, bytes2, res1) != 0) {
667 static int compareFileMem(const char *filename, const char *mem, int size) {
674 if (update_results) {
675 fd = open(filename, WR_FLAGS, 0644);
677 fprintf(stderr, "failed to open %s for writing", filename);
680 res = write(fd, mem, size);
685 if (stat(filename, &info) < 0) {
686 fprintf(stderr, "failed to stat %s\n", filename);
689 if (info.st_size != size) {
690 fprintf(stderr, "file %s is %ld bytes, result is %d bytes\n",
691 filename, info.st_size, size);
694 fd = open(filename, RD_FLAGS);
696 fprintf(stderr, "failed to open %s for reading", filename);
700 res = read(fd, bytes, 4096);
703 if (res + idx > size)
705 if (memcmp(bytes, &mem[idx], res) != 0) {
707 for (ix=0; ix<res; ix++)
708 if (bytes[ix] != mem[idx+ix])
710 fprintf(stderr,"Compare error at position %d\n", idx+ix);
718 fprintf(stderr,"Compare error index %d, size %d\n", idx, size);
723 static int loadMem(const char *filename, const char **mem, int *size) {
728 if (stat(filename, &info) < 0)
730 base = malloc(info.st_size + 1);
733 if ((fd = open(filename, RD_FLAGS)) < 0) {
737 while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
742 if (siz != info.st_size) {
753 static int unloadMem(const char *mem) {
758 /************************************************************************
760 * Tests implementations *
762 ************************************************************************/
764 /************************************************************************
766 * Parse to SAX based tests *
768 ************************************************************************/
770 static FILE *SAXdebug = NULL;
775 static xmlSAXHandler emptySAXHandlerStruct = {
776 NULL, /* internalSubset */
777 NULL, /* isStandalone */
778 NULL, /* hasInternalSubset */
779 NULL, /* hasExternalSubset */
780 NULL, /* resolveEntity */
781 NULL, /* getEntity */
782 NULL, /* entityDecl */
783 NULL, /* notationDecl */
784 NULL, /* attributeDecl */
785 NULL, /* elementDecl */
786 NULL, /* unparsedEntityDecl */
787 NULL, /* setDocumentLocator */
788 NULL, /* startDocument */
789 NULL, /* endDocument */
790 NULL, /* startElement */
791 NULL, /* endElement */
792 NULL, /* reference */
793 NULL, /* characters */
794 NULL, /* ignorableWhitespace */
795 NULL, /* processingInstruction */
797 NULL, /* xmlParserWarning */
798 NULL, /* xmlParserError */
799 NULL, /* xmlParserError */
800 NULL, /* getParameterEntity */
801 NULL, /* cdataBlock; */
802 NULL, /* externalSubset; */
805 NULL, /* startElementNs */
806 NULL, /* endElementNs */
807 NULL /* xmlStructuredErrorFunc */
810 static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
811 static int callbacks = 0;
812 static int quiet = 0;
816 * @ctxt: An XML parser context
818 * Is this document tagged standalone ?
823 isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
828 fprintf(SAXdebug, "SAX.isStandalone()\n");
833 * hasInternalSubsetDebug:
834 * @ctxt: An XML parser context
836 * Does this document has an internal subset
841 hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
846 fprintf(SAXdebug, "SAX.hasInternalSubset()\n");
851 * hasExternalSubsetDebug:
852 * @ctxt: An XML parser context
854 * Does this document has an external subset
859 hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
864 fprintf(SAXdebug, "SAX.hasExternalSubset()\n");
869 * internalSubsetDebug:
870 * @ctxt: An XML parser context
872 * Does this document has an internal subset
875 internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
876 const xmlChar *ExternalID, const xmlChar *SystemID)
881 fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
882 if (ExternalID == NULL)
883 fprintf(SAXdebug, " ,");
885 fprintf(SAXdebug, " %s,", ExternalID);
886 if (SystemID == NULL)
887 fprintf(SAXdebug, " )\n");
889 fprintf(SAXdebug, " %s)\n", SystemID);
893 * externalSubsetDebug:
894 * @ctxt: An XML parser context
896 * Does this document has an external subset
899 externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
900 const xmlChar *ExternalID, const xmlChar *SystemID)
905 fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
906 if (ExternalID == NULL)
907 fprintf(SAXdebug, " ,");
909 fprintf(SAXdebug, " %s,", ExternalID);
910 if (SystemID == NULL)
911 fprintf(SAXdebug, " )\n");
913 fprintf(SAXdebug, " %s)\n", SystemID);
917 * resolveEntityDebug:
918 * @ctxt: An XML parser context
919 * @publicId: The public ID of the entity
920 * @systemId: The system ID of the entity
922 * Special entity resolver, better left to the parser, it has
923 * more context than the application layer.
924 * The default behaviour is to NOT resolve the entities, in that case
925 * the ENTITY_REF nodes are built in the structure (and the parameter
928 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
930 static xmlParserInputPtr
931 resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
936 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
939 fprintf(SAXdebug, "SAX.resolveEntity(");
940 if (publicId != NULL)
941 fprintf(SAXdebug, "%s", (char *)publicId);
943 fprintf(SAXdebug, " ");
944 if (systemId != NULL)
945 fprintf(SAXdebug, ", %s)\n", (char *)systemId);
947 fprintf(SAXdebug, ", )\n");
949 if (systemId != NULL) {
950 return(xmlNewInputFromFile(ctxt, (char *) systemId));
958 * @ctxt: An XML parser context
959 * @name: The entity name
961 * Get an entity by name
963 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
966 getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
971 fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
976 * getParameterEntityDebug:
977 * @ctxt: An XML parser context
978 * @name: The entity name
980 * Get a parameter entity by name
982 * Returns the xmlParserInputPtr
985 getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
990 fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
997 * @ctxt: An XML parser context
998 * @name: the entity name
999 * @type: the entity type
1000 * @publicId: The public ID of the entity
1001 * @systemId: The system ID of the entity
1002 * @content: the entity value (without processing).
1004 * An entity definition has been parsed
1007 entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1008 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
1010 const xmlChar *nullstr = BAD_CAST "(null)";
1011 /* not all libraries handle printing null pointers nicely */
1012 if (publicId == NULL)
1014 if (systemId == NULL)
1016 if (content == NULL)
1017 content = (xmlChar *)nullstr;
1021 fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
1022 name, type, publicId, systemId, content);
1026 * attributeDeclDebug:
1027 * @ctxt: An XML parser context
1028 * @name: the attribute name
1029 * @type: the attribute type
1031 * An attribute definition has been parsed
1034 attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
1035 const xmlChar * name, int type, int def,
1036 const xmlChar * defaultValue, xmlEnumerationPtr tree)
1041 if (defaultValue == NULL)
1042 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
1043 elem, name, type, def);
1045 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
1046 elem, name, type, def, defaultValue);
1047 xmlFreeEnumeration(tree);
1052 * @ctxt: An XML parser context
1053 * @name: the element name
1054 * @type: the element type
1055 * @content: the element value (without processing).
1057 * An element definition has been parsed
1060 elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1061 xmlElementContentPtr content ATTRIBUTE_UNUSED)
1066 fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n",
1071 * notationDeclDebug:
1072 * @ctxt: An XML parser context
1073 * @name: The name of the notation
1074 * @publicId: The public ID of the entity
1075 * @systemId: The system ID of the entity
1077 * What to do when a notation declaration has been parsed.
1080 notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1081 const xmlChar *publicId, const xmlChar *systemId)
1086 fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n",
1087 (char *) name, (char *) publicId, (char *) systemId);
1091 * unparsedEntityDeclDebug:
1092 * @ctxt: An XML parser context
1093 * @name: The name of the entity
1094 * @publicId: The public ID of the entity
1095 * @systemId: The system ID of the entity
1096 * @notationName: the name of the notation
1098 * What to do when an unparsed entity declaration is parsed
1101 unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1102 const xmlChar *publicId, const xmlChar *systemId,
1103 const xmlChar *notationName)
1105 const xmlChar *nullstr = BAD_CAST "(null)";
1107 if (publicId == NULL)
1109 if (systemId == NULL)
1111 if (notationName == NULL)
1112 notationName = nullstr;
1116 fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
1117 (char *) name, (char *) publicId, (char *) systemId,
1118 (char *) notationName);
1122 * setDocumentLocatorDebug:
1123 * @ctxt: An XML parser context
1124 * @loc: A SAX Locator
1126 * Receive the document locator at startup, actually xmlDefaultSAXLocator
1127 * Everything is available on the context, so this is useless in our case.
1130 setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
1135 fprintf(SAXdebug, "SAX.setDocumentLocator()\n");
1139 * startDocumentDebug:
1140 * @ctxt: An XML parser context
1142 * called when the document start being processed.
1145 startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1150 fprintf(SAXdebug, "SAX.startDocument()\n");
1155 * @ctxt: An XML parser context
1157 * called when the document end has been detected.
1160 endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1165 fprintf(SAXdebug, "SAX.endDocument()\n");
1169 * startElementDebug:
1170 * @ctxt: An XML parser context
1171 * @name: The element name
1173 * called when an opening tag has been processed.
1176 startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1183 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1185 for (i = 0;(atts[i] != NULL);i++) {
1186 fprintf(SAXdebug, ", %s='", atts[i++]);
1187 if (atts[i] != NULL)
1188 fprintf(SAXdebug, "%s'", atts[i]);
1191 fprintf(SAXdebug, ")\n");
1196 * @ctxt: An XML parser context
1197 * @name: The element name
1199 * called when the end of an element has been detected.
1202 endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1207 fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name);
1212 * @ctxt: An XML parser context
1213 * @ch: a xmlChar string
1214 * @len: the number of xmlChar
1216 * receiving some chars from the parser.
1217 * Question: how much at a time ???
1220 charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1228 for (i = 0;(i<len) && (i < 30);i++)
1232 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1237 * @ctxt: An XML parser context
1238 * @name: The entity name
1240 * called when an entity reference is detected.
1243 referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1248 fprintf(SAXdebug, "SAX.reference(%s)\n", name);
1252 * ignorableWhitespaceDebug:
1253 * @ctxt: An XML parser context
1254 * @ch: a xmlChar string
1255 * @start: the first char in the string
1256 * @len: the number of xmlChar
1258 * receiving some ignorable whitespaces from the parser.
1259 * Question: how much at a time ???
1262 ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1270 for (i = 0;(i<len) && (i < 30);i++)
1273 fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
1277 * processingInstructionDebug:
1278 * @ctxt: An XML parser context
1279 * @target: the target name
1280 * @data: the PI data's
1281 * @len: the number of xmlChar
1283 * A processing instruction has been parsed.
1286 processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
1287 const xmlChar *data)
1293 fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
1294 (char *) target, (char *) data);
1296 fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n",
1302 * @ctx: the user data (XML parser context)
1303 * @value: The pcdata content
1304 * @len: the block length
1306 * called when a pcdata block has been parsed
1309 cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
1314 fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n",
1315 (char *) value, len);
1320 * @ctxt: An XML parser context
1321 * @value: the comment content
1323 * A comment has been parsed.
1326 commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
1331 fprintf(SAXdebug, "SAX.comment(%s)\n", value);
1336 * @ctxt: An XML parser context
1337 * @msg: the message to display/transmit
1338 * @...: extra parameters for the message display
1340 * Display and format a warning messages, gives file, line, position and
1343 static void XMLCDECL
1344 warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1351 va_start(args, msg);
1352 fprintf(SAXdebug, "SAX.warning: ");
1353 vfprintf(SAXdebug, msg, args);
1359 * @ctxt: An XML parser context
1360 * @msg: the message to display/transmit
1361 * @...: extra parameters for the message display
1363 * Display and format a error messages, gives file, line, position and
1366 static void XMLCDECL
1367 errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1374 va_start(args, msg);
1375 fprintf(SAXdebug, "SAX.error: ");
1376 vfprintf(SAXdebug, msg, args);
1382 * @ctxt: An XML parser context
1383 * @msg: the message to display/transmit
1384 * @...: extra parameters for the message display
1386 * Display and format a fatalError messages, gives file, line, position and
1389 static void XMLCDECL
1390 fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1397 va_start(args, msg);
1398 fprintf(SAXdebug, "SAX.fatalError: ");
1399 vfprintf(SAXdebug, msg, args);
1403 static xmlSAXHandler debugSAXHandlerStruct = {
1404 internalSubsetDebug,
1406 hasInternalSubsetDebug,
1407 hasExternalSubsetDebug,
1414 unparsedEntityDeclDebug,
1415 setDocumentLocatorDebug,
1422 ignorableWhitespaceDebug,
1423 processingInstructionDebug,
1428 getParameterEntityDebug,
1430 externalSubsetDebug,
1438 static xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
1441 * SAX2 specific callbacks
1444 * startElementNsDebug:
1445 * @ctxt: An XML parser context
1446 * @name: The element name
1448 * called when an opening tag has been processed.
1451 startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1452 const xmlChar *localname,
1453 const xmlChar *prefix,
1456 const xmlChar **namespaces,
1459 const xmlChar **attributes)
1466 fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
1468 fprintf(SAXdebug, ", NULL");
1470 fprintf(SAXdebug, ", %s", (char *) prefix);
1472 fprintf(SAXdebug, ", NULL");
1474 fprintf(SAXdebug, ", '%s'", (char *) URI);
1475 fprintf(SAXdebug, ", %d", nb_namespaces);
1477 if (namespaces != NULL) {
1478 for (i = 0;i < nb_namespaces * 2;i++) {
1479 fprintf(SAXdebug, ", xmlns");
1480 if (namespaces[i] != NULL)
1481 fprintf(SAXdebug, ":%s", namespaces[i]);
1483 fprintf(SAXdebug, "='%s'", namespaces[i]);
1486 fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
1487 if (attributes != NULL) {
1488 for (i = 0;i < nb_attributes * 5;i += 5) {
1489 if (attributes[i + 1] != NULL)
1490 fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
1492 fprintf(SAXdebug, ", %s='", attributes[i]);
1493 fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
1494 (int)(attributes[i + 4] - attributes[i + 3]));
1497 fprintf(SAXdebug, ")\n");
1502 * @ctxt: An XML parser context
1503 * @name: The element name
1505 * called when the end of an element has been detected.
1508 endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1509 const xmlChar *localname,
1510 const xmlChar *prefix,
1516 fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
1518 fprintf(SAXdebug, ", NULL");
1520 fprintf(SAXdebug, ", %s", (char *) prefix);
1522 fprintf(SAXdebug, ", NULL)\n");
1524 fprintf(SAXdebug, ", '%s')\n", (char *) URI);
1527 static xmlSAXHandler debugSAX2HandlerStruct = {
1528 internalSubsetDebug,
1530 hasInternalSubsetDebug,
1531 hasExternalSubsetDebug,
1538 unparsedEntityDeclDebug,
1539 setDocumentLocatorDebug,
1546 ignorableWhitespaceDebug,
1547 processingInstructionDebug,
1552 getParameterEntityDebug,
1554 externalSubsetDebug,
1557 startElementNsDebug,
1562 static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
1564 #ifdef LIBXML_HTML_ENABLED
1566 * htmlstartElementDebug:
1567 * @ctxt: An XML parser context
1568 * @name: The element name
1570 * called when an opening tag has been processed.
1573 htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1577 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1579 for (i = 0;(atts[i] != NULL);i++) {
1580 fprintf(SAXdebug, ", %s", atts[i++]);
1581 if (atts[i] != NULL) {
1582 unsigned char output[40];
1583 const unsigned char *att = atts[i];
1585 fprintf(SAXdebug, "='");
1586 while ((attlen = strlen((char*)att)) > 0) {
1587 outlen = sizeof output - 1;
1588 htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
1590 fprintf(SAXdebug, "%s", (char *) output);
1593 fprintf(SAXdebug, "'");
1597 fprintf(SAXdebug, ")\n");
1601 * htmlcharactersDebug:
1602 * @ctxt: An XML parser context
1603 * @ch: a xmlChar string
1604 * @len: the number of xmlChar
1606 * receiving some chars from the parser.
1607 * Question: how much at a time ???
1610 htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1612 unsigned char output[40];
1613 int inlen = len, outlen = 30;
1615 htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1618 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1623 * @ctxt: An XML parser context
1624 * @ch: a xmlChar string
1625 * @len: the number of xmlChar
1627 * receiving some cdata chars from the parser.
1628 * Question: how much at a time ???
1631 htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1633 unsigned char output[40];
1634 int inlen = len, outlen = 30;
1636 htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1639 fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
1642 static xmlSAXHandler debugHTMLSAXHandlerStruct = {
1643 internalSubsetDebug,
1645 hasInternalSubsetDebug,
1646 hasExternalSubsetDebug,
1653 unparsedEntityDeclDebug,
1654 setDocumentLocatorDebug,
1657 htmlstartElementDebug,
1660 htmlcharactersDebug,
1661 ignorableWhitespaceDebug,
1662 processingInstructionDebug,
1667 getParameterEntityDebug,
1669 externalSubsetDebug,
1677 static xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
1678 #endif /* LIBXML_HTML_ENABLED */
1680 #ifdef LIBXML_SAX1_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);
1721 ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
1722 if (ret == XML_WAR_UNDECLARED_ENTITY) {
1723 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1727 fprintf(stderr, "Failed to parse %s\n", filename);
1731 #ifdef LIBXML_HTML_ENABLED
1732 if (options & XML_PARSE_HTML) {
1733 htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
1737 if (options & XML_PARSE_SAX1) {
1738 ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
1740 ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
1742 if (ret == XML_WAR_UNDECLARED_ENTITY) {
1743 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1747 if (compareFiles(temp, result)) {
1748 fprintf(stderr, "Got a difference for %s\n", filename);
1758 /* switch back to structured error handling */
1759 xmlSetGenericErrorFunc(NULL, NULL);
1760 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
1766 /************************************************************************
1768 * Parse to tree based tests *
1770 ************************************************************************/
1773 * @filename: the file to parse
1774 * @result: the file with expected result
1775 * @err: the file with error messages: unused
1777 * Parse a file using the old xmlParseFile API, then serialize back
1778 * reparse the result and serialize again, then check for deviation
1781 * Returns 0 in case of success, an error code otherwise
1784 oldParseTest(const char *filename, const char *result,
1785 const char *err ATTRIBUTE_UNUSED,
1786 int options ATTRIBUTE_UNUSED) {
1793 * base of the test, parse with the old API
1795 #ifdef LIBXML_SAX1_ENABLED
1796 doc = xmlParseFile(filename);
1798 doc = xmlReadFile(filename, NULL, 0);
1802 temp = resultFilename(filename, "", ".res");
1804 fprintf(stderr, "out of memory\n");
1807 xmlSaveFile(temp, doc);
1808 if (compareFiles(temp, result)) {
1814 * Parse the saved result to make sure the round trip is okay
1816 #ifdef LIBXML_SAX1_ENABLED
1817 doc = xmlParseFile(temp);
1819 doc = xmlReadFile(temp, NULL, 0);
1823 xmlSaveFile(temp, doc);
1824 if (compareFiles(temp, result)) {
1836 #ifdef LIBXML_PUSH_ENABLED
1839 * @filename: the file to parse
1840 * @result: the file with expected result
1841 * @err: the file with error messages: unused
1843 * Parse a file using the Push API, then serialize back
1844 * to check for content.
1846 * Returns 0 in case of success, an error code otherwise
1849 pushParseTest(const char *filename, const char *result,
1850 const char *err ATTRIBUTE_UNUSED,
1852 xmlParserCtxtPtr ctxt;
1860 * load the document in memory and work from there.
1862 if (loadMem(filename, &base, &size) != 0) {
1863 fprintf(stderr, "Failed to load %s\n", filename);
1867 #ifdef LIBXML_HTML_ENABLED
1868 if (options & XML_PARSE_HTML)
1869 ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,
1870 XML_CHAR_ENCODING_NONE);
1873 ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
1874 xmlCtxtUseOptions(ctxt, options);
1877 if (cur + 1024 >= size) {
1878 #ifdef LIBXML_HTML_ENABLED
1879 if (options & XML_PARSE_HTML)
1880 htmlParseChunk(ctxt, base + cur, size - cur, 1);
1883 xmlParseChunk(ctxt, base + cur, size - cur, 1);
1886 #ifdef LIBXML_HTML_ENABLED
1887 if (options & XML_PARSE_HTML)
1888 htmlParseChunk(ctxt, base + cur, 1024, 0);
1891 xmlParseChunk(ctxt, base + cur, 1024, 0);
1894 } while (cur < size);
1896 #ifdef LIBXML_HTML_ENABLED
1897 if (options & XML_PARSE_HTML)
1901 res = ctxt->wellFormed;
1902 xmlFreeParserCtxt(ctxt);
1906 fprintf(stderr, "Failed to parse %s\n", filename);
1909 #ifdef LIBXML_HTML_ENABLED
1910 if (options & XML_PARSE_HTML)
1911 htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1914 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1916 res = compareFileMem(result, base, size);
1917 if ((base == NULL) || (res != 0)) {
1919 xmlFree((char *)base);
1920 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
1923 xmlFree((char *)base);
1925 res = compareFileMem(err, testErrors, testErrorsSize);
1927 fprintf(stderr, "Error for %s failed\n", filename);
1937 * @filename: the file to parse
1938 * @result: the file with expected result
1939 * @err: the file with error messages: unused
1941 * Parse a file using the old xmlReadMemory API, then serialize back
1942 * reparse the result and serialize again, then check for deviation
1945 * Returns 0 in case of success, an error code otherwise
1948 memParseTest(const char *filename, const char *result,
1949 const char *err ATTRIBUTE_UNUSED,
1950 int options ATTRIBUTE_UNUSED) {
1957 * load and parse the memory
1959 if (loadMem(filename, &base, &size) != 0) {
1960 fprintf(stderr, "Failed to load %s\n", filename);
1964 doc = xmlReadMemory(base, size, filename, NULL, 0);
1969 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1971 res = compareFileMem(result, base, size);
1972 if ((base == NULL) || (res != 0)) {
1974 xmlFree((char *)base);
1975 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
1978 xmlFree((char *)base);
1984 * @filename: the file to parse
1985 * @result: the file with expected result
1986 * @err: the file with error messages: unused
1988 * Parse a file with entity resolution, then serialize back
1989 * reparse the result and serialize again, then check for deviation
1992 * Returns 0 in case of success, an error code otherwise
1995 noentParseTest(const char *filename, const char *result,
1996 const char *err ATTRIBUTE_UNUSED,
2004 * base of the test, parse with the old API
2006 doc = xmlReadFile(filename, NULL, options);
2009 temp = resultFilename(filename, "", ".res");
2011 fprintf(stderr, "Out of memory\n");
2014 xmlSaveFile(temp, doc);
2015 if (compareFiles(temp, result)) {
2021 * Parse the saved result to make sure the round trip is okay
2023 doc = xmlReadFile(filename, NULL, options);
2026 xmlSaveFile(temp, doc);
2027 if (compareFiles(temp, result)) {
2041 * @filename: the file to parse
2042 * @result: the file with expected result
2043 * @err: the file with error messages
2045 * Parse a file using the xmlReadFile API and check for errors.
2047 * Returns 0 in case of success, an error code otherwise
2050 errParseTest(const char *filename, const char *result, const char *err,
2053 const char *base = NULL;
2057 #ifdef LIBXML_HTML_ENABLED
2058 if (options & XML_PARSE_HTML) {
2059 doc = htmlReadFile(filename, NULL, options);
2062 #ifdef LIBXML_XINCLUDE_ENABLED
2063 if (options & XML_PARSE_XINCLUDE) {
2064 doc = xmlReadFile(filename, NULL, options);
2065 xmlXIncludeProcessFlags(doc, options);
2069 xmlGetWarningsDefaultValue = 1;
2070 doc = xmlReadFile(filename, NULL, options);
2072 xmlGetWarningsDefaultValue = 0;
2078 #ifdef LIBXML_HTML_ENABLED
2079 if (options & XML_PARSE_HTML) {
2080 htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2083 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2085 res = compareFileMem(result, base, size);
2087 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
2093 xmlFree((char *)base);
2097 res = compareFileMem(err, testErrors, testErrorsSize);
2099 fprintf(stderr, "Error for %s failed\n", filename);
2102 } else if (options & XML_PARSE_DTDVALID) {
2103 if (testErrorsSize != 0)
2104 fprintf(stderr, "Validation for %s failed\n", filename);
2110 #ifdef LIBXML_READER_ENABLED
2111 /************************************************************************
2113 * Reader based tests *
2115 ************************************************************************/
2117 static void processNode(FILE *out, xmlTextReaderPtr reader) {
2118 const xmlChar *name, *value;
2121 type = xmlTextReaderNodeType(reader);
2122 empty = xmlTextReaderIsEmptyElement(reader);
2124 name = xmlTextReaderConstName(reader);
2126 name = BAD_CAST "--";
2128 value = xmlTextReaderConstValue(reader);
2131 fprintf(out, "%d %d %s %d %d",
2132 xmlTextReaderDepth(reader),
2136 xmlTextReaderHasValue(reader));
2140 fprintf(out, " %s\n", value);
2144 streamProcessTest(const char *filename, const char *result, const char *err,
2145 xmlTextReaderPtr reader, const char *rng, int options) {
2154 if (result != NULL) {
2155 temp = resultFilename(filename, "", ".res");
2157 fprintf(stderr, "Out of memory\n");
2160 t = fopen(temp, "wb");
2162 fprintf(stderr, "Can't open temp file %s\n", temp);
2167 #ifdef LIBXML_SCHEMAS_ENABLED
2169 ret = xmlTextReaderRelaxNGValidate(reader, rng);
2171 testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
2182 xmlGetWarningsDefaultValue = 1;
2183 ret = xmlTextReaderRead(reader);
2185 if ((t != NULL) && (rng == NULL))
2186 processNode(t, reader);
2187 ret = xmlTextReaderRead(reader);
2190 testErrorHandler(NULL, "%s : failed to parse\n", filename);
2193 if (xmlTextReaderIsValid(reader) != 1) {
2194 testErrorHandler(NULL, "%s fails to validate\n", filename);
2196 testErrorHandler(NULL, "%s validates\n", filename);
2199 xmlGetWarningsDefaultValue = 0;
2202 ret = compareFiles(temp, result);
2208 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
2213 ret = compareFileMem(err, testErrors, testErrorsSize);
2215 fprintf(stderr, "Error for %s failed\n", filename);
2216 printf("%s", testErrors);
2226 * @filename: the file to parse
2227 * @result: the file with expected result
2228 * @err: the file with error messages
2230 * Parse a file using the reader API and check for errors.
2232 * Returns 0 in case of success, an error code otherwise
2235 streamParseTest(const char *filename, const char *result, const char *err,
2237 xmlTextReaderPtr reader;
2240 reader = xmlReaderForFile(filename, NULL, options);
2241 ret = streamProcessTest(filename, result, err, reader, NULL, options);
2242 xmlFreeTextReader(reader);
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 walker, i.e. a reader built from a atree.
2254 * Returns 0 in case of success, an error code otherwise
2257 walkerParseTest(const char *filename, const char *result, const char *err,
2260 xmlTextReaderPtr reader;
2263 doc = xmlReadFile(filename, NULL, options);
2265 fprintf(stderr, "Failed to parse %s\n", filename);
2268 reader = xmlReaderWalker(doc);
2269 ret = streamProcessTest(filename, result, err, reader, NULL, options);
2270 xmlFreeTextReader(reader);
2276 * streamMemParseTest:
2277 * @filename: the file to parse
2278 * @result: the file with expected result
2279 * @err: the file with error messages
2281 * Parse a file using the reader API from memory and check for errors.
2283 * Returns 0 in case of success, an error code otherwise
2286 streamMemParseTest(const char *filename, const char *result, const char *err,
2288 xmlTextReaderPtr reader;
2294 * load and parse the memory
2296 if (loadMem(filename, &base, &size) != 0) {
2297 fprintf(stderr, "Failed to load %s\n", filename);
2300 reader = xmlReaderForMemory(base, size, filename, NULL, options);
2301 ret = streamProcessTest(filename, result, err, reader, NULL, options);
2303 xmlFreeTextReader(reader);
2308 #ifdef LIBXML_XPATH_ENABLED
2309 #ifdef LIBXML_DEBUG_ENABLED
2310 /************************************************************************
2312 * XPath and XPointer based tests *
2314 ************************************************************************/
2316 static FILE *xpathOutput;
2317 static xmlDocPtr xpathDocument;
2320 testXPath(const char *str, int xptr, int expr) {
2321 xmlXPathObjectPtr res;
2322 xmlXPathContextPtr ctxt;
2325 #if defined(LIBXML_XPTR_ENABLED)
2327 ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
2328 res = xmlXPtrEval(BAD_CAST str, ctxt);
2331 ctxt = xmlXPathNewContext(xpathDocument);
2332 ctxt->node = xmlDocGetRootElement(xpathDocument);
2334 res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
2336 /* res = xmlXPathEval(BAD_CAST str, ctxt); */
2337 xmlXPathCompExprPtr comp;
2339 comp = xmlXPathCompile(BAD_CAST str);
2341 res = xmlXPathCompiledEval(comp, ctxt);
2342 xmlXPathFreeCompExpr(comp);
2346 #if defined(LIBXML_XPTR_ENABLED)
2349 xmlXPathDebugDumpObject(xpathOutput, res, 0);
2350 xmlXPathFreeObject(res);
2351 xmlXPathFreeContext(ctxt);
2356 * @filename: the file to parse
2357 * @result: the file with expected result
2358 * @err: the file with error messages
2360 * Parse a file containing XPath standalone expressions and evaluate them
2362 * Returns 0 in case of success, an error code otherwise
2365 xpathCommonTest(const char *filename, const char *result,
2366 int xptr, int expr) {
2368 char expression[5000];
2372 temp = resultFilename(filename, "", ".res");
2374 fprintf(stderr, "Out of memory\n");
2377 xpathOutput = fopen(temp, "wb");
2378 if (xpathOutput == NULL) {
2379 fprintf(stderr, "failed to open output file %s\n", temp);
2384 input = fopen(filename, "rb");
2385 if (input == NULL) {
2386 xmlGenericError(xmlGenericErrorContext,
2387 "Cannot open %s for reading\n", filename);
2391 while (fgets(expression, 4500, input) != NULL) {
2392 len = strlen(expression);
2394 while ((len >= 0) &&
2395 ((expression[len] == '\n') || (expression[len] == '\t') ||
2396 (expression[len] == '\r') || (expression[len] == ' '))) len--;
2397 expression[len + 1] = 0;
2399 fprintf(xpathOutput,
2400 "\n========================\nExpression: %s\n",
2402 testXPath(expression, xptr, expr);
2407 fclose(xpathOutput);
2408 if (result != NULL) {
2409 ret = compareFiles(temp, result);
2411 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
2424 * @filename: the file to parse
2425 * @result: the file with expected result
2426 * @err: the file with error messages
2428 * Parse a file containing XPath standalone expressions and evaluate them
2430 * Returns 0 in case of success, an error code otherwise
2433 xpathExprTest(const char *filename, const char *result,
2434 const char *err ATTRIBUTE_UNUSED,
2435 int options ATTRIBUTE_UNUSED) {
2436 return(xpathCommonTest(filename, result, 0, 1));
2441 * @filename: the file to parse
2442 * @result: the file with expected result
2443 * @err: the file with error messages
2445 * Parse a file containing XPath expressions and evaluate them against
2446 * a set of corresponding documents.
2448 * Returns 0 in case of success, an error code otherwise
2451 xpathDocTest(const char *filename,
2452 const char *resul ATTRIBUTE_UNUSED,
2453 const char *err ATTRIBUTE_UNUSED,
2462 xpathDocument = xmlReadFile(filename, NULL,
2463 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2464 if (xpathDocument == NULL) {
2465 fprintf(stderr, "Failed to load %s\n", filename);
2469 snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
2471 globbuf.gl_offs = 0;
2472 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2473 for (i = 0;i < globbuf.gl_pathc;i++) {
2474 snprintf(result, 499, "result/XPath/tests/%s",
2475 baseFilename(globbuf.gl_pathv[i]));
2476 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
2482 xmlFreeDoc(xpathDocument);
2486 #ifdef LIBXML_XPTR_ENABLED
2489 * @filename: the file to parse
2490 * @result: the file with expected result
2491 * @err: the file with error messages
2493 * Parse a file containing XPath expressions and evaluate them against
2494 * a set of corresponding documents.
2496 * Returns 0 in case of success, an error code otherwise
2499 xptrDocTest(const char *filename,
2500 const char *resul ATTRIBUTE_UNUSED,
2501 const char *err ATTRIBUTE_UNUSED,
2510 xpathDocument = xmlReadFile(filename, NULL,
2511 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2512 if (xpathDocument == NULL) {
2513 fprintf(stderr, "Failed to load %s\n", filename);
2517 snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
2519 globbuf.gl_offs = 0;
2520 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2521 for (i = 0;i < globbuf.gl_pathc;i++) {
2522 snprintf(result, 499, "result/XPath/xptr/%s",
2523 baseFilename(globbuf.gl_pathv[i]));
2524 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
2530 xmlFreeDoc(xpathDocument);
2533 #endif /* LIBXML_XPTR_ENABLED */
2537 * @filename: the file to parse
2538 * @result: the file with expected result
2539 * @err: the file with error messages
2541 * Parse a file containing xml:id and check for errors and verify
2542 * that XPath queries will work on them as expected.
2544 * Returns 0 in case of success, an error code otherwise
2547 xmlidDocTest(const char *filename,
2556 xpathDocument = xmlReadFile(filename, NULL,
2557 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2558 if (xpathDocument == NULL) {
2559 fprintf(stderr, "Failed to load %s\n", filename);
2563 temp = resultFilename(filename, "", ".res");
2565 fprintf(stderr, "Out of memory\n");
2568 xpathOutput = fopen(temp, "wb");
2569 if (xpathOutput == NULL) {
2570 fprintf(stderr, "failed to open output file %s\n", temp);
2571 xmlFreeDoc(xpathDocument);
2576 testXPath("id('bar')", 0, 0);
2578 fclose(xpathOutput);
2579 if (result != NULL) {
2580 ret = compareFiles(temp, result);
2582 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
2591 xmlFreeDoc(xpathDocument);
2594 ret = compareFileMem(err, testErrors, testErrorsSize);
2596 fprintf(stderr, "Error for %s failed\n", filename);
2603 #endif /* LIBXML_DEBUG_ENABLED */
2605 /************************************************************************
2609 ************************************************************************/
2612 handleURI(const char *str, const char *base, FILE *o) {
2615 xmlChar *res = NULL;
2617 uri = xmlCreateURI();
2620 ret = xmlParseURIReference(uri, str);
2622 fprintf(o, "%s : error %d\n", str, ret);
2624 xmlNormalizeURIPath(uri->path);
2625 xmlPrintURI(o, uri);
2629 res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
2631 fprintf(o, "%s\n", (char *) res);
2634 fprintf(o, "::ERROR::\n");
2643 * @filename: the file to parse
2644 * @result: the file with expected result
2645 * @err: the file with error messages
2647 * Parse a file containing URI and check for errors
2649 * Returns 0 in case of success, an error code otherwise
2652 uriCommonTest(const char *filename,
2659 int res = 0, i, ret;
2661 temp = resultFilename(filename, "", ".res");
2663 fprintf(stderr, "Out of memory\n");
2666 o = fopen(temp, "wb");
2668 fprintf(stderr, "failed to open output file %s\n", temp);
2672 f = fopen(filename, "rb");
2674 fprintf(stderr, "failed to open input file %s\n", filename);
2685 * read one line in string buffer.
2687 if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
2691 * remove the ending spaces
2695 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
2696 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
2701 handleURI(str, base, o);
2707 if (result != NULL) {
2708 ret = compareFiles(temp, result);
2710 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
2715 ret = compareFileMem(err, testErrors, testErrorsSize);
2717 fprintf(stderr, "Error for %s failed\n", filename);
2731 * @filename: the file to parse
2732 * @result: the file with expected result
2733 * @err: the file with error messages
2735 * Parse a file containing URI and check for errors
2737 * Returns 0 in case of success, an error code otherwise
2740 uriParseTest(const char *filename,
2743 int options ATTRIBUTE_UNUSED) {
2744 return(uriCommonTest(filename, result, err, NULL));
2749 * @filename: the file to parse
2750 * @result: the file with expected result
2751 * @err: the file with error messages
2753 * Parse a file containing URI, compose them against a fixed base and
2756 * Returns 0 in case of success, an error code otherwise
2759 uriBaseTest(const char *filename,
2762 int options ATTRIBUTE_UNUSED) {
2763 return(uriCommonTest(filename, result, err,
2764 "http://foo.com/path/to/index.html?orig#help"));
2767 static int urip_success = 1;
2768 static int urip_current = 0;
2769 static const char *urip_testURLs[] = {
2770 "urip://example.com/a b.html",
2771 "urip://example.com/a%20b.html",
2772 "file:///path/to/a b.html",
2773 "file:///path/to/a%20b.html",
2774 "/path/to/a b.html",
2775 "/path/to/a%20b.html",
2776 "urip://example.com/r" "\xe9" "sum" "\xe9" ".html",
2777 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2780 static const char *urip_rcvsURLs[] = {
2781 /* it is an URI the strings must be escaped */
2782 "urip://example.com/a%20b.html",
2783 /* check that % escaping is not broken */
2784 "urip://example.com/a%20b.html",
2785 /* it's an URI path the strings must be escaped */
2786 "file:///path/to/a%20b.html",
2787 /* check that % escaping is not broken */
2788 "file:///path/to/a%20b.html",
2789 /* this is not an URI, this is a path, so this should not be escaped */
2790 "/path/to/a b.html",
2791 /* check that paths with % are not broken */
2792 "/path/to/a%20b.html",
2793 /* out of context the encoding can't be guessed byte by byte conversion */
2794 "urip://example.com/r%E9sum%E9.html",
2795 /* verify we don't destroy URIs especially the query part */
2796 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2799 static const char *urip_res = "<list/>";
2800 static const char *urip_cur = NULL;
2801 static int urip_rlen;
2805 * @URI: an URI to test
2807 * Check for an urip: query
2809 * Returns 1 if yes and 0 if another Input module should be used
2812 uripMatch(const char * URI) {
2813 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2815 /* Verify we received the escaped URL */
2816 if (strcmp(urip_rcvsURLs[urip_current], URI))
2823 * @URI: an URI to test
2825 * Return a pointer to the urip: query handler, in this example simply
2826 * the urip_current pointer...
2828 * Returns an Input context or NULL in case or error
2831 uripOpen(const char * URI) {
2832 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2834 /* Verify we received the escaped URL */
2835 if (strcmp(urip_rcvsURLs[urip_current], URI))
2837 urip_cur = urip_res;
2838 urip_rlen = strlen(urip_res);
2839 return((void *) urip_cur);
2844 * @context: the read context
2846 * Close the urip: query handler
2848 * Returns 0 or -1 in case of error
2851 uripClose(void * context) {
2852 if (context == NULL) return(-1);
2860 * @context: the read context
2861 * @buffer: where to store data
2862 * @len: number of bytes to read
2864 * Implement an urip: query read.
2866 * Returns the number of bytes read or -1 in case of error
2869 uripRead(void * context, char * buffer, int len) {
2870 const char *ptr = (const char *) context;
2872 if ((context == NULL) || (buffer == NULL) || (len < 0))
2875 if (len > urip_rlen) len = urip_rlen;
2876 memcpy(buffer, ptr, len);
2882 urip_checkURL(const char *URL) {
2885 doc = xmlReadFile(URL, NULL, 0);
2894 * @filename: ignored
2898 * Run a set of tests to check how Path and URI are handled before
2899 * being passed to the I/O layer
2901 * Returns 0 in case of success, an error code otherwise
2904 uriPathTest(const char *filename ATTRIBUTE_UNUSED,
2905 const char *result ATTRIBUTE_UNUSED,
2906 const char *err ATTRIBUTE_UNUSED,
2907 int options ATTRIBUTE_UNUSED) {
2912 * register the new I/O handlers
2914 if (xmlRegisterInputCallbacks(uripMatch, uripOpen, uripRead, uripClose) < 0)
2916 fprintf(stderr, "failed to register HTTP handler\n");
2920 for (urip_current = 0;urip_testURLs[urip_current] != NULL;urip_current++) {
2922 parsed = urip_checkURL(urip_testURLs[urip_current]);
2923 if (urip_success != 1) {
2924 fprintf(stderr, "failed the URL passing test for %s",
2925 urip_testURLs[urip_current]);
2927 } else if (parsed != 1) {
2928 fprintf(stderr, "failed the parsing test for %s",
2929 urip_testURLs[urip_current]);
2935 xmlPopInputCallbacks();
2939 #ifdef LIBXML_SCHEMAS_ENABLED
2940 /************************************************************************
2944 ************************************************************************/
2946 schemasOneTest(const char *sch,
2947 const char *filename,
2951 xmlSchemaPtr schemas) {
2953 xmlSchemaValidCtxtPtr ctxt;
2955 int validResult = 0;
2957 FILE *schemasOutput;
2959 doc = xmlReadFile(filename, NULL, options);
2961 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
2965 temp = resultFilename(result, "", ".res");
2967 fprintf(stderr, "Out of memory\n");
2970 schemasOutput = fopen(temp, "wb");
2971 if (schemasOutput == NULL) {
2972 fprintf(stderr, "failed to open output file %s\n", temp);
2978 ctxt = xmlSchemaNewValidCtxt(schemas);
2979 xmlSchemaSetValidErrors(ctxt,
2980 (xmlSchemaValidityErrorFunc) testErrorHandler,
2981 (xmlSchemaValidityWarningFunc) testErrorHandler,
2983 validResult = xmlSchemaValidateDoc(ctxt, doc);
2984 if (validResult == 0) {
2985 fprintf(schemasOutput, "%s validates\n", filename);
2986 } else if (validResult > 0) {
2987 fprintf(schemasOutput, "%s fails to validate\n", filename);
2989 fprintf(schemasOutput, "%s validation generated an internal error\n",
2992 fclose(schemasOutput);
2994 if (compareFiles(temp, result)) {
2995 fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
3004 if ((validResult != 0) && (err != NULL)) {
3005 if (compareFileMem(err, testErrors, testErrorsSize)) {
3006 fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
3011 xmlSchemaFreeValidCtxt(ctxt);
3017 * @filename: the schemas file
3018 * @result: the file with expected result
3019 * @err: the file with error messages
3021 * Parse a file containing URI, compose them against a fixed base and
3024 * Returns 0 in case of success, an error code otherwise
3027 schemasTest(const char *filename,
3028 const char *resul ATTRIBUTE_UNUSED,
3029 const char *errr ATTRIBUTE_UNUSED,
3031 const char *base = baseFilename(filename);
3033 const char *instance;
3034 xmlSchemaParserCtxtPtr ctxt;
3035 xmlSchemaPtr schemas;
3036 int res = 0, len, ret;
3045 /* first compile the schemas if possible */
3046 ctxt = xmlSchemaNewParserCtxt(filename);
3047 xmlSchemaSetParserErrors(ctxt,
3048 (xmlSchemaValidityErrorFunc) testErrorHandler,
3049 (xmlSchemaValidityWarningFunc) testErrorHandler,
3051 schemas = xmlSchemaParse(ctxt);
3052 xmlSchemaFreeParserCtxt(ctxt);
3055 * most of the mess is about the output filenames generated by the Makefile
3058 if ((len > 499) || (len < 5)) {
3059 xmlSchemaFree(schemas);
3062 len -= 4; /* remove trailing .xsd */
3063 if (base[len - 2] == '_') {
3064 len -= 2; /* remove subtest number */
3066 if (base[len - 2] == '_') {
3067 len -= 2; /* remove subtest number */
3069 memcpy(prefix, base, len);
3072 snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
3075 if (base[len] == '_') {
3077 memcpy(prefix, base, len);
3081 globbuf.gl_offs = 0;
3082 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3083 for (i = 0;i < globbuf.gl_pathc;i++) {
3086 instance = globbuf.gl_pathv[i];
3087 base2 = baseFilename(instance);
3088 len = strlen(base2);
3089 if ((len > 6) && (base2[len - 6] == '_')) {
3090 count = base2[len - 5];
3091 snprintf(result, 499, "result/schemas/%s_%c",
3094 snprintf(err, 499, "result/schemas/%s_%c.err",
3098 fprintf(stderr, "don't know how to process %s\n", instance);
3101 if (schemas == NULL) {
3104 ret = schemasOneTest(filename, instance, result, err,
3111 xmlSchemaFree(schemas);
3116 /************************************************************************
3120 ************************************************************************/
3122 rngOneTest(const char *sch,
3123 const char *filename,
3127 xmlRelaxNGPtr schemas) {
3129 xmlRelaxNGValidCtxtPtr ctxt;
3132 FILE *schemasOutput;
3134 doc = xmlReadFile(filename, NULL, options);
3136 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
3140 temp = resultFilename(result, "", ".res");
3142 fprintf(stderr, "Out of memory\n");
3145 schemasOutput = fopen(temp, "wb");
3146 if (schemasOutput == NULL) {
3147 fprintf(stderr, "failed to open output file %s\n", temp);
3153 ctxt = xmlRelaxNGNewValidCtxt(schemas);
3154 xmlRelaxNGSetValidErrors(ctxt,
3155 (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3156 (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3158 ret = xmlRelaxNGValidateDoc(ctxt, doc);
3160 testErrorHandler(NULL, "%s validates\n", filename);
3161 } else if (ret > 0) {
3162 testErrorHandler(NULL, "%s fails to validate\n", filename);
3164 testErrorHandler(NULL, "%s validation generated an internal error\n",
3167 fclose(schemasOutput);
3170 if (compareFiles(temp, result)) {
3171 fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
3181 if (compareFileMem(err, testErrors, testErrorsSize)) {
3182 fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
3184 printf("%s", testErrors);
3189 xmlRelaxNGFreeValidCtxt(ctxt);
3195 * @filename: the schemas file
3196 * @result: the file with expected result
3197 * @err: the file with error messages
3199 * Parse an RNG schemas and then apply it to the related .xml
3201 * Returns 0 in case of success, an error code otherwise
3204 rngTest(const char *filename,
3205 const char *resul ATTRIBUTE_UNUSED,
3206 const char *errr ATTRIBUTE_UNUSED,
3208 const char *base = baseFilename(filename);
3210 const char *instance;
3211 xmlRelaxNGParserCtxtPtr ctxt;
3212 xmlRelaxNGPtr schemas;
3213 int res = 0, len, ret = 0;
3222 /* first compile the schemas if possible */
3223 ctxt = xmlRelaxNGNewParserCtxt(filename);
3224 xmlRelaxNGSetParserErrors(ctxt,
3225 (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3226 (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3228 schemas = xmlRelaxNGParse(ctxt);
3229 xmlRelaxNGFreeParserCtxt(ctxt);
3232 * most of the mess is about the output filenames generated by the Makefile
3235 if ((len > 499) || (len < 5)) {
3236 xmlRelaxNGFree(schemas);
3239 len -= 4; /* remove trailing .rng */
3240 memcpy(prefix, base, len);
3243 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3246 globbuf.gl_offs = 0;
3247 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3248 for (i = 0;i < globbuf.gl_pathc;i++) {
3251 instance = globbuf.gl_pathv[i];
3252 base2 = baseFilename(instance);
3253 len = strlen(base2);
3254 if ((len > 6) && (base2[len - 6] == '_')) {
3255 count = base2[len - 5];
3256 snprintf(result, 499, "result/relaxng/%s_%c",
3259 snprintf(err, 499, "result/relaxng/%s_%c.err",
3263 fprintf(stderr, "don't know how to process %s\n", instance);
3266 if (schemas == NULL) {
3269 ret = rngOneTest(filename, instance, result, err,
3276 xmlRelaxNGFree(schemas);
3281 #ifdef LIBXML_READER_ENABLED
3284 * @filename: the schemas file
3285 * @result: the file with expected result
3286 * @err: the file with error messages
3288 * Parse a set of files with streaming, applying an RNG schemas
3290 * Returns 0 in case of success, an error code otherwise
3293 rngStreamTest(const char *filename,
3294 const char *resul ATTRIBUTE_UNUSED,
3295 const char *errr ATTRIBUTE_UNUSED,
3297 const char *base = baseFilename(filename);
3299 const char *instance;
3300 int res = 0, len, ret;
3308 xmlTextReaderPtr reader;
3309 int disable_err = 0;
3312 * most of the mess is about the output filenames generated by the Makefile
3315 if ((len > 499) || (len < 5)) {
3316 fprintf(stderr, "len(base) == %d !\n", len);
3319 len -= 4; /* remove trailing .rng */
3320 memcpy(prefix, base, len);
3324 * strictly unifying the error messages is nearly impossible this
3325 * hack is also done in the Makefile
3327 if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
3328 (!strcmp(prefix, "tutor3_2")) || (!strcmp(prefix, "307377")) ||
3329 (!strcmp(prefix, "tutor8_2")))
3332 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3335 globbuf.gl_offs = 0;
3336 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3337 for (i = 0;i < globbuf.gl_pathc;i++) {
3340 instance = globbuf.gl_pathv[i];
3341 base2 = baseFilename(instance);
3342 len = strlen(base2);
3343 if ((len > 6) && (base2[len - 6] == '_')) {
3344 count = base2[len - 5];
3345 snprintf(result, 499, "result/relaxng/%s_%c",
3348 snprintf(err, 499, "result/relaxng/%s_%c.err",
3352 fprintf(stderr, "don't know how to process %s\n", instance);
3355 reader = xmlReaderForFile(instance, NULL, options);
3356 if (reader == NULL) {
3357 fprintf(stderr, "Failed to build reder for %s\n", instance);
3359 if (disable_err == 1)
3360 ret = streamProcessTest(instance, result, NULL, reader, filename,
3363 ret = streamProcessTest(instance, result, err, reader, filename,
3365 xmlFreeTextReader(reader);
3367 fprintf(stderr, "instance %s failed\n", instance);
3379 #ifdef LIBXML_PATTERN_ENABLED
3380 #ifdef LIBXML_READER_ENABLED
3381 /************************************************************************
3385 ************************************************************************/
3386 static void patternNode(FILE *out, xmlTextReaderPtr reader,
3387 const char *pattern, xmlPatternPtr patternc,
3388 xmlStreamCtxtPtr patstream) {
3389 xmlChar *path = NULL;
3393 type = xmlTextReaderNodeType(reader);
3394 empty = xmlTextReaderIsEmptyElement(reader);
3396 if (type == XML_READER_TYPE_ELEMENT) {
3397 /* do the check only on element start */
3398 match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
3401 path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
3402 fprintf(out, "Node %s matches pattern %s\n", path, pattern);
3405 if (patstream != NULL) {
3408 if (type == XML_READER_TYPE_ELEMENT) {
3409 ret = xmlStreamPush(patstream,
3410 xmlTextReaderConstLocalName(reader),
3411 xmlTextReaderConstNamespaceUri(reader));
3413 fprintf(out, "xmlStreamPush() failure\n");
3414 xmlFreeStreamCtxt(patstream);
3416 } else if (ret != match) {
3418 path = xmlGetNodePath(
3419 xmlTextReaderCurrentNode(reader));
3422 "xmlPatternMatch and xmlStreamPush disagree\n");
3424 " pattern %s node %s\n",
3430 if ((type == XML_READER_TYPE_END_ELEMENT) ||
3431 ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
3432 ret = xmlStreamPop(patstream);
3434 fprintf(out, "xmlStreamPop() failure\n");
3435 xmlFreeStreamCtxt(patstream);
3446 * @filename: the schemas file
3447 * @result: the file with expected result
3448 * @err: the file with error messages
3450 * Parse a set of files with streaming, applying an RNG schemas
3452 * Returns 0 in case of success, an error code otherwise
3455 patternTest(const char *filename,
3456 const char *resul ATTRIBUTE_UNUSED,
3457 const char *err ATTRIBUTE_UNUSED,
3459 xmlPatternPtr patternc = NULL;
3460 xmlStreamCtxtPtr patstream = NULL;
3468 xmlTextReaderPtr reader;
3471 len = strlen(filename);
3473 memcpy(xml, filename, len);
3475 snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
3477 memcpy(xml + len, ".xml", 5);
3479 if (!checkTestFile(xml) && !update_results) {
3480 fprintf(stderr, "Missing xml file %s\n", xml);
3483 if (!checkTestFile(result) && !update_results) {
3484 fprintf(stderr, "Missing result file %s\n", result);
3487 f = fopen(filename, "rb");
3489 fprintf(stderr, "Failed to open %s\n", filename);
3492 temp = resultFilename(filename, "", ".res");
3494 fprintf(stderr, "Out of memory\n");
3497 o = fopen(temp, "wb");
3499 fprintf(stderr, "failed to open output file %s\n", temp);
3506 * read one line in string buffer.
3508 if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
3512 * remove the ending spaces
3516 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
3517 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
3521 doc = xmlReadFile(xml, NULL, options);
3523 fprintf(stderr, "Failed to parse %s\n", xml);
3527 const xmlChar *namespaces[22];
3531 root = xmlDocGetRootElement(doc);
3532 for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
3533 namespaces[j++] = ns->href;
3534 namespaces[j++] = ns->prefix;
3536 namespaces[j++] = NULL;
3537 namespaces[j] = NULL;
3539 patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
3541 if (patternc == NULL) {
3542 testErrorHandler(NULL,
3543 "Pattern %s failed to compile\n", str);
3548 patstream = xmlPatternGetStreamCtxt(patternc);
3549 if (patstream != NULL) {
3550 ret = xmlStreamPush(patstream, NULL, NULL);
3552 fprintf(stderr, "xmlStreamPush() failure\n");
3553 xmlFreeStreamCtxt(patstream);
3559 reader = xmlReaderWalker(doc);
3560 res = xmlTextReaderRead(reader);
3562 patternNode(o, reader, str, patternc, patstream);
3563 res = xmlTextReaderRead(reader);
3566 fprintf(o, "%s : failed to parse\n", filename);
3568 xmlFreeTextReader(reader);
3570 xmlFreeStreamCtxt(patstream);
3572 xmlFreePattern(patternc);
3580 ret = compareFiles(temp, result);
3582 fprintf(stderr, "Result for %s failed in %s\n", filename, result);
3592 #endif /* PATTERN */
3593 #ifdef LIBXML_C14N_ENABLED
3594 /************************************************************************
3596 * Canonicalization tests *
3598 ************************************************************************/
3599 static xmlXPathObjectPtr
3600 load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
3601 xmlXPathObjectPtr xpath;
3604 xmlXPathContextPtr ctx;
3609 * load XPath expr as a file
3611 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3612 xmlSubstituteEntitiesDefault(1);
3614 doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3616 fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
3621 * Check the document is of the right kind
3623 if(xmlDocGetRootElement(doc) == NULL) {
3624 fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
3629 node = doc->children;
3630 while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
3635 fprintf(stderr,"Error: XPath element expected in the file \"%s\"\n", filename);
3640 expr = xmlNodeGetContent(node);
3642 fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
3647 ctx = xmlXPathNewContext(parent_doc);
3649 fprintf(stderr,"Error: unable to create new context\n");
3656 * Register namespaces
3660 if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
3661 fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
3663 xmlXPathFreeContext(ctx);
3673 xpath = xmlXPathEvalExpression(expr, ctx);
3675 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3677 xmlXPathFreeContext(ctx);
3682 /* print_xpath_nodes(xpath->nodesetval); */
3685 xmlXPathFreeContext(ctx);
3691 * Macro used to grow the current buffer.
3693 #define xxx_growBufferReentrant() { \
3695 buffer = (xmlChar **) \
3696 xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \
3697 if (buffer == NULL) { \
3698 perror("realloc failed"); \
3704 parse_list(xmlChar *str) {
3706 xmlChar **out = NULL;
3707 int buffer_size = 0;
3714 len = xmlStrlen(str);
3715 if((str[0] == '\'') && (str[len - 1] == '\'')) {
3716 str[len - 1] = '\0';
3720 * allocate an translation buffer.
3723 buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
3724 if (buffer == NULL) {
3725 perror("malloc failed");
3730 while(*str != '\0') {
3731 if (out - buffer > buffer_size - 10) {
3732 int indx = out - buffer;
3734 xxx_growBufferReentrant();
3735 out = &buffer[indx];
3738 while(*str != ',' && *str != '\0') ++str;
3739 if(*str == ',') *(str++) = '\0';
3746 c14nRunTest(const char* xml_filename, int with_comments, int mode,
3747 const char* xpath_filename, const char *ns_filename,
3748 const char* result_file) {
3750 xmlXPathObjectPtr xpath = NULL;
3751 xmlChar *result = NULL;
3753 xmlChar **inclusive_namespaces = NULL;
3754 const char *nslist = NULL;
3759 * build an XML tree from a the file; we need to add default
3760 * attributes and resolve all character and entities references
3762 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3763 xmlSubstituteEntitiesDefault(1);
3765 doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3767 fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
3772 * Check the document is of the right kind
3774 if(xmlDocGetRootElement(doc) == NULL) {
3775 fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
3781 * load xpath file if specified
3783 if(xpath_filename) {
3784 xpath = load_xpath_expr(doc, xpath_filename);
3786 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3792 if (ns_filename != NULL) {
3793 if (loadMem(ns_filename, &nslist, &nssize)) {
3794 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3795 if(xpath != NULL) xmlXPathFreeObject(xpath);
3799 inclusive_namespaces = parse_list((xmlChar *) nslist);
3805 /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
3806 ret = xmlC14NDocDumpMemory(doc,
3807 (xpath) ? xpath->nodesetval : NULL,
3808 mode, inclusive_namespaces,
3809 with_comments, &result);
3811 if(result != NULL) {
3812 if (compareFileMem(result_file, (const char *) result, ret)) {
3813 fprintf(stderr, "Result mismatch for %s\n", xml_filename);
3814 fprintf(stderr, "RESULT:\n%s\n", (const char*)result);
3819 fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
3826 if (result != NULL) xmlFree(result);
3827 if(xpath != NULL) xmlXPathFreeObject(xpath);
3828 if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
3829 if (nslist != NULL) free((char *) nslist);
3836 c14nCommonTest(const char *filename, int with_comments, int mode,
3837 const char *subdir) {
3842 char *result = NULL;
3847 base = baseFilename(filename);
3850 memcpy(prefix, base, len);
3853 snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
3854 if (!checkTestFile(buf) && !update_results) {
3855 fprintf(stderr, "Missing result file %s", buf);
3858 result = strdup(buf);
3859 snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
3860 if (checkTestFile(buf)) {
3861 xpath = strdup(buf);
3863 snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
3864 if (checkTestFile(buf)) {
3869 if (c14nRunTest(filename, with_comments, mode,
3870 xpath, ns, result) < 0)
3873 if (result != NULL) free(result);
3874 if (xpath != NULL) free(xpath);
3875 if (ns != NULL) free(ns);
3880 c14nWithCommentTest(const char *filename,
3881 const char *resul ATTRIBUTE_UNUSED,
3882 const char *err ATTRIBUTE_UNUSED,
3883 int options ATTRIBUTE_UNUSED) {
3884 return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments"));
3887 c14nWithoutCommentTest(const char *filename,
3888 const char *resul ATTRIBUTE_UNUSED,
3889 const char *err ATTRIBUTE_UNUSED,
3890 int options ATTRIBUTE_UNUSED) {
3891 return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments"));
3894 c14nExcWithoutCommentTest(const char *filename,
3895 const char *resul ATTRIBUTE_UNUSED,
3896 const char *err ATTRIBUTE_UNUSED,
3897 int options ATTRIBUTE_UNUSED) {
3898 return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments"));
3901 c14n11WithoutCommentTest(const char *filename,
3902 const char *resul ATTRIBUTE_UNUSED,
3903 const char *err ATTRIBUTE_UNUSED,
3904 int options ATTRIBUTE_UNUSED) {
3905 return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments"));
3908 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined (LIBXML_SAX1_ENABLED)
3909 /************************************************************************
3911 * Catalog and threads test *
3913 ************************************************************************/
3916 * mostly a cut and paste from testThreads.c
3920 static const char *catalog = "test/threads/complex.xml";
3921 static const char *testfiles[] = {
3922 "test/threads/abc.xml",
3923 "test/threads/acb.xml",
3924 "test/threads/bac.xml",
3925 "test/threads/bca.xml",
3926 "test/threads/cab.xml",
3927 "test/threads/cba.xml",
3928 "test/threads/invalid.xml",
3931 static const char *Okay = "OK";
3932 static const char *Failed = "Failed";
3934 #ifndef xmlDoValidityCheckingDefaultValue
3935 #error xmlDoValidityCheckingDefaultValue is not a macro
3937 #ifndef xmlGenericErrorContext
3938 #error xmlGenericErrorContext is not a macro
3942 thread_specific_data(void *private_data)
3945 const char *filename = (const char *) private_data;
3948 if (!strcmp(filename, "test/threads/invalid.xml")) {
3949 xmlDoValidityCheckingDefaultValue = 0;
3950 xmlGenericErrorContext = stdout;
3952 xmlDoValidityCheckingDefaultValue = 1;
3953 xmlGenericErrorContext = stderr;
3955 myDoc = xmlParseFile(filename);
3959 printf("parse failed\n");
3962 if (!strcmp(filename, "test/threads/invalid.xml")) {
3963 if (xmlDoValidityCheckingDefaultValue != 0) {
3964 printf("ValidityCheckingDefaultValue override failed\n");
3967 if (xmlGenericErrorContext != stdout) {
3968 printf("xmlGenericErrorContext override failed\n");
3972 if (xmlDoValidityCheckingDefaultValue != 1) {
3973 printf("ValidityCheckingDefaultValue override failed\n");
3976 if (xmlGenericErrorContext != stderr) {
3977 printf("xmlGenericErrorContext override failed\n");
3982 return ((void *) Failed);
3983 return ((void *) Okay);
3987 #include <windows.h>
3990 #define TEST_REPEAT_COUNT 500
3992 static HANDLE tid[MAX_ARGC];
3995 win32_thread_specific_data(void *private_data)
3997 return((DWORD) thread_specific_data(private_data));
4003 unsigned int i, repeat;
4004 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4005 DWORD results[MAX_ARGC];
4010 for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
4011 xmlLoadCatalog(catalog);
4014 for (i = 0; i < num_threads; i++) {
4016 tid[i] = (HANDLE) - 1;
4019 for (i = 0; i < num_threads; i++) {
4022 tid[i] = CreateThread(NULL, 0,
4023 win32_thread_specific_data,
4024 (void *) testfiles[i], 0,
4026 if (tid[i] == NULL) {
4027 fprintf(stderr, "CreateThread failed\n");
4032 if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
4034 fprintf(stderr, "WaitForMultipleObjects failed\n");
4038 for (i = 0; i < num_threads; i++) {
4039 ret = GetExitCodeThread(tid[i], &results[i]);
4041 fprintf(stderr, "GetExitCodeThread failed\n");
4044 CloseHandle(tid[i]);
4047 xmlCatalogCleanup();
4048 for (i = 0; i < num_threads; i++) {
4049 if (results[i] != (DWORD) Okay) {
4050 fprintf(stderr, "Thread %d handling %s failed\n",
4060 #elif defined __BEOS__
4063 static thread_id tid[MAX_ARGC];
4068 unsigned int i, repeat;
4069 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4070 void *results[MAX_ARGC];
4075 for (repeat = 0; repeat < 500; repeat++) {
4076 xmlLoadCatalog(catalog);
4077 for (i = 0; i < num_threads; i++) {
4079 tid[i] = (thread_id) - 1;
4081 for (i = 0; i < num_threads; i++) {
4083 spawn_thread(thread_specific_data, "xmlTestThread",
4084 B_NORMAL_PRIORITY, (void *) testfiles[i]);
4085 if (tid[i] < B_OK) {
4086 fprintf(stderr, "beos_thread_create failed\n");
4089 printf("beos_thread_create %d -> %d\n", i, tid[i]);
4091 for (i = 0; i < num_threads; i++) {
4092 ret = wait_for_thread(tid[i], &results[i]);
4093 printf("beos_thread_wait %d -> %d\n", i, ret);
4095 fprintf(stderr, "beos_thread_wait failed\n");
4100 xmlCatalogCleanup();
4102 for (i = 0; i < num_threads; i++)
4103 if (results[i] != (void *) Okay) {
4104 printf("Thread %d handling %s failed\n", i, testfiles[i]);
4113 #elif defined HAVE_PTHREAD_H
4114 #include <pthread.h>
4116 static pthread_t tid[MAX_ARGC];
4121 unsigned int i, repeat;
4122 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4123 void *results[MAX_ARGC];
4129 for (repeat = 0; repeat < 500; repeat++) {
4130 xmlLoadCatalog(catalog);
4133 for (i = 0; i < num_threads; i++) {
4135 tid[i] = (pthread_t) - 1;
4138 for (i = 0; i < num_threads; i++) {
4139 ret = pthread_create(&tid[i], 0, thread_specific_data,
4140 (void *) testfiles[i]);
4142 fprintf(stderr, "pthread_create failed\n");
4146 for (i = 0; i < num_threads; i++) {
4147 ret = pthread_join(tid[i], &results[i]);
4149 fprintf(stderr, "pthread_join failed\n");
4154 xmlCatalogCleanup();
4155 for (i = 0; i < num_threads; i++)
4156 if (results[i] != (void *) Okay) {
4157 fprintf(stderr, "Thread %d handling %s failed\n",
4170 "Specific platform thread support not detected\n");
4175 threadsTest(const char *filename ATTRIBUTE_UNUSED,
4176 const char *resul ATTRIBUTE_UNUSED,
4177 const char *err ATTRIBUTE_UNUSED,
4178 int options ATTRIBUTE_UNUSED) {
4179 return(testThread());
4182 /************************************************************************
4184 * Tests Descriptions *
4186 ************************************************************************/
4189 testDesc testDescriptions[] = {
4190 { "XML regression tests" ,
4191 oldParseTest, "./test/*", "result/", "", NULL,
4193 { "XML regression tests on memory" ,
4194 memParseTest, "./test/*", "result/", "", NULL,
4196 { "XML entity subst regression tests" ,
4197 noentParseTest, "./test/*", "result/noent/", "", NULL,
4199 { "XML Namespaces regression tests",
4200 errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
4202 { "Error cases regression tests",
4203 errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
4205 #ifdef LIBXML_READER_ENABLED
4206 { "Error cases stream regression tests",
4207 streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
4209 { "Reader regression tests",
4210 streamParseTest, "./test/*", "result/", ".rdr", NULL,
4212 { "Reader entities substitution regression tests",
4213 streamParseTest, "./test/*", "result/", ".rde", NULL,
4215 { "Reader on memory regression tests",
4216 streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
4218 { "Walker regression tests",
4219 walkerParseTest, "./test/*", "result/", ".rdr", NULL,
4222 #ifdef LIBXML_SAX1_ENABLED
4223 { "SAX1 callbacks regression tests" ,
4224 saxParseTest, "./test/*", "result/", ".sax", NULL,
4226 { "SAX2 callbacks regression tests" ,
4227 saxParseTest, "./test/*", "result/", ".sax2", NULL,
4230 #ifdef LIBXML_PUSH_ENABLED
4231 { "XML push regression tests" ,
4232 pushParseTest, "./test/*", "result/", "", NULL,
4235 #ifdef LIBXML_HTML_ENABLED
4236 { "HTML regression tests" ,
4237 errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4239 #ifdef LIBXML_PUSH_ENABLED
4240 { "Push HTML regression tests" ,
4241 pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4244 #ifdef LIBXML_SAX1_ENABLED
4245 { "HTML SAX regression tests" ,
4246 saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
4250 #ifdef LIBXML_VALID_ENABLED
4251 { "Valid documents regression tests" ,
4252 errParseTest, "./test/VCM/*", NULL, NULL, NULL,
4253 XML_PARSE_DTDVALID },
4254 { "Validity checking regression tests" ,
4255 errParseTest, "./test/VC/*", "result/VC/", NULL, "",
4256 XML_PARSE_DTDVALID },
4257 #ifdef LIBXML_READER_ENABLED
4258 { "Streaming validity checking regression tests" ,
4259 streamParseTest, "./test/valid/*.xml", "result/valid/", NULL, ".err.rdr",
4260 XML_PARSE_DTDVALID },
4261 { "Streaming validity error checking regression tests" ,
4262 streamParseTest, "./test/VC/*", "result/VC/", NULL, ".rdr",
4263 XML_PARSE_DTDVALID },
4265 { "General documents valid regression tests" ,
4266 errParseTest, "./test/valid/*", "result/valid/", "", ".err",
4267 XML_PARSE_DTDVALID },
4269 #ifdef LIBXML_XINCLUDE_ENABLED
4270 { "XInclude regression tests" ,
4271 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4272 /* Ignore errors at this point ".err", */
4273 XML_PARSE_XINCLUDE },
4274 #ifdef LIBXML_READER_ENABLED
4275 { "XInclude xmlReader regression tests",
4276 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4277 /* Ignore errors at this point ".err", */
4278 NULL, XML_PARSE_XINCLUDE },
4280 { "XInclude regression tests stripping include nodes" ,
4281 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4282 /* Ignore errors at this point ".err", */
4283 XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4284 #ifdef LIBXML_READER_ENABLED
4285 { "XInclude xmlReader regression tests stripping include nodes",
4286 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4287 /* Ignore errors at this point ".err", */
4288 NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4291 #ifdef LIBXML_XPATH_ENABLED
4292 #ifdef LIBXML_DEBUG_ENABLED
4293 { "XPath expressions regression tests" ,
4294 xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
4296 { "XPath document queries regression tests" ,
4297 xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4299 #ifdef LIBXML_XPTR_ENABLED
4300 { "XPointer document queries regression tests" ,
4301 xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4304 { "xml:id regression tests" ,
4305 xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
4309 { "URI parsing tests" ,
4310 uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
4312 { "URI base composition tests" ,
4313 uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
4315 { "Path URI conversion tests" ,
4316 uriPathTest, NULL, NULL, NULL, NULL,
4318 #ifdef LIBXML_SCHEMAS_ENABLED
4319 { "Schemas regression tests" ,
4320 schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
4322 { "Relax-NG regression tests" ,
4323 rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4324 XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4325 #ifdef LIBXML_READER_ENABLED
4326 { "Relax-NG streaming regression tests" ,
4327 rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4328 XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4331 #ifdef LIBXML_PATTERN_ENABLED
4332 #ifdef LIBXML_READER_ENABLED
4333 { "Pattern regression tests" ,
4334 patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
4338 #ifdef LIBXML_C14N_ENABLED
4339 { "C14N with comments regression tests" ,
4340 c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
4342 { "C14N without comments regression tests" ,
4343 c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
4345 { "C14N exclusive without comments regression tests" ,
4346 c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
4348 { "C14N 1.1 without comments regression tests" ,
4349 c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL,
4352 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_SAX1_ENABLED)
4353 { "Catalog and Threads regression tests" ,
4354 threadsTest, NULL, NULL, NULL, NULL,
4357 {NULL, NULL, NULL, NULL, NULL, NULL, 0}
4360 /************************************************************************
4362 * The main code driving the tests *
4364 ************************************************************************/
4367 launchTests(testDescPtr tst) {
4368 int res = 0, err = 0;
4374 if (tst == NULL) return(-1);
4375 if (tst->in != NULL) {
4378 globbuf.gl_offs = 0;
4379 glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
4380 for (i = 0;i < globbuf.gl_pathc;i++) {
4381 if (!checkTestFile(globbuf.gl_pathv[i]))
4383 if (tst->suffix != NULL) {
4384 result = resultFilename(globbuf.gl_pathv[i], tst->out,
4386 if (result == NULL) {
4387 fprintf(stderr, "Out of memory !\n");
4393 if (tst->err != NULL) {
4394 error = resultFilename(globbuf.gl_pathv[i], tst->out,
4396 if (error == NULL) {
4397 fprintf(stderr, "Out of memory !\n");
4403 if ((result) &&(!checkTestFile(result)) && !update_results) {
4404 fprintf(stderr, "Missing result file %s\n", result);
4405 } else if ((error) &&(!checkTestFile(error)) && !update_results) {
4406 fprintf(stderr, "Missing error file %s\n", error);
4409 extraMemoryFromResolver = 0;
4412 res = tst->func(globbuf.gl_pathv[i], result, error,
4413 tst->options | XML_PARSE_COMPACT);
4414 xmlResetLastError();
4416 fprintf(stderr, "File %s generated an error\n",
4417 globbuf.gl_pathv[i]);
4421 else if (xmlMemUsed() != mem) {
4422 if ((xmlMemUsed() != mem) &&
4423 (extraMemoryFromResolver == 0)) {
4424 fprintf(stderr, "File %s leaked %d bytes\n",
4425 globbuf.gl_pathv[i], xmlMemUsed() - mem);
4441 extraMemoryFromResolver = 0;
4442 res = tst->func(NULL, NULL, NULL, tst->options);
4451 static int verbose = 0;
4452 static int tests_quiet = 0;
4457 int old_errors, old_tests, old_leaks;
4459 old_errors = nb_errors;
4460 old_tests = nb_tests;
4461 old_leaks = nb_leaks;
4462 if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
4463 printf("## %s\n", testDescriptions[i].desc);
4464 res = launchTests(&testDescriptions[i]);
4468 if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
4469 printf("Ran %d tests, no errors\n", nb_tests - old_tests);
4471 printf("Ran %d tests, %d errors, %d leaks\n",
4472 nb_tests - old_tests,
4473 nb_errors - old_errors,
4474 nb_leaks - old_leaks);
4480 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4484 initializeLibxml2();
4486 for (a = 1; a < argc;a++) {
4487 if (!strcmp(argv[a], "-v"))
4489 else if (!strcmp(argv[a], "-u"))
4491 else if (!strcmp(argv[a], "-quiet"))
4494 for (i = 0; testDescriptions[i].func != NULL; i++) {
4495 if (strstr(testDescriptions[i].desc, argv[a])) {
4503 for (i = 0; testDescriptions[i].func != NULL; i++) {
4507 if ((nb_errors == 0) && (nb_leaks == 0)) {
4509 printf("Total %d tests, no errors\n",
4513 printf("Total %d tests, %d errors, %d leaks\n",
4514 nb_tests, nb_errors, nb_leaks);
4522 #else /* ! LIBXML_OUTPUT_ENABLED */
4524 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4525 fprintf(stderr, "runtest requires output to be enabled in libxml2\n");