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]);
198 #if !defined(__MINGW32__)
199 #define vsnprintf _vsnprintf
200 #define snprintf _snprintf
206 /************************************************************************
208 * Libxml2 specific routines *
210 ************************************************************************/
212 static int nb_tests = 0;
213 static int nb_errors = 0;
214 static int nb_leaks = 0;
215 static int extraMemoryFromResolver = 0;
219 fprintf(stderr, "Exitting tests on fatal error\n");
224 * We need to trap calls to the resolver to not account memory for the catalog
225 * which is shared to the current running test. We also don't want to have
226 * network downloads modifying tests.
228 static xmlParserInputPtr
229 testExternalEntityLoader(const char *URL, const char *ID,
230 xmlParserCtxtPtr ctxt) {
231 xmlParserInputPtr ret;
233 if (checkTestFile(URL)) {
234 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
236 int memused = xmlMemUsed();
237 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
238 extraMemoryFromResolver += xmlMemUsed() - memused;
245 * Trapping the error messages at the generic level to grab the equivalent of
246 * stderr messages on CLI tools.
248 static char testErrors[32769];
249 static int testErrorsSize = 0;
252 testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
256 if (testErrorsSize >= 32768)
259 res = vsnprintf(&testErrors[testErrorsSize],
260 32768 - testErrorsSize,
263 if (testErrorsSize + res >= 32768) {
265 testErrorsSize = 32768;
266 testErrors[testErrorsSize] = 0;
268 testErrorsSize += res;
270 testErrors[testErrorsSize] = 0;
274 channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
278 if (testErrorsSize >= 32768)
281 res = vsnprintf(&testErrors[testErrorsSize],
282 32768 - testErrorsSize,
285 if (testErrorsSize + res >= 32768) {
287 testErrorsSize = 32768;
288 testErrors[testErrorsSize] = 0;
290 testErrorsSize += res;
292 testErrors[testErrorsSize] = 0;
296 * xmlParserPrintFileContext:
297 * @input: an xmlParserInputPtr input
299 * Displays current context within the input content for error tracking
303 xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
304 xmlGenericErrorFunc chanl, void *data ) {
305 const xmlChar *cur, *base;
306 unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
307 xmlChar content[81]; /* space for 80 chars + line terminator */
310 if (input == NULL) return;
313 /* skip backwards over any end-of-lines */
314 while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
318 /* search backwards for beginning-of-line (to max buff size) */
319 while ((n++ < (sizeof(content)-1)) && (cur > base) &&
320 (*(cur) != '\n') && (*(cur) != '\r'))
322 if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
323 /* calculate the error position in terms of the current position */
324 col = input->cur - cur;
325 /* search forward for end-of-line (to max buff size) */
328 /* copy selected text to our buffer */
329 while ((*cur != 0) && (*(cur) != '\n') &&
330 (*(cur) != '\r') && (n < sizeof(content)-1)) {
335 /* print out the selected text */
336 chanl(data ,"%s\n", content);
337 /* create blank line with problem pointer */
340 /* (leave buffer space for pointer + line terminator) */
341 while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
348 chanl(data ,"%s\n", content);
352 testStructuredErrorHandler(void *ctx ATTRIBUTE_UNUSED, xmlErrorPtr err) {
359 const xmlChar *name = NULL;
362 xmlParserInputPtr input = NULL;
363 xmlParserInputPtr cur = NULL;
364 xmlParserCtxtPtr ctxt = NULL;
372 domain = err->domain;
375 if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
376 (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
377 (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
382 if (code == XML_ERR_OK)
385 if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
389 * Maintain the compatibility with the legacy error handling
393 if ((input != NULL) && (input->filename == NULL) &&
394 (ctxt->inputNr > 1)) {
396 input = ctxt->inputTab[ctxt->inputNr - 2];
400 channel(data, "%s:%d: ", input->filename, input->line);
401 else if ((line != 0) && (domain == XML_FROM_PARSER))
402 channel(data, "Entity: line %d: ", input->line);
406 channel(data, "%s:%d: ", file, line);
407 else if ((line != 0) && (domain == XML_FROM_PARSER))
408 channel(data, "Entity: line %d: ", line);
411 channel(data, "element %s: ", name);
413 if (code == XML_ERR_OK)
416 case XML_FROM_PARSER:
417 channel(data, "parser ");
419 case XML_FROM_NAMESPACE:
420 channel(data, "namespace ");
424 channel(data, "validity ");
427 channel(data, "HTML parser ");
429 case XML_FROM_MEMORY:
430 channel(data, "memory ");
432 case XML_FROM_OUTPUT:
433 channel(data, "output ");
436 channel(data, "I/O ");
438 case XML_FROM_XINCLUDE:
439 channel(data, "XInclude ");
442 channel(data, "XPath ");
444 case XML_FROM_XPOINTER:
445 channel(data, "parser ");
447 case XML_FROM_REGEXP:
448 channel(data, "regexp ");
450 case XML_FROM_MODULE:
451 channel(data, "module ");
453 case XML_FROM_SCHEMASV:
454 channel(data, "Schemas validity ");
456 case XML_FROM_SCHEMASP:
457 channel(data, "Schemas parser ");
459 case XML_FROM_RELAXNGP:
460 channel(data, "Relax-NG parser ");
462 case XML_FROM_RELAXNGV:
463 channel(data, "Relax-NG validity ");
465 case XML_FROM_CATALOG:
466 channel(data, "Catalog ");
469 channel(data, "C14N ");
472 channel(data, "XSLT ");
477 if (code == XML_ERR_OK)
483 case XML_ERR_WARNING:
484 channel(data, "warning : ");
487 channel(data, "error : ");
490 channel(data, "error : ");
493 if (code == XML_ERR_OK)
497 len = xmlStrlen((const xmlChar *)str);
498 if ((len > 0) && (str[len - 1] != '\n'))
499 channel(data, "%s\n", str);
501 channel(data, "%s", str);
503 channel(data, "%s\n", "out of memory error");
505 if (code == XML_ERR_OK)
509 xmlParserPrintFileContextInternal(input, channel, data);
512 channel(data, "%s:%d: \n", cur->filename, cur->line);
513 else if ((line != 0) && (domain == XML_FROM_PARSER))
514 channel(data, "Entity: line %d: \n", cur->line);
515 xmlParserPrintFileContextInternal(cur, channel, data);
518 if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
520 (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
524 channel(data, "%s\n", err->str1);
525 for (i=0;i < err->int1;i++)
529 channel(data, "%s\n", buf);
534 initializeLibxml2(void) {
535 xmlGetWarningsDefaultValue = 0;
536 xmlPedanticParserDefault(0);
538 xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
540 xmlSetExternalEntityLoader(testExternalEntityLoader);
541 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
542 #ifdef LIBXML_SCHEMAS_ENABLED
543 xmlSchemaInitTypes();
544 xmlRelaxNGInitTypes();
549 /************************************************************************
551 * File name and path utilities *
553 ************************************************************************/
555 static const char *baseFilename(const char *filename) {
557 if (filename == NULL)
559 cur = &filename[strlen(filename)];
560 while ((cur > filename) && (*cur != '/'))
567 static char *resultFilename(const char *filename, const char *out,
568 const char *suffix) {
571 char suffixbuff[500];
574 if ((filename[0] == 't') && (filename[1] == 'e') &&
575 (filename[2] == 's') && (filename[3] == 't') &&
576 (filename[4] == '/'))
577 filename = &filename[5];
580 base = baseFilename(filename);
586 strncpy(suffixbuff,suffix,499);
588 if(strstr(base,".") && suffixbuff[0]=='.')
592 snprintf(res, 499, "%s%s%s", out, base, suffixbuff);
597 static int checkTestFile(const char *filename) {
600 if (stat(filename, &buf) == -1)
603 #if defined(_WIN32) && !defined(__CYGWIN__)
604 if (!(buf.st_mode & _S_IFREG))
607 if (!S_ISREG(buf.st_mode))
614 static int compareFiles(const char *r1, const char *r2) {
620 fd1 = open(r1, RD_FLAGS);
623 fd2 = open(r2, RD_FLAGS);
629 res1 = read(fd1, bytes1, 4096);
630 res2 = read(fd2, bytes2, 4096);
631 if ((res1 != res2) || (res1 < 0)) {
638 if (memcmp(bytes1, bytes2, res1) != 0) {
649 static int compareFileMem(const char *filename, const char *mem, int size) {
656 if (stat(filename, &info) < 0)
658 if (info.st_size != size)
660 fd = open(filename, RD_FLAGS);
664 res = read(fd, bytes, 4096);
667 if (res + idx > size)
669 if (memcmp(bytes, &mem[idx], res) != 0) {
671 for (ix=0; ix<res; ix++)
672 if (bytes[ix] != mem[idx+ix])
674 fprintf(stderr,"Compare error at position %d\n", idx+ix);
684 static int loadMem(const char *filename, const char **mem, int *size) {
689 if (stat(filename, &info) < 0)
691 base = malloc(info.st_size + 1);
694 if ((fd = open(filename, RD_FLAGS)) < 0) {
698 while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
703 if (siz != info.st_size) {
714 static int unloadMem(const char *mem) {
719 /************************************************************************
721 * Tests implementations *
723 ************************************************************************/
725 /************************************************************************
727 * Parse to SAX based tests *
729 ************************************************************************/
731 static FILE *SAXdebug = NULL;
736 static xmlSAXHandler emptySAXHandlerStruct = {
737 NULL, /* internalSubset */
738 NULL, /* isStandalone */
739 NULL, /* hasInternalSubset */
740 NULL, /* hasExternalSubset */
741 NULL, /* resolveEntity */
742 NULL, /* getEntity */
743 NULL, /* entityDecl */
744 NULL, /* notationDecl */
745 NULL, /* attributeDecl */
746 NULL, /* elementDecl */
747 NULL, /* unparsedEntityDecl */
748 NULL, /* setDocumentLocator */
749 NULL, /* startDocument */
750 NULL, /* endDocument */
751 NULL, /* startElement */
752 NULL, /* endElement */
753 NULL, /* reference */
754 NULL, /* characters */
755 NULL, /* ignorableWhitespace */
756 NULL, /* processingInstruction */
758 NULL, /* xmlParserWarning */
759 NULL, /* xmlParserError */
760 NULL, /* xmlParserError */
761 NULL, /* getParameterEntity */
762 NULL, /* cdataBlock; */
763 NULL, /* externalSubset; */
766 NULL, /* startElementNs */
767 NULL, /* endElementNs */
768 NULL /* xmlStructuredErrorFunc */
771 static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
772 static int callbacks = 0;
773 static int quiet = 0;
777 * @ctxt: An XML parser context
779 * Is this document tagged standalone ?
784 isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
789 fprintf(SAXdebug, "SAX.isStandalone()\n");
794 * hasInternalSubsetDebug:
795 * @ctxt: An XML parser context
797 * Does this document has an internal subset
802 hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
807 fprintf(SAXdebug, "SAX.hasInternalSubset()\n");
812 * hasExternalSubsetDebug:
813 * @ctxt: An XML parser context
815 * Does this document has an external subset
820 hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
825 fprintf(SAXdebug, "SAX.hasExternalSubset()\n");
830 * internalSubsetDebug:
831 * @ctxt: An XML parser context
833 * Does this document has an internal subset
836 internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
837 const xmlChar *ExternalID, const xmlChar *SystemID)
842 fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
843 if (ExternalID == NULL)
844 fprintf(SAXdebug, " ,");
846 fprintf(SAXdebug, " %s,", ExternalID);
847 if (SystemID == NULL)
848 fprintf(SAXdebug, " )\n");
850 fprintf(SAXdebug, " %s)\n", SystemID);
854 * externalSubsetDebug:
855 * @ctxt: An XML parser context
857 * Does this document has an external subset
860 externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
861 const xmlChar *ExternalID, const xmlChar *SystemID)
866 fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
867 if (ExternalID == NULL)
868 fprintf(SAXdebug, " ,");
870 fprintf(SAXdebug, " %s,", ExternalID);
871 if (SystemID == NULL)
872 fprintf(SAXdebug, " )\n");
874 fprintf(SAXdebug, " %s)\n", SystemID);
878 * resolveEntityDebug:
879 * @ctxt: An XML parser context
880 * @publicId: The public ID of the entity
881 * @systemId: The system ID of the entity
883 * Special entity resolver, better left to the parser, it has
884 * more context than the application layer.
885 * The default behaviour is to NOT resolve the entities, in that case
886 * the ENTITY_REF nodes are built in the structure (and the parameter
889 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
891 static xmlParserInputPtr
892 resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
897 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
900 fprintf(SAXdebug, "SAX.resolveEntity(");
901 if (publicId != NULL)
902 fprintf(SAXdebug, "%s", (char *)publicId);
904 fprintf(SAXdebug, " ");
905 if (systemId != NULL)
906 fprintf(SAXdebug, ", %s)\n", (char *)systemId);
908 fprintf(SAXdebug, ", )\n");
910 if (systemId != NULL) {
911 return(xmlNewInputFromFile(ctxt, (char *) systemId));
919 * @ctxt: An XML parser context
920 * @name: The entity name
922 * Get an entity by name
924 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
927 getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
932 fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
937 * getParameterEntityDebug:
938 * @ctxt: An XML parser context
939 * @name: The entity name
941 * Get a parameter entity by name
943 * Returns the xmlParserInputPtr
946 getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
951 fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
958 * @ctxt: An XML parser context
959 * @name: the entity name
960 * @type: the entity type
961 * @publicId: The public ID of the entity
962 * @systemId: The system ID of the entity
963 * @content: the entity value (without processing).
965 * An entity definition has been parsed
968 entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
969 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
971 const xmlChar *nullstr = BAD_CAST "(null)";
972 /* not all libraries handle printing null pointers nicely */
973 if (publicId == NULL)
975 if (systemId == NULL)
978 content = (xmlChar *)nullstr;
982 fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
983 name, type, publicId, systemId, content);
987 * attributeDeclDebug:
988 * @ctxt: An XML parser context
989 * @name: the attribute name
990 * @type: the attribute type
992 * An attribute definition has been parsed
995 attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
996 const xmlChar * name, int type, int def,
997 const xmlChar * defaultValue, xmlEnumerationPtr tree)
1002 if (defaultValue == NULL)
1003 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
1004 elem, name, type, def);
1006 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
1007 elem, name, type, def, defaultValue);
1008 xmlFreeEnumeration(tree);
1013 * @ctxt: An XML parser context
1014 * @name: the element name
1015 * @type: the element type
1016 * @content: the element value (without processing).
1018 * An element definition has been parsed
1021 elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1022 xmlElementContentPtr content ATTRIBUTE_UNUSED)
1027 fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n",
1032 * notationDeclDebug:
1033 * @ctxt: An XML parser context
1034 * @name: The name of the notation
1035 * @publicId: The public ID of the entity
1036 * @systemId: The system ID of the entity
1038 * What to do when a notation declaration has been parsed.
1041 notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1042 const xmlChar *publicId, const xmlChar *systemId)
1047 fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n",
1048 (char *) name, (char *) publicId, (char *) systemId);
1052 * unparsedEntityDeclDebug:
1053 * @ctxt: An XML parser context
1054 * @name: The name of the entity
1055 * @publicId: The public ID of the entity
1056 * @systemId: The system ID of the entity
1057 * @notationName: the name of the notation
1059 * What to do when an unparsed entity declaration is parsed
1062 unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1063 const xmlChar *publicId, const xmlChar *systemId,
1064 const xmlChar *notationName)
1066 const xmlChar *nullstr = BAD_CAST "(null)";
1068 if (publicId == NULL)
1070 if (systemId == NULL)
1072 if (notationName == NULL)
1073 notationName = nullstr;
1077 fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
1078 (char *) name, (char *) publicId, (char *) systemId,
1079 (char *) notationName);
1083 * setDocumentLocatorDebug:
1084 * @ctxt: An XML parser context
1085 * @loc: A SAX Locator
1087 * Receive the document locator at startup, actually xmlDefaultSAXLocator
1088 * Everything is available on the context, so this is useless in our case.
1091 setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
1096 fprintf(SAXdebug, "SAX.setDocumentLocator()\n");
1100 * startDocumentDebug:
1101 * @ctxt: An XML parser context
1103 * called when the document start being processed.
1106 startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1111 fprintf(SAXdebug, "SAX.startDocument()\n");
1116 * @ctxt: An XML parser context
1118 * called when the document end has been detected.
1121 endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1126 fprintf(SAXdebug, "SAX.endDocument()\n");
1130 * startElementDebug:
1131 * @ctxt: An XML parser context
1132 * @name: The element name
1134 * called when an opening tag has been processed.
1137 startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1144 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1146 for (i = 0;(atts[i] != NULL);i++) {
1147 fprintf(SAXdebug, ", %s='", atts[i++]);
1148 if (atts[i] != NULL)
1149 fprintf(SAXdebug, "%s'", atts[i]);
1152 fprintf(SAXdebug, ")\n");
1157 * @ctxt: An XML parser context
1158 * @name: The element name
1160 * called when the end of an element has been detected.
1163 endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1168 fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name);
1173 * @ctxt: An XML parser context
1174 * @ch: a xmlChar string
1175 * @len: the number of xmlChar
1177 * receiving some chars from the parser.
1178 * Question: how much at a time ???
1181 charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1189 for (i = 0;(i<len) && (i < 30);i++)
1193 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1198 * @ctxt: An XML parser context
1199 * @name: The entity name
1201 * called when an entity reference is detected.
1204 referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1209 fprintf(SAXdebug, "SAX.reference(%s)\n", name);
1213 * ignorableWhitespaceDebug:
1214 * @ctxt: An XML parser context
1215 * @ch: a xmlChar string
1216 * @start: the first char in the string
1217 * @len: the number of xmlChar
1219 * receiving some ignorable whitespaces from the parser.
1220 * Question: how much at a time ???
1223 ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1231 for (i = 0;(i<len) && (i < 30);i++)
1234 fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
1238 * processingInstructionDebug:
1239 * @ctxt: An XML parser context
1240 * @target: the target name
1241 * @data: the PI data's
1242 * @len: the number of xmlChar
1244 * A processing instruction has been parsed.
1247 processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
1248 const xmlChar *data)
1254 fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
1255 (char *) target, (char *) data);
1257 fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n",
1263 * @ctx: the user data (XML parser context)
1264 * @value: The pcdata content
1265 * @len: the block length
1267 * called when a pcdata block has been parsed
1270 cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
1275 fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n",
1276 (char *) value, len);
1281 * @ctxt: An XML parser context
1282 * @value: the comment content
1284 * A comment has been parsed.
1287 commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
1292 fprintf(SAXdebug, "SAX.comment(%s)\n", value);
1297 * @ctxt: An XML parser context
1298 * @msg: the message to display/transmit
1299 * @...: extra parameters for the message display
1301 * Display and format a warning messages, gives file, line, position and
1304 static void XMLCDECL
1305 warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1312 va_start(args, msg);
1313 fprintf(SAXdebug, "SAX.warning: ");
1314 vfprintf(SAXdebug, msg, args);
1320 * @ctxt: An XML parser context
1321 * @msg: the message to display/transmit
1322 * @...: extra parameters for the message display
1324 * Display and format a error messages, gives file, line, position and
1327 static void XMLCDECL
1328 errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1335 va_start(args, msg);
1336 fprintf(SAXdebug, "SAX.error: ");
1337 vfprintf(SAXdebug, msg, args);
1343 * @ctxt: An XML parser context
1344 * @msg: the message to display/transmit
1345 * @...: extra parameters for the message display
1347 * Display and format a fatalError messages, gives file, line, position and
1350 static void XMLCDECL
1351 fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1358 va_start(args, msg);
1359 fprintf(SAXdebug, "SAX.fatalError: ");
1360 vfprintf(SAXdebug, msg, args);
1364 static xmlSAXHandler debugSAXHandlerStruct = {
1365 internalSubsetDebug,
1367 hasInternalSubsetDebug,
1368 hasExternalSubsetDebug,
1375 unparsedEntityDeclDebug,
1376 setDocumentLocatorDebug,
1383 ignorableWhitespaceDebug,
1384 processingInstructionDebug,
1389 getParameterEntityDebug,
1391 externalSubsetDebug,
1399 static xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
1402 * SAX2 specific callbacks
1405 * startElementNsDebug:
1406 * @ctxt: An XML parser context
1407 * @name: The element name
1409 * called when an opening tag has been processed.
1412 startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1413 const xmlChar *localname,
1414 const xmlChar *prefix,
1417 const xmlChar **namespaces,
1420 const xmlChar **attributes)
1427 fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
1429 fprintf(SAXdebug, ", NULL");
1431 fprintf(SAXdebug, ", %s", (char *) prefix);
1433 fprintf(SAXdebug, ", NULL");
1435 fprintf(SAXdebug, ", '%s'", (char *) URI);
1436 fprintf(SAXdebug, ", %d", nb_namespaces);
1438 if (namespaces != NULL) {
1439 for (i = 0;i < nb_namespaces * 2;i++) {
1440 fprintf(SAXdebug, ", xmlns");
1441 if (namespaces[i] != NULL)
1442 fprintf(SAXdebug, ":%s", namespaces[i]);
1444 fprintf(SAXdebug, "='%s'", namespaces[i]);
1447 fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
1448 if (attributes != NULL) {
1449 for (i = 0;i < nb_attributes * 5;i += 5) {
1450 if (attributes[i + 1] != NULL)
1451 fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
1453 fprintf(SAXdebug, ", %s='", attributes[i]);
1454 fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
1455 (int)(attributes[i + 4] - attributes[i + 3]));
1458 fprintf(SAXdebug, ")\n");
1463 * @ctxt: An XML parser context
1464 * @name: The element name
1466 * called when the end of an element has been detected.
1469 endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1470 const xmlChar *localname,
1471 const xmlChar *prefix,
1477 fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
1479 fprintf(SAXdebug, ", NULL");
1481 fprintf(SAXdebug, ", %s", (char *) prefix);
1483 fprintf(SAXdebug, ", NULL)\n");
1485 fprintf(SAXdebug, ", '%s')\n", (char *) URI);
1488 static xmlSAXHandler debugSAX2HandlerStruct = {
1489 internalSubsetDebug,
1491 hasInternalSubsetDebug,
1492 hasExternalSubsetDebug,
1499 unparsedEntityDeclDebug,
1500 setDocumentLocatorDebug,
1507 ignorableWhitespaceDebug,
1508 processingInstructionDebug,
1513 getParameterEntityDebug,
1515 externalSubsetDebug,
1518 startElementNsDebug,
1523 static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
1525 #ifdef LIBXML_HTML_ENABLED
1527 * htmlstartElementDebug:
1528 * @ctxt: An XML parser context
1529 * @name: The element name
1531 * called when an opening tag has been processed.
1534 htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1538 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1540 for (i = 0;(atts[i] != NULL);i++) {
1541 fprintf(SAXdebug, ", %s", atts[i++]);
1542 if (atts[i] != NULL) {
1543 unsigned char output[40];
1544 const unsigned char *att = atts[i];
1546 fprintf(SAXdebug, "='");
1547 while ((attlen = strlen((char*)att)) > 0) {
1548 outlen = sizeof output - 1;
1549 htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
1551 fprintf(SAXdebug, "%s", (char *) output);
1554 fprintf(SAXdebug, "'");
1558 fprintf(SAXdebug, ")\n");
1562 * htmlcharactersDebug:
1563 * @ctxt: An XML parser context
1564 * @ch: a xmlChar string
1565 * @len: the number of xmlChar
1567 * receiving some chars from the parser.
1568 * Question: how much at a time ???
1571 htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1573 unsigned char output[40];
1574 int inlen = len, outlen = 30;
1576 htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1579 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1584 * @ctxt: An XML parser context
1585 * @ch: a xmlChar string
1586 * @len: the number of xmlChar
1588 * receiving some cdata chars from the parser.
1589 * Question: how much at a time ???
1592 htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1594 unsigned char output[40];
1595 int inlen = len, outlen = 30;
1597 htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1600 fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
1603 static xmlSAXHandler debugHTMLSAXHandlerStruct = {
1604 internalSubsetDebug,
1606 hasInternalSubsetDebug,
1607 hasExternalSubsetDebug,
1614 unparsedEntityDeclDebug,
1615 setDocumentLocatorDebug,
1618 htmlstartElementDebug,
1621 htmlcharactersDebug,
1622 ignorableWhitespaceDebug,
1623 processingInstructionDebug,
1628 getParameterEntityDebug,
1630 externalSubsetDebug,
1638 static xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
1639 #endif /* LIBXML_HTML_ENABLED */
1641 #ifdef LIBXML_SAX1_ENABLED
1644 * @filename: the file to parse
1645 * @result: the file with expected result
1646 * @err: the file with error messages
1648 * Parse a file using the SAX API and check for errors.
1650 * Returns 0 in case of success, an error code otherwise
1653 saxParseTest(const char *filename, const char *result,
1654 const char *err ATTRIBUTE_UNUSED,
1660 temp = resultFilename(filename, "", ".res");
1662 fprintf(stderr, "out of memory\n");
1665 SAXdebug = fopen(temp, "wb");
1666 if (SAXdebug == NULL) {
1667 fprintf(stderr, "Failed to write to %s\n", temp);
1672 /* for SAX we really want the callbacks though the context handlers */
1673 xmlSetStructuredErrorFunc(NULL, NULL);
1674 xmlSetGenericErrorFunc(NULL, testErrorHandler);
1676 #ifdef LIBXML_HTML_ENABLED
1677 if (options & XML_PARSE_HTML) {
1678 htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);
1682 ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
1683 if (ret == XML_WAR_UNDECLARED_ENTITY) {
1684 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1688 fprintf(stderr, "Failed to parse %s\n", filename);
1691 #ifdef LIBXML_HTML_ENABLED
1692 if (options & XML_PARSE_HTML) {
1693 htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
1697 if (options & XML_PARSE_SAX1) {
1698 ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
1700 ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
1702 if (ret == XML_WAR_UNDECLARED_ENTITY) {
1703 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1707 if (compareFiles(temp, result)) {
1708 fprintf(stderr, "Got a difference for %s\n", filename);
1716 /* switch back to structured error handling */
1717 xmlSetGenericErrorFunc(NULL, NULL);
1718 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
1724 /************************************************************************
1726 * Parse to tree based tests *
1728 ************************************************************************/
1731 * @filename: the file to parse
1732 * @result: the file with expected result
1733 * @err: the file with error messages: unused
1735 * Parse a file using the old xmlParseFile API, then serialize back
1736 * reparse the result and serialize again, then check for deviation
1739 * Returns 0 in case of success, an error code otherwise
1742 oldParseTest(const char *filename, const char *result,
1743 const char *err ATTRIBUTE_UNUSED,
1744 int options ATTRIBUTE_UNUSED) {
1751 * base of the test, parse with the old API
1753 #ifdef LIBXML_SAX1_ENABLED
1754 doc = xmlParseFile(filename);
1756 doc = xmlReadFile(filename, NULL, 0);
1760 temp = resultFilename(filename, "", ".res");
1762 fprintf(stderr, "out of memory\n");
1765 xmlSaveFile(temp, doc);
1766 if (compareFiles(temp, result)) {
1772 * Parse the saved result to make sure the round trip is okay
1774 #ifdef LIBXML_SAX1_ENABLED
1775 doc = xmlParseFile(temp);
1777 doc = xmlReadFile(temp, NULL, 0);
1781 xmlSaveFile(temp, doc);
1782 if (compareFiles(temp, result)) {
1794 #ifdef LIBXML_PUSH_ENABLED
1797 * @filename: the file to parse
1798 * @result: the file with expected result
1799 * @err: the file with error messages: unused
1801 * Parse a file using the Push API, then serialize back
1802 * to check for content.
1804 * Returns 0 in case of success, an error code otherwise
1807 pushParseTest(const char *filename, const char *result,
1808 const char *err ATTRIBUTE_UNUSED,
1810 xmlParserCtxtPtr ctxt;
1818 * load the document in memory and work from there.
1820 if (loadMem(filename, &base, &size) != 0) {
1821 fprintf(stderr, "Failed to load %s\n", filename);
1825 #ifdef LIBXML_HTML_ENABLED
1826 if (options & XML_PARSE_HTML)
1827 ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,
1828 XML_CHAR_ENCODING_NONE);
1831 ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
1832 xmlCtxtUseOptions(ctxt, options);
1834 while (cur < size) {
1835 if (cur + 1024 >= size) {
1836 #ifdef LIBXML_HTML_ENABLED
1837 if (options & XML_PARSE_HTML)
1838 htmlParseChunk(ctxt, base + cur, size - cur, 1);
1841 xmlParseChunk(ctxt, base + cur, size - cur, 1);
1844 #ifdef LIBXML_HTML_ENABLED
1845 if (options & XML_PARSE_HTML)
1846 htmlParseChunk(ctxt, base + cur, 1024, 0);
1849 xmlParseChunk(ctxt, base + cur, 1024, 0);
1854 #ifdef LIBXML_HTML_ENABLED
1855 if (options & XML_PARSE_HTML)
1859 res = ctxt->wellFormed;
1860 xmlFreeParserCtxt(ctxt);
1864 fprintf(stderr, "Failed to parse %s\n", filename);
1867 #ifdef LIBXML_HTML_ENABLED
1868 if (options & XML_PARSE_HTML)
1869 htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1872 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1874 res = compareFileMem(result, base, size);
1875 if ((base == NULL) || (res != 0)) {
1877 xmlFree((char *)base);
1878 fprintf(stderr, "Result for %s failed\n", filename);
1881 xmlFree((char *)base);
1883 res = compareFileMem(err, testErrors, testErrorsSize);
1885 fprintf(stderr, "Error for %s failed\n", filename);
1895 * @filename: the file to parse
1896 * @result: the file with expected result
1897 * @err: the file with error messages: unused
1899 * Parse a file using the old xmlReadMemory API, then serialize back
1900 * reparse the result and serialize again, then check for deviation
1903 * Returns 0 in case of success, an error code otherwise
1906 memParseTest(const char *filename, const char *result,
1907 const char *err ATTRIBUTE_UNUSED,
1908 int options ATTRIBUTE_UNUSED) {
1915 * load and parse the memory
1917 if (loadMem(filename, &base, &size) != 0) {
1918 fprintf(stderr, "Failed to load %s\n", filename);
1922 doc = xmlReadMemory(base, size, filename, NULL, 0);
1927 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1929 res = compareFileMem(result, base, size);
1930 if ((base == NULL) || (res != 0)) {
1932 xmlFree((char *)base);
1933 fprintf(stderr, "Result for %s failed\n", filename);
1936 xmlFree((char *)base);
1942 * @filename: the file to parse
1943 * @result: the file with expected result
1944 * @err: the file with error messages: unused
1946 * Parse a file with entity resolution, then serialize back
1947 * reparse the result and serialize again, then check for deviation
1950 * Returns 0 in case of success, an error code otherwise
1953 noentParseTest(const char *filename, const char *result,
1954 const char *err ATTRIBUTE_UNUSED,
1962 * base of the test, parse with the old API
1964 doc = xmlReadFile(filename, NULL, options);
1967 temp = resultFilename(filename, "", ".res");
1969 fprintf(stderr, "Out of memory\n");
1972 xmlSaveFile(temp, doc);
1973 if (compareFiles(temp, result)) {
1979 * Parse the saved result to make sure the round trip is okay
1981 doc = xmlReadFile(filename, NULL, options);
1984 xmlSaveFile(temp, doc);
1985 if (compareFiles(temp, result)) {
1999 * @filename: the file to parse
2000 * @result: the file with expected result
2001 * @err: the file with error messages
2003 * Parse a file using the xmlReadFile API and check for errors.
2005 * Returns 0 in case of success, an error code otherwise
2008 errParseTest(const char *filename, const char *result, const char *err,
2011 const char *base = NULL;
2015 #ifdef LIBXML_HTML_ENABLED
2016 if (options & XML_PARSE_HTML) {
2017 doc = htmlReadFile(filename, NULL, options);
2020 #ifdef LIBXML_XINCLUDE_ENABLED
2021 if (options & XML_PARSE_XINCLUDE) {
2022 doc = xmlReadFile(filename, NULL, options);
2023 xmlXIncludeProcessFlags(doc, options);
2027 xmlGetWarningsDefaultValue = 1;
2028 doc = xmlReadFile(filename, NULL, options);
2030 xmlGetWarningsDefaultValue = 0;
2036 #ifdef LIBXML_HTML_ENABLED
2037 if (options & XML_PARSE_HTML) {
2038 htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2041 xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2043 res = compareFileMem(result, base, size);
2047 xmlFree((char *)base);
2051 fprintf(stderr, "Result for %s failed\n", filename);
2055 res = compareFileMem(err, testErrors, testErrorsSize);
2057 fprintf(stderr, "Error for %s failed\n", filename);
2060 } else if (options & XML_PARSE_DTDVALID) {
2061 if (testErrorsSize != 0)
2062 fprintf(stderr, "Validation for %s failed\n", filename);
2068 #ifdef LIBXML_READER_ENABLED
2069 /************************************************************************
2071 * Reader based tests *
2073 ************************************************************************/
2075 static void processNode(FILE *out, xmlTextReaderPtr reader) {
2076 const xmlChar *name, *value;
2079 type = xmlTextReaderNodeType(reader);
2080 empty = xmlTextReaderIsEmptyElement(reader);
2082 name = xmlTextReaderConstName(reader);
2084 name = BAD_CAST "--";
2086 value = xmlTextReaderConstValue(reader);
2089 fprintf(out, "%d %d %s %d %d",
2090 xmlTextReaderDepth(reader),
2094 xmlTextReaderHasValue(reader));
2098 fprintf(out, " %s\n", value);
2102 streamProcessTest(const char *filename, const char *result, const char *err,
2103 xmlTextReaderPtr reader, const char *rng) {
2112 if (result != NULL) {
2113 temp = resultFilename(filename, "", ".res");
2115 fprintf(stderr, "Out of memory\n");
2118 t = fopen(temp, "wb");
2120 fprintf(stderr, "Can't open temp file %s\n", temp);
2125 #ifdef LIBXML_SCHEMAS_ENABLED
2127 ret = xmlTextReaderRelaxNGValidate(reader, rng);
2129 testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
2140 xmlGetWarningsDefaultValue = 1;
2141 ret = xmlTextReaderRead(reader);
2143 if ((t != NULL) && (rng == NULL))
2144 processNode(t, reader);
2145 ret = xmlTextReaderRead(reader);
2148 testErrorHandler(NULL, "%s : failed to parse\n", filename);
2151 if (xmlTextReaderIsValid(reader) != 1) {
2152 testErrorHandler(NULL, "%s fails to validate\n", filename);
2154 testErrorHandler(NULL, "%s validates\n", filename);
2157 xmlGetWarningsDefaultValue = 0;
2160 ret = compareFiles(temp, result);
2166 fprintf(stderr, "Result for %s failed\n", filename);
2171 ret = compareFileMem(err, testErrors, testErrorsSize);
2173 fprintf(stderr, "Error for %s failed\n", filename);
2174 printf("%s", testErrors);
2184 * @filename: the file to parse
2185 * @result: the file with expected result
2186 * @err: the file with error messages
2188 * Parse a file using the reader API and check for errors.
2190 * Returns 0 in case of success, an error code otherwise
2193 streamParseTest(const char *filename, const char *result, const char *err,
2195 xmlTextReaderPtr reader;
2198 reader = xmlReaderForFile(filename, NULL, options);
2199 ret = streamProcessTest(filename, result, err, reader, NULL);
2200 xmlFreeTextReader(reader);
2206 * @filename: the file to parse
2207 * @result: the file with expected result
2208 * @err: the file with error messages
2210 * Parse a file using the walker, i.e. a reader built from a atree.
2212 * Returns 0 in case of success, an error code otherwise
2215 walkerParseTest(const char *filename, const char *result, const char *err,
2218 xmlTextReaderPtr reader;
2221 doc = xmlReadFile(filename, NULL, options);
2223 fprintf(stderr, "Failed to parse %s\n", filename);
2226 reader = xmlReaderWalker(doc);
2227 ret = streamProcessTest(filename, result, err, reader, NULL);
2228 xmlFreeTextReader(reader);
2234 * streamMemParseTest:
2235 * @filename: the file to parse
2236 * @result: the file with expected result
2237 * @err: the file with error messages
2239 * Parse a file using the reader API from memory and check for errors.
2241 * Returns 0 in case of success, an error code otherwise
2244 streamMemParseTest(const char *filename, const char *result, const char *err,
2246 xmlTextReaderPtr reader;
2252 * load and parse the memory
2254 if (loadMem(filename, &base, &size) != 0) {
2255 fprintf(stderr, "Failed to load %s\n", filename);
2258 reader = xmlReaderForMemory(base, size, filename, NULL, options);
2259 ret = streamProcessTest(filename, result, err, reader, NULL);
2261 xmlFreeTextReader(reader);
2266 #ifdef LIBXML_XPATH_ENABLED
2267 #ifdef LIBXML_DEBUG_ENABLED
2268 /************************************************************************
2270 * XPath and XPointer based tests *
2272 ************************************************************************/
2274 static FILE *xpathOutput;
2275 static xmlDocPtr xpathDocument;
2278 testXPath(const char *str, int xptr, int expr) {
2279 xmlXPathObjectPtr res;
2280 xmlXPathContextPtr ctxt;
2283 #if defined(LIBXML_XPTR_ENABLED)
2285 ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
2286 res = xmlXPtrEval(BAD_CAST str, ctxt);
2289 ctxt = xmlXPathNewContext(xpathDocument);
2290 ctxt->node = xmlDocGetRootElement(xpathDocument);
2292 res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
2294 /* res = xmlXPathEval(BAD_CAST str, ctxt); */
2295 xmlXPathCompExprPtr comp;
2297 comp = xmlXPathCompile(BAD_CAST str);
2299 res = xmlXPathCompiledEval(comp, ctxt);
2300 xmlXPathFreeCompExpr(comp);
2304 #if defined(LIBXML_XPTR_ENABLED)
2307 xmlXPathDebugDumpObject(xpathOutput, res, 0);
2308 xmlXPathFreeObject(res);
2309 xmlXPathFreeContext(ctxt);
2314 * @filename: the file to parse
2315 * @result: the file with expected result
2316 * @err: the file with error messages
2318 * Parse a file containing XPath standalone expressions and evaluate them
2320 * Returns 0 in case of success, an error code otherwise
2323 xpathCommonTest(const char *filename, const char *result,
2324 int xptr, int expr) {
2326 char expression[5000];
2330 temp = resultFilename(filename, "", ".res");
2332 fprintf(stderr, "Out of memory\n");
2335 xpathOutput = fopen(temp, "wb");
2336 if (xpathOutput == NULL) {
2337 fprintf(stderr, "failed to open output file %s\n", temp);
2342 input = fopen(filename, "rb");
2343 if (input == NULL) {
2344 xmlGenericError(xmlGenericErrorContext,
2345 "Cannot open %s for reading\n", filename);
2349 while (fgets(expression, 4500, input) != NULL) {
2350 len = strlen(expression);
2352 while ((len >= 0) &&
2353 ((expression[len] == '\n') || (expression[len] == '\t') ||
2354 (expression[len] == '\r') || (expression[len] == ' '))) len--;
2355 expression[len + 1] = 0;
2357 fprintf(xpathOutput,
2358 "\n========================\nExpression: %s\n",
2360 testXPath(expression, xptr, expr);
2365 fclose(xpathOutput);
2366 if (result != NULL) {
2367 ret = compareFiles(temp, result);
2369 fprintf(stderr, "Result for %s failed\n", filename);
2382 * @filename: the file to parse
2383 * @result: the file with expected result
2384 * @err: the file with error messages
2386 * Parse a file containing XPath standalone expressions and evaluate them
2388 * Returns 0 in case of success, an error code otherwise
2391 xpathExprTest(const char *filename, const char *result,
2392 const char *err ATTRIBUTE_UNUSED,
2393 int options ATTRIBUTE_UNUSED) {
2394 return(xpathCommonTest(filename, result, 0, 1));
2399 * @filename: the file to parse
2400 * @result: the file with expected result
2401 * @err: the file with error messages
2403 * Parse a file containing XPath expressions and evaluate them against
2404 * a set of corresponding documents.
2406 * Returns 0 in case of success, an error code otherwise
2409 xpathDocTest(const char *filename,
2410 const char *resul ATTRIBUTE_UNUSED,
2411 const char *err ATTRIBUTE_UNUSED,
2420 xpathDocument = xmlReadFile(filename, NULL,
2421 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2422 if (xpathDocument == NULL) {
2423 fprintf(stderr, "Failed to load %s\n", filename);
2427 snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
2429 globbuf.gl_offs = 0;
2430 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2431 for (i = 0;i < globbuf.gl_pathc;i++) {
2432 snprintf(result, 499, "result/XPath/tests/%s",
2433 baseFilename(globbuf.gl_pathv[i]));
2434 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
2440 xmlFreeDoc(xpathDocument);
2444 #ifdef LIBXML_XPTR_ENABLED
2447 * @filename: the file to parse
2448 * @result: the file with expected result
2449 * @err: the file with error messages
2451 * Parse a file containing XPath expressions and evaluate them against
2452 * a set of corresponding documents.
2454 * Returns 0 in case of success, an error code otherwise
2457 xptrDocTest(const char *filename,
2458 const char *resul ATTRIBUTE_UNUSED,
2459 const char *err ATTRIBUTE_UNUSED,
2468 xpathDocument = xmlReadFile(filename, NULL,
2469 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2470 if (xpathDocument == NULL) {
2471 fprintf(stderr, "Failed to load %s\n", filename);
2475 snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
2477 globbuf.gl_offs = 0;
2478 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2479 for (i = 0;i < globbuf.gl_pathc;i++) {
2480 snprintf(result, 499, "result/XPath/xptr/%s",
2481 baseFilename(globbuf.gl_pathv[i]));
2482 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
2488 xmlFreeDoc(xpathDocument);
2491 #endif /* LIBXML_XPTR_ENABLED */
2495 * @filename: the file to parse
2496 * @result: the file with expected result
2497 * @err: the file with error messages
2499 * Parse a file containing xml:id and check for errors and verify
2500 * that XPath queries will work on them as expected.
2502 * Returns 0 in case of success, an error code otherwise
2505 xmlidDocTest(const char *filename,
2514 xpathDocument = xmlReadFile(filename, NULL,
2515 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2516 if (xpathDocument == NULL) {
2517 fprintf(stderr, "Failed to load %s\n", filename);
2521 temp = resultFilename(filename, "", ".res");
2523 fprintf(stderr, "Out of memory\n");
2526 xpathOutput = fopen(temp, "wb");
2527 if (xpathOutput == NULL) {
2528 fprintf(stderr, "failed to open output file %s\n", temp);
2529 xmlFreeDoc(xpathDocument);
2534 testXPath("id('bar')", 0, 0);
2536 fclose(xpathOutput);
2537 if (result != NULL) {
2538 ret = compareFiles(temp, result);
2540 fprintf(stderr, "Result for %s failed\n", filename);
2549 xmlFreeDoc(xpathDocument);
2552 ret = compareFileMem(err, testErrors, testErrorsSize);
2554 fprintf(stderr, "Error for %s failed\n", filename);
2561 #endif /* LIBXML_DEBUG_ENABLED */
2563 /************************************************************************
2567 ************************************************************************/
2570 handleURI(const char *str, const char *base, FILE *o) {
2573 xmlChar *res = NULL;
2575 uri = xmlCreateURI();
2578 ret = xmlParseURIReference(uri, str);
2580 fprintf(o, "%s : error %d\n", str, ret);
2582 xmlNormalizeURIPath(uri->path);
2583 xmlPrintURI(o, uri);
2587 res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
2589 fprintf(o, "%s\n", (char *) res);
2592 fprintf(o, "::ERROR::\n");
2601 * @filename: the file to parse
2602 * @result: the file with expected result
2603 * @err: the file with error messages
2605 * Parse a file containing URI and check for errors
2607 * Returns 0 in case of success, an error code otherwise
2610 uriCommonTest(const char *filename,
2617 int res = 0, i, ret;
2619 temp = resultFilename(filename, "", ".res");
2621 fprintf(stderr, "Out of memory\n");
2624 o = fopen(temp, "wb");
2626 fprintf(stderr, "failed to open output file %s\n", temp);
2630 f = fopen(filename, "rb");
2632 fprintf(stderr, "failed to open input file %s\n", filename);
2643 * read one line in string buffer.
2645 if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
2649 * remove the ending spaces
2653 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
2654 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
2659 handleURI(str, base, o);
2665 if (result != NULL) {
2666 ret = compareFiles(temp, result);
2668 fprintf(stderr, "Result for %s failed\n", filename);
2673 ret = compareFileMem(err, testErrors, testErrorsSize);
2675 fprintf(stderr, "Error for %s failed\n", filename);
2689 * @filename: the file to parse
2690 * @result: the file with expected result
2691 * @err: the file with error messages
2693 * Parse a file containing URI and check for errors
2695 * Returns 0 in case of success, an error code otherwise
2698 uriParseTest(const char *filename,
2701 int options ATTRIBUTE_UNUSED) {
2702 return(uriCommonTest(filename, result, err, NULL));
2707 * @filename: the file to parse
2708 * @result: the file with expected result
2709 * @err: the file with error messages
2711 * Parse a file containing URI, compose them against a fixed base and
2714 * Returns 0 in case of success, an error code otherwise
2717 uriBaseTest(const char *filename,
2720 int options ATTRIBUTE_UNUSED) {
2721 return(uriCommonTest(filename, result, err,
2722 "http://foo.com/path/to/index.html?orig#help"));
2725 static int urip_success = 1;
2726 static int urip_current = 0;
2727 static const char *urip_testURLs[] = {
2728 "urip://example.com/a b.html",
2729 "urip://example.com/a%20b.html",
2730 "file:///path/to/a b.html",
2731 "file:///path/to/a%20b.html",
2732 "/path/to/a b.html",
2733 "/path/to/a%20b.html",
2734 "urip://example.com/résumé.html",
2735 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2738 static const char *urip_rcvsURLs[] = {
2739 /* it is an URI the strings must be escaped */
2740 "urip://example.com/a%20b.html",
2741 /* check that % escaping is not broken */
2742 "urip://example.com/a%20b.html",
2743 /* it's an URI path the strings must be escaped */
2744 "file:///path/to/a%20b.html",
2745 /* check that % escaping is not broken */
2746 "file:///path/to/a%20b.html",
2747 /* this is not an URI, this is a path, so this should not be escaped */
2748 "/path/to/a b.html",
2749 /* check that paths with % are not broken */
2750 "/path/to/a%20b.html",
2751 /* out of context the encoding can't be guessed byte by byte conversion */
2752 "urip://example.com/r%E9sum%E9.html",
2753 /* verify we don't destroy URIs especially the query part */
2754 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2757 static const char *urip_res = "<list/>";
2758 static const char *urip_cur = NULL;
2759 static int urip_rlen;
2763 * @URI: an URI to test
2765 * Check for an urip: query
2767 * Returns 1 if yes and 0 if another Input module should be used
2770 uripMatch(const char * URI) {
2771 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2773 /* Verify we received the escaped URL */
2774 if (strcmp(urip_rcvsURLs[urip_current], URI))
2781 * @URI: an URI to test
2783 * Return a pointer to the urip: query handler, in this example simply
2784 * the urip_current pointer...
2786 * Returns an Input context or NULL in case or error
2789 uripOpen(const char * URI) {
2790 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2792 /* Verify we received the escaped URL */
2793 if (strcmp(urip_rcvsURLs[urip_current], URI))
2795 urip_cur = urip_res;
2796 urip_rlen = strlen(urip_res);
2797 return((void *) urip_cur);
2802 * @context: the read context
2804 * Close the urip: query handler
2806 * Returns 0 or -1 in case of error
2809 uripClose(void * context) {
2810 if (context == NULL) return(-1);
2818 * @context: the read context
2819 * @buffer: where to store data
2820 * @len: number of bytes to read
2822 * Implement an urip: query read.
2824 * Returns the number of bytes read or -1 in case of error
2827 uripRead(void * context, char * buffer, int len) {
2828 const char *ptr = (const char *) context;
2830 if ((context == NULL) || (buffer == NULL) || (len < 0))
2833 if (len > urip_rlen) len = urip_rlen;
2834 memcpy(buffer, ptr, len);
2840 urip_checkURL(const char *URL) {
2843 doc = xmlReadFile(URL, NULL, 0);
2852 * @filename: ignored
2856 * Run a set of tests to check how Path and URI are handled before
2857 * being passed to the I/O layer
2859 * Returns 0 in case of success, an error code otherwise
2862 uriPathTest(const char *filename ATTRIBUTE_UNUSED,
2863 const char *result ATTRIBUTE_UNUSED,
2864 const char *err ATTRIBUTE_UNUSED,
2865 int options ATTRIBUTE_UNUSED) {
2870 * register the new I/O handlers
2872 if (xmlRegisterInputCallbacks(uripMatch, uripOpen, uripRead, uripClose) < 0)
2874 fprintf(stderr, "failed to register HTTP handler\n");
2878 for (urip_current = 0;urip_testURLs[urip_current] != NULL;urip_current++) {
2880 parsed = urip_checkURL(urip_testURLs[urip_current]);
2881 if (urip_success != 1) {
2882 fprintf(stderr, "failed the URL passing test for %s",
2883 urip_testURLs[urip_current]);
2885 } else if (parsed != 1) {
2886 fprintf(stderr, "failed the parsing test for %s",
2887 urip_testURLs[urip_current]);
2893 xmlPopInputCallbacks();
2897 #ifdef LIBXML_SCHEMAS_ENABLED
2898 /************************************************************************
2902 ************************************************************************/
2904 schemasOneTest(const char *sch,
2905 const char *filename,
2909 xmlSchemaPtr schemas) {
2911 xmlSchemaValidCtxtPtr ctxt;
2913 int validResult = 0;
2915 FILE *schemasOutput;
2917 doc = xmlReadFile(filename, NULL, options);
2919 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
2923 temp = resultFilename(result, "", ".res");
2925 fprintf(stderr, "Out of memory\n");
2928 schemasOutput = fopen(temp, "wb");
2929 if (schemasOutput == NULL) {
2930 fprintf(stderr, "failed to open output file %s\n", temp);
2936 ctxt = xmlSchemaNewValidCtxt(schemas);
2937 xmlSchemaSetValidErrors(ctxt,
2938 (xmlSchemaValidityErrorFunc) testErrorHandler,
2939 (xmlSchemaValidityWarningFunc) testErrorHandler,
2941 validResult = xmlSchemaValidateDoc(ctxt, doc);
2942 if (validResult == 0) {
2943 fprintf(schemasOutput, "%s validates\n", filename);
2944 } else if (validResult > 0) {
2945 fprintf(schemasOutput, "%s fails to validate\n", filename);
2947 fprintf(schemasOutput, "%s validation generated an internal error\n",
2950 fclose(schemasOutput);
2952 if (compareFiles(temp, result)) {
2953 fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
2962 if ((validResult != 0) && (err != NULL)) {
2963 if (compareFileMem(err, testErrors, testErrorsSize)) {
2964 fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
2969 xmlSchemaFreeValidCtxt(ctxt);
2975 * @filename: the schemas file
2976 * @result: the file with expected result
2977 * @err: the file with error messages
2979 * Parse a file containing URI, compose them against a fixed base and
2982 * Returns 0 in case of success, an error code otherwise
2985 schemasTest(const char *filename,
2986 const char *resul ATTRIBUTE_UNUSED,
2987 const char *errr ATTRIBUTE_UNUSED,
2989 const char *base = baseFilename(filename);
2991 const char *instance;
2992 xmlSchemaParserCtxtPtr ctxt;
2993 xmlSchemaPtr schemas;
2994 int res = 0, len, ret;
3003 /* first compile the schemas if possible */
3004 ctxt = xmlSchemaNewParserCtxt(filename);
3005 xmlSchemaSetParserErrors(ctxt,
3006 (xmlSchemaValidityErrorFunc) testErrorHandler,
3007 (xmlSchemaValidityWarningFunc) testErrorHandler,
3009 schemas = xmlSchemaParse(ctxt);
3010 xmlSchemaFreeParserCtxt(ctxt);
3013 * most of the mess is about the output filenames generated by the Makefile
3016 if ((len > 499) || (len < 5)) {
3017 xmlSchemaFree(schemas);
3020 len -= 4; /* remove trailing .xsd */
3021 if (base[len - 2] == '_') {
3022 len -= 2; /* remove subtest number */
3024 if (base[len - 2] == '_') {
3025 len -= 2; /* remove subtest number */
3027 memcpy(prefix, base, len);
3030 snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
3033 if (base[len] == '_') {
3035 memcpy(prefix, base, len);
3039 globbuf.gl_offs = 0;
3040 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3041 for (i = 0;i < globbuf.gl_pathc;i++) {
3044 instance = globbuf.gl_pathv[i];
3045 base2 = baseFilename(instance);
3046 len = strlen(base2);
3047 if ((len > 6) && (base2[len - 6] == '_')) {
3048 count = base2[len - 5];
3049 snprintf(result, 499, "result/schemas/%s_%c",
3052 snprintf(err, 499, "result/schemas/%s_%c.err",
3056 fprintf(stderr, "don't know how to process %s\n", instance);
3059 if (schemas == NULL) {
3062 ret = schemasOneTest(filename, instance, result, err,
3069 xmlSchemaFree(schemas);
3074 /************************************************************************
3078 ************************************************************************/
3080 rngOneTest(const char *sch,
3081 const char *filename,
3085 xmlRelaxNGPtr schemas) {
3087 xmlRelaxNGValidCtxtPtr ctxt;
3090 FILE *schemasOutput;
3092 doc = xmlReadFile(filename, NULL, options);
3094 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
3098 temp = resultFilename(result, "", ".res");
3100 fprintf(stderr, "Out of memory\n");
3103 schemasOutput = fopen(temp, "wb");
3104 if (schemasOutput == NULL) {
3105 fprintf(stderr, "failed to open output file %s\n", temp);
3111 ctxt = xmlRelaxNGNewValidCtxt(schemas);
3112 xmlRelaxNGSetValidErrors(ctxt,
3113 (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3114 (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3116 ret = xmlRelaxNGValidateDoc(ctxt, doc);
3118 testErrorHandler(NULL, "%s validates\n", filename);
3119 } else if (ret > 0) {
3120 testErrorHandler(NULL, "%s fails to validate\n", filename);
3122 testErrorHandler(NULL, "%s validation generated an internal error\n",
3125 fclose(schemasOutput);
3128 if (compareFiles(temp, result)) {
3129 fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
3139 if (compareFileMem(err, testErrors, testErrorsSize)) {
3140 fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
3142 printf("%s", testErrors);
3147 xmlRelaxNGFreeValidCtxt(ctxt);
3153 * @filename: the schemas file
3154 * @result: the file with expected result
3155 * @err: the file with error messages
3157 * Parse an RNG schemas and then apply it to the related .xml
3159 * Returns 0 in case of success, an error code otherwise
3162 rngTest(const char *filename,
3163 const char *resul ATTRIBUTE_UNUSED,
3164 const char *errr ATTRIBUTE_UNUSED,
3166 const char *base = baseFilename(filename);
3168 const char *instance;
3169 xmlRelaxNGParserCtxtPtr ctxt;
3170 xmlRelaxNGPtr schemas;
3171 int res = 0, len, ret = 0;
3180 /* first compile the schemas if possible */
3181 ctxt = xmlRelaxNGNewParserCtxt(filename);
3182 xmlRelaxNGSetParserErrors(ctxt,
3183 (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3184 (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3186 schemas = xmlRelaxNGParse(ctxt);
3187 xmlRelaxNGFreeParserCtxt(ctxt);
3190 * most of the mess is about the output filenames generated by the Makefile
3193 if ((len > 499) || (len < 5)) {
3194 xmlRelaxNGFree(schemas);
3197 len -= 4; /* remove trailing .rng */
3198 memcpy(prefix, base, len);
3201 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3204 globbuf.gl_offs = 0;
3205 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3206 for (i = 0;i < globbuf.gl_pathc;i++) {
3209 instance = globbuf.gl_pathv[i];
3210 base2 = baseFilename(instance);
3211 len = strlen(base2);
3212 if ((len > 6) && (base2[len - 6] == '_')) {
3213 count = base2[len - 5];
3214 snprintf(result, 499, "result/relaxng/%s_%c",
3217 snprintf(err, 499, "result/relaxng/%s_%c.err",
3221 fprintf(stderr, "don't know how to process %s\n", instance);
3224 if (schemas == NULL) {
3227 ret = rngOneTest(filename, instance, result, err,
3234 xmlRelaxNGFree(schemas);
3239 #ifdef LIBXML_READER_ENABLED
3242 * @filename: the schemas file
3243 * @result: the file with expected result
3244 * @err: the file with error messages
3246 * Parse a set of files with streaming, applying an RNG schemas
3248 * Returns 0 in case of success, an error code otherwise
3251 rngStreamTest(const char *filename,
3252 const char *resul ATTRIBUTE_UNUSED,
3253 const char *errr ATTRIBUTE_UNUSED,
3255 const char *base = baseFilename(filename);
3257 const char *instance;
3258 int res = 0, len, ret;
3266 xmlTextReaderPtr reader;
3267 int disable_err = 0;
3270 * most of the mess is about the output filenames generated by the Makefile
3273 if ((len > 499) || (len < 5)) {
3274 fprintf(stderr, "len(base) == %d !\n", len);
3277 len -= 4; /* remove trailing .rng */
3278 memcpy(prefix, base, len);
3282 * strictly unifying the error messages is nearly impossible this
3283 * hack is also done in the Makefile
3285 if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
3286 (!strcmp(prefix, "tutor3_2")) || (!strcmp(prefix, "307377")) ||
3287 (!strcmp(prefix, "tutor8_2")))
3290 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3293 globbuf.gl_offs = 0;
3294 glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3295 for (i = 0;i < globbuf.gl_pathc;i++) {
3298 instance = globbuf.gl_pathv[i];
3299 base2 = baseFilename(instance);
3300 len = strlen(base2);
3301 if ((len > 6) && (base2[len - 6] == '_')) {
3302 count = base2[len - 5];
3303 snprintf(result, 499, "result/relaxng/%s_%c",
3306 snprintf(err, 499, "result/relaxng/%s_%c.err",
3310 fprintf(stderr, "don't know how to process %s\n", instance);
3313 reader = xmlReaderForFile(instance, NULL, options);
3314 if (reader == NULL) {
3315 fprintf(stderr, "Failed to build reder for %s\n", instance);
3317 if (disable_err == 1)
3318 ret = streamProcessTest(instance, result, NULL, reader, filename);
3320 ret = streamProcessTest(instance, result, err, reader, filename);
3321 xmlFreeTextReader(reader);
3323 fprintf(stderr, "instance %s failed\n", instance);
3335 #ifdef LIBXML_PATTERN_ENABLED
3336 #ifdef LIBXML_READER_ENABLED
3337 /************************************************************************
3341 ************************************************************************/
3342 static void patternNode(FILE *out, xmlTextReaderPtr reader,
3343 const char *pattern, xmlPatternPtr patternc,
3344 xmlStreamCtxtPtr patstream) {
3345 xmlChar *path = NULL;
3349 type = xmlTextReaderNodeType(reader);
3350 empty = xmlTextReaderIsEmptyElement(reader);
3352 if (type == XML_READER_TYPE_ELEMENT) {
3353 /* do the check only on element start */
3354 match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
3357 path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
3358 fprintf(out, "Node %s matches pattern %s\n", path, pattern);
3361 if (patstream != NULL) {
3364 if (type == XML_READER_TYPE_ELEMENT) {
3365 ret = xmlStreamPush(patstream,
3366 xmlTextReaderConstLocalName(reader),
3367 xmlTextReaderConstNamespaceUri(reader));
3369 fprintf(out, "xmlStreamPush() failure\n");
3370 xmlFreeStreamCtxt(patstream);
3372 } else if (ret != match) {
3374 path = xmlGetNodePath(
3375 xmlTextReaderCurrentNode(reader));
3378 "xmlPatternMatch and xmlStreamPush disagree\n");
3380 " pattern %s node %s\n",
3386 if ((type == XML_READER_TYPE_END_ELEMENT) ||
3387 ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
3388 ret = xmlStreamPop(patstream);
3390 fprintf(out, "xmlStreamPop() failure\n");
3391 xmlFreeStreamCtxt(patstream);
3402 * @filename: the schemas file
3403 * @result: the file with expected result
3404 * @err: the file with error messages
3406 * Parse a set of files with streaming, applying an RNG schemas
3408 * Returns 0 in case of success, an error code otherwise
3411 patternTest(const char *filename,
3412 const char *resul ATTRIBUTE_UNUSED,
3413 const char *err ATTRIBUTE_UNUSED,
3415 xmlPatternPtr patternc = NULL;
3416 xmlStreamCtxtPtr patstream = NULL;
3424 xmlTextReaderPtr reader;
3427 len = strlen(filename);
3429 memcpy(xml, filename, len);
3431 snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
3433 memcpy(xml + len, ".xml", 5);
3435 if (!checkTestFile(xml)) {
3436 fprintf(stderr, "Missing xml file %s\n", xml);
3439 if (!checkTestFile(result)) {
3440 fprintf(stderr, "Missing result file %s\n", result);
3443 f = fopen(filename, "rb");
3445 fprintf(stderr, "Failed to open %s\n", filename);
3448 temp = resultFilename(filename, "", ".res");
3450 fprintf(stderr, "Out of memory\n");
3453 o = fopen(temp, "wb");
3455 fprintf(stderr, "failed to open output file %s\n", temp);
3462 * read one line in string buffer.
3464 if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
3468 * remove the ending spaces
3472 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
3473 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
3477 doc = xmlReadFile(xml, NULL, options);
3479 fprintf(stderr, "Failed to parse %s\n", xml);
3483 const xmlChar *namespaces[22];
3487 root = xmlDocGetRootElement(doc);
3488 for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
3489 namespaces[j++] = ns->href;
3490 namespaces[j++] = ns->prefix;
3492 namespaces[j++] = NULL;
3493 namespaces[j] = NULL;
3495 patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
3497 if (patternc == NULL) {
3498 testErrorHandler(NULL,
3499 "Pattern %s failed to compile\n", str);
3504 patstream = xmlPatternGetStreamCtxt(patternc);
3505 if (patstream != NULL) {
3506 ret = xmlStreamPush(patstream, NULL, NULL);
3508 fprintf(stderr, "xmlStreamPush() failure\n");
3509 xmlFreeStreamCtxt(patstream);
3515 reader = xmlReaderWalker(doc);
3516 res = xmlTextReaderRead(reader);
3518 patternNode(o, reader, str, patternc, patstream);
3519 res = xmlTextReaderRead(reader);
3522 fprintf(o, "%s : failed to parse\n", filename);
3524 xmlFreeTextReader(reader);
3526 xmlFreeStreamCtxt(patstream);
3528 xmlFreePattern(patternc);
3536 ret = compareFiles(temp, result);
3538 fprintf(stderr, "Result for %s failed\n", filename);
3548 #endif /* PATTERN */
3549 #ifdef LIBXML_C14N_ENABLED
3550 /************************************************************************
3552 * Canonicalization tests *
3554 ************************************************************************/
3555 static xmlXPathObjectPtr
3556 load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
3557 xmlXPathObjectPtr xpath;
3560 xmlXPathContextPtr ctx;
3565 * load XPath expr as a file
3567 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3568 xmlSubstituteEntitiesDefault(1);
3570 doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3572 fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
3577 * Check the document is of the right kind
3579 if(xmlDocGetRootElement(doc) == NULL) {
3580 fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
3585 node = doc->children;
3586 while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
3591 fprintf(stderr,"Error: XPath element expected in the file \"%s\"\n", filename);
3596 expr = xmlNodeGetContent(node);
3598 fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
3603 ctx = xmlXPathNewContext(parent_doc);
3605 fprintf(stderr,"Error: unable to create new context\n");
3612 * Register namespaces
3616 if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
3617 fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
3619 xmlXPathFreeContext(ctx);
3629 xpath = xmlXPathEvalExpression(expr, ctx);
3631 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3633 xmlXPathFreeContext(ctx);
3638 /* print_xpath_nodes(xpath->nodesetval); */
3641 xmlXPathFreeContext(ctx);
3647 * Macro used to grow the current buffer.
3649 #define xxx_growBufferReentrant() { \
3651 buffer = (xmlChar **) \
3652 xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \
3653 if (buffer == NULL) { \
3654 perror("realloc failed"); \
3660 parse_list(xmlChar *str) {
3662 xmlChar **out = NULL;
3663 int buffer_size = 0;
3670 len = xmlStrlen(str);
3671 if((str[0] == '\'') && (str[len - 1] == '\'')) {
3672 str[len - 1] = '\0';
3676 * allocate an translation buffer.
3679 buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
3680 if (buffer == NULL) {
3681 perror("malloc failed");
3686 while(*str != '\0') {
3687 if (out - buffer > buffer_size - 10) {
3688 int indx = out - buffer;
3690 xxx_growBufferReentrant();
3691 out = &buffer[indx];
3694 while(*str != ',' && *str != '\0') ++str;
3695 if(*str == ',') *(str++) = '\0';
3702 c14nRunTest(const char* xml_filename, int with_comments, int mode,
3703 const char* xpath_filename, const char *ns_filename,
3704 const char* result_file) {
3706 xmlXPathObjectPtr xpath = NULL;
3707 xmlChar *result = NULL;
3709 xmlChar **inclusive_namespaces = NULL;
3710 const char *nslist = NULL;
3715 * build an XML tree from a the file; we need to add default
3716 * attributes and resolve all character and entities references
3718 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3719 xmlSubstituteEntitiesDefault(1);
3721 doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3723 fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
3728 * Check the document is of the right kind
3730 if(xmlDocGetRootElement(doc) == NULL) {
3731 fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
3737 * load xpath file if specified
3739 if(xpath_filename) {
3740 xpath = load_xpath_expr(doc, xpath_filename);
3742 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3748 if (ns_filename != NULL) {
3749 if (loadMem(ns_filename, &nslist, &nssize)) {
3750 fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3751 if(xpath != NULL) xmlXPathFreeObject(xpath);
3755 inclusive_namespaces = parse_list((xmlChar *) nslist);
3761 /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
3762 ret = xmlC14NDocDumpMemory(doc,
3763 (xpath) ? xpath->nodesetval : NULL,
3764 mode, inclusive_namespaces,
3765 with_comments, &result);
3767 if(result != NULL) {
3768 if (compareFileMem(result_file, (const char *) result, ret)) {
3769 fprintf(stderr, "Result mismatch for %s\n", xml_filename);
3770 fprintf(stderr, "RESULT:\n%s\n", (const char*)result);
3775 fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
3782 if (result != NULL) xmlFree(result);
3783 if(xpath != NULL) xmlXPathFreeObject(xpath);
3784 if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
3785 if (nslist != NULL) free((char *) nslist);
3792 c14nCommonTest(const char *filename, int with_comments, int mode,
3793 const char *subdir) {
3798 char *result = NULL;
3803 base = baseFilename(filename);
3806 memcpy(prefix, base, len);
3809 snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
3810 if (!checkTestFile(buf)) {
3811 fprintf(stderr, "Missing result file %s", buf);
3814 result = strdup(buf);
3815 snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
3816 if (checkTestFile(buf)) {
3817 xpath = strdup(buf);
3819 snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
3820 if (checkTestFile(buf)) {
3825 if (c14nRunTest(filename, with_comments, mode,
3826 xpath, ns, result) < 0)
3829 if (result != NULL) free(result);
3830 if (xpath != NULL) free(xpath);
3831 if (ns != NULL) free(ns);
3836 c14nWithCommentTest(const char *filename,
3837 const char *resul ATTRIBUTE_UNUSED,
3838 const char *err ATTRIBUTE_UNUSED,
3839 int options ATTRIBUTE_UNUSED) {
3840 return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments"));
3843 c14nWithoutCommentTest(const char *filename,
3844 const char *resul ATTRIBUTE_UNUSED,
3845 const char *err ATTRIBUTE_UNUSED,
3846 int options ATTRIBUTE_UNUSED) {
3847 return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments"));
3850 c14nExcWithoutCommentTest(const char *filename,
3851 const char *resul ATTRIBUTE_UNUSED,
3852 const char *err ATTRIBUTE_UNUSED,
3853 int options ATTRIBUTE_UNUSED) {
3854 return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments"));
3857 c14n11WithoutCommentTest(const char *filename,
3858 const char *resul ATTRIBUTE_UNUSED,
3859 const char *err ATTRIBUTE_UNUSED,
3860 int options ATTRIBUTE_UNUSED) {
3861 return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments"));
3864 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined (LIBXML_SAX1_ENABLED)
3865 /************************************************************************
3867 * Catalog and threads test *
3869 ************************************************************************/
3872 * mostly a cut and paste from testThreads.c
3876 static const char *catalog = "test/threads/complex.xml";
3877 static const char *testfiles[] = {
3878 "test/threads/abc.xml",
3879 "test/threads/acb.xml",
3880 "test/threads/bac.xml",
3881 "test/threads/bca.xml",
3882 "test/threads/cab.xml",
3883 "test/threads/cba.xml",
3884 "test/threads/invalid.xml",
3887 static const char *Okay = "OK";
3888 static const char *Failed = "Failed";
3890 #ifndef xmlDoValidityCheckingDefaultValue
3891 #error xmlDoValidityCheckingDefaultValue is not a macro
3893 #ifndef xmlGenericErrorContext
3894 #error xmlGenericErrorContext is not a macro
3898 thread_specific_data(void *private_data)
3901 const char *filename = (const char *) private_data;
3904 if (!strcmp(filename, "test/threads/invalid.xml")) {
3905 xmlDoValidityCheckingDefaultValue = 0;
3906 xmlGenericErrorContext = stdout;
3908 xmlDoValidityCheckingDefaultValue = 1;
3909 xmlGenericErrorContext = stderr;
3911 myDoc = xmlParseFile(filename);
3915 printf("parse failed\n");
3918 if (!strcmp(filename, "test/threads/invalid.xml")) {
3919 if (xmlDoValidityCheckingDefaultValue != 0) {
3920 printf("ValidityCheckingDefaultValue override failed\n");
3923 if (xmlGenericErrorContext != stdout) {
3924 printf("xmlGenericErrorContext override failed\n");
3928 if (xmlDoValidityCheckingDefaultValue != 1) {
3929 printf("ValidityCheckingDefaultValue override failed\n");
3932 if (xmlGenericErrorContext != stderr) {
3933 printf("xmlGenericErrorContext override failed\n");
3938 return ((void *) Failed);
3939 return ((void *) Okay);
3942 #if defined(linux) || defined(__sun) || defined(__APPLE_CC__)
3944 #include <pthread.h>
3946 static pthread_t tid[MAX_ARGC];
3951 unsigned int i, repeat;
3952 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
3953 void *results[MAX_ARGC];
3959 for (repeat = 0; repeat < 500; repeat++) {
3960 xmlLoadCatalog(catalog);
3963 for (i = 0; i < num_threads; i++) {
3965 tid[i] = (pthread_t) - 1;
3968 for (i = 0; i < num_threads; i++) {
3969 ret = pthread_create(&tid[i], 0, thread_specific_data,
3970 (void *) testfiles[i]);
3972 fprintf(stderr, "pthread_create failed\n");
3976 for (i = 0; i < num_threads; i++) {
3977 ret = pthread_join(tid[i], &results[i]);
3979 fprintf(stderr, "pthread_join failed\n");
3984 xmlCatalogCleanup();
3985 for (i = 0; i < num_threads; i++)
3986 if (results[i] != (void *) Okay) {
3987 fprintf(stderr, "Thread %d handling %s failed\n",
3996 #include <windows.h>
3999 #define TEST_REPEAT_COUNT 500
4001 static HANDLE tid[MAX_ARGC];
4004 win32_thread_specific_data(void *private_data)
4006 return((DWORD) thread_specific_data(private_data));
4012 unsigned int i, repeat;
4013 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4014 DWORD results[MAX_ARGC];
4019 for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
4020 xmlLoadCatalog(catalog);
4023 for (i = 0; i < num_threads; i++) {
4025 tid[i] = (HANDLE) - 1;
4028 for (i = 0; i < num_threads; i++) {
4031 tid[i] = CreateThread(NULL, 0,
4032 win32_thread_specific_data,
4033 (void *) testfiles[i], 0,
4035 if (tid[i] == NULL) {
4036 fprintf(stderr, "CreateThread failed\n");
4041 if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
4043 fprintf(stderr, "WaitForMultipleObjects failed\n");
4047 for (i = 0; i < num_threads; i++) {
4048 ret = GetExitCodeThread(tid[i], &results[i]);
4050 fprintf(stderr, "GetExitCodeThread failed\n");
4053 CloseHandle(tid[i]);
4056 xmlCatalogCleanup();
4057 for (i = 0; i < num_threads; i++) {
4058 if (results[i] != (DWORD) Okay) {
4059 fprintf(stderr, "Thread %d handling %s failed\n",
4069 #elif defined __BEOS__
4072 static thread_id tid[MAX_ARGC];
4077 unsigned int i, repeat;
4078 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4079 void *results[MAX_ARGC];
4084 for (repeat = 0; repeat < 500; repeat++) {
4085 xmlLoadCatalog(catalog);
4086 for (i = 0; i < num_threads; i++) {
4088 tid[i] = (thread_id) - 1;
4090 for (i = 0; i < num_threads; i++) {
4092 spawn_thread(thread_specific_data, "xmlTestThread",
4093 B_NORMAL_PRIORITY, (void *) testfiles[i]);
4094 if (tid[i] < B_OK) {
4095 fprintf(stderr, "beos_thread_create failed\n");
4098 printf("beos_thread_create %d -> %d\n", i, tid[i]);
4100 for (i = 0; i < num_threads; i++) {
4101 ret = wait_for_thread(tid[i], &results[i]);
4102 printf("beos_thread_wait %d -> %d\n", i, ret);
4104 fprintf(stderr, "beos_thread_wait failed\n");
4109 xmlCatalogCleanup();
4111 for (i = 0; i < num_threads; i++)
4112 if (results[i] != (void *) Okay) {
4113 printf("Thread %d handling %s failed\n", i, testfiles[i]);
4126 "Specific platform thread support not detected\n");
4131 threadsTest(const char *filename ATTRIBUTE_UNUSED,
4132 const char *resul ATTRIBUTE_UNUSED,
4133 const char *err ATTRIBUTE_UNUSED,
4134 int options ATTRIBUTE_UNUSED) {
4135 return(testThread());
4138 /************************************************************************
4140 * Tests Descriptions *
4142 ************************************************************************/
4145 testDesc testDescriptions[] = {
4146 { "XML regression tests" ,
4147 oldParseTest, "./test/*", "result/", "", NULL,
4149 { "XML regression tests on memory" ,
4150 memParseTest, "./test/*", "result/", "", NULL,
4152 { "XML entity subst regression tests" ,
4153 noentParseTest, "./test/*", "result/noent/", "", NULL,
4155 { "XML Namespaces regression tests",
4156 errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
4158 { "Error cases regression tests",
4159 errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
4161 #ifdef LIBXML_READER_ENABLED
4162 { "Error cases stream regression tests",
4163 streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
4165 { "Reader regression tests",
4166 streamParseTest, "./test/*", "result/", ".rdr", NULL,
4168 { "Reader entities substitution regression tests",
4169 streamParseTest, "./test/*", "result/", ".rde", NULL,
4171 { "Reader on memory regression tests",
4172 streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
4174 { "Walker regression tests",
4175 walkerParseTest, "./test/*", "result/", ".rdr", NULL,
4178 #ifdef LIBXML_SAX1_ENABLED
4179 { "SAX1 callbacks regression tests" ,
4180 saxParseTest, "./test/*", "result/", ".sax", NULL,
4182 { "SAX2 callbacks regression tests" ,
4183 saxParseTest, "./test/*", "result/", ".sax2", NULL,
4186 #ifdef LIBXML_PUSH_ENABLED
4187 { "XML push regression tests" ,
4188 pushParseTest, "./test/*", "result/", "", NULL,
4191 #ifdef LIBXML_HTML_ENABLED
4192 { "HTML regression tests" ,
4193 errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4195 #ifdef LIBXML_PUSH_ENABLED
4196 { "Push HTML regression tests" ,
4197 pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4200 #ifdef LIBXML_SAX1_ENABLED
4201 { "HTML SAX regression tests" ,
4202 saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
4206 #ifdef LIBXML_VALID_ENABLED
4207 { "Valid documents regression tests" ,
4208 errParseTest, "./test/VCM/*", NULL, NULL, NULL,
4209 XML_PARSE_DTDVALID },
4210 { "Validity checking regression tests" ,
4211 errParseTest, "./test/VC/*", "result/VC/", NULL, "",
4212 XML_PARSE_DTDVALID },
4213 { "General documents valid regression tests" ,
4214 errParseTest, "./test/valid/*", "result/valid/", "", ".err",
4215 XML_PARSE_DTDVALID },
4217 #ifdef LIBXML_XINCLUDE_ENABLED
4218 { "XInclude regression tests" ,
4219 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4220 /* Ignore errors at this point ".err", */
4221 XML_PARSE_XINCLUDE },
4222 #ifdef LIBXML_READER_ENABLED
4223 { "XInclude xmlReader regression tests",
4224 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4225 /* Ignore errors at this point ".err", */
4226 NULL, XML_PARSE_XINCLUDE },
4228 { "XInclude regression tests stripping include nodes" ,
4229 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4230 /* Ignore errors at this point ".err", */
4231 XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4232 #ifdef LIBXML_READER_ENABLED
4233 { "XInclude xmlReader regression tests stripping include nodes",
4234 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4235 /* Ignore errors at this point ".err", */
4236 NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4239 #ifdef LIBXML_XPATH_ENABLED
4240 #ifdef LIBXML_DEBUG_ENABLED
4241 { "XPath expressions regression tests" ,
4242 xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
4244 { "XPath document queries regression tests" ,
4245 xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4247 #ifdef LIBXML_XPTR_ENABLED
4248 { "XPointer document queries regression tests" ,
4249 xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4252 { "xml:id regression tests" ,
4253 xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
4257 { "URI parsing tests" ,
4258 uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
4260 { "URI base composition tests" ,
4261 uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
4263 { "Path URI conversion tests" ,
4264 uriPathTest, NULL, NULL, NULL, NULL,
4266 #ifdef LIBXML_SCHEMAS_ENABLED
4267 { "Schemas regression tests" ,
4268 schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
4270 { "Relax-NG regression tests" ,
4271 rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4272 XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4273 #ifdef LIBXML_READER_ENABLED
4274 { "Relax-NG streaming regression tests" ,
4275 rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4276 XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4279 #ifdef LIBXML_PATTERN_ENABLED
4280 #ifdef LIBXML_READER_ENABLED
4281 { "Pattern regression tests" ,
4282 patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
4286 #ifdef LIBXML_C14N_ENABLED
4287 { "C14N with comments regression tests" ,
4288 c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
4290 { "C14N without comments regression tests" ,
4291 c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
4293 { "C14N exclusive without comments regression tests" ,
4294 c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
4296 { "C14N 1.1 without comments regression tests" ,
4297 c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL,
4300 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_SAX1_ENABLED)
4301 { "Catalog and Threads regression tests" ,
4302 threadsTest, NULL, NULL, NULL, NULL,
4305 {NULL, NULL, NULL, NULL, NULL, NULL, 0}
4308 /************************************************************************
4310 * The main code driving the tests *
4312 ************************************************************************/
4315 launchTests(testDescPtr tst) {
4316 int res = 0, err = 0;
4322 if (tst == NULL) return(-1);
4323 if (tst->in != NULL) {
4326 globbuf.gl_offs = 0;
4327 glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
4328 for (i = 0;i < globbuf.gl_pathc;i++) {
4329 if (!checkTestFile(globbuf.gl_pathv[i]))
4331 if (tst->suffix != NULL) {
4332 result = resultFilename(globbuf.gl_pathv[i], tst->out,
4334 if (result == NULL) {
4335 fprintf(stderr, "Out of memory !\n");
4341 if (tst->err != NULL) {
4342 error = resultFilename(globbuf.gl_pathv[i], tst->out,
4344 if (error == NULL) {
4345 fprintf(stderr, "Out of memory !\n");
4351 if ((result) &&(!checkTestFile(result))) {
4352 fprintf(stderr, "Missing result file %s\n", result);
4353 } else if ((error) &&(!checkTestFile(error))) {
4354 fprintf(stderr, "Missing error file %s\n", error);
4357 extraMemoryFromResolver = 0;
4360 res = tst->func(globbuf.gl_pathv[i], result, error,
4361 tst->options | XML_PARSE_COMPACT);
4362 xmlResetLastError();
4364 fprintf(stderr, "File %s generated an error\n",
4365 globbuf.gl_pathv[i]);
4369 else if (xmlMemUsed() != mem) {
4370 if ((xmlMemUsed() != mem) &&
4371 (extraMemoryFromResolver == 0)) {
4372 fprintf(stderr, "File %s leaked %d bytes\n",
4373 globbuf.gl_pathv[i], xmlMemUsed() - mem);
4389 extraMemoryFromResolver = 0;
4390 res = tst->func(NULL, NULL, NULL, tst->options);
4399 static int verbose = 0;
4400 static int tests_quiet = 0;
4405 int old_errors, old_tests, old_leaks;
4407 old_errors = nb_errors;
4408 old_tests = nb_tests;
4409 old_leaks = nb_leaks;
4410 if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
4411 printf("## %s\n", testDescriptions[i].desc);
4412 res = launchTests(&testDescriptions[i]);
4416 if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
4417 printf("Ran %d tests, no errors\n", nb_tests - old_tests);
4419 printf("Ran %d tests, %d errors, %d leaks\n",
4420 nb_tests - old_tests,
4421 nb_errors - old_errors,
4422 nb_leaks - old_leaks);
4428 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4432 initializeLibxml2();
4434 for (a = 1; a < argc;a++) {
4435 if (!strcmp(argv[a], "-v"))
4437 else if (!strcmp(argv[a], "-quiet"))
4440 for (i = 0; testDescriptions[i].func != NULL; i++) {
4441 if (strstr(testDescriptions[i].desc, argv[a])) {
4449 for (i = 0; testDescriptions[i].func != NULL; i++) {
4453 if ((nb_errors == 0) && (nb_leaks == 0)) {
4455 printf("Total %d tests, no errors\n",
4459 printf("Total %d tests, %d errors, %d leaks\n",
4460 nb_tests, nb_errors, nb_leaks);
4468 #else /* ! LIBXML_OUTPUT_ENABLED */
4470 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4471 fprintf(stderr, "runtest requires output to be enabled in libxml2\n");