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.
20 #if !defined(_WIN32) || defined(__CYGWIN__)
24 #include <sys/types.h>
28 #include <libxml/parser.h>
29 #include <libxml/tree.h>
30 #include <libxml/uri.h>
32 #ifdef LIBXML_OUTPUT_ENABLED
33 #ifdef LIBXML_READER_ENABLED
34 #include <libxml/xmlreader.h>
37 #ifdef LIBXML_XINCLUDE_ENABLED
38 #include <libxml/xinclude.h>
41 #ifdef LIBXML_XPATH_ENABLED
42 #include <libxml/xpath.h>
43 #include <libxml/xpathInternals.h>
44 #ifdef LIBXML_XPTR_ENABLED
45 #include <libxml/xpointer.h>
49 #ifdef LIBXML_SCHEMAS_ENABLED
50 #include <libxml/relaxng.h>
51 #include <libxml/xmlschemas.h>
52 #include <libxml/xmlschemastypes.h>
55 #ifdef LIBXML_PATTERN_ENABLED
56 #include <libxml/pattern.h>
59 #ifdef LIBXML_C14N_ENABLED
60 #include <libxml/c14n.h>
63 #ifdef LIBXML_HTML_ENABLED
64 #include <libxml/HTMLparser.h>
65 #include <libxml/HTMLtree.h>
68 * pseudo flag for the unification of HTML and XML tests
70 #define XML_PARSE_HTML 1 << 24
73 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
74 #include <libxml/globals.h>
75 #include <libxml/threads.h>
76 #include <libxml/parser.h>
77 #include <libxml/catalog.h>
82 * O_BINARY is just for Windows compatibility - if it isn't defined
83 * on this system, avoid any compilation error
86 #define RD_FLAGS O_RDONLY | O_BINARY
88 #define RD_FLAGS O_RDONLY
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 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]);
197 #define vsnprintf _vsnprintf
198 #define snprintf _snprintf
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, const char *r2) {
617 fd1 = open(r1, RD_FLAGS);
620 fd2 = open(r2, RD_FLAGS);
626 res1 = read(fd1, bytes1, 4096);
627 res2 = read(fd2, bytes2, 4096);
628 if ((res1 != res2) || (res1 < 0)) {
635 if (memcmp(bytes1, bytes2, res1) != 0) {
646 static int compareFileMem(const char *filename, const char *mem, int size) {
653 if (stat(filename, &info) < 0)
655 if (info.st_size != size)
657 fd = open(filename, RD_FLAGS);
661 res = read(fd, bytes, 4096);
664 if (res + idx > size)
666 if (memcmp(bytes, &mem[idx], res) != 0) {
668 for (ix=0; ix<res; ix++)
669 if (bytes[ix] != mem[idx+ix])
671 fprintf(stderr,"Compare error at position %d\n", idx+ix);
681 static int loadMem(const char *filename, const char **mem, int *size) {
686 if (stat(filename, &info) < 0)
688 base = malloc(info.st_size + 1);
691 if ((fd = open(filename, RD_FLAGS)) < 0) {
695 while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
700 if (siz != info.st_size) {
711 static int unloadMem(const char *mem) {
716 /************************************************************************
718 * Tests implementations *
720 ************************************************************************/
722 /************************************************************************
724 * Parse to SAX based tests *
726 ************************************************************************/
728 static FILE *SAXdebug = NULL;
733 static xmlSAXHandler emptySAXHandlerStruct = {
734 NULL, /* internalSubset */
735 NULL, /* isStandalone */
736 NULL, /* hasInternalSubset */
737 NULL, /* hasExternalSubset */
738 NULL, /* resolveEntity */
739 NULL, /* getEntity */
740 NULL, /* entityDecl */
741 NULL, /* notationDecl */
742 NULL, /* attributeDecl */
743 NULL, /* elementDecl */
744 NULL, /* unparsedEntityDecl */
745 NULL, /* setDocumentLocator */
746 NULL, /* startDocument */
747 NULL, /* endDocument */
748 NULL, /* startElement */
749 NULL, /* endElement */
750 NULL, /* reference */
751 NULL, /* characters */
752 NULL, /* ignorableWhitespace */
753 NULL, /* processingInstruction */
755 NULL, /* xmlParserWarning */
756 NULL, /* xmlParserError */
757 NULL, /* xmlParserError */
758 NULL, /* getParameterEntity */
759 NULL, /* cdataBlock; */
760 NULL, /* externalSubset; */
763 NULL, /* startElementNs */
764 NULL, /* endElementNs */
765 NULL /* xmlStructuredErrorFunc */
768 static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
769 static int callbacks = 0;
770 static int quiet = 0;
774 * @ctxt: An XML parser context
776 * Is this document tagged standalone ?
781 isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
786 fprintf(SAXdebug, "SAX.isStandalone()\n");
791 * hasInternalSubsetDebug:
792 * @ctxt: An XML parser context
794 * Does this document has an internal subset
799 hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
804 fprintf(SAXdebug, "SAX.hasInternalSubset()\n");
809 * hasExternalSubsetDebug:
810 * @ctxt: An XML parser context
812 * Does this document has an external subset
817 hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
822 fprintf(SAXdebug, "SAX.hasExternalSubset()\n");
827 * internalSubsetDebug:
828 * @ctxt: An XML parser context
830 * Does this document has an internal subset
833 internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
834 const xmlChar *ExternalID, const xmlChar *SystemID)
839 fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
840 if (ExternalID == NULL)
841 fprintf(SAXdebug, " ,");
843 fprintf(SAXdebug, " %s,", ExternalID);
844 if (SystemID == NULL)
845 fprintf(SAXdebug, " )\n");
847 fprintf(SAXdebug, " %s)\n", SystemID);
851 * externalSubsetDebug:
852 * @ctxt: An XML parser context
854 * Does this document has an external subset
857 externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
858 const xmlChar *ExternalID, const xmlChar *SystemID)
863 fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
864 if (ExternalID == NULL)
865 fprintf(SAXdebug, " ,");
867 fprintf(SAXdebug, " %s,", ExternalID);
868 if (SystemID == NULL)
869 fprintf(SAXdebug, " )\n");
871 fprintf(SAXdebug, " %s)\n", SystemID);
875 * resolveEntityDebug:
876 * @ctxt: An XML parser context
877 * @publicId: The public ID of the entity
878 * @systemId: The system ID of the entity
880 * Special entity resolver, better left to the parser, it has
881 * more context than the application layer.
882 * The default behaviour is to NOT resolve the entities, in that case
883 * the ENTITY_REF nodes are built in the structure (and the parameter
886 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
888 static xmlParserInputPtr
889 resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
894 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
897 fprintf(SAXdebug, "SAX.resolveEntity(");
898 if (publicId != NULL)
899 fprintf(SAXdebug, "%s", (char *)publicId);
901 fprintf(SAXdebug, " ");
902 if (systemId != NULL)
903 fprintf(SAXdebug, ", %s)\n", (char *)systemId);
905 fprintf(SAXdebug, ", )\n");
907 if (systemId != NULL) {
908 return(xmlNewInputFromFile(ctxt, (char *) systemId));
916 * @ctxt: An XML parser context
917 * @name: The entity name
919 * Get an entity by name
921 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
924 getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
929 fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
934 * getParameterEntityDebug:
935 * @ctxt: An XML parser context
936 * @name: The entity name
938 * Get a parameter entity by name
940 * Returns the xmlParserInputPtr
943 getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
948 fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
955 * @ctxt: An XML parser context
956 * @name: the entity name
957 * @type: the entity type
958 * @publicId: The public ID of the entity
959 * @systemId: The system ID of the entity
960 * @content: the entity value (without processing).
962 * An entity definition has been parsed
965 entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
966 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
968 const xmlChar *nullstr = BAD_CAST "(null)";
969 /* not all libraries handle printing null pointers nicely */
970 if (publicId == NULL)
972 if (systemId == NULL)
975 content = (xmlChar *)nullstr;
979 fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
980 name, type, publicId, systemId, content);
984 * attributeDeclDebug:
985 * @ctxt: An XML parser context
986 * @name: the attribute name
987 * @type: the attribute type
989 * An attribute definition has been parsed
992 attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
993 const xmlChar * name, int type, int def,
994 const xmlChar * defaultValue, xmlEnumerationPtr tree)
999 if (defaultValue == NULL)
1000 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
1001 elem, name, type, def);
1003 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
1004 elem, name, type, def, defaultValue);
1005 xmlFreeEnumeration(tree);
1010 * @ctxt: An XML parser context
1011 * @name: the element name
1012 * @type: the element type
1013 * @content: the element value (without processing).
1015 * An element definition has been parsed
1018 elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1019 xmlElementContentPtr content ATTRIBUTE_UNUSED)
1024 fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n",
1029 * notationDeclDebug:
1030 * @ctxt: An XML parser context
1031 * @name: The name of the notation
1032 * @publicId: The public ID of the entity
1033 * @systemId: The system ID of the entity
1035 * What to do when a notation declaration has been parsed.
1038 notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1039 const xmlChar *publicId, const xmlChar *systemId)
1044 fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n",
1045 (char *) name, (char *) publicId, (char *) systemId);
1049 * unparsedEntityDeclDebug:
1050 * @ctxt: An XML parser context
1051 * @name: The name of the entity
1052 * @publicId: The public ID of the entity
1053 * @systemId: The system ID of the entity
1054 * @notationName: the name of the notation
1056 * What to do when an unparsed entity declaration is parsed
1059 unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1060 const xmlChar *publicId, const xmlChar *systemId,
1061 const xmlChar *notationName)
1063 const xmlChar *nullstr = BAD_CAST "(null)";
1065 if (publicId == NULL)
1067 if (systemId == NULL)
1069 if (notationName == NULL)
1070 notationName = nullstr;
1074 fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
1075 (char *) name, (char *) publicId, (char *) systemId,
1076 (char *) notationName);
1080 * setDocumentLocatorDebug:
1081 * @ctxt: An XML parser context
1082 * @loc: A SAX Locator
1084 * Receive the document locator at startup, actually xmlDefaultSAXLocator
1085 * Everything is available on the context, so this is useless in our case.
1088 setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
1093 fprintf(SAXdebug, "SAX.setDocumentLocator()\n");
1097 * startDocumentDebug:
1098 * @ctxt: An XML parser context
1100 * called when the document start being processed.
1103 startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1108 fprintf(SAXdebug, "SAX.startDocument()\n");
1113 * @ctxt: An XML parser context
1115 * called when the document end has been detected.
1118 endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1123 fprintf(SAXdebug, "SAX.endDocument()\n");
1127 * startElementDebug:
1128 * @ctxt: An XML parser context
1129 * @name: The element name
1131 * called when an opening tag has been processed.
1134 startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1141 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1143 for (i = 0;(atts[i] != NULL);i++) {
1144 fprintf(SAXdebug, ", %s='", atts[i++]);
1145 if (atts[i] != NULL)
1146 fprintf(SAXdebug, "%s'", atts[i]);
1149 fprintf(SAXdebug, ")\n");
1154 * @ctxt: An XML parser context
1155 * @name: The element name
1157 * called when the end of an element has been detected.
1160 endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1165 fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name);
1170 * @ctxt: An XML parser context
1171 * @ch: a xmlChar string
1172 * @len: the number of xmlChar
1174 * receiving some chars from the parser.
1175 * Question: how much at a time ???
1178 charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1186 for (i = 0;(i<len) && (i < 30);i++)
1190 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1195 * @ctxt: An XML parser context
1196 * @name: The entity name
1198 * called when an entity reference is detected.
1201 referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1206 fprintf(SAXdebug, "SAX.reference(%s)\n", name);
1210 * ignorableWhitespaceDebug:
1211 * @ctxt: An XML parser context
1212 * @ch: a xmlChar string
1213 * @start: the first char in the string
1214 * @len: the number of xmlChar
1216 * receiving some ignorable whitespaces from the parser.
1217 * Question: how much at a time ???
1220 ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1228 for (i = 0;(i<len) && (i < 30);i++)
1231 fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
1235 * processingInstructionDebug:
1236 * @ctxt: An XML parser context
1237 * @target: the target name
1238 * @data: the PI data's
1239 * @len: the number of xmlChar
1241 * A processing instruction has been parsed.
1244 processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
1245 const xmlChar *data)
1251 fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
1252 (char *) target, (char *) data);
1254 fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n",
1260 * @ctx: the user data (XML parser context)
1261 * @value: The pcdata content
1262 * @len: the block length
1264 * called when a pcdata block has been parsed
1267 cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
1272 fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n",
1273 (char *) value, len);
1278 * @ctxt: An XML parser context
1279 * @value: the comment content
1281 * A comment has been parsed.
1284 commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
1289 fprintf(SAXdebug, "SAX.comment(%s)\n", value);
1294 * @ctxt: An XML parser context
1295 * @msg: the message to display/transmit
1296 * @...: extra parameters for the message display
1298 * Display and format a warning messages, gives file, line, position and
1301 static void XMLCDECL
1302 warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1309 va_start(args, msg);
1310 fprintf(SAXdebug, "SAX.warning: ");
1311 vfprintf(SAXdebug, msg, args);
1317 * @ctxt: An XML parser context
1318 * @msg: the message to display/transmit
1319 * @...: extra parameters for the message display
1321 * Display and format a error messages, gives file, line, position and
1324 static void XMLCDECL
1325 errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1332 va_start(args, msg);
1333 fprintf(SAXdebug, "SAX.error: ");
1334 vfprintf(SAXdebug, msg, args);
1340 * @ctxt: An XML parser context
1341 * @msg: the message to display/transmit
1342 * @...: extra parameters for the message display
1344 * Display and format a fatalError messages, gives file, line, position and
1347 static void XMLCDECL
1348 fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1355 va_start(args, msg);
1356 fprintf(SAXdebug, "SAX.fatalError: ");
1357 vfprintf(SAXdebug, msg, args);
1361 static xmlSAXHandler debugSAXHandlerStruct = {
1362 internalSubsetDebug,
1364 hasInternalSubsetDebug,
1365 hasExternalSubsetDebug,
1372 unparsedEntityDeclDebug,
1373 setDocumentLocatorDebug,
1380 ignorableWhitespaceDebug,
1381 processingInstructionDebug,
1386 getParameterEntityDebug,
1388 externalSubsetDebug,
1396 static xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
1399 * SAX2 specific callbacks
1402 * startElementNsDebug:
1403 * @ctxt: An XML parser context
1404 * @name: The element name
1406 * called when an opening tag has been processed.
1409 startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1410 const xmlChar *localname,
1411 const xmlChar *prefix,
1414 const xmlChar **namespaces,
1417 const xmlChar **attributes)
1424 fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
1426 fprintf(SAXdebug, ", NULL");
1428 fprintf(SAXdebug, ", %s", (char *) prefix);
1430 fprintf(SAXdebug, ", NULL");
1432 fprintf(SAXdebug, ", '%s'", (char *) URI);
1433 fprintf(SAXdebug, ", %d", nb_namespaces);
1435 if (namespaces != NULL) {
1436 for (i = 0;i < nb_namespaces * 2;i++) {
1437 fprintf(SAXdebug, ", xmlns");
1438 if (namespaces[i] != NULL)
1439 fprintf(SAXdebug, ":%s", namespaces[i]);
1441 fprintf(SAXdebug, "='%s'", namespaces[i]);
1444 fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
1445 if (attributes != NULL) {
1446 for (i = 0;i < nb_attributes * 5;i += 5) {
1447 if (attributes[i + 1] != NULL)
1448 fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
1450 fprintf(SAXdebug, ", %s='", attributes[i]);
1451 fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
1452 (int)(attributes[i + 4] - attributes[i + 3]));
1455 fprintf(SAXdebug, ")\n");
1460 * @ctxt: An XML parser context
1461 * @name: The element name
1463 * called when the end of an element has been detected.
1466 endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1467 const xmlChar *localname,
1468 const xmlChar *prefix,
1474 fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
1476 fprintf(SAXdebug, ", NULL");
1478 fprintf(SAXdebug, ", %s", (char *) prefix);
1480 fprintf(SAXdebug, ", NULL)\n");
1482 fprintf(SAXdebug, ", '%s')\n", (char *) URI);
1485 static xmlSAXHandler debugSAX2HandlerStruct = {
1486 internalSubsetDebug,
1488 hasInternalSubsetDebug,
1489 hasExternalSubsetDebug,
1496 unparsedEntityDeclDebug,
1497 setDocumentLocatorDebug,
1504 ignorableWhitespaceDebug,
1505 processingInstructionDebug,
1510 getParameterEntityDebug,
1512 externalSubsetDebug,
1515 startElementNsDebug,
1520 static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
1522 #ifdef LIBXML_HTML_ENABLED
1524 * htmlstartElementDebug:
1525 * @ctxt: An XML parser context
1526 * @name: The element name
1528 * called when an opening tag has been processed.
1531 htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1535 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1537 for (i = 0;(atts[i] != NULL);i++) {
1538 fprintf(SAXdebug, ", %s", atts[i++]);
1539 if (atts[i] != NULL) {
1540 unsigned char output[40];
1541 const unsigned char *att = atts[i];
1543 fprintf(SAXdebug, "='");
1544 while ((attlen = strlen((char*)att)) > 0) {
1545 outlen = sizeof output - 1;
1546 htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
1548 fprintf(SAXdebug, "%s", (char *) output);
1551 fprintf(SAXdebug, "'");
1555 fprintf(SAXdebug, ")\n");
1559 * htmlcharactersDebug:
1560 * @ctxt: An XML parser context
1561 * @ch: a xmlChar string
1562 * @len: the number of xmlChar
1564 * receiving some chars from the parser.
1565 * Question: how much at a time ???
1568 htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1570 unsigned char output[40];
1571 int inlen = len, outlen = 30;
1573 htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1576 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1581 * @ctxt: An XML parser context
1582 * @ch: a xmlChar string
1583 * @len: the number of xmlChar
1585 * receiving some cdata chars from the parser.
1586 * Question: how much at a time ???
1589 htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1591 unsigned char output[40];
1592 int inlen = len, outlen = 30;
1594 htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1597 fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
1600 static xmlSAXHandler debugHTMLSAXHandlerStruct = {
1601 internalSubsetDebug,
1603 hasInternalSubsetDebug,
1604 hasExternalSubsetDebug,
1611 unparsedEntityDeclDebug,
1612 setDocumentLocatorDebug,
1615 htmlstartElementDebug,
1618 htmlcharactersDebug,
1619 ignorableWhitespaceDebug,
1620 processingInstructionDebug,
1625 getParameterEntityDebug,
1627 externalSubsetDebug,
1635 static xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
1636 #endif /* LIBXML_HTML_ENABLED */
1638 #ifdef LIBXML_SAX1_ENABLED
1641 * @filename: the file to parse
1642 * @result: the file with expected result
1643 * @err: the file with error messages
1645 * Parse a file using the SAX API and check for errors.
1647 * Returns 0 in case of success, an error code otherwise
1650 saxParseTest(const char *filename, const char *result,
1651 const char *err ATTRIBUTE_UNUSED,
1657 temp = resultFilename(filename, "", ".res");
1659 fprintf(stderr, "out of memory\n");
1662 SAXdebug = fopen(temp, "wb");
1663 if (SAXdebug == NULL) {
1664 fprintf(stderr, "Failed to write to %s\n", temp);
1669 /* for SAX we really want the callbacks though the context handlers */
1670 xmlSetStructuredErrorFunc(NULL, NULL);
1671 xmlSetGenericErrorFunc(NULL, testErrorHandler);
1673 #ifdef LIBXML_HTML_ENABLED
1674 if (options & XML_PARSE_HTML) {
1675 htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);
1679 ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
1680 if (ret == XML_WAR_UNDECLARED_ENTITY) {
1681 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1685 fprintf(stderr, "Failed to parse %s\n", filename);
1688 #ifdef LIBXML_HTML_ENABLED
1689 if (options & XML_PARSE_HTML) {
1690 htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
1694 if (options & XML_PARSE_SAX1) {
1695 ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
1697 ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
1699 if (ret == XML_WAR_UNDECLARED_ENTITY) {
1700 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1704 if (compareFiles(temp, result)) {
1705 fprintf(stderr, "Got a difference for %s\n", filename);
1713 /* switch back to structured error handling */
1714 xmlSetGenericErrorFunc(NULL, NULL);
1715 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
1721 /************************************************************************
1723 * Parse to tree based tests *
1725 ************************************************************************/
1728 * @filename: the file to parse
1729 * @result: the file with expected result
1730 * @err: the file with error messages: unused
1732 * Parse a file using the old xmlParseFile API, then serialize back
1733 * reparse the result and serialize again, then check for deviation
1736 * Returns 0 in case of success, an error code otherwise
1739 oldParseTest(const char *filename, const char *result,
1740 const char *err ATTRIBUTE_UNUSED,
1741 int options ATTRIBUTE_UNUSED) {
1748 * base of the test, parse with the old API
1750 #ifdef LIBXML_SAX1_ENABLED
1751 doc = xmlParseFile(filename);
1753 doc = xmlReadFile(filename, NULL, 0);
1757 temp = resultFilename(filename, "", ".res");
1759 fprintf(stderr, "out of memory\n");
1762 xmlSaveFile(temp, doc);
1763 if (compareFiles(temp, result)) {
1769 * Parse the saved result to make sure the round trip is okay
1771 #ifdef LIBXML_SAX1_ENABLED
1772 doc = xmlParseFile(temp);
1774 doc = xmlReadFile(temp, NULL, 0);
1778 xmlSaveFile(temp, doc);
1779 if (compareFiles(temp, result)) {
1791 #ifdef LIBXML_PUSH_ENABLED
1794 * @filename: the file to parse
1795 * @result: the file with expected result
1796 * @err: the file with error messages: unused
1798 * Parse a file using the Push API, then serialize back
1799 * to check for content.
1801 * Returns 0 in case of success, an error code otherwise
1804 pushParseTest(const char *filename, const char *result,
1805 const char *err ATTRIBUTE_UNUSED,
1807 xmlParserCtxtPtr ctxt;
1815 * load the document in memory and work from there.
1817 if (loadMem(filename, &base, &size) != 0) {
1818 fprintf(stderr, "Failed to load %s\n", filename);
1822 #ifdef LIBXML_HTML_ENABLED
1823 if (options & XML_PARSE_HTML)
1824 ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,
1825 XML_CHAR_ENCODING_NONE);
1828 ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
1829 xmlCtxtUseOptions(ctxt, options);
1831 while (cur < size) {
1832 if (cur + 1024 >= size) {
1833 #ifdef LIBXML_HTML_ENABLED
1834 if (options & XML_PARSE_HTML)
1835 htmlParseChunk(ctxt, base + cur, size - cur, 1);
1838 xmlParseChunk(ctxt, base + cur, size - cur, 1);
1841 #ifdef LIBXML_HTML_ENABLED
1842 if (options & XML_PARSE_HTML)
1843 htmlParseChunk(ctxt, base + cur, 1024, 0);
1846 xmlParseChunk(ctxt, base + cur, 1024, 0);
1851 #ifdef LIBXML_HTML_ENABLED
1852 if (options & XML_PARSE_HTML)
1856 res = ctxt->wellFormed;
1857 xmlFreeParserCtxt(ctxt);
1861 fprintf(stderr, "Failed to parse %s\n", filename);
1864 #ifdef LIBXML_HTML_ENABLED
1865 if (options & XML_PARSE_HTML)
1866 htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1869 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1871 res = compareFileMem(result, base, size);
1872 if ((base == NULL) || (res != 0)) {
1874 xmlFree((char *)base);
1875 fprintf(stderr, "Result for %s failed\n", filename);
1878 xmlFree((char *)base);
1880 res = compareFileMem(err, testErrors, testErrorsSize);
1882 fprintf(stderr, "Error for %s failed\n", filename);
1892 * @filename: the file to parse
1893 * @result: the file with expected result
1894 * @err: the file with error messages: unused
1896 * Parse a file using the old xmlReadMemory API, then serialize back
1897 * reparse the result and serialize again, then check for deviation
1900 * Returns 0 in case of success, an error code otherwise
1903 memParseTest(const char *filename, const char *result,
1904 const char *err ATTRIBUTE_UNUSED,
1905 int options ATTRIBUTE_UNUSED) {
1912 * load and parse the memory
1914 if (loadMem(filename, &base, &size) != 0) {
1915 fprintf(stderr, "Failed to load %s\n", filename);
1919 doc = xmlReadMemory(base, size, filename, NULL, 0);
1924 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1926 res = compareFileMem(result, base, size);
1927 if ((base == NULL) || (res != 0)) {
1929 xmlFree((char *)base);
1930 fprintf(stderr, "Result for %s failed\n", filename);
1933 xmlFree((char *)base);
1939 * @filename: the file to parse
1940 * @result: the file with expected result
1941 * @err: the file with error messages: unused
1943 * Parse a file with entity resolution, then serialize back
1944 * reparse the result and serialize again, then check for deviation
1947 * Returns 0 in case of success, an error code otherwise
1950 noentParseTest(const char *filename, const char *result,
1951 const char *err ATTRIBUTE_UNUSED,
1959 * base of the test, parse with the old API
1961 doc = xmlReadFile(filename, NULL, options);
1964 temp = resultFilename(filename, "", ".res");
1966 fprintf(stderr, "Out of memory\n");
1969 xmlSaveFile(temp, doc);
1970 if (compareFiles(temp, result)) {
1976 * Parse the saved result to make sure the round trip is okay
1978 doc = xmlReadFile(filename, NULL, options);
1981 xmlSaveFile(temp, doc);
1982 if (compareFiles(temp, result)) {
1996 * @filename: the file to parse
1997 * @result: the file with expected result
1998 * @err: the file with error messages
2000 * Parse a file using the xmlReadFile API and check for errors.
2002 * Returns 0 in case of success, an error code otherwise
2005 errParseTest(const char *filename, const char *result, const char *err,
2008 const char *base = NULL;
2012 #ifdef LIBXML_HTML_ENABLED
2013 if (options & XML_PARSE_HTML) {
2014 doc = htmlReadFile(filename, NULL, options);
2017 #ifdef LIBXML_XINCLUDE_ENABLED
2018 if (options & XML_PARSE_XINCLUDE) {
2019 doc = xmlReadFile(filename, NULL, options);
2020 xmlXIncludeProcessFlags(doc, options);
2024 xmlGetWarningsDefaultValue = 1;
2025 doc = xmlReadFile(filename, NULL, options);
2027 xmlGetWarningsDefaultValue = 0;
2033 #ifdef LIBXML_HTML_ENABLED
2034 if (options & XML_PARSE_HTML) {
2035 htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2038 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2040 res = compareFileMem(result, base, size);
2044 xmlFree((char *)base);
2048 fprintf(stderr, "Result for %s failed\n", filename);
2052 res = compareFileMem(err, testErrors, testErrorsSize);
2054 fprintf(stderr, "Error for %s failed\n", filename);
2057 } else if (options & XML_PARSE_DTDVALID) {
2058 if (testErrorsSize != 0)
2059 fprintf(stderr, "Validation for %s failed\n", filename);
2065 #ifdef LIBXML_READER_ENABLED
2066 /************************************************************************
2068 * Reader based tests *
2070 ************************************************************************/
2072 static void processNode(FILE *out, xmlTextReaderPtr reader) {
2073 const xmlChar *name, *value;
2076 type = xmlTextReaderNodeType(reader);
2077 empty = xmlTextReaderIsEmptyElement(reader);
2079 name = xmlTextReaderConstName(reader);
2081 name = BAD_CAST "--";
2083 value = xmlTextReaderConstValue(reader);
2086 fprintf(out, "%d %d %s %d %d",
2087 xmlTextReaderDepth(reader),
2091 xmlTextReaderHasValue(reader));
2095 fprintf(out, " %s\n", value);
2099 streamProcessTest(const char *filename, const char *result, const char *err,
2100 xmlTextReaderPtr reader, const char *rng) {
2109 if (result != NULL) {
2110 temp = resultFilename(filename, "", ".res");
2112 fprintf(stderr, "Out of memory\n");
2115 t = fopen(temp, "wb");
2117 fprintf(stderr, "Can't open temp file %s\n", temp);
2122 #ifdef LIBXML_SCHEMAS_ENABLED
2124 ret = xmlTextReaderRelaxNGValidate(reader, rng);
2126 testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
2137 xmlGetWarningsDefaultValue = 1;
2138 ret = xmlTextReaderRead(reader);
2140 if ((t != NULL) && (rng == NULL))
2141 processNode(t, reader);
2142 ret = xmlTextReaderRead(reader);
2145 testErrorHandler(NULL, "%s : failed to parse\n", filename);
2148 if (xmlTextReaderIsValid(reader) != 1) {
2149 testErrorHandler(NULL, "%s fails to validate\n", filename);
2151 testErrorHandler(NULL, "%s validates\n", filename);
2154 xmlGetWarningsDefaultValue = 0;
2157 ret = compareFiles(temp, result);
2163 fprintf(stderr, "Result for %s failed\n", filename);
2168 ret = compareFileMem(err, testErrors, testErrorsSize);
2170 fprintf(stderr, "Error for %s failed\n", filename);
2171 printf("%s", testErrors);
2181 * @filename: the file to parse
2182 * @result: the file with expected result
2183 * @err: the file with error messages
2185 * Parse a file using the reader API and check for errors.
2187 * Returns 0 in case of success, an error code otherwise
2190 streamParseTest(const char *filename, const char *result, const char *err,
2192 xmlTextReaderPtr reader;
2195 reader = xmlReaderForFile(filename, NULL, options);
2196 ret = streamProcessTest(filename, result, err, reader, NULL);
2197 xmlFreeTextReader(reader);
2203 * @filename: the file to parse
2204 * @result: the file with expected result
2205 * @err: the file with error messages
2207 * Parse a file using the walker, i.e. a reader built from a atree.
2209 * Returns 0 in case of success, an error code otherwise
2212 walkerParseTest(const char *filename, const char *result, const char *err,
2215 xmlTextReaderPtr reader;
2218 doc = xmlReadFile(filename, NULL, options);
2220 fprintf(stderr, "Failed to parse %s\n", filename);
2223 reader = xmlReaderWalker(doc);
2224 ret = streamProcessTest(filename, result, err, reader, NULL);
2225 xmlFreeTextReader(reader);
2231 * streamMemParseTest:
2232 * @filename: the file to parse
2233 * @result: the file with expected result
2234 * @err: the file with error messages
2236 * Parse a file using the reader API from memory and check for errors.
2238 * Returns 0 in case of success, an error code otherwise
2241 streamMemParseTest(const char *filename, const char *result, const char *err,
2243 xmlTextReaderPtr reader;
2249 * load and parse the memory
2251 if (loadMem(filename, &base, &size) != 0) {
2252 fprintf(stderr, "Failed to load %s\n", filename);
2255 reader = xmlReaderForMemory(base, size, filename, NULL, options);
2256 ret = streamProcessTest(filename, result, err, reader, NULL);
2258 xmlFreeTextReader(reader);
2263 #ifdef LIBXML_XPATH_ENABLED
2264 #ifdef LIBXML_DEBUG_ENABLED
2265 /************************************************************************
2267 * XPath and XPointer based tests *
2269 ************************************************************************/
2271 static FILE *xpathOutput;
2272 static xmlDocPtr xpathDocument;
2275 testXPath(const char *str, int xptr, int expr) {
2276 xmlXPathObjectPtr res;
2277 xmlXPathContextPtr ctxt;
2280 #if defined(LIBXML_XPTR_ENABLED)
2282 ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
2283 res = xmlXPtrEval(BAD_CAST str, ctxt);
2286 ctxt = xmlXPathNewContext(xpathDocument);
2287 ctxt->node = xmlDocGetRootElement(xpathDocument);
2289 res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
2291 /* res = xmlXPathEval(BAD_CAST str, ctxt); */
2292 xmlXPathCompExprPtr comp;
2294 comp = xmlXPathCompile(BAD_CAST str);
2296 res = xmlXPathCompiledEval(comp, ctxt);
2297 xmlXPathFreeCompExpr(comp);
2301 #if defined(LIBXML_XPTR_ENABLED)
2304 xmlXPathDebugDumpObject(xpathOutput, res, 0);
2305 xmlXPathFreeObject(res);
2306 xmlXPathFreeContext(ctxt);
2311 * @filename: the file to parse
2312 * @result: the file with expected result
2313 * @err: the file with error messages
2315 * Parse a file containing XPath standalone expressions and evaluate them
2317 * Returns 0 in case of success, an error code otherwise
2320 xpathCommonTest(const char *filename, const char *result,
2321 int xptr, int expr) {
2323 char expression[5000];
2327 temp = resultFilename(filename, "", ".res");
2329 fprintf(stderr, "Out of memory\n");
2332 xpathOutput = fopen(temp, "wb");
2333 if (xpathOutput == NULL) {
2334 fprintf(stderr, "failed to open output file %s\n", temp);
2339 input = fopen(filename, "rb");
2340 if (input == NULL) {
2341 xmlGenericError(xmlGenericErrorContext,
2342 "Cannot open %s for reading\n", filename);
2346 while (fgets(expression, 4500, input) != NULL) {
2347 len = strlen(expression);
2349 while ((len >= 0) &&
2350 ((expression[len] == '\n') || (expression[len] == '\t') ||
2351 (expression[len] == '\r') || (expression[len] == ' '))) len--;
2352 expression[len + 1] = 0;
2354 fprintf(xpathOutput,
2355 "\n========================\nExpression: %s\n",
2357 testXPath(expression, xptr, expr);
2362 fclose(xpathOutput);
2363 if (result != NULL) {
2364 ret = compareFiles(temp, result);
2366 fprintf(stderr, "Result for %s failed\n", filename);
2379 * @filename: the file to parse
2380 * @result: the file with expected result
2381 * @err: the file with error messages
2383 * Parse a file containing XPath standalone expressions and evaluate them
2385 * Returns 0 in case of success, an error code otherwise
2388 xpathExprTest(const char *filename, const char *result,
2389 const char *err ATTRIBUTE_UNUSED,
2390 int options ATTRIBUTE_UNUSED) {
2391 return(xpathCommonTest(filename, result, 0, 1));
2396 * @filename: the file to parse
2397 * @result: the file with expected result
2398 * @err: the file with error messages
2400 * Parse a file containing XPath expressions and evaluate them against
2401 * a set of corresponding documents.
2403 * Returns 0 in case of success, an error code otherwise
2406 xpathDocTest(const char *filename,
2407 const char *resul ATTRIBUTE_UNUSED,
2408 const char *err ATTRIBUTE_UNUSED,
2417 xpathDocument = xmlReadFile(filename, NULL,
2418 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2419 if (xpathDocument == NULL) {
2420 fprintf(stderr, "Failed to load %s\n", filename);
2424 snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
2426 globbuf.gl_offs = 0;
2427 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2428 for (i = 0;i < globbuf.gl_pathc;i++) {
2429 snprintf(result, 499, "result/XPath/tests/%s",
2430 baseFilename(globbuf.gl_pathv[i]));
2431 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
2437 xmlFreeDoc(xpathDocument);
2441 #ifdef LIBXML_XPTR_ENABLED
2444 * @filename: the file to parse
2445 * @result: the file with expected result
2446 * @err: the file with error messages
2448 * Parse a file containing XPath expressions and evaluate them against
2449 * a set of corresponding documents.
2451 * Returns 0 in case of success, an error code otherwise
2454 xptrDocTest(const char *filename,
2455 const char *resul ATTRIBUTE_UNUSED,
2456 const char *err ATTRIBUTE_UNUSED,
2465 xpathDocument = xmlReadFile(filename, NULL,
2466 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2467 if (xpathDocument == NULL) {
2468 fprintf(stderr, "Failed to load %s\n", filename);
2472 snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
2474 globbuf.gl_offs = 0;
2475 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2476 for (i = 0;i < globbuf.gl_pathc;i++) {
2477 snprintf(result, 499, "result/XPath/xptr/%s",
2478 baseFilename(globbuf.gl_pathv[i]));
2479 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
2485 xmlFreeDoc(xpathDocument);
2488 #endif /* LIBXML_XPTR_ENABLED */
2492 * @filename: the file to parse
2493 * @result: the file with expected result
2494 * @err: the file with error messages
2496 * Parse a file containing xml:id and check for errors and verify
2497 * that XPath queries will work on them as expected.
2499 * Returns 0 in case of success, an error code otherwise
2502 xmlidDocTest(const char *filename,
2511 xpathDocument = xmlReadFile(filename, NULL,
2512 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2513 if (xpathDocument == NULL) {
2514 fprintf(stderr, "Failed to load %s\n", filename);
2518 temp = resultFilename(filename, "", ".res");
2520 fprintf(stderr, "Out of memory\n");
2523 xpathOutput = fopen(temp, "wb");
2524 if (xpathOutput == NULL) {
2525 fprintf(stderr, "failed to open output file %s\n", temp);
2526 xmlFreeDoc(xpathDocument);
2531 testXPath("id('bar')", 0, 0);
2533 fclose(xpathOutput);
2534 if (result != NULL) {
2535 ret = compareFiles(temp, result);
2537 fprintf(stderr, "Result for %s failed\n", filename);
2546 xmlFreeDoc(xpathDocument);
2549 ret = compareFileMem(err, testErrors, testErrorsSize);
2551 fprintf(stderr, "Error for %s failed\n", filename);
2558 #endif /* LIBXML_DEBUG_ENABLED */
2560 /************************************************************************
2564 ************************************************************************/
2567 handleURI(const char *str, const char *base, FILE *o) {
2570 xmlChar *res = NULL;
2572 uri = xmlCreateURI();
2575 ret = xmlParseURIReference(uri, str);
2577 fprintf(o, "%s : error %d\n", str, ret);
2579 xmlNormalizeURIPath(uri->path);
2580 xmlPrintURI(o, uri);
2584 res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
2586 fprintf(o, "%s\n", (char *) res);
2589 fprintf(o, "::ERROR::\n");
2598 * @filename: the file to parse
2599 * @result: the file with expected result
2600 * @err: the file with error messages
2602 * Parse a file containing URI and check for errors
2604 * Returns 0 in case of success, an error code otherwise
2607 uriCommonTest(const char *filename,
2614 int res = 0, i, ret;
2616 temp = resultFilename(filename, "", ".res");
2618 fprintf(stderr, "Out of memory\n");
2621 o = fopen(temp, "wb");
2623 fprintf(stderr, "failed to open output file %s\n", temp);
2627 f = fopen(filename, "rb");
2629 fprintf(stderr, "failed to open input file %s\n", filename);
2640 * read one line in string buffer.
2642 if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
2646 * remove the ending spaces
2650 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
2651 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
2656 handleURI(str, base, o);
2662 if (result != NULL) {
2663 ret = compareFiles(temp, result);
2665 fprintf(stderr, "Result for %s failed\n", filename);
2670 ret = compareFileMem(err, testErrors, testErrorsSize);
2672 fprintf(stderr, "Error for %s failed\n", filename);
2686 * @filename: the file to parse
2687 * @result: the file with expected result
2688 * @err: the file with error messages
2690 * Parse a file containing URI and check for errors
2692 * Returns 0 in case of success, an error code otherwise
2695 uriParseTest(const char *filename,
2698 int options ATTRIBUTE_UNUSED) {
2699 return(uriCommonTest(filename, result, err, NULL));
2704 * @filename: the file to parse
2705 * @result: the file with expected result
2706 * @err: the file with error messages
2708 * Parse a file containing URI, compose them against a fixed base and
2711 * Returns 0 in case of success, an error code otherwise
2714 uriBaseTest(const char *filename,
2717 int options ATTRIBUTE_UNUSED) {
2718 return(uriCommonTest(filename, result, err,
2719 "http://foo.com/path/to/index.html?orig#help"));
2722 static int urip_success = 1;
2723 static int urip_current = 0;
2724 static const char *urip_testURLs[] = {
2725 "urip://example.com/a b.html",
2726 "urip://example.com/a%20b.html",
2727 "file:///path/to/a b.html",
2728 "file:///path/to/a%20b.html",
2729 "/path/to/a b.html",
2730 "/path/to/a%20b.html",
2731 "urip://example.com/résumé.html",
2732 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2735 static const char *urip_rcvsURLs[] = {
2736 /* it is an URI the strings must be escaped */
2737 "urip://example.com/a%20b.html",
2738 /* check that % escaping is not broken */
2739 "urip://example.com/a%20b.html",
2740 /* it's an URI path the strings must be escaped */
2741 "file:///path/to/a%20b.html",
2742 /* check that % escaping is not broken */
2743 "file:///path/to/a%20b.html",
2744 /* this is not an URI, this is a path, so this should not be escaped */
2745 "/path/to/a b.html",
2746 /* check that paths with % are not broken */
2747 "/path/to/a%20b.html",
2748 /* out of context the encoding can't be guessed byte by byte conversion */
2749 "urip://example.com/r%E9sum%E9.html",
2750 /* verify we don't destroy URIs especially the query part */
2751 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2754 static const char *urip_res = "<list/>";
2755 static const char *urip_cur = NULL;
2756 static int urip_rlen;
2760 * @URI: an URI to test
2762 * Check for an urip: query
2764 * Returns 1 if yes and 0 if another Input module should be used
2767 uripMatch(const char * URI) {
2768 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2770 /* Verify we received the escaped URL */
2771 if (strcmp(urip_rcvsURLs[urip_current], URI))
2778 * @URI: an URI to test
2780 * Return a pointer to the urip: query handler, in this example simply
2781 * the urip_current pointer...
2783 * Returns an Input context or NULL in case or error
2786 uripOpen(const char * URI) {
2787 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2789 /* Verify we received the escaped URL */
2790 if (strcmp(urip_rcvsURLs[urip_current], URI))
2792 urip_cur = urip_res;
2793 urip_rlen = strlen(urip_res);
2794 return((void *) urip_cur);
2799 * @context: the read context
2801 * Close the urip: query handler
2803 * Returns 0 or -1 in case of error
2806 uripClose(void * context) {
2807 if (context == NULL) return(-1);
2815 * @context: the read context
2816 * @buffer: where to store data
2817 * @len: number of bytes to read
2819 * Implement an urip: query read.
2821 * Returns the number of bytes read or -1 in case of error
2824 uripRead(void * context, char * buffer, int len) {
2825 const char *ptr = (const char *) context;
2827 if ((context == NULL) || (buffer == NULL) || (len < 0))
2830 if (len > urip_rlen) len = urip_rlen;
2831 memcpy(buffer, ptr, len);
2837 urip_checkURL(const char *URL) {
2840 doc = xmlReadFile(URL, NULL, 0);
2849 * @filename: ignored
2853 * Run a set of tests to check how Path and URI are handled before
2854 * being passed to the I/O layer
2856 * Returns 0 in case of success, an error code otherwise
2859 uriPathTest(const char *filename ATTRIBUTE_UNUSED,
2860 const char *result ATTRIBUTE_UNUSED,
2861 const char *err ATTRIBUTE_UNUSED,
2862 int options ATTRIBUTE_UNUSED) {
2867 * register the new I/O handlers
2869 if (xmlRegisterInputCallbacks(uripMatch, uripOpen, uripRead, uripClose) < 0)
2871 fprintf(stderr, "failed to register HTTP handler\n");
2875 for (urip_current = 0;urip_testURLs[urip_current] != NULL;urip_current++) {
2877 parsed = urip_checkURL(urip_testURLs[urip_current]);
2878 if (urip_success != 1) {
2879 fprintf(stderr, "failed the URL passing test for %s",
2880 urip_testURLs[urip_current]);
2882 } else if (parsed != 1) {
2883 fprintf(stderr, "failed the parsing test for %s",
2884 urip_testURLs[urip_current]);
2890 xmlPopInputCallbacks();
2894 #ifdef LIBXML_SCHEMAS_ENABLED
2895 /************************************************************************
2899 ************************************************************************/
2901 schemasOneTest(const char *sch,
2902 const char *filename,
2906 xmlSchemaPtr schemas) {
2908 xmlSchemaValidCtxtPtr ctxt;
2910 int validResult = 0;
2912 FILE *schemasOutput;
2914 doc = xmlReadFile(filename, NULL, options);
2916 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
2920 temp = resultFilename(result, "", ".res");
2922 fprintf(stderr, "Out of memory\n");
2925 schemasOutput = fopen(temp, "wb");
2926 if (schemasOutput == NULL) {
2927 fprintf(stderr, "failed to open output file %s\n", temp);
2933 ctxt = xmlSchemaNewValidCtxt(schemas);
2934 xmlSchemaSetValidErrors(ctxt,
2935 (xmlSchemaValidityErrorFunc) testErrorHandler,
2936 (xmlSchemaValidityWarningFunc) testErrorHandler,
2938 validResult = xmlSchemaValidateDoc(ctxt, doc);
2939 if (validResult == 0) {
2940 fprintf(schemasOutput, "%s validates\n", filename);
2941 } else if (validResult > 0) {
2942 fprintf(schemasOutput, "%s fails to validate\n", filename);
2944 fprintf(schemasOutput, "%s validation generated an internal error\n",
2947 fclose(schemasOutput);
2949 if (compareFiles(temp, result)) {
2950 fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
2959 if ((validResult != 0) && (err != NULL)) {
2960 if (compareFileMem(err, testErrors, testErrorsSize)) {
2961 fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
2966 xmlSchemaFreeValidCtxt(ctxt);
2972 * @filename: the schemas file
2973 * @result: the file with expected result
2974 * @err: the file with error messages
2976 * Parse a file containing URI, compose them against a fixed base and
2979 * Returns 0 in case of success, an error code otherwise
2982 schemasTest(const char *filename,
2983 const char *resul ATTRIBUTE_UNUSED,
2984 const char *errr ATTRIBUTE_UNUSED,
2986 const char *base = baseFilename(filename);
2988 const char *instance;
2989 xmlSchemaParserCtxtPtr ctxt;
2990 xmlSchemaPtr schemas;
2991 int res = 0, len, ret;
3000 /* first compile the schemas if possible */
3001 ctxt = xmlSchemaNewParserCtxt(filename);
3002 xmlSchemaSetParserErrors(ctxt,
3003 (xmlSchemaValidityErrorFunc) testErrorHandler,
3004 (xmlSchemaValidityWarningFunc) testErrorHandler,
3006 schemas = xmlSchemaParse(ctxt);
3007 xmlSchemaFreeParserCtxt(ctxt);
3010 * most of the mess is about the output filenames generated by the Makefile
3013 if ((len > 499) || (len < 5)) {
3014 xmlSchemaFree(schemas);
3017 len -= 4; /* remove trailing .xsd */
3018 if (base[len - 2] == '_') {
3019 len -= 2; /* remove subtest number */
3021 if (base[len - 2] == '_') {
3022 len -= 2; /* remove subtest number */
3024 memcpy(prefix, base, len);
3027 snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
3030 if (base[len] == '_') {
3032 memcpy(prefix, base, len);
3036 globbuf.gl_offs = 0;
3037 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3038 for (i = 0;i < globbuf.gl_pathc;i++) {
3041 instance = globbuf.gl_pathv[i];
3042 base2 = baseFilename(instance);
3043 len = strlen(base2);
3044 if ((len > 6) && (base2[len - 6] == '_')) {
3045 count = base2[len - 5];
3046 snprintf(result, 499, "result/schemas/%s_%c",
3049 snprintf(err, 499, "result/schemas/%s_%c.err",
3053 fprintf(stderr, "don't know how to process %s\n", instance);
3056 if (schemas == NULL) {
3059 ret = schemasOneTest(filename, instance, result, err,
3066 xmlSchemaFree(schemas);
3071 /************************************************************************
3075 ************************************************************************/
3077 rngOneTest(const char *sch,
3078 const char *filename,
3082 xmlRelaxNGPtr schemas) {
3084 xmlRelaxNGValidCtxtPtr ctxt;
3087 FILE *schemasOutput;
3089 doc = xmlReadFile(filename, NULL, options);
3091 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
3095 temp = resultFilename(result, "", ".res");
3097 fprintf(stderr, "Out of memory\n");
3100 schemasOutput = fopen(temp, "wb");
3101 if (schemasOutput == NULL) {
3102 fprintf(stderr, "failed to open output file %s\n", temp);
3108 ctxt = xmlRelaxNGNewValidCtxt(schemas);
3109 xmlRelaxNGSetValidErrors(ctxt,
3110 (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3111 (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3113 ret = xmlRelaxNGValidateDoc(ctxt, doc);
3115 testErrorHandler(NULL, "%s validates\n", filename);
3116 } else if (ret > 0) {
3117 testErrorHandler(NULL, "%s fails to validate\n", filename);
3119 testErrorHandler(NULL, "%s validation generated an internal error\n",
3122 fclose(schemasOutput);
3125 if (compareFiles(temp, result)) {
3126 fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
3136 if (compareFileMem(err, testErrors, testErrorsSize)) {
3137 fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
3139 printf("%s", testErrors);
3144 xmlRelaxNGFreeValidCtxt(ctxt);
3150 * @filename: the schemas file
3151 * @result: the file with expected result
3152 * @err: the file with error messages
3154 * Parse an RNG schemas and then apply it to the related .xml
3156 * Returns 0 in case of success, an error code otherwise
3159 rngTest(const char *filename,
3160 const char *resul ATTRIBUTE_UNUSED,
3161 const char *errr ATTRIBUTE_UNUSED,
3163 const char *base = baseFilename(filename);
3165 const char *instance;
3166 xmlRelaxNGParserCtxtPtr ctxt;
3167 xmlRelaxNGPtr schemas;
3168 int res = 0, len, ret = 0;
3177 /* first compile the schemas if possible */
3178 ctxt = xmlRelaxNGNewParserCtxt(filename);
3179 xmlRelaxNGSetParserErrors(ctxt,
3180 (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3181 (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3183 schemas = xmlRelaxNGParse(ctxt);
3184 xmlRelaxNGFreeParserCtxt(ctxt);
3187 * most of the mess is about the output filenames generated by the Makefile
3190 if ((len > 499) || (len < 5)) {
3191 xmlRelaxNGFree(schemas);
3194 len -= 4; /* remove trailing .rng */
3195 memcpy(prefix, base, len);
3198 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3201 globbuf.gl_offs = 0;
3202 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3203 for (i = 0;i < globbuf.gl_pathc;i++) {
3206 instance = globbuf.gl_pathv[i];
3207 base2 = baseFilename(instance);
3208 len = strlen(base2);
3209 if ((len > 6) && (base2[len - 6] == '_')) {
3210 count = base2[len - 5];
3211 snprintf(result, 499, "result/relaxng/%s_%c",
3214 snprintf(err, 499, "result/relaxng/%s_%c.err",
3218 fprintf(stderr, "don't know how to process %s\n", instance);
3221 if (schemas == NULL) {
3224 ret = rngOneTest(filename, instance, result, err,
3231 xmlRelaxNGFree(schemas);
3236 #ifdef LIBXML_READER_ENABLED
3239 * @filename: the schemas file
3240 * @result: the file with expected result
3241 * @err: the file with error messages
3243 * Parse a set of files with streaming, applying an RNG schemas
3245 * Returns 0 in case of success, an error code otherwise
3248 rngStreamTest(const char *filename,
3249 const char *resul ATTRIBUTE_UNUSED,
3250 const char *errr ATTRIBUTE_UNUSED,
3252 const char *base = baseFilename(filename);
3254 const char *instance;
3255 int res = 0, len, ret;
3263 xmlTextReaderPtr reader;
3264 int disable_err = 0;
3267 * most of the mess is about the output filenames generated by the Makefile
3270 if ((len > 499) || (len < 5)) {
3271 fprintf(stderr, "len(base) == %d !\n", len);
3274 len -= 4; /* remove trailing .rng */
3275 memcpy(prefix, base, len);
3279 * strictly unifying the error messages is nearly impossible this
3280 * hack is also done in the Makefile
3282 if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
3283 (!strcmp(prefix, "tutor3_2")) || (!strcmp(prefix, "307377")) ||
3284 (!strcmp(prefix, "tutor8_2")))
3287 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3290 globbuf.gl_offs = 0;
3291 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3292 for (i = 0;i < globbuf.gl_pathc;i++) {
3295 instance = globbuf.gl_pathv[i];
3296 base2 = baseFilename(instance);
3297 len = strlen(base2);
3298 if ((len > 6) && (base2[len - 6] == '_')) {
3299 count = base2[len - 5];
3300 snprintf(result, 499, "result/relaxng/%s_%c",
3303 snprintf(err, 499, "result/relaxng/%s_%c.err",
3307 fprintf(stderr, "don't know how to process %s\n", instance);
3310 reader = xmlReaderForFile(instance, NULL, options);
3311 if (reader == NULL) {
3312 fprintf(stderr, "Failed to build reder for %s\n", instance);
3314 if (disable_err == 1)
3315 ret = streamProcessTest(instance, result, NULL, reader, filename);
3317 ret = streamProcessTest(instance, result, err, reader, filename);
3318 xmlFreeTextReader(reader);
3320 fprintf(stderr, "instance %s failed\n", instance);
3332 #ifdef LIBXML_PATTERN_ENABLED
3333 #ifdef LIBXML_READER_ENABLED
3334 /************************************************************************
3338 ************************************************************************/
3339 static void patternNode(FILE *out, xmlTextReaderPtr reader,
3340 const char *pattern, xmlPatternPtr patternc,
3341 xmlStreamCtxtPtr patstream) {
3342 xmlChar *path = NULL;
3346 type = xmlTextReaderNodeType(reader);
3347 empty = xmlTextReaderIsEmptyElement(reader);
3349 if (type == XML_READER_TYPE_ELEMENT) {
3350 /* do the check only on element start */
3351 match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
3354 path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
3355 fprintf(out, "Node %s matches pattern %s\n", path, pattern);
3358 if (patstream != NULL) {
3361 if (type == XML_READER_TYPE_ELEMENT) {
3362 ret = xmlStreamPush(patstream,
3363 xmlTextReaderConstLocalName(reader),
3364 xmlTextReaderConstNamespaceUri(reader));
3366 fprintf(out, "xmlStreamPush() failure\n");
3367 xmlFreeStreamCtxt(patstream);
3369 } else if (ret != match) {
3371 path = xmlGetNodePath(
3372 xmlTextReaderCurrentNode(reader));
3375 "xmlPatternMatch and xmlStreamPush disagree\n");
3377 " pattern %s node %s\n",
3383 if ((type == XML_READER_TYPE_END_ELEMENT) ||
3384 ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
3385 ret = xmlStreamPop(patstream);
3387 fprintf(out, "xmlStreamPop() failure\n");
3388 xmlFreeStreamCtxt(patstream);
3399 * @filename: the schemas file
3400 * @result: the file with expected result
3401 * @err: the file with error messages
3403 * Parse a set of files with streaming, applying an RNG schemas
3405 * Returns 0 in case of success, an error code otherwise
3408 patternTest(const char *filename,
3409 const char *resul ATTRIBUTE_UNUSED,
3410 const char *err ATTRIBUTE_UNUSED,
3412 xmlPatternPtr patternc = NULL;
3413 xmlStreamCtxtPtr patstream = NULL;
3421 xmlTextReaderPtr reader;
3424 len = strlen(filename);
3426 memcpy(xml, filename, len);
3428 snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
3430 memcpy(xml + len, ".xml", 5);
3432 if (!checkTestFile(xml)) {
3433 fprintf(stderr, "Missing xml file %s\n", xml);
3436 if (!checkTestFile(result)) {
3437 fprintf(stderr, "Missing result file %s\n", result);
3440 f = fopen(filename, "rb");
3442 fprintf(stderr, "Failed to open %s\n", filename);
3445 temp = resultFilename(filename, "", ".res");
3447 fprintf(stderr, "Out of memory\n");
3450 o = fopen(temp, "wb");
3452 fprintf(stderr, "failed to open output file %s\n", temp);
3459 * read one line in string buffer.
3461 if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
3465 * remove the ending spaces
3469 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
3470 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
3474 doc = xmlReadFile(xml, NULL, options);
3476 fprintf(stderr, "Failed to parse %s\n", xml);
3480 const xmlChar *namespaces[22];
3484 root = xmlDocGetRootElement(doc);
3485 for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
3486 namespaces[j++] = ns->href;
3487 namespaces[j++] = ns->prefix;
3489 namespaces[j++] = NULL;
3490 namespaces[j] = NULL;
3492 patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
3494 if (patternc == NULL) {
3495 testErrorHandler(NULL,
3496 "Pattern %s failed to compile\n", str);
3501 patstream = xmlPatternGetStreamCtxt(patternc);
3502 if (patstream != NULL) {
3503 ret = xmlStreamPush(patstream, NULL, NULL);
3505 fprintf(stderr, "xmlStreamPush() failure\n");
3506 xmlFreeStreamCtxt(patstream);
3512 reader = xmlReaderWalker(doc);
3513 res = xmlTextReaderRead(reader);
3515 patternNode(o, reader, str, patternc, patstream);
3516 res = xmlTextReaderRead(reader);
3519 fprintf(o, "%s : failed to parse\n", filename);
3521 xmlFreeTextReader(reader);
3523 xmlFreeStreamCtxt(patstream);
3525 xmlFreePattern(patternc);
3533 ret = compareFiles(temp, result);
3535 fprintf(stderr, "Result for %s failed\n", filename);
3545 #endif /* PATTERN */
3546 #ifdef LIBXML_C14N_ENABLED
3547 /************************************************************************
3549 * Canonicalization tests *
3551 ************************************************************************/
3552 static xmlXPathObjectPtr
3553 load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
3554 xmlXPathObjectPtr xpath;
3557 xmlXPathContextPtr ctx;
3562 * load XPath expr as a file
3564 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3565 xmlSubstituteEntitiesDefault(1);
3567 doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3569 fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
3574 * Check the document is of the right kind
3576 if(xmlDocGetRootElement(doc) == NULL) {
3577 fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
3582 node = doc->children;
3583 while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
3588 fprintf(stderr,"Error: XPath element expected in the file \"%s\"\n", filename);
3593 expr = xmlNodeGetContent(node);
3595 fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
3600 ctx = xmlXPathNewContext(parent_doc);
3602 fprintf(stderr,"Error: unable to create new context\n");
3609 * Register namespaces
3613 if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
3614 fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
3616 xmlXPathFreeContext(ctx);
3626 xpath = xmlXPathEvalExpression(expr, ctx);
3628 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3630 xmlXPathFreeContext(ctx);
3635 /* print_xpath_nodes(xpath->nodesetval); */
3638 xmlXPathFreeContext(ctx);
3644 * Macro used to grow the current buffer.
3646 #define xxx_growBufferReentrant() { \
3648 buffer = (xmlChar **) \
3649 xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \
3650 if (buffer == NULL) { \
3651 perror("realloc failed"); \
3657 parse_list(xmlChar *str) {
3659 xmlChar **out = NULL;
3660 int buffer_size = 0;
3667 len = xmlStrlen(str);
3668 if((str[0] == '\'') && (str[len - 1] == '\'')) {
3669 str[len - 1] = '\0';
3673 * allocate an translation buffer.
3676 buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
3677 if (buffer == NULL) {
3678 perror("malloc failed");
3683 while(*str != '\0') {
3684 if (out - buffer > buffer_size - 10) {
3685 int indx = out - buffer;
3687 xxx_growBufferReentrant();
3688 out = &buffer[indx];
3691 while(*str != ',' && *str != '\0') ++str;
3692 if(*str == ',') *(str++) = '\0';
3699 c14nRunTest(const char* xml_filename, int with_comments, int mode,
3700 const char* xpath_filename, const char *ns_filename,
3701 const char* result_file) {
3703 xmlXPathObjectPtr xpath = NULL;
3704 xmlChar *result = NULL;
3706 xmlChar **inclusive_namespaces = NULL;
3707 const char *nslist = NULL;
3712 * build an XML tree from a the file; we need to add default
3713 * attributes and resolve all character and entities references
3715 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3716 xmlSubstituteEntitiesDefault(1);
3718 doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3720 fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
3725 * Check the document is of the right kind
3727 if(xmlDocGetRootElement(doc) == NULL) {
3728 fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
3734 * load xpath file if specified
3736 if(xpath_filename) {
3737 xpath = load_xpath_expr(doc, xpath_filename);
3739 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3745 if (ns_filename != NULL) {
3746 if (loadMem(ns_filename, &nslist, &nssize)) {
3747 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3748 if(xpath != NULL) xmlXPathFreeObject(xpath);
3752 inclusive_namespaces = parse_list((xmlChar *) nslist);
3758 /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
3759 ret = xmlC14NDocDumpMemory(doc,
3760 (xpath) ? xpath->nodesetval : NULL,
3761 mode, inclusive_namespaces,
3762 with_comments, &result);
3764 if(result != NULL) {
3765 if (compareFileMem(result_file, (const char *) result, ret)) {
3766 fprintf(stderr, "Result mismatch for %s\n", xml_filename);
3767 fprintf(stderr, "RESULT:\n%s\n", (const char*)result);
3772 fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
3779 if (result != NULL) xmlFree(result);
3780 if(xpath != NULL) xmlXPathFreeObject(xpath);
3781 if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
3782 if (nslist != NULL) free((char *) nslist);
3789 c14nCommonTest(const char *filename, int with_comments, int mode,
3790 const char *subdir) {
3795 char *result = NULL;
3800 base = baseFilename(filename);
3803 memcpy(prefix, base, len);
3806 snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
3807 if (!checkTestFile(buf)) {
3808 fprintf(stderr, "Missing result file %s", buf);
3811 result = strdup(buf);
3812 snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
3813 if (checkTestFile(buf)) {
3814 xpath = strdup(buf);
3816 snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
3817 if (checkTestFile(buf)) {
3822 if (c14nRunTest(filename, with_comments, mode,
3823 xpath, ns, result) < 0)
3826 if (result != NULL) free(result);
3827 if (xpath != NULL) free(xpath);
3828 if (ns != NULL) free(ns);
3833 c14nWithCommentTest(const char *filename,
3834 const char *resul ATTRIBUTE_UNUSED,
3835 const char *err ATTRIBUTE_UNUSED,
3836 int options ATTRIBUTE_UNUSED) {
3837 return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments"));
3840 c14nWithoutCommentTest(const char *filename,
3841 const char *resul ATTRIBUTE_UNUSED,
3842 const char *err ATTRIBUTE_UNUSED,
3843 int options ATTRIBUTE_UNUSED) {
3844 return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments"));
3847 c14nExcWithoutCommentTest(const char *filename,
3848 const char *resul ATTRIBUTE_UNUSED,
3849 const char *err ATTRIBUTE_UNUSED,
3850 int options ATTRIBUTE_UNUSED) {
3851 return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments"));
3854 c14n11WithoutCommentTest(const char *filename,
3855 const char *resul ATTRIBUTE_UNUSED,
3856 const char *err ATTRIBUTE_UNUSED,
3857 int options ATTRIBUTE_UNUSED) {
3858 return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments"));
3861 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined (LIBXML_SAX1_ENABLED)
3862 /************************************************************************
3864 * Catalog and threads test *
3866 ************************************************************************/
3869 * mostly a cut and paste from testThreads.c
3873 static const char *catalog = "test/threads/complex.xml";
3874 static const char *testfiles[] = {
3875 "test/threads/abc.xml",
3876 "test/threads/acb.xml",
3877 "test/threads/bac.xml",
3878 "test/threads/bca.xml",
3879 "test/threads/cab.xml",
3880 "test/threads/cba.xml",
3881 "test/threads/invalid.xml",
3884 static const char *Okay = "OK";
3885 static const char *Failed = "Failed";
3887 #ifndef xmlDoValidityCheckingDefaultValue
3888 #error xmlDoValidityCheckingDefaultValue is not a macro
3890 #ifndef xmlGenericErrorContext
3891 #error xmlGenericErrorContext is not a macro
3895 thread_specific_data(void *private_data)
3898 const char *filename = (const char *) private_data;
3901 if (!strcmp(filename, "test/threads/invalid.xml")) {
3902 xmlDoValidityCheckingDefaultValue = 0;
3903 xmlGenericErrorContext = stdout;
3905 xmlDoValidityCheckingDefaultValue = 1;
3906 xmlGenericErrorContext = stderr;
3908 myDoc = xmlParseFile(filename);
3912 printf("parse failed\n");
3915 if (!strcmp(filename, "test/threads/invalid.xml")) {
3916 if (xmlDoValidityCheckingDefaultValue != 0) {
3917 printf("ValidityCheckingDefaultValue override failed\n");
3920 if (xmlGenericErrorContext != stdout) {
3921 printf("xmlGenericErrorContext override failed\n");
3925 if (xmlDoValidityCheckingDefaultValue != 1) {
3926 printf("ValidityCheckingDefaultValue override failed\n");
3929 if (xmlGenericErrorContext != stderr) {
3930 printf("xmlGenericErrorContext override failed\n");
3935 return ((void *) Failed);
3936 return ((void *) Okay);
3939 #if defined(linux) || defined(__sun) || defined(__APPLE_CC__)
3941 #include <pthread.h>
3943 static pthread_t tid[MAX_ARGC];
3948 unsigned int i, repeat;
3949 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
3950 void *results[MAX_ARGC];
3956 for (repeat = 0; repeat < 500; repeat++) {
3957 xmlLoadCatalog(catalog);
3960 for (i = 0; i < num_threads; i++) {
3962 tid[i] = (pthread_t) - 1;
3965 for (i = 0; i < num_threads; i++) {
3966 ret = pthread_create(&tid[i], 0, thread_specific_data,
3967 (void *) testfiles[i]);
3969 fprintf(stderr, "pthread_create failed\n");
3973 for (i = 0; i < num_threads; i++) {
3974 ret = pthread_join(tid[i], &results[i]);
3976 fprintf(stderr, "pthread_join failed\n");
3981 xmlCatalogCleanup();
3982 for (i = 0; i < num_threads; i++)
3983 if (results[i] != (void *) Okay) {
3984 fprintf(stderr, "Thread %d handling %s failed\n",
3993 #include <windows.h>
3996 #define TEST_REPEAT_COUNT 500
3998 static HANDLE tid[MAX_ARGC];
4001 win32_thread_specific_data(void *private_data)
4003 return((DWORD) thread_specific_data(private_data));
4009 unsigned int i, repeat;
4010 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4011 DWORD results[MAX_ARGC];
4016 for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
4017 xmlLoadCatalog(catalog);
4020 for (i = 0; i < num_threads; i++) {
4022 tid[i] = (HANDLE) - 1;
4025 for (i = 0; i < num_threads; i++) {
4028 tid[i] = CreateThread(NULL, 0,
4029 win32_thread_specific_data,
4030 (void *) testfiles[i], 0,
4032 if (tid[i] == NULL) {
4033 fprintf(stderr, "CreateThread failed\n");
4038 if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
4040 fprintf(stderr, "WaitForMultipleObjects failed\n");
4044 for (i = 0; i < num_threads; i++) {
4045 ret = GetExitCodeThread(tid[i], &results[i]);
4047 fprintf(stderr, "GetExitCodeThread failed\n");
4050 CloseHandle(tid[i]);
4053 xmlCatalogCleanup();
4054 for (i = 0; i < num_threads; i++) {
4055 if (results[i] != (DWORD) Okay) {
4056 fprintf(stderr, "Thread %d handling %s failed\n",
4066 #elif defined __BEOS__
4069 static thread_id tid[MAX_ARGC];
4074 unsigned int i, repeat;
4075 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4076 void *results[MAX_ARGC];
4081 for (repeat = 0; repeat < 500; repeat++) {
4082 xmlLoadCatalog(catalog);
4083 for (i = 0; i < num_threads; i++) {
4085 tid[i] = (thread_id) - 1;
4087 for (i = 0; i < num_threads; i++) {
4089 spawn_thread(thread_specific_data, "xmlTestThread",
4090 B_NORMAL_PRIORITY, (void *) testfiles[i]);
4091 if (tid[i] < B_OK) {
4092 fprintf(stderr, "beos_thread_create failed\n");
4095 printf("beos_thread_create %d -> %d\n", i, tid[i]);
4097 for (i = 0; i < num_threads; i++) {
4098 ret = wait_for_thread(tid[i], &results[i]);
4099 printf("beos_thread_wait %d -> %d\n", i, ret);
4101 fprintf(stderr, "beos_thread_wait failed\n");
4106 xmlCatalogCleanup();
4108 for (i = 0; i < num_threads; i++)
4109 if (results[i] != (void *) Okay) {
4110 printf("Thread %d handling %s failed\n", i, testfiles[i]);
4123 "Specific platform thread support not detected\n");
4128 threadsTest(const char *filename ATTRIBUTE_UNUSED,
4129 const char *resul ATTRIBUTE_UNUSED,
4130 const char *err ATTRIBUTE_UNUSED,
4131 int options ATTRIBUTE_UNUSED) {
4132 return(testThread());
4135 /************************************************************************
4137 * Tests Descriptions *
4139 ************************************************************************/
4142 testDesc testDescriptions[] = {
4143 { "XML regression tests" ,
4144 oldParseTest, "./test/*", "result/", "", NULL,
4146 { "XML regression tests on memory" ,
4147 memParseTest, "./test/*", "result/", "", NULL,
4149 { "XML entity subst regression tests" ,
4150 noentParseTest, "./test/*", "result/noent/", "", NULL,
4152 { "XML Namespaces regression tests",
4153 errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
4155 { "Error cases regression tests",
4156 errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
4158 #ifdef LIBXML_READER_ENABLED
4159 { "Error cases stream regression tests",
4160 streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
4162 { "Reader regression tests",
4163 streamParseTest, "./test/*", "result/", ".rdr", NULL,
4165 { "Reader entities substitution regression tests",
4166 streamParseTest, "./test/*", "result/", ".rde", NULL,
4168 { "Reader on memory regression tests",
4169 streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
4171 { "Walker regression tests",
4172 walkerParseTest, "./test/*", "result/", ".rdr", NULL,
4175 #ifdef LIBXML_SAX1_ENABLED
4176 { "SAX1 callbacks regression tests" ,
4177 saxParseTest, "./test/*", "result/", ".sax", NULL,
4179 { "SAX2 callbacks regression tests" ,
4180 saxParseTest, "./test/*", "result/", ".sax2", NULL,
4183 #ifdef LIBXML_PUSH_ENABLED
4184 { "XML push regression tests" ,
4185 pushParseTest, "./test/*", "result/", "", NULL,
4188 #ifdef LIBXML_HTML_ENABLED
4189 { "HTML regression tests" ,
4190 errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4192 #ifdef LIBXML_PUSH_ENABLED
4193 { "Push HTML regression tests" ,
4194 pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4197 #ifdef LIBXML_SAX1_ENABLED
4198 { "HTML SAX regression tests" ,
4199 saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
4203 #ifdef LIBXML_VALID_ENABLED
4204 { "Valid documents regression tests" ,
4205 errParseTest, "./test/VCM/*", NULL, NULL, NULL,
4206 XML_PARSE_DTDVALID },
4207 { "Validity checking regression tests" ,
4208 errParseTest, "./test/VC/*", "result/VC/", NULL, "",
4209 XML_PARSE_DTDVALID },
4210 { "General documents valid regression tests" ,
4211 errParseTest, "./test/valid/*", "result/valid/", "", ".err",
4212 XML_PARSE_DTDVALID },
4214 #ifdef LIBXML_XINCLUDE_ENABLED
4215 { "XInclude regression tests" ,
4216 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4217 /* Ignore errors at this point ".err", */
4218 XML_PARSE_XINCLUDE },
4219 #ifdef LIBXML_READER_ENABLED
4220 { "XInclude xmlReader regression tests",
4221 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4222 /* Ignore errors at this point ".err", */
4223 NULL, XML_PARSE_XINCLUDE },
4225 { "XInclude regression tests stripping include nodes" ,
4226 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4227 /* Ignore errors at this point ".err", */
4228 XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4229 #ifdef LIBXML_READER_ENABLED
4230 { "XInclude xmlReader regression tests stripping include nodes",
4231 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4232 /* Ignore errors at this point ".err", */
4233 NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4236 #ifdef LIBXML_XPATH_ENABLED
4237 #ifdef LIBXML_DEBUG_ENABLED
4238 { "XPath expressions regression tests" ,
4239 xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
4241 { "XPath document queries regression tests" ,
4242 xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4244 #ifdef LIBXML_XPTR_ENABLED
4245 { "XPointer document queries regression tests" ,
4246 xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4249 { "xml:id regression tests" ,
4250 xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
4254 { "URI parsing tests" ,
4255 uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
4257 { "URI base composition tests" ,
4258 uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
4260 { "Path URI conversion tests" ,
4261 uriPathTest, NULL, NULL, NULL, NULL,
4263 #ifdef LIBXML_SCHEMAS_ENABLED
4264 { "Schemas regression tests" ,
4265 schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
4267 { "Relax-NG regression tests" ,
4268 rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4269 XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4270 #ifdef LIBXML_READER_ENABLED
4271 { "Relax-NG streaming regression tests" ,
4272 rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4273 XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4276 #ifdef LIBXML_PATTERN_ENABLED
4277 #ifdef LIBXML_READER_ENABLED
4278 { "Pattern regression tests" ,
4279 patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
4283 #ifdef LIBXML_C14N_ENABLED
4284 { "C14N with comments regression tests" ,
4285 c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
4287 { "C14N without comments regression tests" ,
4288 c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
4290 { "C14N exclusive without comments regression tests" ,
4291 c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
4293 { "C14N 1.1 without comments regression tests" ,
4294 c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL,
4297 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_SAX1_ENABLED)
4298 { "Catalog and Threads regression tests" ,
4299 threadsTest, NULL, NULL, NULL, NULL,
4302 {NULL, NULL, NULL, NULL, NULL, NULL, 0}
4305 /************************************************************************
4307 * The main code driving the tests *
4309 ************************************************************************/
4312 launchTests(testDescPtr tst) {
4313 int res = 0, err = 0;
4319 if (tst == NULL) return(-1);
4320 if (tst->in != NULL) {
4323 globbuf.gl_offs = 0;
4324 glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
4325 for (i = 0;i < globbuf.gl_pathc;i++) {
4326 if (!checkTestFile(globbuf.gl_pathv[i]))
4328 if (tst->suffix != NULL) {
4329 result = resultFilename(globbuf.gl_pathv[i], tst->out,
4331 if (result == NULL) {
4332 fprintf(stderr, "Out of memory !\n");
4338 if (tst->err != NULL) {
4339 error = resultFilename(globbuf.gl_pathv[i], tst->out,
4341 if (error == NULL) {
4342 fprintf(stderr, "Out of memory !\n");
4348 if ((result) &&(!checkTestFile(result))) {
4349 fprintf(stderr, "Missing result file %s\n", result);
4350 } else if ((error) &&(!checkTestFile(error))) {
4351 fprintf(stderr, "Missing error file %s\n", error);
4354 extraMemoryFromResolver = 0;
4357 res = tst->func(globbuf.gl_pathv[i], result, error,
4358 tst->options | XML_PARSE_COMPACT);
4359 xmlResetLastError();
4361 fprintf(stderr, "File %s generated an error\n",
4362 globbuf.gl_pathv[i]);
4366 else if (xmlMemUsed() != mem) {
4367 if ((xmlMemUsed() != mem) &&
4368 (extraMemoryFromResolver == 0)) {
4369 fprintf(stderr, "File %s leaked %d bytes\n",
4370 globbuf.gl_pathv[i], xmlMemUsed() - mem);
4386 extraMemoryFromResolver = 0;
4387 res = tst->func(NULL, NULL, NULL, tst->options);
4396 static int verbose = 0;
4397 static int tests_quiet = 0;
4402 int old_errors, old_tests, old_leaks;
4404 old_errors = nb_errors;
4405 old_tests = nb_tests;
4406 old_leaks = nb_leaks;
4407 if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
4408 printf("## %s\n", testDescriptions[i].desc);
4409 res = launchTests(&testDescriptions[i]);
4413 if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
4414 printf("Ran %d tests, no errors\n", nb_tests - old_tests);
4416 printf("Ran %d tests, %d errors, %d leaks\n",
4417 nb_tests - old_tests,
4418 nb_errors - old_errors,
4419 nb_leaks - old_leaks);
4425 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4429 initializeLibxml2();
4431 for (a = 1; a < argc;a++) {
4432 if (!strcmp(argv[a], "-v"))
4434 else if (!strcmp(argv[a], "-quiet"))
4437 for (i = 0; testDescriptions[i].func != NULL; i++) {
4438 if (strstr(testDescriptions[i].desc, argv[a])) {
4446 for (i = 0; testDescriptions[i].func != NULL; i++) {
4450 if ((nb_errors == 0) && (nb_leaks == 0)) {
4452 printf("Total %d tests, no errors\n",
4456 printf("Total %d tests, %d errors, %d leaks\n",
4457 nb_tests, nb_errors, nb_leaks);
4465 #else /* ! LIBXML_OUTPUT_ENABLED */
4467 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4468 fprintf(stderr, "runtest requires output to be enabled in libxml2\n");