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
85 #define RD_FLAGS O_RDONLY
88 typedef int (*functest) (const char *filename, const char *result,
89 const char *error, int options);
91 typedef struct testDesc testDesc;
92 typedef testDesc *testDescPtr;
94 const char *desc; /* descripton of the test */
95 functest func; /* function implementing the test */
96 const char *in; /* glob to path for input files */
97 const char *out; /* output directory */
98 const char *suffix;/* suffix for output files */
99 const char *err; /* suffix for error output files */
100 int options; /* parser options for the test */
103 static int checkTestFile(const char *filename);
105 #if defined(_WIN32) && !defined(__CYGWIN__)
112 size_t gl_pathc; /* Count of paths matched so far */
113 char **gl_pathv; /* List of matched pathnames. */
114 size_t gl_offs; /* Slots to reserve in 'gl_pathv'. */
117 #define GLOB_DOOFFS 0
118 static int glob(const char *pattern, int flags,
119 int errfunc(const char *epath, int eerrno),
122 WIN32_FIND_DATA FindFileData;
124 unsigned int nb_paths = 0;
128 if ((pattern == NULL) || (pglob == NULL)) return(-1);
130 strncpy(directory, pattern, 499);
131 for (len = strlen(directory);len >= 0;len--) {
132 if (directory[len] == '/') {
143 memset(ret, 0, sizeof(glob_t));
145 hFind = FindFirstFileA(pattern, &FindFileData);
146 if (hFind == INVALID_HANDLE_VALUE)
149 ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
150 if (ret->gl_pathv == NULL) {
154 strncpy(directory + len, FindFileData.cFileName, 499 - len);
155 ret->gl_pathv[ret->gl_pathc] = strdup(directory);
156 if (ret->gl_pathv[ret->gl_pathc] == NULL)
159 while(FindNextFileA(hFind, &FindFileData)) {
160 if (FindFileData.cFileName[0] == '.')
162 if (ret->gl_pathc + 2 > nb_paths) {
163 char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
169 strncpy(directory + len, FindFileData.cFileName, 499 - len);
170 ret->gl_pathv[ret->gl_pathc] = strdup(directory);
171 if (ret->gl_pathv[ret->gl_pathc] == NULL)
175 ret->gl_pathv[ret->gl_pathc] = NULL;
184 static void globfree(glob_t *pglob) {
189 for (i = 0;i < pglob->gl_pathc;i++) {
190 if (pglob->gl_pathv[i] != NULL)
191 free(pglob->gl_pathv[i]);
199 /************************************************************************
201 * Libxml2 specific routines *
203 ************************************************************************/
205 static int nb_tests = 0;
206 static int nb_errors = 0;
207 static int nb_leaks = 0;
208 static int extraMemoryFromResolver = 0;
212 fprintf(stderr, "Exitting tests on fatal error\n");
217 * We need to trap calls to the resolver to not account memory for the catalog
218 * which is shared to the current running test. We also don't want to have
219 * network downloads modifying tests.
221 static xmlParserInputPtr
222 testExternalEntityLoader(const char *URL, const char *ID,
223 xmlParserCtxtPtr ctxt) {
224 xmlParserInputPtr ret;
226 if (checkTestFile(URL)) {
227 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
229 int memused = xmlMemUsed();
230 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
231 extraMemoryFromResolver += xmlMemUsed() - memused;
238 * Trapping the error messages at the generic level to grab the equivalent of
239 * stderr messages on CLI tools.
241 static char testErrors[32769];
242 static int testErrorsSize = 0;
245 testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
249 if (testErrorsSize >= 32768)
252 res = vsnprintf(&testErrors[testErrorsSize],
253 32768 - testErrorsSize,
256 if (testErrorsSize + res >= 32768) {
258 testErrorsSize = 32768;
259 testErrors[testErrorsSize] = 0;
261 testErrorsSize += res;
263 testErrors[testErrorsSize] = 0;
267 channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
271 if (testErrorsSize >= 32768)
274 res = vsnprintf(&testErrors[testErrorsSize],
275 32768 - testErrorsSize,
278 if (testErrorsSize + res >= 32768) {
280 testErrorsSize = 32768;
281 testErrors[testErrorsSize] = 0;
283 testErrorsSize += res;
285 testErrors[testErrorsSize] = 0;
289 * xmlParserPrintFileContext:
290 * @input: an xmlParserInputPtr input
292 * Displays current context within the input content for error tracking
296 xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
297 xmlGenericErrorFunc chanl, void *data ) {
298 const xmlChar *cur, *base;
299 unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
300 xmlChar content[81]; /* space for 80 chars + line terminator */
303 if (input == NULL) return;
306 /* skip backwards over any end-of-lines */
307 while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
311 /* search backwards for beginning-of-line (to max buff size) */
312 while ((n++ < (sizeof(content)-1)) && (cur > base) &&
313 (*(cur) != '\n') && (*(cur) != '\r'))
315 if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
316 /* calculate the error position in terms of the current position */
317 col = input->cur - cur;
318 /* search forward for end-of-line (to max buff size) */
321 /* copy selected text to our buffer */
322 while ((*cur != 0) && (*(cur) != '\n') &&
323 (*(cur) != '\r') && (n < sizeof(content)-1)) {
328 /* print out the selected text */
329 chanl(data ,"%s\n", content);
330 /* create blank line with problem pointer */
333 /* (leave buffer space for pointer + line terminator) */
334 while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
341 chanl(data ,"%s\n", content);
345 testStructuredErrorHandler(void *ctx ATTRIBUTE_UNUSED, xmlErrorPtr err) {
352 const xmlChar *name = NULL;
355 xmlParserInputPtr input = NULL;
356 xmlParserInputPtr cur = NULL;
357 xmlParserCtxtPtr ctxt = NULL;
365 domain = err->domain;
368 if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
369 (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
370 (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
375 if (code == XML_ERR_OK)
378 if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
382 * Maintain the compatibility with the legacy error handling
386 if ((input != NULL) && (input->filename == NULL) &&
387 (ctxt->inputNr > 1)) {
389 input = ctxt->inputTab[ctxt->inputNr - 2];
393 channel(data, "%s:%d: ", input->filename, input->line);
394 else if ((line != 0) && (domain == XML_FROM_PARSER))
395 channel(data, "Entity: line %d: ", input->line);
399 channel(data, "%s:%d: ", file, line);
400 else if ((line != 0) && (domain == XML_FROM_PARSER))
401 channel(data, "Entity: line %d: ", line);
404 channel(data, "element %s: ", name);
406 if (code == XML_ERR_OK)
409 case XML_FROM_PARSER:
410 channel(data, "parser ");
412 case XML_FROM_NAMESPACE:
413 channel(data, "namespace ");
417 channel(data, "validity ");
420 channel(data, "HTML parser ");
422 case XML_FROM_MEMORY:
423 channel(data, "memory ");
425 case XML_FROM_OUTPUT:
426 channel(data, "output ");
429 channel(data, "I/O ");
431 case XML_FROM_XINCLUDE:
432 channel(data, "XInclude ");
435 channel(data, "XPath ");
437 case XML_FROM_XPOINTER:
438 channel(data, "parser ");
440 case XML_FROM_REGEXP:
441 channel(data, "regexp ");
443 case XML_FROM_MODULE:
444 channel(data, "module ");
446 case XML_FROM_SCHEMASV:
447 channel(data, "Schemas validity ");
449 case XML_FROM_SCHEMASP:
450 channel(data, "Schemas parser ");
452 case XML_FROM_RELAXNGP:
453 channel(data, "Relax-NG parser ");
455 case XML_FROM_RELAXNGV:
456 channel(data, "Relax-NG validity ");
458 case XML_FROM_CATALOG:
459 channel(data, "Catalog ");
462 channel(data, "C14N ");
465 channel(data, "XSLT ");
470 if (code == XML_ERR_OK)
476 case XML_ERR_WARNING:
477 channel(data, "warning : ");
480 channel(data, "error : ");
483 channel(data, "error : ");
486 if (code == XML_ERR_OK)
490 len = xmlStrlen((const xmlChar *)str);
491 if ((len > 0) && (str[len - 1] != '\n'))
492 channel(data, "%s\n", str);
494 channel(data, "%s", str);
496 channel(data, "%s\n", "out of memory error");
498 if (code == XML_ERR_OK)
502 xmlParserPrintFileContextInternal(input, channel, data);
505 channel(data, "%s:%d: \n", cur->filename, cur->line);
506 else if ((line != 0) && (domain == XML_FROM_PARSER))
507 channel(data, "Entity: line %d: \n", cur->line);
508 xmlParserPrintFileContextInternal(cur, channel, data);
511 if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
513 (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
517 channel(data, "%s\n", err->str1);
518 for (i=0;i < err->int1;i++)
522 channel(data, "%s\n", buf);
527 initializeLibxml2(void) {
528 xmlGetWarningsDefaultValue = 0;
529 xmlPedanticParserDefault(0);
531 xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
533 xmlSetExternalEntityLoader(testExternalEntityLoader);
534 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
535 #ifdef LIBXML_SCHEMAS_ENABLED
536 xmlSchemaInitTypes();
537 xmlRelaxNGInitTypes();
542 /************************************************************************
544 * File name and path utilities *
546 ************************************************************************/
548 static const char *baseFilename(const char *filename) {
550 if (filename == NULL)
552 cur = &filename[strlen(filename)];
553 while ((cur > filename) && (*cur != '/'))
560 static char *resultFilename(const char *filename, const char *out,
561 const char *suffix) {
564 char suffixbuff[500];
567 if ((filename[0] == 't') && (filename[1] == 'e') &&
568 (filename[2] == 's') && (filename[3] == 't') &&
569 (filename[4] == '/'))
570 filename = &filename[5];
573 base = baseFilename(filename);
579 strncpy(suffixbuff,suffix,499);
581 if(strstr(base,".") && suffixbuff[0]=='.')
585 snprintf(res, 499, "%s%s%s", out, base, suffixbuff);
590 static int checkTestFile(const char *filename) {
593 if (stat(filename, &buf) == -1)
596 #if defined(_WIN32) && !defined(__CYGWIN__)
597 if (!(buf.st_mode & _S_IFREG))
600 if (!S_ISREG(buf.st_mode))
607 static int compareFiles(const char *r1, const char *r2) {
613 fd1 = open(r1, RD_FLAGS);
616 fd2 = open(r2, RD_FLAGS);
622 res1 = read(fd1, bytes1, 4096);
623 res2 = read(fd2, bytes2, 4096);
624 if ((res1 != res2) || (res1 < 0)) {
631 if (memcmp(bytes1, bytes2, res1) != 0) {
642 static int compareFileMem(const char *filename, const char *mem, int size) {
649 if (stat(filename, &info) < 0)
651 if (info.st_size != size)
653 fd = open(filename, RD_FLAGS);
657 res = read(fd, bytes, 4096);
660 if (res + idx > size)
662 if (memcmp(bytes, &mem[idx], res) != 0) {
664 for (ix=0; ix<res; ix++)
665 if (bytes[ix] != mem[idx+ix])
667 fprintf(stderr,"Compare error at position %d\n", idx+ix);
677 static int loadMem(const char *filename, const char **mem, int *size) {
682 if (stat(filename, &info) < 0)
684 base = malloc(info.st_size + 1);
687 if ((fd = open(filename, RD_FLAGS)) < 0) {
691 while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
696 if (siz != info.st_size) {
707 static int unloadMem(const char *mem) {
712 /************************************************************************
714 * Tests implementations *
716 ************************************************************************/
718 /************************************************************************
720 * Parse to SAX based tests *
722 ************************************************************************/
724 static FILE *SAXdebug = NULL;
729 static xmlSAXHandler emptySAXHandlerStruct = {
730 NULL, /* internalSubset */
731 NULL, /* isStandalone */
732 NULL, /* hasInternalSubset */
733 NULL, /* hasExternalSubset */
734 NULL, /* resolveEntity */
735 NULL, /* getEntity */
736 NULL, /* entityDecl */
737 NULL, /* notationDecl */
738 NULL, /* attributeDecl */
739 NULL, /* elementDecl */
740 NULL, /* unparsedEntityDecl */
741 NULL, /* setDocumentLocator */
742 NULL, /* startDocument */
743 NULL, /* endDocument */
744 NULL, /* startElement */
745 NULL, /* endElement */
746 NULL, /* reference */
747 NULL, /* characters */
748 NULL, /* ignorableWhitespace */
749 NULL, /* processingInstruction */
751 NULL, /* xmlParserWarning */
752 NULL, /* xmlParserError */
753 NULL, /* xmlParserError */
754 NULL, /* getParameterEntity */
755 NULL, /* cdataBlock; */
756 NULL, /* externalSubset; */
759 NULL, /* startElementNs */
760 NULL, /* endElementNs */
761 NULL /* xmlStructuredErrorFunc */
764 static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
765 static int callbacks = 0;
766 static int quiet = 0;
770 * @ctxt: An XML parser context
772 * Is this document tagged standalone ?
777 isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
782 fprintf(SAXdebug, "SAX.isStandalone()\n");
787 * hasInternalSubsetDebug:
788 * @ctxt: An XML parser context
790 * Does this document has an internal subset
795 hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
800 fprintf(SAXdebug, "SAX.hasInternalSubset()\n");
805 * hasExternalSubsetDebug:
806 * @ctxt: An XML parser context
808 * Does this document has an external subset
813 hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
818 fprintf(SAXdebug, "SAX.hasExternalSubset()\n");
823 * internalSubsetDebug:
824 * @ctxt: An XML parser context
826 * Does this document has an internal subset
829 internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
830 const xmlChar *ExternalID, const xmlChar *SystemID)
835 fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
836 if (ExternalID == NULL)
837 fprintf(SAXdebug, " ,");
839 fprintf(SAXdebug, " %s,", ExternalID);
840 if (SystemID == NULL)
841 fprintf(SAXdebug, " )\n");
843 fprintf(SAXdebug, " %s)\n", SystemID);
847 * externalSubsetDebug:
848 * @ctxt: An XML parser context
850 * Does this document has an external subset
853 externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
854 const xmlChar *ExternalID, const xmlChar *SystemID)
859 fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
860 if (ExternalID == NULL)
861 fprintf(SAXdebug, " ,");
863 fprintf(SAXdebug, " %s,", ExternalID);
864 if (SystemID == NULL)
865 fprintf(SAXdebug, " )\n");
867 fprintf(SAXdebug, " %s)\n", SystemID);
871 * resolveEntityDebug:
872 * @ctxt: An XML parser context
873 * @publicId: The public ID of the entity
874 * @systemId: The system ID of the entity
876 * Special entity resolver, better left to the parser, it has
877 * more context than the application layer.
878 * The default behaviour is to NOT resolve the entities, in that case
879 * the ENTITY_REF nodes are built in the structure (and the parameter
882 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
884 static xmlParserInputPtr
885 resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
890 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
893 fprintf(SAXdebug, "SAX.resolveEntity(");
894 if (publicId != NULL)
895 fprintf(SAXdebug, "%s", (char *)publicId);
897 fprintf(SAXdebug, " ");
898 if (systemId != NULL)
899 fprintf(SAXdebug, ", %s)\n", (char *)systemId);
901 fprintf(SAXdebug, ", )\n");
903 if (systemId != NULL) {
904 return(xmlNewInputFromFile(ctxt, (char *) systemId));
912 * @ctxt: An XML parser context
913 * @name: The entity name
915 * Get an entity by name
917 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
920 getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
925 fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
930 * getParameterEntityDebug:
931 * @ctxt: An XML parser context
932 * @name: The entity name
934 * Get a parameter entity by name
936 * Returns the xmlParserInputPtr
939 getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
944 fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
951 * @ctxt: An XML parser context
952 * @name: the entity name
953 * @type: the entity type
954 * @publicId: The public ID of the entity
955 * @systemId: The system ID of the entity
956 * @content: the entity value (without processing).
958 * An entity definition has been parsed
961 entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
962 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
964 const xmlChar *nullstr = BAD_CAST "(null)";
965 /* not all libraries handle printing null pointers nicely */
966 if (publicId == NULL)
968 if (systemId == NULL)
971 content = (xmlChar *)nullstr;
975 fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
976 name, type, publicId, systemId, content);
980 * attributeDeclDebug:
981 * @ctxt: An XML parser context
982 * @name: the attribute name
983 * @type: the attribute type
985 * An attribute definition has been parsed
988 attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
989 const xmlChar * name, int type, int def,
990 const xmlChar * defaultValue, xmlEnumerationPtr tree)
995 if (defaultValue == NULL)
996 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
997 elem, name, type, def);
999 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
1000 elem, name, type, def, defaultValue);
1001 xmlFreeEnumeration(tree);
1006 * @ctxt: An XML parser context
1007 * @name: the element name
1008 * @type: the element type
1009 * @content: the element value (without processing).
1011 * An element definition has been parsed
1014 elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1015 xmlElementContentPtr content ATTRIBUTE_UNUSED)
1020 fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n",
1025 * notationDeclDebug:
1026 * @ctxt: An XML parser context
1027 * @name: The name of the notation
1028 * @publicId: The public ID of the entity
1029 * @systemId: The system ID of the entity
1031 * What to do when a notation declaration has been parsed.
1034 notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1035 const xmlChar *publicId, const xmlChar *systemId)
1040 fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n",
1041 (char *) name, (char *) publicId, (char *) systemId);
1045 * unparsedEntityDeclDebug:
1046 * @ctxt: An XML parser context
1047 * @name: The name of the entity
1048 * @publicId: The public ID of the entity
1049 * @systemId: The system ID of the entity
1050 * @notationName: the name of the notation
1052 * What to do when an unparsed entity declaration is parsed
1055 unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1056 const xmlChar *publicId, const xmlChar *systemId,
1057 const xmlChar *notationName)
1059 const xmlChar *nullstr = BAD_CAST "(null)";
1061 if (publicId == NULL)
1063 if (systemId == NULL)
1065 if (notationName == NULL)
1066 notationName = nullstr;
1070 fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
1071 (char *) name, (char *) publicId, (char *) systemId,
1072 (char *) notationName);
1076 * setDocumentLocatorDebug:
1077 * @ctxt: An XML parser context
1078 * @loc: A SAX Locator
1080 * Receive the document locator at startup, actually xmlDefaultSAXLocator
1081 * Everything is available on the context, so this is useless in our case.
1084 setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
1089 fprintf(SAXdebug, "SAX.setDocumentLocator()\n");
1093 * startDocumentDebug:
1094 * @ctxt: An XML parser context
1096 * called when the document start being processed.
1099 startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1104 fprintf(SAXdebug, "SAX.startDocument()\n");
1109 * @ctxt: An XML parser context
1111 * called when the document end has been detected.
1114 endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1119 fprintf(SAXdebug, "SAX.endDocument()\n");
1123 * startElementDebug:
1124 * @ctxt: An XML parser context
1125 * @name: The element name
1127 * called when an opening tag has been processed.
1130 startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1137 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1139 for (i = 0;(atts[i] != NULL);i++) {
1140 fprintf(SAXdebug, ", %s='", atts[i++]);
1141 if (atts[i] != NULL)
1142 fprintf(SAXdebug, "%s'", atts[i]);
1145 fprintf(SAXdebug, ")\n");
1150 * @ctxt: An XML parser context
1151 * @name: The element name
1153 * called when the end of an element has been detected.
1156 endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1161 fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name);
1166 * @ctxt: An XML parser context
1167 * @ch: a xmlChar string
1168 * @len: the number of xmlChar
1170 * receiving some chars from the parser.
1171 * Question: how much at a time ???
1174 charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1182 for (i = 0;(i<len) && (i < 30);i++)
1186 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1191 * @ctxt: An XML parser context
1192 * @name: The entity name
1194 * called when an entity reference is detected.
1197 referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1202 fprintf(SAXdebug, "SAX.reference(%s)\n", name);
1206 * ignorableWhitespaceDebug:
1207 * @ctxt: An XML parser context
1208 * @ch: a xmlChar string
1209 * @start: the first char in the string
1210 * @len: the number of xmlChar
1212 * receiving some ignorable whitespaces from the parser.
1213 * Question: how much at a time ???
1216 ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1224 for (i = 0;(i<len) && (i < 30);i++)
1227 fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
1231 * processingInstructionDebug:
1232 * @ctxt: An XML parser context
1233 * @target: the target name
1234 * @data: the PI data's
1235 * @len: the number of xmlChar
1237 * A processing instruction has been parsed.
1240 processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
1241 const xmlChar *data)
1247 fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
1248 (char *) target, (char *) data);
1250 fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n",
1256 * @ctx: the user data (XML parser context)
1257 * @value: The pcdata content
1258 * @len: the block length
1260 * called when a pcdata block has been parsed
1263 cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
1268 fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n",
1269 (char *) value, len);
1274 * @ctxt: An XML parser context
1275 * @value: the comment content
1277 * A comment has been parsed.
1280 commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
1285 fprintf(SAXdebug, "SAX.comment(%s)\n", value);
1290 * @ctxt: An XML parser context
1291 * @msg: the message to display/transmit
1292 * @...: extra parameters for the message display
1294 * Display and format a warning messages, gives file, line, position and
1297 static void XMLCDECL
1298 warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1305 va_start(args, msg);
1306 fprintf(SAXdebug, "SAX.warning: ");
1307 vfprintf(SAXdebug, msg, args);
1313 * @ctxt: An XML parser context
1314 * @msg: the message to display/transmit
1315 * @...: extra parameters for the message display
1317 * Display and format a error messages, gives file, line, position and
1320 static void XMLCDECL
1321 errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1328 va_start(args, msg);
1329 fprintf(SAXdebug, "SAX.error: ");
1330 vfprintf(SAXdebug, msg, args);
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 fatalError messages, gives file, line, position and
1343 static void XMLCDECL
1344 fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1351 va_start(args, msg);
1352 fprintf(SAXdebug, "SAX.fatalError: ");
1353 vfprintf(SAXdebug, msg, args);
1357 static xmlSAXHandler debugSAXHandlerStruct = {
1358 internalSubsetDebug,
1360 hasInternalSubsetDebug,
1361 hasExternalSubsetDebug,
1368 unparsedEntityDeclDebug,
1369 setDocumentLocatorDebug,
1376 ignorableWhitespaceDebug,
1377 processingInstructionDebug,
1382 getParameterEntityDebug,
1384 externalSubsetDebug,
1392 static xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
1395 * SAX2 specific callbacks
1398 * startElementNsDebug:
1399 * @ctxt: An XML parser context
1400 * @name: The element name
1402 * called when an opening tag has been processed.
1405 startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1406 const xmlChar *localname,
1407 const xmlChar *prefix,
1410 const xmlChar **namespaces,
1413 const xmlChar **attributes)
1420 fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
1422 fprintf(SAXdebug, ", NULL");
1424 fprintf(SAXdebug, ", %s", (char *) prefix);
1426 fprintf(SAXdebug, ", NULL");
1428 fprintf(SAXdebug, ", '%s'", (char *) URI);
1429 fprintf(SAXdebug, ", %d", nb_namespaces);
1431 if (namespaces != NULL) {
1432 for (i = 0;i < nb_namespaces * 2;i++) {
1433 fprintf(SAXdebug, ", xmlns");
1434 if (namespaces[i] != NULL)
1435 fprintf(SAXdebug, ":%s", namespaces[i]);
1437 fprintf(SAXdebug, "='%s'", namespaces[i]);
1440 fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
1441 if (attributes != NULL) {
1442 for (i = 0;i < nb_attributes * 5;i += 5) {
1443 if (attributes[i + 1] != NULL)
1444 fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
1446 fprintf(SAXdebug, ", %s='", attributes[i]);
1447 fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
1448 (int)(attributes[i + 4] - attributes[i + 3]));
1451 fprintf(SAXdebug, ")\n");
1456 * @ctxt: An XML parser context
1457 * @name: The element name
1459 * called when the end of an element has been detected.
1462 endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1463 const xmlChar *localname,
1464 const xmlChar *prefix,
1470 fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
1472 fprintf(SAXdebug, ", NULL");
1474 fprintf(SAXdebug, ", %s", (char *) prefix);
1476 fprintf(SAXdebug, ", NULL)\n");
1478 fprintf(SAXdebug, ", '%s')\n", (char *) URI);
1481 static xmlSAXHandler debugSAX2HandlerStruct = {
1482 internalSubsetDebug,
1484 hasInternalSubsetDebug,
1485 hasExternalSubsetDebug,
1492 unparsedEntityDeclDebug,
1493 setDocumentLocatorDebug,
1500 ignorableWhitespaceDebug,
1501 processingInstructionDebug,
1506 getParameterEntityDebug,
1508 externalSubsetDebug,
1511 startElementNsDebug,
1516 static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
1518 #ifdef LIBXML_HTML_ENABLED
1520 * htmlstartElementDebug:
1521 * @ctxt: An XML parser context
1522 * @name: The element name
1524 * called when an opening tag has been processed.
1527 htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1531 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1533 for (i = 0;(atts[i] != NULL);i++) {
1534 fprintf(SAXdebug, ", %s", atts[i++]);
1535 if (atts[i] != NULL) {
1536 unsigned char output[40];
1537 const unsigned char *att = atts[i];
1539 fprintf(SAXdebug, "='");
1540 while ((attlen = strlen((char*)att)) > 0) {
1541 outlen = sizeof output - 1;
1542 htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
1544 fprintf(SAXdebug, "%s", (char *) output);
1547 fprintf(SAXdebug, "'");
1551 fprintf(SAXdebug, ")\n");
1555 * htmlcharactersDebug:
1556 * @ctxt: An XML parser context
1557 * @ch: a xmlChar string
1558 * @len: the number of xmlChar
1560 * receiving some chars from the parser.
1561 * Question: how much at a time ???
1564 htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1566 unsigned char output[40];
1567 int inlen = len, outlen = 30;
1569 htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1572 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1577 * @ctxt: An XML parser context
1578 * @ch: a xmlChar string
1579 * @len: the number of xmlChar
1581 * receiving some cdata chars from the parser.
1582 * Question: how much at a time ???
1585 htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1587 unsigned char output[40];
1588 int inlen = len, outlen = 30;
1590 htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1593 fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
1596 static xmlSAXHandler debugHTMLSAXHandlerStruct = {
1597 internalSubsetDebug,
1599 hasInternalSubsetDebug,
1600 hasExternalSubsetDebug,
1607 unparsedEntityDeclDebug,
1608 setDocumentLocatorDebug,
1611 htmlstartElementDebug,
1614 htmlcharactersDebug,
1615 ignorableWhitespaceDebug,
1616 processingInstructionDebug,
1621 getParameterEntityDebug,
1623 externalSubsetDebug,
1631 static xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
1632 #endif /* LIBXML_HTML_ENABLED */
1634 #ifdef LIBXML_SAX1_ENABLED
1637 * @filename: the file to parse
1638 * @result: the file with expected result
1639 * @err: the file with error messages
1641 * Parse a file using the SAX API and check for errors.
1643 * Returns 0 in case of success, an error code otherwise
1646 saxParseTest(const char *filename, const char *result,
1647 const char *err ATTRIBUTE_UNUSED,
1653 temp = resultFilename(filename, "", ".res");
1655 fprintf(stderr, "out of memory\n");
1658 SAXdebug = fopen(temp, "wb");
1659 if (SAXdebug == NULL) {
1660 fprintf(stderr, "Failed to write to %s\n", temp);
1665 /* for SAX we really want the callbacks though the context handlers */
1666 xmlSetStructuredErrorFunc(NULL, NULL);
1667 xmlSetGenericErrorFunc(NULL, testErrorHandler);
1669 #ifdef LIBXML_HTML_ENABLED
1670 if (options & XML_PARSE_HTML) {
1671 htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);
1675 ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
1676 if (ret == XML_WAR_UNDECLARED_ENTITY) {
1677 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1681 fprintf(stderr, "Failed to parse %s\n", filename);
1684 #ifdef LIBXML_HTML_ENABLED
1685 if (options & XML_PARSE_HTML) {
1686 htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
1690 if (options & XML_PARSE_SAX1) {
1691 ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
1693 ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
1695 if (ret == XML_WAR_UNDECLARED_ENTITY) {
1696 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1700 if (compareFiles(temp, result)) {
1701 fprintf(stderr, "Got a difference for %s\n", filename);
1709 /* switch back to structured error handling */
1710 xmlSetGenericErrorFunc(NULL, NULL);
1711 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
1717 /************************************************************************
1719 * Parse to tree based tests *
1721 ************************************************************************/
1724 * @filename: the file to parse
1725 * @result: the file with expected result
1726 * @err: the file with error messages: unused
1728 * Parse a file using the old xmlParseFile API, then serialize back
1729 * reparse the result and serialize again, then check for deviation
1732 * Returns 0 in case of success, an error code otherwise
1735 oldParseTest(const char *filename, const char *result,
1736 const char *err ATTRIBUTE_UNUSED,
1737 int options ATTRIBUTE_UNUSED) {
1744 * base of the test, parse with the old API
1746 #ifdef LIBXML_SAX1_ENABLED
1747 doc = xmlParseFile(filename);
1749 doc = xmlReadFile(filename, NULL, 0);
1753 temp = resultFilename(filename, "", ".res");
1755 fprintf(stderr, "out of memory\n");
1758 xmlSaveFile(temp, doc);
1759 if (compareFiles(temp, result)) {
1765 * Parse the saved result to make sure the round trip is okay
1767 #ifdef LIBXML_SAX1_ENABLED
1768 doc = xmlParseFile(temp);
1770 doc = xmlReadFile(temp, NULL, 0);
1774 xmlSaveFile(temp, doc);
1775 if (compareFiles(temp, result)) {
1787 #ifdef LIBXML_PUSH_ENABLED
1790 * @filename: the file to parse
1791 * @result: the file with expected result
1792 * @err: the file with error messages: unused
1794 * Parse a file using the Push API, then serialize back
1795 * to check for content.
1797 * Returns 0 in case of success, an error code otherwise
1800 pushParseTest(const char *filename, const char *result,
1801 const char *err ATTRIBUTE_UNUSED,
1803 xmlParserCtxtPtr ctxt;
1811 * load the document in memory and work from there.
1813 if (loadMem(filename, &base, &size) != 0) {
1814 fprintf(stderr, "Failed to load %s\n", filename);
1818 #ifdef LIBXML_HTML_ENABLED
1819 if (options & XML_PARSE_HTML)
1820 ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,
1821 XML_CHAR_ENCODING_NONE);
1824 ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
1825 xmlCtxtUseOptions(ctxt, options);
1827 while (cur < size) {
1828 if (cur + 1024 >= size) {
1829 #ifdef LIBXML_HTML_ENABLED
1830 if (options & XML_PARSE_HTML)
1831 htmlParseChunk(ctxt, base + cur, size - cur, 1);
1834 xmlParseChunk(ctxt, base + cur, size - cur, 1);
1837 #ifdef LIBXML_HTML_ENABLED
1838 if (options & XML_PARSE_HTML)
1839 htmlParseChunk(ctxt, base + cur, 1024, 0);
1842 xmlParseChunk(ctxt, base + cur, 1024, 0);
1847 #ifdef LIBXML_HTML_ENABLED
1848 if (options & XML_PARSE_HTML)
1852 res = ctxt->wellFormed;
1853 xmlFreeParserCtxt(ctxt);
1857 fprintf(stderr, "Failed to parse %s\n", filename);
1860 #ifdef LIBXML_HTML_ENABLED
1861 if (options & XML_PARSE_HTML)
1862 htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1865 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1867 res = compareFileMem(result, base, size);
1868 if ((base == NULL) || (res != 0)) {
1870 xmlFree((char *)base);
1871 fprintf(stderr, "Result for %s failed\n", filename);
1874 xmlFree((char *)base);
1876 res = compareFileMem(err, testErrors, testErrorsSize);
1878 fprintf(stderr, "Error for %s failed\n", filename);
1888 * @filename: the file to parse
1889 * @result: the file with expected result
1890 * @err: the file with error messages: unused
1892 * Parse a file using the old xmlReadMemory API, then serialize back
1893 * reparse the result and serialize again, then check for deviation
1896 * Returns 0 in case of success, an error code otherwise
1899 memParseTest(const char *filename, const char *result,
1900 const char *err ATTRIBUTE_UNUSED,
1901 int options ATTRIBUTE_UNUSED) {
1908 * load and parse the memory
1910 if (loadMem(filename, &base, &size) != 0) {
1911 fprintf(stderr, "Failed to load %s\n", filename);
1915 doc = xmlReadMemory(base, size, filename, NULL, 0);
1920 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1922 res = compareFileMem(result, base, size);
1923 if ((base == NULL) || (res != 0)) {
1925 xmlFree((char *)base);
1926 fprintf(stderr, "Result for %s failed\n", filename);
1929 xmlFree((char *)base);
1935 * @filename: the file to parse
1936 * @result: the file with expected result
1937 * @err: the file with error messages: unused
1939 * Parse a file with entity resolution, then serialize back
1940 * reparse the result and serialize again, then check for deviation
1943 * Returns 0 in case of success, an error code otherwise
1946 noentParseTest(const char *filename, const char *result,
1947 const char *err ATTRIBUTE_UNUSED,
1955 * base of the test, parse with the old API
1957 doc = xmlReadFile(filename, NULL, options);
1960 temp = resultFilename(filename, "", ".res");
1962 fprintf(stderr, "Out of memory\n");
1965 xmlSaveFile(temp, doc);
1966 if (compareFiles(temp, result)) {
1972 * Parse the saved result to make sure the round trip is okay
1974 doc = xmlReadFile(filename, NULL, options);
1977 xmlSaveFile(temp, doc);
1978 if (compareFiles(temp, result)) {
1992 * @filename: the file to parse
1993 * @result: the file with expected result
1994 * @err: the file with error messages
1996 * Parse a file using the xmlReadFile API and check for errors.
1998 * Returns 0 in case of success, an error code otherwise
2001 errParseTest(const char *filename, const char *result, const char *err,
2004 const char *base = NULL;
2008 #ifdef LIBXML_HTML_ENABLED
2009 if (options & XML_PARSE_HTML) {
2010 doc = htmlReadFile(filename, NULL, options);
2013 #ifdef LIBXML_XINCLUDE_ENABLED
2014 if (options & XML_PARSE_XINCLUDE) {
2015 doc = xmlReadFile(filename, NULL, options);
2016 xmlXIncludeProcessFlags(doc, options);
2020 xmlGetWarningsDefaultValue = 1;
2021 doc = xmlReadFile(filename, NULL, options);
2023 xmlGetWarningsDefaultValue = 0;
2029 #ifdef LIBXML_HTML_ENABLED
2030 if (options & XML_PARSE_HTML) {
2031 htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2034 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2036 res = compareFileMem(result, base, size);
2040 xmlFree((char *)base);
2044 fprintf(stderr, "Result for %s failed\n", filename);
2048 res = compareFileMem(err, testErrors, testErrorsSize);
2050 fprintf(stderr, "Error for %s failed\n", filename);
2053 } else if (options & XML_PARSE_DTDVALID) {
2054 if (testErrorsSize != 0)
2055 fprintf(stderr, "Validation for %s failed\n", filename);
2061 #ifdef LIBXML_READER_ENABLED
2062 /************************************************************************
2064 * Reader based tests *
2066 ************************************************************************/
2068 static void processNode(FILE *out, xmlTextReaderPtr reader) {
2069 const xmlChar *name, *value;
2072 type = xmlTextReaderNodeType(reader);
2073 empty = xmlTextReaderIsEmptyElement(reader);
2075 name = xmlTextReaderConstName(reader);
2077 name = BAD_CAST "--";
2079 value = xmlTextReaderConstValue(reader);
2082 fprintf(out, "%d %d %s %d %d",
2083 xmlTextReaderDepth(reader),
2087 xmlTextReaderHasValue(reader));
2091 fprintf(out, " %s\n", value);
2095 streamProcessTest(const char *filename, const char *result, const char *err,
2096 xmlTextReaderPtr reader, const char *rng, int options) {
2105 if (result != NULL) {
2106 temp = resultFilename(filename, "", ".res");
2108 fprintf(stderr, "Out of memory\n");
2111 t = fopen(temp, "wb");
2113 fprintf(stderr, "Can't open temp file %s\n", temp);
2118 #ifdef LIBXML_SCHEMAS_ENABLED
2120 ret = xmlTextReaderRelaxNGValidate(reader, rng);
2122 testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
2133 xmlGetWarningsDefaultValue = 1;
2134 ret = xmlTextReaderRead(reader);
2136 if ((t != NULL) && (rng == NULL))
2137 processNode(t, reader);
2138 ret = xmlTextReaderRead(reader);
2141 testErrorHandler(NULL, "%s : failed to parse\n", filename);
2144 if (xmlTextReaderIsValid(reader) != 1) {
2145 testErrorHandler(NULL, "%s fails to validate\n", filename);
2147 testErrorHandler(NULL, "%s validates\n", filename);
2150 xmlGetWarningsDefaultValue = 0;
2153 ret = compareFiles(temp, result);
2159 fprintf(stderr, "Result for %s failed\n", filename);
2164 ret = compareFileMem(err, testErrors, testErrorsSize);
2166 fprintf(stderr, "Error for %s failed\n", filename);
2167 printf("%s", testErrors);
2177 * @filename: the file to parse
2178 * @result: the file with expected result
2179 * @err: the file with error messages
2181 * Parse a file using the reader API and check for errors.
2183 * Returns 0 in case of success, an error code otherwise
2186 streamParseTest(const char *filename, const char *result, const char *err,
2188 xmlTextReaderPtr reader;
2191 reader = xmlReaderForFile(filename, NULL, options);
2192 ret = streamProcessTest(filename, result, err, reader, NULL, options);
2193 xmlFreeTextReader(reader);
2199 * @filename: the file to parse
2200 * @result: the file with expected result
2201 * @err: the file with error messages
2203 * Parse a file using the walker, i.e. a reader built from a atree.
2205 * Returns 0 in case of success, an error code otherwise
2208 walkerParseTest(const char *filename, const char *result, const char *err,
2211 xmlTextReaderPtr reader;
2214 doc = xmlReadFile(filename, NULL, options);
2216 fprintf(stderr, "Failed to parse %s\n", filename);
2219 reader = xmlReaderWalker(doc);
2220 ret = streamProcessTest(filename, result, err, reader, NULL, options);
2221 xmlFreeTextReader(reader);
2227 * streamMemParseTest:
2228 * @filename: the file to parse
2229 * @result: the file with expected result
2230 * @err: the file with error messages
2232 * Parse a file using the reader API from memory and check for errors.
2234 * Returns 0 in case of success, an error code otherwise
2237 streamMemParseTest(const char *filename, const char *result, const char *err,
2239 xmlTextReaderPtr reader;
2245 * load and parse the memory
2247 if (loadMem(filename, &base, &size) != 0) {
2248 fprintf(stderr, "Failed to load %s\n", filename);
2251 reader = xmlReaderForMemory(base, size, filename, NULL, options);
2252 ret = streamProcessTest(filename, result, err, reader, NULL, options);
2254 xmlFreeTextReader(reader);
2259 #ifdef LIBXML_XPATH_ENABLED
2260 #ifdef LIBXML_DEBUG_ENABLED
2261 /************************************************************************
2263 * XPath and XPointer based tests *
2265 ************************************************************************/
2267 static FILE *xpathOutput;
2268 static xmlDocPtr xpathDocument;
2271 testXPath(const char *str, int xptr, int expr) {
2272 xmlXPathObjectPtr res;
2273 xmlXPathContextPtr ctxt;
2276 #if defined(LIBXML_XPTR_ENABLED)
2278 ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
2279 res = xmlXPtrEval(BAD_CAST str, ctxt);
2282 ctxt = xmlXPathNewContext(xpathDocument);
2283 ctxt->node = xmlDocGetRootElement(xpathDocument);
2285 res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
2287 /* res = xmlXPathEval(BAD_CAST str, ctxt); */
2288 xmlXPathCompExprPtr comp;
2290 comp = xmlXPathCompile(BAD_CAST str);
2292 res = xmlXPathCompiledEval(comp, ctxt);
2293 xmlXPathFreeCompExpr(comp);
2297 #if defined(LIBXML_XPTR_ENABLED)
2300 xmlXPathDebugDumpObject(xpathOutput, res, 0);
2301 xmlXPathFreeObject(res);
2302 xmlXPathFreeContext(ctxt);
2307 * @filename: the file to parse
2308 * @result: the file with expected result
2309 * @err: the file with error messages
2311 * Parse a file containing XPath standalone expressions and evaluate them
2313 * Returns 0 in case of success, an error code otherwise
2316 xpathCommonTest(const char *filename, const char *result,
2317 int xptr, int expr) {
2319 char expression[5000];
2323 temp = resultFilename(filename, "", ".res");
2325 fprintf(stderr, "Out of memory\n");
2328 xpathOutput = fopen(temp, "wb");
2329 if (xpathOutput == NULL) {
2330 fprintf(stderr, "failed to open output file %s\n", temp);
2335 input = fopen(filename, "rb");
2336 if (input == NULL) {
2337 xmlGenericError(xmlGenericErrorContext,
2338 "Cannot open %s for reading\n", filename);
2342 while (fgets(expression, 4500, input) != NULL) {
2343 len = strlen(expression);
2345 while ((len >= 0) &&
2346 ((expression[len] == '\n') || (expression[len] == '\t') ||
2347 (expression[len] == '\r') || (expression[len] == ' '))) len--;
2348 expression[len + 1] = 0;
2350 fprintf(xpathOutput,
2351 "\n========================\nExpression: %s\n",
2353 testXPath(expression, xptr, expr);
2358 fclose(xpathOutput);
2359 if (result != NULL) {
2360 ret = compareFiles(temp, result);
2362 fprintf(stderr, "Result for %s failed\n", filename);
2375 * @filename: the file to parse
2376 * @result: the file with expected result
2377 * @err: the file with error messages
2379 * Parse a file containing XPath standalone expressions and evaluate them
2381 * Returns 0 in case of success, an error code otherwise
2384 xpathExprTest(const char *filename, const char *result,
2385 const char *err ATTRIBUTE_UNUSED,
2386 int options ATTRIBUTE_UNUSED) {
2387 return(xpathCommonTest(filename, result, 0, 1));
2392 * @filename: the file to parse
2393 * @result: the file with expected result
2394 * @err: the file with error messages
2396 * Parse a file containing XPath expressions and evaluate them against
2397 * a set of corresponding documents.
2399 * Returns 0 in case of success, an error code otherwise
2402 xpathDocTest(const char *filename,
2403 const char *resul ATTRIBUTE_UNUSED,
2404 const char *err ATTRIBUTE_UNUSED,
2413 xpathDocument = xmlReadFile(filename, NULL,
2414 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2415 if (xpathDocument == NULL) {
2416 fprintf(stderr, "Failed to load %s\n", filename);
2420 snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
2422 globbuf.gl_offs = 0;
2423 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2424 for (i = 0;i < globbuf.gl_pathc;i++) {
2425 snprintf(result, 499, "result/XPath/tests/%s",
2426 baseFilename(globbuf.gl_pathv[i]));
2427 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
2433 xmlFreeDoc(xpathDocument);
2437 #ifdef LIBXML_XPTR_ENABLED
2440 * @filename: the file to parse
2441 * @result: the file with expected result
2442 * @err: the file with error messages
2444 * Parse a file containing XPath expressions and evaluate them against
2445 * a set of corresponding documents.
2447 * Returns 0 in case of success, an error code otherwise
2450 xptrDocTest(const char *filename,
2451 const char *resul ATTRIBUTE_UNUSED,
2452 const char *err ATTRIBUTE_UNUSED,
2461 xpathDocument = xmlReadFile(filename, NULL,
2462 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2463 if (xpathDocument == NULL) {
2464 fprintf(stderr, "Failed to load %s\n", filename);
2468 snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
2470 globbuf.gl_offs = 0;
2471 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2472 for (i = 0;i < globbuf.gl_pathc;i++) {
2473 snprintf(result, 499, "result/XPath/xptr/%s",
2474 baseFilename(globbuf.gl_pathv[i]));
2475 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
2481 xmlFreeDoc(xpathDocument);
2484 #endif /* LIBXML_XPTR_ENABLED */
2488 * @filename: the file to parse
2489 * @result: the file with expected result
2490 * @err: the file with error messages
2492 * Parse a file containing xml:id and check for errors and verify
2493 * that XPath queries will work on them as expected.
2495 * Returns 0 in case of success, an error code otherwise
2498 xmlidDocTest(const char *filename,
2507 xpathDocument = xmlReadFile(filename, NULL,
2508 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2509 if (xpathDocument == NULL) {
2510 fprintf(stderr, "Failed to load %s\n", filename);
2514 temp = resultFilename(filename, "", ".res");
2516 fprintf(stderr, "Out of memory\n");
2519 xpathOutput = fopen(temp, "wb");
2520 if (xpathOutput == NULL) {
2521 fprintf(stderr, "failed to open output file %s\n", temp);
2522 xmlFreeDoc(xpathDocument);
2527 testXPath("id('bar')", 0, 0);
2529 fclose(xpathOutput);
2530 if (result != NULL) {
2531 ret = compareFiles(temp, result);
2533 fprintf(stderr, "Result for %s failed\n", filename);
2542 xmlFreeDoc(xpathDocument);
2545 ret = compareFileMem(err, testErrors, testErrorsSize);
2547 fprintf(stderr, "Error for %s failed\n", filename);
2554 #endif /* LIBXML_DEBUG_ENABLED */
2556 /************************************************************************
2560 ************************************************************************/
2563 handleURI(const char *str, const char *base, FILE *o) {
2566 xmlChar *res = NULL;
2568 uri = xmlCreateURI();
2571 ret = xmlParseURIReference(uri, str);
2573 fprintf(o, "%s : error %d\n", str, ret);
2575 xmlNormalizeURIPath(uri->path);
2576 xmlPrintURI(o, uri);
2580 res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
2582 fprintf(o, "%s\n", (char *) res);
2585 fprintf(o, "::ERROR::\n");
2594 * @filename: the file to parse
2595 * @result: the file with expected result
2596 * @err: the file with error messages
2598 * Parse a file containing URI and check for errors
2600 * Returns 0 in case of success, an error code otherwise
2603 uriCommonTest(const char *filename,
2610 int res = 0, i, ret;
2612 temp = resultFilename(filename, "", ".res");
2614 fprintf(stderr, "Out of memory\n");
2617 o = fopen(temp, "wb");
2619 fprintf(stderr, "failed to open output file %s\n", temp);
2623 f = fopen(filename, "rb");
2625 fprintf(stderr, "failed to open input file %s\n", filename);
2636 * read one line in string buffer.
2638 if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
2642 * remove the ending spaces
2646 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
2647 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
2652 handleURI(str, base, o);
2658 if (result != NULL) {
2659 ret = compareFiles(temp, result);
2661 fprintf(stderr, "Result for %s failed\n", filename);
2666 ret = compareFileMem(err, testErrors, testErrorsSize);
2668 fprintf(stderr, "Error for %s failed\n", filename);
2682 * @filename: the file to parse
2683 * @result: the file with expected result
2684 * @err: the file with error messages
2686 * Parse a file containing URI and check for errors
2688 * Returns 0 in case of success, an error code otherwise
2691 uriParseTest(const char *filename,
2694 int options ATTRIBUTE_UNUSED) {
2695 return(uriCommonTest(filename, result, err, NULL));
2700 * @filename: the file to parse
2701 * @result: the file with expected result
2702 * @err: the file with error messages
2704 * Parse a file containing URI, compose them against a fixed base and
2707 * Returns 0 in case of success, an error code otherwise
2710 uriBaseTest(const char *filename,
2713 int options ATTRIBUTE_UNUSED) {
2714 return(uriCommonTest(filename, result, err,
2715 "http://foo.com/path/to/index.html?orig#help"));
2718 static int urip_success = 1;
2719 static int urip_current = 0;
2720 static const char *urip_testURLs[] = {
2721 "urip://example.com/a b.html",
2722 "urip://example.com/a%20b.html",
2723 "file:///path/to/a b.html",
2724 "file:///path/to/a%20b.html",
2725 "/path/to/a b.html",
2726 "/path/to/a%20b.html",
2727 "urip://example.com/r" "\xe9" "sum" "\xe9" ".html",
2728 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2731 static const char *urip_rcvsURLs[] = {
2732 /* it is an URI the strings must be escaped */
2733 "urip://example.com/a%20b.html",
2734 /* check that % escaping is not broken */
2735 "urip://example.com/a%20b.html",
2736 /* it's an URI path the strings must be escaped */
2737 "file:///path/to/a%20b.html",
2738 /* check that % escaping is not broken */
2739 "file:///path/to/a%20b.html",
2740 /* this is not an URI, this is a path, so this should not be escaped */
2741 "/path/to/a b.html",
2742 /* check that paths with % are not broken */
2743 "/path/to/a%20b.html",
2744 /* out of context the encoding can't be guessed byte by byte conversion */
2745 "urip://example.com/r%E9sum%E9.html",
2746 /* verify we don't destroy URIs especially the query part */
2747 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2750 static const char *urip_res = "<list/>";
2751 static const char *urip_cur = NULL;
2752 static int urip_rlen;
2756 * @URI: an URI to test
2758 * Check for an urip: query
2760 * Returns 1 if yes and 0 if another Input module should be used
2763 uripMatch(const char * URI) {
2764 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2766 /* Verify we received the escaped URL */
2767 if (strcmp(urip_rcvsURLs[urip_current], URI))
2774 * @URI: an URI to test
2776 * Return a pointer to the urip: query handler, in this example simply
2777 * the urip_current pointer...
2779 * Returns an Input context or NULL in case or error
2782 uripOpen(const char * URI) {
2783 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2785 /* Verify we received the escaped URL */
2786 if (strcmp(urip_rcvsURLs[urip_current], URI))
2788 urip_cur = urip_res;
2789 urip_rlen = strlen(urip_res);
2790 return((void *) urip_cur);
2795 * @context: the read context
2797 * Close the urip: query handler
2799 * Returns 0 or -1 in case of error
2802 uripClose(void * context) {
2803 if (context == NULL) return(-1);
2811 * @context: the read context
2812 * @buffer: where to store data
2813 * @len: number of bytes to read
2815 * Implement an urip: query read.
2817 * Returns the number of bytes read or -1 in case of error
2820 uripRead(void * context, char * buffer, int len) {
2821 const char *ptr = (const char *) context;
2823 if ((context == NULL) || (buffer == NULL) || (len < 0))
2826 if (len > urip_rlen) len = urip_rlen;
2827 memcpy(buffer, ptr, len);
2833 urip_checkURL(const char *URL) {
2836 doc = xmlReadFile(URL, NULL, 0);
2845 * @filename: ignored
2849 * Run a set of tests to check how Path and URI are handled before
2850 * being passed to the I/O layer
2852 * Returns 0 in case of success, an error code otherwise
2855 uriPathTest(const char *filename ATTRIBUTE_UNUSED,
2856 const char *result ATTRIBUTE_UNUSED,
2857 const char *err ATTRIBUTE_UNUSED,
2858 int options ATTRIBUTE_UNUSED) {
2863 * register the new I/O handlers
2865 if (xmlRegisterInputCallbacks(uripMatch, uripOpen, uripRead, uripClose) < 0)
2867 fprintf(stderr, "failed to register HTTP handler\n");
2871 for (urip_current = 0;urip_testURLs[urip_current] != NULL;urip_current++) {
2873 parsed = urip_checkURL(urip_testURLs[urip_current]);
2874 if (urip_success != 1) {
2875 fprintf(stderr, "failed the URL passing test for %s",
2876 urip_testURLs[urip_current]);
2878 } else if (parsed != 1) {
2879 fprintf(stderr, "failed the parsing test for %s",
2880 urip_testURLs[urip_current]);
2886 xmlPopInputCallbacks();
2890 #ifdef LIBXML_SCHEMAS_ENABLED
2891 /************************************************************************
2895 ************************************************************************/
2897 schemasOneTest(const char *sch,
2898 const char *filename,
2902 xmlSchemaPtr schemas) {
2904 xmlSchemaValidCtxtPtr ctxt;
2906 int validResult = 0;
2908 FILE *schemasOutput;
2910 doc = xmlReadFile(filename, NULL, options);
2912 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
2916 temp = resultFilename(result, "", ".res");
2918 fprintf(stderr, "Out of memory\n");
2921 schemasOutput = fopen(temp, "wb");
2922 if (schemasOutput == NULL) {
2923 fprintf(stderr, "failed to open output file %s\n", temp);
2929 ctxt = xmlSchemaNewValidCtxt(schemas);
2930 xmlSchemaSetValidErrors(ctxt,
2931 (xmlSchemaValidityErrorFunc) testErrorHandler,
2932 (xmlSchemaValidityWarningFunc) testErrorHandler,
2934 validResult = xmlSchemaValidateDoc(ctxt, doc);
2935 if (validResult == 0) {
2936 fprintf(schemasOutput, "%s validates\n", filename);
2937 } else if (validResult > 0) {
2938 fprintf(schemasOutput, "%s fails to validate\n", filename);
2940 fprintf(schemasOutput, "%s validation generated an internal error\n",
2943 fclose(schemasOutput);
2945 if (compareFiles(temp, result)) {
2946 fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
2955 if ((validResult != 0) && (err != NULL)) {
2956 if (compareFileMem(err, testErrors, testErrorsSize)) {
2957 fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
2962 xmlSchemaFreeValidCtxt(ctxt);
2968 * @filename: the schemas file
2969 * @result: the file with expected result
2970 * @err: the file with error messages
2972 * Parse a file containing URI, compose them against a fixed base and
2975 * Returns 0 in case of success, an error code otherwise
2978 schemasTest(const char *filename,
2979 const char *resul ATTRIBUTE_UNUSED,
2980 const char *errr ATTRIBUTE_UNUSED,
2982 const char *base = baseFilename(filename);
2984 const char *instance;
2985 xmlSchemaParserCtxtPtr ctxt;
2986 xmlSchemaPtr schemas;
2987 int res = 0, len, ret;
2996 /* first compile the schemas if possible */
2997 ctxt = xmlSchemaNewParserCtxt(filename);
2998 xmlSchemaSetParserErrors(ctxt,
2999 (xmlSchemaValidityErrorFunc) testErrorHandler,
3000 (xmlSchemaValidityWarningFunc) testErrorHandler,
3002 schemas = xmlSchemaParse(ctxt);
3003 xmlSchemaFreeParserCtxt(ctxt);
3006 * most of the mess is about the output filenames generated by the Makefile
3009 if ((len > 499) || (len < 5)) {
3010 xmlSchemaFree(schemas);
3013 len -= 4; /* remove trailing .xsd */
3014 if (base[len - 2] == '_') {
3015 len -= 2; /* remove subtest number */
3017 if (base[len - 2] == '_') {
3018 len -= 2; /* remove subtest number */
3020 memcpy(prefix, base, len);
3023 snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
3026 if (base[len] == '_') {
3028 memcpy(prefix, base, len);
3032 globbuf.gl_offs = 0;
3033 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3034 for (i = 0;i < globbuf.gl_pathc;i++) {
3037 instance = globbuf.gl_pathv[i];
3038 base2 = baseFilename(instance);
3039 len = strlen(base2);
3040 if ((len > 6) && (base2[len - 6] == '_')) {
3041 count = base2[len - 5];
3042 snprintf(result, 499, "result/schemas/%s_%c",
3045 snprintf(err, 499, "result/schemas/%s_%c.err",
3049 fprintf(stderr, "don't know how to process %s\n", instance);
3052 if (schemas == NULL) {
3055 ret = schemasOneTest(filename, instance, result, err,
3062 xmlSchemaFree(schemas);
3067 /************************************************************************
3071 ************************************************************************/
3073 rngOneTest(const char *sch,
3074 const char *filename,
3078 xmlRelaxNGPtr schemas) {
3080 xmlRelaxNGValidCtxtPtr ctxt;
3083 FILE *schemasOutput;
3085 doc = xmlReadFile(filename, NULL, options);
3087 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
3091 temp = resultFilename(result, "", ".res");
3093 fprintf(stderr, "Out of memory\n");
3096 schemasOutput = fopen(temp, "wb");
3097 if (schemasOutput == NULL) {
3098 fprintf(stderr, "failed to open output file %s\n", temp);
3104 ctxt = xmlRelaxNGNewValidCtxt(schemas);
3105 xmlRelaxNGSetValidErrors(ctxt,
3106 (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3107 (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3109 ret = xmlRelaxNGValidateDoc(ctxt, doc);
3111 testErrorHandler(NULL, "%s validates\n", filename);
3112 } else if (ret > 0) {
3113 testErrorHandler(NULL, "%s fails to validate\n", filename);
3115 testErrorHandler(NULL, "%s validation generated an internal error\n",
3118 fclose(schemasOutput);
3121 if (compareFiles(temp, result)) {
3122 fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
3132 if (compareFileMem(err, testErrors, testErrorsSize)) {
3133 fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
3135 printf("%s", testErrors);
3140 xmlRelaxNGFreeValidCtxt(ctxt);
3146 * @filename: the schemas file
3147 * @result: the file with expected result
3148 * @err: the file with error messages
3150 * Parse an RNG schemas and then apply it to the related .xml
3152 * Returns 0 in case of success, an error code otherwise
3155 rngTest(const char *filename,
3156 const char *resul ATTRIBUTE_UNUSED,
3157 const char *errr ATTRIBUTE_UNUSED,
3159 const char *base = baseFilename(filename);
3161 const char *instance;
3162 xmlRelaxNGParserCtxtPtr ctxt;
3163 xmlRelaxNGPtr schemas;
3164 int res = 0, len, ret = 0;
3173 /* first compile the schemas if possible */
3174 ctxt = xmlRelaxNGNewParserCtxt(filename);
3175 xmlRelaxNGSetParserErrors(ctxt,
3176 (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3177 (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3179 schemas = xmlRelaxNGParse(ctxt);
3180 xmlRelaxNGFreeParserCtxt(ctxt);
3183 * most of the mess is about the output filenames generated by the Makefile
3186 if ((len > 499) || (len < 5)) {
3187 xmlRelaxNGFree(schemas);
3190 len -= 4; /* remove trailing .rng */
3191 memcpy(prefix, base, len);
3194 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3197 globbuf.gl_offs = 0;
3198 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3199 for (i = 0;i < globbuf.gl_pathc;i++) {
3202 instance = globbuf.gl_pathv[i];
3203 base2 = baseFilename(instance);
3204 len = strlen(base2);
3205 if ((len > 6) && (base2[len - 6] == '_')) {
3206 count = base2[len - 5];
3207 snprintf(result, 499, "result/relaxng/%s_%c",
3210 snprintf(err, 499, "result/relaxng/%s_%c.err",
3214 fprintf(stderr, "don't know how to process %s\n", instance);
3217 if (schemas == NULL) {
3220 ret = rngOneTest(filename, instance, result, err,
3227 xmlRelaxNGFree(schemas);
3232 #ifdef LIBXML_READER_ENABLED
3235 * @filename: the schemas file
3236 * @result: the file with expected result
3237 * @err: the file with error messages
3239 * Parse a set of files with streaming, applying an RNG schemas
3241 * Returns 0 in case of success, an error code otherwise
3244 rngStreamTest(const char *filename,
3245 const char *resul ATTRIBUTE_UNUSED,
3246 const char *errr ATTRIBUTE_UNUSED,
3248 const char *base = baseFilename(filename);
3250 const char *instance;
3251 int res = 0, len, ret;
3259 xmlTextReaderPtr reader;
3260 int disable_err = 0;
3263 * most of the mess is about the output filenames generated by the Makefile
3266 if ((len > 499) || (len < 5)) {
3267 fprintf(stderr, "len(base) == %d !\n", len);
3270 len -= 4; /* remove trailing .rng */
3271 memcpy(prefix, base, len);
3275 * strictly unifying the error messages is nearly impossible this
3276 * hack is also done in the Makefile
3278 if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
3279 (!strcmp(prefix, "tutor3_2")) || (!strcmp(prefix, "307377")) ||
3280 (!strcmp(prefix, "tutor8_2")))
3283 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3286 globbuf.gl_offs = 0;
3287 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3288 for (i = 0;i < globbuf.gl_pathc;i++) {
3291 instance = globbuf.gl_pathv[i];
3292 base2 = baseFilename(instance);
3293 len = strlen(base2);
3294 if ((len > 6) && (base2[len - 6] == '_')) {
3295 count = base2[len - 5];
3296 snprintf(result, 499, "result/relaxng/%s_%c",
3299 snprintf(err, 499, "result/relaxng/%s_%c.err",
3303 fprintf(stderr, "don't know how to process %s\n", instance);
3306 reader = xmlReaderForFile(instance, NULL, options);
3307 if (reader == NULL) {
3308 fprintf(stderr, "Failed to build reder for %s\n", instance);
3310 if (disable_err == 1)
3311 ret = streamProcessTest(instance, result, NULL, reader, filename,
3314 ret = streamProcessTest(instance, result, err, reader, filename,
3316 xmlFreeTextReader(reader);
3318 fprintf(stderr, "instance %s failed\n", instance);
3330 #ifdef LIBXML_PATTERN_ENABLED
3331 #ifdef LIBXML_READER_ENABLED
3332 /************************************************************************
3336 ************************************************************************/
3337 static void patternNode(FILE *out, xmlTextReaderPtr reader,
3338 const char *pattern, xmlPatternPtr patternc,
3339 xmlStreamCtxtPtr patstream) {
3340 xmlChar *path = NULL;
3344 type = xmlTextReaderNodeType(reader);
3345 empty = xmlTextReaderIsEmptyElement(reader);
3347 if (type == XML_READER_TYPE_ELEMENT) {
3348 /* do the check only on element start */
3349 match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
3352 path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
3353 fprintf(out, "Node %s matches pattern %s\n", path, pattern);
3356 if (patstream != NULL) {
3359 if (type == XML_READER_TYPE_ELEMENT) {
3360 ret = xmlStreamPush(patstream,
3361 xmlTextReaderConstLocalName(reader),
3362 xmlTextReaderConstNamespaceUri(reader));
3364 fprintf(out, "xmlStreamPush() failure\n");
3365 xmlFreeStreamCtxt(patstream);
3367 } else if (ret != match) {
3369 path = xmlGetNodePath(
3370 xmlTextReaderCurrentNode(reader));
3373 "xmlPatternMatch and xmlStreamPush disagree\n");
3375 " pattern %s node %s\n",
3381 if ((type == XML_READER_TYPE_END_ELEMENT) ||
3382 ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
3383 ret = xmlStreamPop(patstream);
3385 fprintf(out, "xmlStreamPop() failure\n");
3386 xmlFreeStreamCtxt(patstream);
3397 * @filename: the schemas file
3398 * @result: the file with expected result
3399 * @err: the file with error messages
3401 * Parse a set of files with streaming, applying an RNG schemas
3403 * Returns 0 in case of success, an error code otherwise
3406 patternTest(const char *filename,
3407 const char *resul ATTRIBUTE_UNUSED,
3408 const char *err ATTRIBUTE_UNUSED,
3410 xmlPatternPtr patternc = NULL;
3411 xmlStreamCtxtPtr patstream = NULL;
3419 xmlTextReaderPtr reader;
3422 len = strlen(filename);
3424 memcpy(xml, filename, len);
3426 snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
3428 memcpy(xml + len, ".xml", 5);
3430 if (!checkTestFile(xml)) {
3431 fprintf(stderr, "Missing xml file %s\n", xml);
3434 if (!checkTestFile(result)) {
3435 fprintf(stderr, "Missing result file %s\n", result);
3438 f = fopen(filename, "rb");
3440 fprintf(stderr, "Failed to open %s\n", filename);
3443 temp = resultFilename(filename, "", ".res");
3445 fprintf(stderr, "Out of memory\n");
3448 o = fopen(temp, "wb");
3450 fprintf(stderr, "failed to open output file %s\n", temp);
3457 * read one line in string buffer.
3459 if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
3463 * remove the ending spaces
3467 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
3468 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
3472 doc = xmlReadFile(xml, NULL, options);
3474 fprintf(stderr, "Failed to parse %s\n", xml);
3478 const xmlChar *namespaces[22];
3482 root = xmlDocGetRootElement(doc);
3483 for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
3484 namespaces[j++] = ns->href;
3485 namespaces[j++] = ns->prefix;
3487 namespaces[j++] = NULL;
3488 namespaces[j] = NULL;
3490 patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
3492 if (patternc == NULL) {
3493 testErrorHandler(NULL,
3494 "Pattern %s failed to compile\n", str);
3499 patstream = xmlPatternGetStreamCtxt(patternc);
3500 if (patstream != NULL) {
3501 ret = xmlStreamPush(patstream, NULL, NULL);
3503 fprintf(stderr, "xmlStreamPush() failure\n");
3504 xmlFreeStreamCtxt(patstream);
3510 reader = xmlReaderWalker(doc);
3511 res = xmlTextReaderRead(reader);
3513 patternNode(o, reader, str, patternc, patstream);
3514 res = xmlTextReaderRead(reader);
3517 fprintf(o, "%s : failed to parse\n", filename);
3519 xmlFreeTextReader(reader);
3521 xmlFreeStreamCtxt(patstream);
3523 xmlFreePattern(patternc);
3531 ret = compareFiles(temp, result);
3533 fprintf(stderr, "Result for %s failed\n", filename);
3543 #endif /* PATTERN */
3544 #ifdef LIBXML_C14N_ENABLED
3545 /************************************************************************
3547 * Canonicalization tests *
3549 ************************************************************************/
3550 static xmlXPathObjectPtr
3551 load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
3552 xmlXPathObjectPtr xpath;
3555 xmlXPathContextPtr ctx;
3560 * load XPath expr as a file
3562 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3563 xmlSubstituteEntitiesDefault(1);
3565 doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3567 fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
3572 * Check the document is of the right kind
3574 if(xmlDocGetRootElement(doc) == NULL) {
3575 fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
3580 node = doc->children;
3581 while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
3586 fprintf(stderr,"Error: XPath element expected in the file \"%s\"\n", filename);
3591 expr = xmlNodeGetContent(node);
3593 fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
3598 ctx = xmlXPathNewContext(parent_doc);
3600 fprintf(stderr,"Error: unable to create new context\n");
3607 * Register namespaces
3611 if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
3612 fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
3614 xmlXPathFreeContext(ctx);
3624 xpath = xmlXPathEvalExpression(expr, ctx);
3626 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3628 xmlXPathFreeContext(ctx);
3633 /* print_xpath_nodes(xpath->nodesetval); */
3636 xmlXPathFreeContext(ctx);
3642 * Macro used to grow the current buffer.
3644 #define xxx_growBufferReentrant() { \
3646 buffer = (xmlChar **) \
3647 xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \
3648 if (buffer == NULL) { \
3649 perror("realloc failed"); \
3655 parse_list(xmlChar *str) {
3657 xmlChar **out = NULL;
3658 int buffer_size = 0;
3665 len = xmlStrlen(str);
3666 if((str[0] == '\'') && (str[len - 1] == '\'')) {
3667 str[len - 1] = '\0';
3671 * allocate an translation buffer.
3674 buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
3675 if (buffer == NULL) {
3676 perror("malloc failed");
3681 while(*str != '\0') {
3682 if (out - buffer > buffer_size - 10) {
3683 int indx = out - buffer;
3685 xxx_growBufferReentrant();
3686 out = &buffer[indx];
3689 while(*str != ',' && *str != '\0') ++str;
3690 if(*str == ',') *(str++) = '\0';
3697 c14nRunTest(const char* xml_filename, int with_comments, int mode,
3698 const char* xpath_filename, const char *ns_filename,
3699 const char* result_file) {
3701 xmlXPathObjectPtr xpath = NULL;
3702 xmlChar *result = NULL;
3704 xmlChar **inclusive_namespaces = NULL;
3705 const char *nslist = NULL;
3710 * build an XML tree from a the file; we need to add default
3711 * attributes and resolve all character and entities references
3713 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3714 xmlSubstituteEntitiesDefault(1);
3716 doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3718 fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
3723 * Check the document is of the right kind
3725 if(xmlDocGetRootElement(doc) == NULL) {
3726 fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
3732 * load xpath file if specified
3734 if(xpath_filename) {
3735 xpath = load_xpath_expr(doc, xpath_filename);
3737 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3743 if (ns_filename != NULL) {
3744 if (loadMem(ns_filename, &nslist, &nssize)) {
3745 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3746 if(xpath != NULL) xmlXPathFreeObject(xpath);
3750 inclusive_namespaces = parse_list((xmlChar *) nslist);
3756 /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
3757 ret = xmlC14NDocDumpMemory(doc,
3758 (xpath) ? xpath->nodesetval : NULL,
3759 mode, inclusive_namespaces,
3760 with_comments, &result);
3762 if(result != NULL) {
3763 if (compareFileMem(result_file, (const char *) result, ret)) {
3764 fprintf(stderr, "Result mismatch for %s\n", xml_filename);
3765 fprintf(stderr, "RESULT:\n%s\n", (const char*)result);
3770 fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
3777 if (result != NULL) xmlFree(result);
3778 if(xpath != NULL) xmlXPathFreeObject(xpath);
3779 if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
3780 if (nslist != NULL) free((char *) nslist);
3787 c14nCommonTest(const char *filename, int with_comments, int mode,
3788 const char *subdir) {
3793 char *result = NULL;
3798 base = baseFilename(filename);
3801 memcpy(prefix, base, len);
3804 snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
3805 if (!checkTestFile(buf)) {
3806 fprintf(stderr, "Missing result file %s", buf);
3809 result = strdup(buf);
3810 snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
3811 if (checkTestFile(buf)) {
3812 xpath = strdup(buf);
3814 snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
3815 if (checkTestFile(buf)) {
3820 if (c14nRunTest(filename, with_comments, mode,
3821 xpath, ns, result) < 0)
3824 if (result != NULL) free(result);
3825 if (xpath != NULL) free(xpath);
3826 if (ns != NULL) free(ns);
3831 c14nWithCommentTest(const char *filename,
3832 const char *resul ATTRIBUTE_UNUSED,
3833 const char *err ATTRIBUTE_UNUSED,
3834 int options ATTRIBUTE_UNUSED) {
3835 return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments"));
3838 c14nWithoutCommentTest(const char *filename,
3839 const char *resul ATTRIBUTE_UNUSED,
3840 const char *err ATTRIBUTE_UNUSED,
3841 int options ATTRIBUTE_UNUSED) {
3842 return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments"));
3845 c14nExcWithoutCommentTest(const char *filename,
3846 const char *resul ATTRIBUTE_UNUSED,
3847 const char *err ATTRIBUTE_UNUSED,
3848 int options ATTRIBUTE_UNUSED) {
3849 return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments"));
3852 c14n11WithoutCommentTest(const char *filename,
3853 const char *resul ATTRIBUTE_UNUSED,
3854 const char *err ATTRIBUTE_UNUSED,
3855 int options ATTRIBUTE_UNUSED) {
3856 return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments"));
3859 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined (LIBXML_SAX1_ENABLED)
3860 /************************************************************************
3862 * Catalog and threads test *
3864 ************************************************************************/
3867 * mostly a cut and paste from testThreads.c
3871 static const char *catalog = "test/threads/complex.xml";
3872 static const char *testfiles[] = {
3873 "test/threads/abc.xml",
3874 "test/threads/acb.xml",
3875 "test/threads/bac.xml",
3876 "test/threads/bca.xml",
3877 "test/threads/cab.xml",
3878 "test/threads/cba.xml",
3879 "test/threads/invalid.xml",
3882 static const char *Okay = "OK";
3883 static const char *Failed = "Failed";
3885 #ifndef xmlDoValidityCheckingDefaultValue
3886 #error xmlDoValidityCheckingDefaultValue is not a macro
3888 #ifndef xmlGenericErrorContext
3889 #error xmlGenericErrorContext is not a macro
3893 thread_specific_data(void *private_data)
3896 const char *filename = (const char *) private_data;
3899 if (!strcmp(filename, "test/threads/invalid.xml")) {
3900 xmlDoValidityCheckingDefaultValue = 0;
3901 xmlGenericErrorContext = stdout;
3903 xmlDoValidityCheckingDefaultValue = 1;
3904 xmlGenericErrorContext = stderr;
3906 myDoc = xmlParseFile(filename);
3910 printf("parse failed\n");
3913 if (!strcmp(filename, "test/threads/invalid.xml")) {
3914 if (xmlDoValidityCheckingDefaultValue != 0) {
3915 printf("ValidityCheckingDefaultValue override failed\n");
3918 if (xmlGenericErrorContext != stdout) {
3919 printf("xmlGenericErrorContext override failed\n");
3923 if (xmlDoValidityCheckingDefaultValue != 1) {
3924 printf("ValidityCheckingDefaultValue override failed\n");
3927 if (xmlGenericErrorContext != stderr) {
3928 printf("xmlGenericErrorContext override failed\n");
3933 return ((void *) Failed);
3934 return ((void *) Okay);
3938 #include <windows.h>
3941 #define TEST_REPEAT_COUNT 500
3943 static HANDLE tid[MAX_ARGC];
3946 win32_thread_specific_data(void *private_data)
3948 return((DWORD) thread_specific_data(private_data));
3954 unsigned int i, repeat;
3955 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
3956 DWORD results[MAX_ARGC];
3961 for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
3962 xmlLoadCatalog(catalog);
3965 for (i = 0; i < num_threads; i++) {
3967 tid[i] = (HANDLE) - 1;
3970 for (i = 0; i < num_threads; i++) {
3973 tid[i] = CreateThread(NULL, 0,
3974 win32_thread_specific_data,
3975 (void *) testfiles[i], 0,
3977 if (tid[i] == NULL) {
3978 fprintf(stderr, "CreateThread failed\n");
3983 if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
3985 fprintf(stderr, "WaitForMultipleObjects failed\n");
3989 for (i = 0; i < num_threads; i++) {
3990 ret = GetExitCodeThread(tid[i], &results[i]);
3992 fprintf(stderr, "GetExitCodeThread failed\n");
3995 CloseHandle(tid[i]);
3998 xmlCatalogCleanup();
3999 for (i = 0; i < num_threads; i++) {
4000 if (results[i] != (DWORD) Okay) {
4001 fprintf(stderr, "Thread %d handling %s failed\n",
4011 #elif defined __BEOS__
4014 static thread_id tid[MAX_ARGC];
4019 unsigned int i, repeat;
4020 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4021 void *results[MAX_ARGC];
4026 for (repeat = 0; repeat < 500; repeat++) {
4027 xmlLoadCatalog(catalog);
4028 for (i = 0; i < num_threads; i++) {
4030 tid[i] = (thread_id) - 1;
4032 for (i = 0; i < num_threads; i++) {
4034 spawn_thread(thread_specific_data, "xmlTestThread",
4035 B_NORMAL_PRIORITY, (void *) testfiles[i]);
4036 if (tid[i] < B_OK) {
4037 fprintf(stderr, "beos_thread_create failed\n");
4040 printf("beos_thread_create %d -> %d\n", i, tid[i]);
4042 for (i = 0; i < num_threads; i++) {
4043 ret = wait_for_thread(tid[i], &results[i]);
4044 printf("beos_thread_wait %d -> %d\n", i, ret);
4046 fprintf(stderr, "beos_thread_wait failed\n");
4051 xmlCatalogCleanup();
4053 for (i = 0; i < num_threads; i++)
4054 if (results[i] != (void *) Okay) {
4055 printf("Thread %d handling %s failed\n", i, testfiles[i]);
4064 #elif defined HAVE_PTHREAD_H
4065 #include <pthread.h>
4067 static pthread_t tid[MAX_ARGC];
4072 unsigned int i, repeat;
4073 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4074 void *results[MAX_ARGC];
4080 for (repeat = 0; repeat < 500; repeat++) {
4081 xmlLoadCatalog(catalog);
4084 for (i = 0; i < num_threads; i++) {
4086 tid[i] = (pthread_t) - 1;
4089 for (i = 0; i < num_threads; i++) {
4090 ret = pthread_create(&tid[i], 0, thread_specific_data,
4091 (void *) testfiles[i]);
4093 fprintf(stderr, "pthread_create failed\n");
4097 for (i = 0; i < num_threads; i++) {
4098 ret = pthread_join(tid[i], &results[i]);
4100 fprintf(stderr, "pthread_join failed\n");
4105 xmlCatalogCleanup();
4106 for (i = 0; i < num_threads; i++)
4107 if (results[i] != (void *) Okay) {
4108 fprintf(stderr, "Thread %d handling %s failed\n",
4121 "Specific platform thread support not detected\n");
4126 threadsTest(const char *filename ATTRIBUTE_UNUSED,
4127 const char *resul ATTRIBUTE_UNUSED,
4128 const char *err ATTRIBUTE_UNUSED,
4129 int options ATTRIBUTE_UNUSED) {
4130 return(testThread());
4133 /************************************************************************
4135 * Tests Descriptions *
4137 ************************************************************************/
4140 testDesc testDescriptions[] = {
4141 { "XML regression tests" ,
4142 oldParseTest, "./test/*", "result/", "", NULL,
4144 { "XML regression tests on memory" ,
4145 memParseTest, "./test/*", "result/", "", NULL,
4147 { "XML entity subst regression tests" ,
4148 noentParseTest, "./test/*", "result/noent/", "", NULL,
4150 { "XML Namespaces regression tests",
4151 errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
4153 { "Error cases regression tests",
4154 errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
4156 #ifdef LIBXML_READER_ENABLED
4157 { "Error cases stream regression tests",
4158 streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
4160 { "Reader regression tests",
4161 streamParseTest, "./test/*", "result/", ".rdr", NULL,
4163 { "Reader entities substitution regression tests",
4164 streamParseTest, "./test/*", "result/", ".rde", NULL,
4166 { "Reader on memory regression tests",
4167 streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
4169 { "Walker regression tests",
4170 walkerParseTest, "./test/*", "result/", ".rdr", NULL,
4173 #ifdef LIBXML_SAX1_ENABLED
4174 { "SAX1 callbacks regression tests" ,
4175 saxParseTest, "./test/*", "result/", ".sax", NULL,
4177 { "SAX2 callbacks regression tests" ,
4178 saxParseTest, "./test/*", "result/", ".sax2", NULL,
4181 #ifdef LIBXML_PUSH_ENABLED
4182 { "XML push regression tests" ,
4183 pushParseTest, "./test/*", "result/", "", NULL,
4186 #ifdef LIBXML_HTML_ENABLED
4187 { "HTML regression tests" ,
4188 errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4190 #ifdef LIBXML_PUSH_ENABLED
4191 { "Push HTML regression tests" ,
4192 pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4195 #ifdef LIBXML_SAX1_ENABLED
4196 { "HTML SAX regression tests" ,
4197 saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
4201 #ifdef LIBXML_VALID_ENABLED
4202 { "Valid documents regression tests" ,
4203 errParseTest, "./test/VCM/*", NULL, NULL, NULL,
4204 XML_PARSE_DTDVALID },
4205 { "Validity checking regression tests" ,
4206 errParseTest, "./test/VC/*", "result/VC/", NULL, "",
4207 XML_PARSE_DTDVALID },
4208 #ifdef LIBXML_READER_ENABLED
4209 { "Streaming validity checking regression tests" ,
4210 streamParseTest, "./test/valid/*.xml", "result/valid/", NULL, ".err.rdr",
4211 XML_PARSE_DTDVALID },
4212 { "Streaming validity error checking regression tests" ,
4213 streamParseTest, "./test/VC/*", "result/VC/", NULL, ".rdr",
4214 XML_PARSE_DTDVALID },
4216 { "General documents valid regression tests" ,
4217 errParseTest, "./test/valid/*", "result/valid/", "", ".err",
4218 XML_PARSE_DTDVALID },
4220 #ifdef LIBXML_XINCLUDE_ENABLED
4221 { "XInclude regression tests" ,
4222 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4223 /* Ignore errors at this point ".err", */
4224 XML_PARSE_XINCLUDE },
4225 #ifdef LIBXML_READER_ENABLED
4226 { "XInclude xmlReader regression tests",
4227 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4228 /* Ignore errors at this point ".err", */
4229 NULL, XML_PARSE_XINCLUDE },
4231 { "XInclude regression tests stripping include nodes" ,
4232 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4233 /* Ignore errors at this point ".err", */
4234 XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4235 #ifdef LIBXML_READER_ENABLED
4236 { "XInclude xmlReader regression tests stripping include nodes",
4237 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4238 /* Ignore errors at this point ".err", */
4239 NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4242 #ifdef LIBXML_XPATH_ENABLED
4243 #ifdef LIBXML_DEBUG_ENABLED
4244 { "XPath expressions regression tests" ,
4245 xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
4247 { "XPath document queries regression tests" ,
4248 xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4250 #ifdef LIBXML_XPTR_ENABLED
4251 { "XPointer document queries regression tests" ,
4252 xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4255 { "xml:id regression tests" ,
4256 xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
4260 { "URI parsing tests" ,
4261 uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
4263 { "URI base composition tests" ,
4264 uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
4266 { "Path URI conversion tests" ,
4267 uriPathTest, NULL, NULL, NULL, NULL,
4269 #ifdef LIBXML_SCHEMAS_ENABLED
4270 { "Schemas regression tests" ,
4271 schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
4273 { "Relax-NG regression tests" ,
4274 rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4275 XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4276 #ifdef LIBXML_READER_ENABLED
4277 { "Relax-NG streaming regression tests" ,
4278 rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4279 XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4282 #ifdef LIBXML_PATTERN_ENABLED
4283 #ifdef LIBXML_READER_ENABLED
4284 { "Pattern regression tests" ,
4285 patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
4289 #ifdef LIBXML_C14N_ENABLED
4290 { "C14N with comments regression tests" ,
4291 c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
4293 { "C14N without comments regression tests" ,
4294 c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
4296 { "C14N exclusive without comments regression tests" ,
4297 c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
4299 { "C14N 1.1 without comments regression tests" ,
4300 c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL,
4303 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_SAX1_ENABLED)
4304 { "Catalog and Threads regression tests" ,
4305 threadsTest, NULL, NULL, NULL, NULL,
4308 {NULL, NULL, NULL, NULL, NULL, NULL, 0}
4311 /************************************************************************
4313 * The main code driving the tests *
4315 ************************************************************************/
4318 launchTests(testDescPtr tst) {
4319 int res = 0, err = 0;
4325 if (tst == NULL) return(-1);
4326 if (tst->in != NULL) {
4329 globbuf.gl_offs = 0;
4330 glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
4331 for (i = 0;i < globbuf.gl_pathc;i++) {
4332 if (!checkTestFile(globbuf.gl_pathv[i]))
4334 if (tst->suffix != NULL) {
4335 result = resultFilename(globbuf.gl_pathv[i], tst->out,
4337 if (result == NULL) {
4338 fprintf(stderr, "Out of memory !\n");
4344 if (tst->err != NULL) {
4345 error = resultFilename(globbuf.gl_pathv[i], tst->out,
4347 if (error == NULL) {
4348 fprintf(stderr, "Out of memory !\n");
4354 if ((result) &&(!checkTestFile(result))) {
4355 fprintf(stderr, "Missing result file %s\n", result);
4356 } else if ((error) &&(!checkTestFile(error))) {
4357 fprintf(stderr, "Missing error file %s\n", error);
4360 extraMemoryFromResolver = 0;
4363 res = tst->func(globbuf.gl_pathv[i], result, error,
4364 tst->options | XML_PARSE_COMPACT);
4365 xmlResetLastError();
4367 fprintf(stderr, "File %s generated an error\n",
4368 globbuf.gl_pathv[i]);
4372 else if (xmlMemUsed() != mem) {
4373 if ((xmlMemUsed() != mem) &&
4374 (extraMemoryFromResolver == 0)) {
4375 fprintf(stderr, "File %s leaked %d bytes\n",
4376 globbuf.gl_pathv[i], xmlMemUsed() - mem);
4392 extraMemoryFromResolver = 0;
4393 res = tst->func(NULL, NULL, NULL, tst->options);
4402 static int verbose = 0;
4403 static int tests_quiet = 0;
4408 int old_errors, old_tests, old_leaks;
4410 old_errors = nb_errors;
4411 old_tests = nb_tests;
4412 old_leaks = nb_leaks;
4413 if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
4414 printf("## %s\n", testDescriptions[i].desc);
4415 res = launchTests(&testDescriptions[i]);
4419 if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
4420 printf("Ran %d tests, no errors\n", nb_tests - old_tests);
4422 printf("Ran %d tests, %d errors, %d leaks\n",
4423 nb_tests - old_tests,
4424 nb_errors - old_errors,
4425 nb_leaks - old_leaks);
4431 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4435 initializeLibxml2();
4437 for (a = 1; a < argc;a++) {
4438 if (!strcmp(argv[a], "-v"))
4440 else if (!strcmp(argv[a], "-quiet"))
4443 for (i = 0; testDescriptions[i].func != NULL; i++) {
4444 if (strstr(testDescriptions[i].desc, argv[a])) {
4452 for (i = 0; testDescriptions[i].func != NULL; i++) {
4456 if ((nb_errors == 0) && (nb_leaks == 0)) {
4458 printf("Total %d tests, no errors\n",
4462 printf("Total %d tests, %d errors, %d leaks\n",
4463 nb_tests, nb_errors, nb_leaks);
4471 #else /* ! LIBXML_OUTPUT_ENABLED */
4473 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4474 fprintf(stderr, "runtest requires output to be enabled in libxml2\n");