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
);
1685 #ifdef LIBXML_HTML_ENABLED
1686 if (options
& XML_PARSE_HTML
) {
1687 htmlSAXParseFile(filename
, NULL
, debugHTMLSAXHandler
, NULL
);
1691 if (options
& XML_PARSE_SAX1
) {
1692 ret
= xmlSAXUserParseFile(debugSAXHandler
, NULL
, filename
);
1694 ret
= xmlSAXUserParseFile(debugSAX2Handler
, NULL
, filename
);
1696 if (ret
== XML_WAR_UNDECLARED_ENTITY
) {
1697 fprintf(SAXdebug
, "xmlSAXUserParseFile returned error %d\n", ret
);
1701 if (compareFiles(temp
, result
)) {
1702 fprintf(stderr
, "Got a difference for %s\n", filename
);
1712 /* switch back to structured error handling */
1713 xmlSetGenericErrorFunc(NULL
, NULL
);
1714 xmlSetStructuredErrorFunc(NULL
, testStructuredErrorHandler
);
1720 /************************************************************************
1722 * Parse to tree based tests *
1724 ************************************************************************/
1727 * @filename: the file to parse
1728 * @result: the file with expected result
1729 * @err: the file with error messages: unused
1731 * Parse a file using the old xmlParseFile API, then serialize back
1732 * reparse the result and serialize again, then check for deviation
1735 * Returns 0 in case of success, an error code otherwise
1738 oldParseTest(const char *filename
, const char *result
,
1739 const char *err ATTRIBUTE_UNUSED
,
1740 int options ATTRIBUTE_UNUSED
) {
1747 * base of the test, parse with the old API
1749 #ifdef LIBXML_SAX1_ENABLED
1750 doc
= xmlParseFile(filename
);
1752 doc
= xmlReadFile(filename
, NULL
, 0);
1756 temp
= resultFilename(filename
, "", ".res");
1758 fprintf(stderr
, "out of memory\n");
1761 xmlSaveFile(temp
, doc
);
1762 if (compareFiles(temp
, result
)) {
1768 * Parse the saved result to make sure the round trip is okay
1770 #ifdef LIBXML_SAX1_ENABLED
1771 doc
= xmlParseFile(temp
);
1773 doc
= xmlReadFile(temp
, NULL
, 0);
1777 xmlSaveFile(temp
, doc
);
1778 if (compareFiles(temp
, result
)) {
1790 #ifdef LIBXML_PUSH_ENABLED
1793 * @filename: the file to parse
1794 * @result: the file with expected result
1795 * @err: the file with error messages: unused
1797 * Parse a file using the Push API, then serialize back
1798 * to check for content.
1800 * Returns 0 in case of success, an error code otherwise
1803 pushParseTest(const char *filename
, const char *result
,
1804 const char *err ATTRIBUTE_UNUSED
,
1806 xmlParserCtxtPtr ctxt
;
1814 * load the document in memory and work from there.
1816 if (loadMem(filename
, &base
, &size
) != 0) {
1817 fprintf(stderr
, "Failed to load %s\n", filename
);
1821 #ifdef LIBXML_HTML_ENABLED
1822 if (options
& XML_PARSE_HTML
)
1823 ctxt
= htmlCreatePushParserCtxt(NULL
, NULL
, base
+ cur
, 4, filename
,
1824 XML_CHAR_ENCODING_NONE
);
1827 ctxt
= xmlCreatePushParserCtxt(NULL
, NULL
, base
+ cur
, 4, filename
);
1828 xmlCtxtUseOptions(ctxt
, options
);
1830 while (cur
< size
) {
1831 if (cur
+ 1024 >= size
) {
1832 #ifdef LIBXML_HTML_ENABLED
1833 if (options
& XML_PARSE_HTML
)
1834 htmlParseChunk(ctxt
, base
+ cur
, size
- cur
, 1);
1837 xmlParseChunk(ctxt
, base
+ cur
, size
- cur
, 1);
1840 #ifdef LIBXML_HTML_ENABLED
1841 if (options
& XML_PARSE_HTML
)
1842 htmlParseChunk(ctxt
, base
+ cur
, 1024, 0);
1845 xmlParseChunk(ctxt
, base
+ cur
, 1024, 0);
1850 #ifdef LIBXML_HTML_ENABLED
1851 if (options
& XML_PARSE_HTML
)
1855 res
= ctxt
->wellFormed
;
1856 xmlFreeParserCtxt(ctxt
);
1860 fprintf(stderr
, "Failed to parse %s\n", filename
);
1863 #ifdef LIBXML_HTML_ENABLED
1864 if (options
& XML_PARSE_HTML
)
1865 htmlDocDumpMemory(doc
, (xmlChar
**) &base
, &size
);
1868 xmlDocDumpMemory(doc
, (xmlChar
**) &base
, &size
);
1870 res
= compareFileMem(result
, base
, size
);
1871 if ((base
== NULL
) || (res
!= 0)) {
1873 xmlFree((char *)base
);
1874 fprintf(stderr
, "Result for %s failed\n", filename
);
1877 xmlFree((char *)base
);
1879 res
= compareFileMem(err
, testErrors
, testErrorsSize
);
1881 fprintf(stderr
, "Error for %s failed\n", filename
);
1891 * @filename: the file to parse
1892 * @result: the file with expected result
1893 * @err: the file with error messages: unused
1895 * Parse a file using the old xmlReadMemory API, then serialize back
1896 * reparse the result and serialize again, then check for deviation
1899 * Returns 0 in case of success, an error code otherwise
1902 memParseTest(const char *filename
, const char *result
,
1903 const char *err ATTRIBUTE_UNUSED
,
1904 int options ATTRIBUTE_UNUSED
) {
1911 * load and parse the memory
1913 if (loadMem(filename
, &base
, &size
) != 0) {
1914 fprintf(stderr
, "Failed to load %s\n", filename
);
1918 doc
= xmlReadMemory(base
, size
, filename
, NULL
, 0);
1923 xmlDocDumpMemory(doc
, (xmlChar
**) &base
, &size
);
1925 res
= compareFileMem(result
, base
, size
);
1926 if ((base
== NULL
) || (res
!= 0)) {
1928 xmlFree((char *)base
);
1929 fprintf(stderr
, "Result for %s failed\n", filename
);
1932 xmlFree((char *)base
);
1938 * @filename: the file to parse
1939 * @result: the file with expected result
1940 * @err: the file with error messages: unused
1942 * Parse a file with entity resolution, then serialize back
1943 * reparse the result and serialize again, then check for deviation
1946 * Returns 0 in case of success, an error code otherwise
1949 noentParseTest(const char *filename
, const char *result
,
1950 const char *err ATTRIBUTE_UNUSED
,
1958 * base of the test, parse with the old API
1960 doc
= xmlReadFile(filename
, NULL
, options
);
1963 temp
= resultFilename(filename
, "", ".res");
1965 fprintf(stderr
, "Out of memory\n");
1968 xmlSaveFile(temp
, doc
);
1969 if (compareFiles(temp
, result
)) {
1975 * Parse the saved result to make sure the round trip is okay
1977 doc
= xmlReadFile(filename
, NULL
, options
);
1980 xmlSaveFile(temp
, doc
);
1981 if (compareFiles(temp
, result
)) {
1995 * @filename: the file to parse
1996 * @result: the file with expected result
1997 * @err: the file with error messages
1999 * Parse a file using the xmlReadFile API and check for errors.
2001 * Returns 0 in case of success, an error code otherwise
2004 errParseTest(const char *filename
, const char *result
, const char *err
,
2007 const char *base
= NULL
;
2011 #ifdef LIBXML_HTML_ENABLED
2012 if (options
& XML_PARSE_HTML
) {
2013 doc
= htmlReadFile(filename
, NULL
, options
);
2016 #ifdef LIBXML_XINCLUDE_ENABLED
2017 if (options
& XML_PARSE_XINCLUDE
) {
2018 doc
= xmlReadFile(filename
, NULL
, options
);
2019 xmlXIncludeProcessFlags(doc
, options
);
2023 xmlGetWarningsDefaultValue
= 1;
2024 doc
= xmlReadFile(filename
, NULL
, options
);
2026 xmlGetWarningsDefaultValue
= 0;
2032 #ifdef LIBXML_HTML_ENABLED
2033 if (options
& XML_PARSE_HTML
) {
2034 htmlDocDumpMemory(doc
, (xmlChar
**) &base
, &size
);
2037 xmlDocDumpMemory(doc
, (xmlChar
**) &base
, &size
);
2039 res
= compareFileMem(result
, base
, size
);
2043 xmlFree((char *)base
);
2047 fprintf(stderr
, "Result for %s failed\n", filename
);
2051 res
= compareFileMem(err
, testErrors
, testErrorsSize
);
2053 fprintf(stderr
, "Error for %s failed\n", filename
);
2056 } else if (options
& XML_PARSE_DTDVALID
) {
2057 if (testErrorsSize
!= 0)
2058 fprintf(stderr
, "Validation for %s failed\n", filename
);
2064 #ifdef LIBXML_READER_ENABLED
2065 /************************************************************************
2067 * Reader based tests *
2069 ************************************************************************/
2071 static void processNode(FILE *out
, xmlTextReaderPtr reader
) {
2072 const xmlChar
*name
, *value
;
2075 type
= xmlTextReaderNodeType(reader
);
2076 empty
= xmlTextReaderIsEmptyElement(reader
);
2078 name
= xmlTextReaderConstName(reader
);
2080 name
= BAD_CAST
"--";
2082 value
= xmlTextReaderConstValue(reader
);
2085 fprintf(out
, "%d %d %s %d %d",
2086 xmlTextReaderDepth(reader
),
2090 xmlTextReaderHasValue(reader
));
2094 fprintf(out
, " %s\n", value
);
2098 streamProcessTest(const char *filename
, const char *result
, const char *err
,
2099 xmlTextReaderPtr reader
, const char *rng
, int options
) {
2108 if (result
!= NULL
) {
2109 temp
= resultFilename(filename
, "", ".res");
2111 fprintf(stderr
, "Out of memory\n");
2114 t
= fopen(temp
, "wb");
2116 fprintf(stderr
, "Can't open temp file %s\n", temp
);
2121 #ifdef LIBXML_SCHEMAS_ENABLED
2123 ret
= xmlTextReaderRelaxNGValidate(reader
, rng
);
2125 testErrorHandler(NULL
, "Relax-NG schema %s failed to compile\n",
2136 xmlGetWarningsDefaultValue
= 1;
2137 ret
= xmlTextReaderRead(reader
);
2139 if ((t
!= NULL
) && (rng
== NULL
))
2140 processNode(t
, reader
);
2141 ret
= xmlTextReaderRead(reader
);
2144 testErrorHandler(NULL
, "%s : failed to parse\n", filename
);
2147 if (xmlTextReaderIsValid(reader
) != 1) {
2148 testErrorHandler(NULL
, "%s fails to validate\n", filename
);
2150 testErrorHandler(NULL
, "%s validates\n", filename
);
2153 xmlGetWarningsDefaultValue
= 0;
2156 ret
= compareFiles(temp
, result
);
2162 fprintf(stderr
, "Result for %s failed\n", filename
);
2167 ret
= compareFileMem(err
, testErrors
, testErrorsSize
);
2169 fprintf(stderr
, "Error for %s failed\n", filename
);
2170 printf("%s", testErrors
);
2180 * @filename: the file to parse
2181 * @result: the file with expected result
2182 * @err: the file with error messages
2184 * Parse a file using the reader API and check for errors.
2186 * Returns 0 in case of success, an error code otherwise
2189 streamParseTest(const char *filename
, const char *result
, const char *err
,
2191 xmlTextReaderPtr reader
;
2194 reader
= xmlReaderForFile(filename
, NULL
, options
);
2195 ret
= streamProcessTest(filename
, result
, err
, reader
, NULL
, options
);
2196 xmlFreeTextReader(reader
);
2202 * @filename: the file to parse
2203 * @result: the file with expected result
2204 * @err: the file with error messages
2206 * Parse a file using the walker, i.e. a reader built from a atree.
2208 * Returns 0 in case of success, an error code otherwise
2211 walkerParseTest(const char *filename
, const char *result
, const char *err
,
2214 xmlTextReaderPtr reader
;
2217 doc
= xmlReadFile(filename
, NULL
, options
);
2219 fprintf(stderr
, "Failed to parse %s\n", filename
);
2222 reader
= xmlReaderWalker(doc
);
2223 ret
= streamProcessTest(filename
, result
, err
, reader
, NULL
, options
);
2224 xmlFreeTextReader(reader
);
2230 * streamMemParseTest:
2231 * @filename: the file to parse
2232 * @result: the file with expected result
2233 * @err: the file with error messages
2235 * Parse a file using the reader API from memory and check for errors.
2237 * Returns 0 in case of success, an error code otherwise
2240 streamMemParseTest(const char *filename
, const char *result
, const char *err
,
2242 xmlTextReaderPtr reader
;
2248 * load and parse the memory
2250 if (loadMem(filename
, &base
, &size
) != 0) {
2251 fprintf(stderr
, "Failed to load %s\n", filename
);
2254 reader
= xmlReaderForMemory(base
, size
, filename
, NULL
, options
);
2255 ret
= streamProcessTest(filename
, result
, err
, reader
, NULL
, options
);
2257 xmlFreeTextReader(reader
);
2262 #ifdef LIBXML_XPATH_ENABLED
2263 #ifdef LIBXML_DEBUG_ENABLED
2264 /************************************************************************
2266 * XPath and XPointer based tests *
2268 ************************************************************************/
2270 static FILE *xpathOutput
;
2271 static xmlDocPtr xpathDocument
;
2274 testXPath(const char *str
, int xptr
, int expr
) {
2275 xmlXPathObjectPtr res
;
2276 xmlXPathContextPtr ctxt
;
2279 #if defined(LIBXML_XPTR_ENABLED)
2281 ctxt
= xmlXPtrNewContext(xpathDocument
, NULL
, NULL
);
2282 res
= xmlXPtrEval(BAD_CAST str
, ctxt
);
2285 ctxt
= xmlXPathNewContext(xpathDocument
);
2286 ctxt
->node
= xmlDocGetRootElement(xpathDocument
);
2288 res
= xmlXPathEvalExpression(BAD_CAST str
, ctxt
);
2290 /* res = xmlXPathEval(BAD_CAST str, ctxt); */
2291 xmlXPathCompExprPtr comp
;
2293 comp
= xmlXPathCompile(BAD_CAST str
);
2295 res
= xmlXPathCompiledEval(comp
, ctxt
);
2296 xmlXPathFreeCompExpr(comp
);
2300 #if defined(LIBXML_XPTR_ENABLED)
2303 xmlXPathDebugDumpObject(xpathOutput
, res
, 0);
2304 xmlXPathFreeObject(res
);
2305 xmlXPathFreeContext(ctxt
);
2310 * @filename: the file to parse
2311 * @result: the file with expected result
2312 * @err: the file with error messages
2314 * Parse a file containing XPath standalone expressions and evaluate them
2316 * Returns 0 in case of success, an error code otherwise
2319 xpathCommonTest(const char *filename
, const char *result
,
2320 int xptr
, int expr
) {
2322 char expression
[5000];
2326 temp
= resultFilename(filename
, "", ".res");
2328 fprintf(stderr
, "Out of memory\n");
2331 xpathOutput
= fopen(temp
, "wb");
2332 if (xpathOutput
== NULL
) {
2333 fprintf(stderr
, "failed to open output file %s\n", temp
);
2338 input
= fopen(filename
, "rb");
2339 if (input
== NULL
) {
2340 xmlGenericError(xmlGenericErrorContext
,
2341 "Cannot open %s for reading\n", filename
);
2345 while (fgets(expression
, 4500, input
) != NULL
) {
2346 len
= strlen(expression
);
2348 while ((len
>= 0) &&
2349 ((expression
[len
] == '\n') || (expression
[len
] == '\t') ||
2350 (expression
[len
] == '\r') || (expression
[len
] == ' '))) len
--;
2351 expression
[len
+ 1] = 0;
2353 fprintf(xpathOutput
,
2354 "\n========================\nExpression: %s\n",
2356 testXPath(expression
, xptr
, expr
);
2361 fclose(xpathOutput
);
2362 if (result
!= NULL
) {
2363 ret
= compareFiles(temp
, result
);
2365 fprintf(stderr
, "Result for %s failed\n", filename
);
2378 * @filename: the file to parse
2379 * @result: the file with expected result
2380 * @err: the file with error messages
2382 * Parse a file containing XPath standalone expressions and evaluate them
2384 * Returns 0 in case of success, an error code otherwise
2387 xpathExprTest(const char *filename
, const char *result
,
2388 const char *err ATTRIBUTE_UNUSED
,
2389 int options ATTRIBUTE_UNUSED
) {
2390 return(xpathCommonTest(filename
, result
, 0, 1));
2395 * @filename: the file to parse
2396 * @result: the file with expected result
2397 * @err: the file with error messages
2399 * Parse a file containing XPath expressions and evaluate them against
2400 * a set of corresponding documents.
2402 * Returns 0 in case of success, an error code otherwise
2405 xpathDocTest(const char *filename
,
2406 const char *resul ATTRIBUTE_UNUSED
,
2407 const char *err ATTRIBUTE_UNUSED
,
2416 xpathDocument
= xmlReadFile(filename
, NULL
,
2417 options
| XML_PARSE_DTDATTR
| XML_PARSE_NOENT
);
2418 if (xpathDocument
== NULL
) {
2419 fprintf(stderr
, "Failed to load %s\n", filename
);
2423 snprintf(pattern
, 499, "./test/XPath/tests/%s*", baseFilename(filename
));
2425 globbuf
.gl_offs
= 0;
2426 glob(pattern
, GLOB_DOOFFS
, NULL
, &globbuf
);
2427 for (i
= 0;i
< globbuf
.gl_pathc
;i
++) {
2428 snprintf(result
, 499, "result/XPath/tests/%s",
2429 baseFilename(globbuf
.gl_pathv
[i
]));
2430 res
= xpathCommonTest(globbuf
.gl_pathv
[i
], &result
[0], 0, 0);
2436 xmlFreeDoc(xpathDocument
);
2440 #ifdef LIBXML_XPTR_ENABLED
2443 * @filename: the file to parse
2444 * @result: the file with expected result
2445 * @err: the file with error messages
2447 * Parse a file containing XPath expressions and evaluate them against
2448 * a set of corresponding documents.
2450 * Returns 0 in case of success, an error code otherwise
2453 xptrDocTest(const char *filename
,
2454 const char *resul ATTRIBUTE_UNUSED
,
2455 const char *err ATTRIBUTE_UNUSED
,
2464 xpathDocument
= xmlReadFile(filename
, NULL
,
2465 options
| XML_PARSE_DTDATTR
| XML_PARSE_NOENT
);
2466 if (xpathDocument
== NULL
) {
2467 fprintf(stderr
, "Failed to load %s\n", filename
);
2471 snprintf(pattern
, 499, "./test/XPath/xptr/%s*", baseFilename(filename
));
2473 globbuf
.gl_offs
= 0;
2474 glob(pattern
, GLOB_DOOFFS
, NULL
, &globbuf
);
2475 for (i
= 0;i
< globbuf
.gl_pathc
;i
++) {
2476 snprintf(result
, 499, "result/XPath/xptr/%s",
2477 baseFilename(globbuf
.gl_pathv
[i
]));
2478 res
= xpathCommonTest(globbuf
.gl_pathv
[i
], &result
[0], 1, 0);
2484 xmlFreeDoc(xpathDocument
);
2487 #endif /* LIBXML_XPTR_ENABLED */
2491 * @filename: the file to parse
2492 * @result: the file with expected result
2493 * @err: the file with error messages
2495 * Parse a file containing xml:id and check for errors and verify
2496 * that XPath queries will work on them as expected.
2498 * Returns 0 in case of success, an error code otherwise
2501 xmlidDocTest(const char *filename
,
2510 xpathDocument
= xmlReadFile(filename
, NULL
,
2511 options
| XML_PARSE_DTDATTR
| XML_PARSE_NOENT
);
2512 if (xpathDocument
== NULL
) {
2513 fprintf(stderr
, "Failed to load %s\n", filename
);
2517 temp
= resultFilename(filename
, "", ".res");
2519 fprintf(stderr
, "Out of memory\n");
2522 xpathOutput
= fopen(temp
, "wb");
2523 if (xpathOutput
== NULL
) {
2524 fprintf(stderr
, "failed to open output file %s\n", temp
);
2525 xmlFreeDoc(xpathDocument
);
2530 testXPath("id('bar')", 0, 0);
2532 fclose(xpathOutput
);
2533 if (result
!= NULL
) {
2534 ret
= compareFiles(temp
, result
);
2536 fprintf(stderr
, "Result for %s failed\n", filename
);
2545 xmlFreeDoc(xpathDocument
);
2548 ret
= compareFileMem(err
, testErrors
, testErrorsSize
);
2550 fprintf(stderr
, "Error for %s failed\n", filename
);
2557 #endif /* LIBXML_DEBUG_ENABLED */
2559 /************************************************************************
2563 ************************************************************************/
2566 handleURI(const char *str
, const char *base
, FILE *o
) {
2569 xmlChar
*res
= NULL
;
2571 uri
= xmlCreateURI();
2574 ret
= xmlParseURIReference(uri
, str
);
2576 fprintf(o
, "%s : error %d\n", str
, ret
);
2578 xmlNormalizeURIPath(uri
->path
);
2579 xmlPrintURI(o
, uri
);
2583 res
= xmlBuildURI((xmlChar
*)str
, (xmlChar
*) base
);
2585 fprintf(o
, "%s\n", (char *) res
);
2588 fprintf(o
, "::ERROR::\n");
2597 * @filename: the file to parse
2598 * @result: the file with expected result
2599 * @err: the file with error messages
2601 * Parse a file containing URI and check for errors
2603 * Returns 0 in case of success, an error code otherwise
2606 uriCommonTest(const char *filename
,
2613 int res
= 0, i
, ret
;
2615 temp
= resultFilename(filename
, "", ".res");
2617 fprintf(stderr
, "Out of memory\n");
2620 o
= fopen(temp
, "wb");
2622 fprintf(stderr
, "failed to open output file %s\n", temp
);
2626 f
= fopen(filename
, "rb");
2628 fprintf(stderr
, "failed to open input file %s\n", filename
);
2639 * read one line in string buffer.
2641 if (fgets (&str
[0], sizeof (str
) - 1, f
) == NULL
)
2645 * remove the ending spaces
2649 ((str
[i
- 1] == '\n') || (str
[i
- 1] == '\r') ||
2650 (str
[i
- 1] == ' ') || (str
[i
- 1] == '\t'))) {
2655 handleURI(str
, base
, o
);
2661 if (result
!= NULL
) {
2662 ret
= compareFiles(temp
, result
);
2664 fprintf(stderr
, "Result for %s failed\n", filename
);
2669 ret
= compareFileMem(err
, testErrors
, testErrorsSize
);
2671 fprintf(stderr
, "Error for %s failed\n", filename
);
2685 * @filename: the file to parse
2686 * @result: the file with expected result
2687 * @err: the file with error messages
2689 * Parse a file containing URI and check for errors
2691 * Returns 0 in case of success, an error code otherwise
2694 uriParseTest(const char *filename
,
2697 int options ATTRIBUTE_UNUSED
) {
2698 return(uriCommonTest(filename
, result
, err
, NULL
));
2703 * @filename: the file to parse
2704 * @result: the file with expected result
2705 * @err: the file with error messages
2707 * Parse a file containing URI, compose them against a fixed base and
2710 * Returns 0 in case of success, an error code otherwise
2713 uriBaseTest(const char *filename
,
2716 int options ATTRIBUTE_UNUSED
) {
2717 return(uriCommonTest(filename
, result
, err
,
2718 "http://foo.com/path/to/index.html?orig#help"));
2721 static int urip_success
= 1;
2722 static int urip_current
= 0;
2723 static const char *urip_testURLs
[] = {
2724 "urip://example.com/a b.html",
2725 "urip://example.com/a%20b.html",
2726 "file:///path/to/a b.html",
2727 "file:///path/to/a%20b.html",
2728 "/path/to/a b.html",
2729 "/path/to/a%20b.html",
2730 "urip://example.com/r" "\xe9" "sum" "\xe9" ".html",
2731 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2734 static const char *urip_rcvsURLs
[] = {
2735 /* it is an URI the strings must be escaped */
2736 "urip://example.com/a%20b.html",
2737 /* check that % escaping is not broken */
2738 "urip://example.com/a%20b.html",
2739 /* it's an URI path the strings must be escaped */
2740 "file:///path/to/a%20b.html",
2741 /* check that % escaping is not broken */
2742 "file:///path/to/a%20b.html",
2743 /* this is not an URI, this is a path, so this should not be escaped */
2744 "/path/to/a b.html",
2745 /* check that paths with % are not broken */
2746 "/path/to/a%20b.html",
2747 /* out of context the encoding can't be guessed byte by byte conversion */
2748 "urip://example.com/r%E9sum%E9.html",
2749 /* verify we don't destroy URIs especially the query part */
2750 "urip://example.com/test?a=1&b=2%263&c=4#foo",
2753 static const char *urip_res
= "<list/>";
2754 static const char *urip_cur
= NULL
;
2755 static int urip_rlen
;
2759 * @URI: an URI to test
2761 * Check for an urip: query
2763 * Returns 1 if yes and 0 if another Input module should be used
2766 uripMatch(const char * URI
) {
2767 if ((URI
== NULL
) || (!strcmp(URI
, "file:///etc/xml/catalog")))
2769 /* Verify we received the escaped URL */
2770 if (strcmp(urip_rcvsURLs
[urip_current
], URI
))
2777 * @URI: an URI to test
2779 * Return a pointer to the urip: query handler, in this example simply
2780 * the urip_current pointer...
2782 * Returns an Input context or NULL in case or error
2785 uripOpen(const char * URI
) {
2786 if ((URI
== NULL
) || (!strcmp(URI
, "file:///etc/xml/catalog")))
2788 /* Verify we received the escaped URL */
2789 if (strcmp(urip_rcvsURLs
[urip_current
], URI
))
2791 urip_cur
= urip_res
;
2792 urip_rlen
= strlen(urip_res
);
2793 return((void *) urip_cur
);
2798 * @context: the read context
2800 * Close the urip: query handler
2802 * Returns 0 or -1 in case of error
2805 uripClose(void * context
) {
2806 if (context
== NULL
) return(-1);
2814 * @context: the read context
2815 * @buffer: where to store data
2816 * @len: number of bytes to read
2818 * Implement an urip: query read.
2820 * Returns the number of bytes read or -1 in case of error
2823 uripRead(void * context
, char * buffer
, int len
) {
2824 const char *ptr
= (const char *) context
;
2826 if ((context
== NULL
) || (buffer
== NULL
) || (len
< 0))
2829 if (len
> urip_rlen
) len
= urip_rlen
;
2830 memcpy(buffer
, ptr
, len
);
2836 urip_checkURL(const char *URL
) {
2839 doc
= xmlReadFile(URL
, NULL
, 0);
2848 * @filename: ignored
2852 * Run a set of tests to check how Path and URI are handled before
2853 * being passed to the I/O layer
2855 * Returns 0 in case of success, an error code otherwise
2858 uriPathTest(const char *filename ATTRIBUTE_UNUSED
,
2859 const char *result ATTRIBUTE_UNUSED
,
2860 const char *err ATTRIBUTE_UNUSED
,
2861 int options ATTRIBUTE_UNUSED
) {
2866 * register the new I/O handlers
2868 if (xmlRegisterInputCallbacks(uripMatch
, uripOpen
, uripRead
, uripClose
) < 0)
2870 fprintf(stderr
, "failed to register HTTP handler\n");
2874 for (urip_current
= 0;urip_testURLs
[urip_current
] != NULL
;urip_current
++) {
2876 parsed
= urip_checkURL(urip_testURLs
[urip_current
]);
2877 if (urip_success
!= 1) {
2878 fprintf(stderr
, "failed the URL passing test for %s",
2879 urip_testURLs
[urip_current
]);
2881 } else if (parsed
!= 1) {
2882 fprintf(stderr
, "failed the parsing test for %s",
2883 urip_testURLs
[urip_current
]);
2889 xmlPopInputCallbacks();
2893 #ifdef LIBXML_SCHEMAS_ENABLED
2894 /************************************************************************
2898 ************************************************************************/
2900 schemasOneTest(const char *sch
,
2901 const char *filename
,
2905 xmlSchemaPtr schemas
) {
2907 xmlSchemaValidCtxtPtr ctxt
;
2909 int validResult
= 0;
2911 FILE *schemasOutput
;
2913 doc
= xmlReadFile(filename
, NULL
, options
);
2915 fprintf(stderr
, "failed to parse instance %s for %s\n", filename
, sch
);
2919 temp
= resultFilename(result
, "", ".res");
2921 fprintf(stderr
, "Out of memory\n");
2924 schemasOutput
= fopen(temp
, "wb");
2925 if (schemasOutput
== NULL
) {
2926 fprintf(stderr
, "failed to open output file %s\n", temp
);
2932 ctxt
= xmlSchemaNewValidCtxt(schemas
);
2933 xmlSchemaSetValidErrors(ctxt
,
2934 (xmlSchemaValidityErrorFunc
) testErrorHandler
,
2935 (xmlSchemaValidityWarningFunc
) testErrorHandler
,
2937 validResult
= xmlSchemaValidateDoc(ctxt
, doc
);
2938 if (validResult
== 0) {
2939 fprintf(schemasOutput
, "%s validates\n", filename
);
2940 } else if (validResult
> 0) {
2941 fprintf(schemasOutput
, "%s fails to validate\n", filename
);
2943 fprintf(schemasOutput
, "%s validation generated an internal error\n",
2946 fclose(schemasOutput
);
2948 if (compareFiles(temp
, result
)) {
2949 fprintf(stderr
, "Result for %s on %s failed\n", filename
, sch
);
2958 if ((validResult
!= 0) && (err
!= NULL
)) {
2959 if (compareFileMem(err
, testErrors
, testErrorsSize
)) {
2960 fprintf(stderr
, "Error for %s on %s failed\n", filename
, sch
);
2965 xmlSchemaFreeValidCtxt(ctxt
);
2971 * @filename: the schemas file
2972 * @result: the file with expected result
2973 * @err: the file with error messages
2975 * Parse a file containing URI, compose them against a fixed base and
2978 * Returns 0 in case of success, an error code otherwise
2981 schemasTest(const char *filename
,
2982 const char *resul ATTRIBUTE_UNUSED
,
2983 const char *errr ATTRIBUTE_UNUSED
,
2985 const char *base
= baseFilename(filename
);
2987 const char *instance
;
2988 xmlSchemaParserCtxtPtr ctxt
;
2989 xmlSchemaPtr schemas
;
2990 int res
= 0, len
, ret
;
2999 /* first compile the schemas if possible */
3000 ctxt
= xmlSchemaNewParserCtxt(filename
);
3001 xmlSchemaSetParserErrors(ctxt
,
3002 (xmlSchemaValidityErrorFunc
) testErrorHandler
,
3003 (xmlSchemaValidityWarningFunc
) testErrorHandler
,
3005 schemas
= xmlSchemaParse(ctxt
);
3006 xmlSchemaFreeParserCtxt(ctxt
);
3009 * most of the mess is about the output filenames generated by the Makefile
3012 if ((len
> 499) || (len
< 5)) {
3013 xmlSchemaFree(schemas
);
3016 len
-= 4; /* remove trailing .xsd */
3017 if (base
[len
- 2] == '_') {
3018 len
-= 2; /* remove subtest number */
3020 if (base
[len
- 2] == '_') {
3021 len
-= 2; /* remove subtest number */
3023 memcpy(prefix
, base
, len
);
3026 snprintf(pattern
, 499, "./test/schemas/%s_?.xml", prefix
);
3029 if (base
[len
] == '_') {
3031 memcpy(prefix
, base
, len
);
3035 globbuf
.gl_offs
= 0;
3036 glob(pattern
, GLOB_DOOFFS
, NULL
, &globbuf
);
3037 for (i
= 0;i
< globbuf
.gl_pathc
;i
++) {
3040 instance
= globbuf
.gl_pathv
[i
];
3041 base2
= baseFilename(instance
);
3042 len
= strlen(base2
);
3043 if ((len
> 6) && (base2
[len
- 6] == '_')) {
3044 count
= base2
[len
- 5];
3045 snprintf(result
, 499, "result/schemas/%s_%c",
3048 snprintf(err
, 499, "result/schemas/%s_%c.err",
3052 fprintf(stderr
, "don't know how to process %s\n", instance
);
3055 if (schemas
== NULL
) {
3058 ret
= schemasOneTest(filename
, instance
, result
, err
,
3065 xmlSchemaFree(schemas
);
3070 /************************************************************************
3074 ************************************************************************/
3076 rngOneTest(const char *sch
,
3077 const char *filename
,
3081 xmlRelaxNGPtr schemas
) {
3083 xmlRelaxNGValidCtxtPtr ctxt
;
3086 FILE *schemasOutput
;
3088 doc
= xmlReadFile(filename
, NULL
, options
);
3090 fprintf(stderr
, "failed to parse instance %s for %s\n", filename
, sch
);
3094 temp
= resultFilename(result
, "", ".res");
3096 fprintf(stderr
, "Out of memory\n");
3099 schemasOutput
= fopen(temp
, "wb");
3100 if (schemasOutput
== NULL
) {
3101 fprintf(stderr
, "failed to open output file %s\n", temp
);
3107 ctxt
= xmlRelaxNGNewValidCtxt(schemas
);
3108 xmlRelaxNGSetValidErrors(ctxt
,
3109 (xmlRelaxNGValidityErrorFunc
) testErrorHandler
,
3110 (xmlRelaxNGValidityWarningFunc
) testErrorHandler
,
3112 ret
= xmlRelaxNGValidateDoc(ctxt
, doc
);
3114 testErrorHandler(NULL
, "%s validates\n", filename
);
3115 } else if (ret
> 0) {
3116 testErrorHandler(NULL
, "%s fails to validate\n", filename
);
3118 testErrorHandler(NULL
, "%s validation generated an internal error\n",
3121 fclose(schemasOutput
);
3124 if (compareFiles(temp
, result
)) {
3125 fprintf(stderr
, "Result for %s on %s failed\n", filename
, sch
);
3135 if (compareFileMem(err
, testErrors
, testErrorsSize
)) {
3136 fprintf(stderr
, "Error for %s on %s failed\n", filename
, sch
);
3138 printf("%s", testErrors
);
3143 xmlRelaxNGFreeValidCtxt(ctxt
);
3149 * @filename: the schemas file
3150 * @result: the file with expected result
3151 * @err: the file with error messages
3153 * Parse an RNG schemas and then apply it to the related .xml
3155 * Returns 0 in case of success, an error code otherwise
3158 rngTest(const char *filename
,
3159 const char *resul ATTRIBUTE_UNUSED
,
3160 const char *errr ATTRIBUTE_UNUSED
,
3162 const char *base
= baseFilename(filename
);
3164 const char *instance
;
3165 xmlRelaxNGParserCtxtPtr ctxt
;
3166 xmlRelaxNGPtr schemas
;
3167 int res
= 0, len
, ret
= 0;
3176 /* first compile the schemas if possible */
3177 ctxt
= xmlRelaxNGNewParserCtxt(filename
);
3178 xmlRelaxNGSetParserErrors(ctxt
,
3179 (xmlRelaxNGValidityErrorFunc
) testErrorHandler
,
3180 (xmlRelaxNGValidityWarningFunc
) testErrorHandler
,
3182 schemas
= xmlRelaxNGParse(ctxt
);
3183 xmlRelaxNGFreeParserCtxt(ctxt
);
3186 * most of the mess is about the output filenames generated by the Makefile
3189 if ((len
> 499) || (len
< 5)) {
3190 xmlRelaxNGFree(schemas
);
3193 len
-= 4; /* remove trailing .rng */
3194 memcpy(prefix
, base
, len
);
3197 snprintf(pattern
, 499, "./test/relaxng/%s_?.xml", prefix
);
3200 globbuf
.gl_offs
= 0;
3201 glob(pattern
, GLOB_DOOFFS
, NULL
, &globbuf
);
3202 for (i
= 0;i
< globbuf
.gl_pathc
;i
++) {
3205 instance
= globbuf
.gl_pathv
[i
];
3206 base2
= baseFilename(instance
);
3207 len
= strlen(base2
);
3208 if ((len
> 6) && (base2
[len
- 6] == '_')) {
3209 count
= base2
[len
- 5];
3210 snprintf(result
, 499, "result/relaxng/%s_%c",
3213 snprintf(err
, 499, "result/relaxng/%s_%c.err",
3217 fprintf(stderr
, "don't know how to process %s\n", instance
);
3220 if (schemas
== NULL
) {
3223 ret
= rngOneTest(filename
, instance
, result
, err
,
3230 xmlRelaxNGFree(schemas
);
3235 #ifdef LIBXML_READER_ENABLED
3238 * @filename: the schemas file
3239 * @result: the file with expected result
3240 * @err: the file with error messages
3242 * Parse a set of files with streaming, applying an RNG schemas
3244 * Returns 0 in case of success, an error code otherwise
3247 rngStreamTest(const char *filename
,
3248 const char *resul ATTRIBUTE_UNUSED
,
3249 const char *errr ATTRIBUTE_UNUSED
,
3251 const char *base
= baseFilename(filename
);
3253 const char *instance
;
3254 int res
= 0, len
, ret
;
3262 xmlTextReaderPtr reader
;
3263 int disable_err
= 0;
3266 * most of the mess is about the output filenames generated by the Makefile
3269 if ((len
> 499) || (len
< 5)) {
3270 fprintf(stderr
, "len(base) == %d !\n", len
);
3273 len
-= 4; /* remove trailing .rng */
3274 memcpy(prefix
, base
, len
);
3278 * strictly unifying the error messages is nearly impossible this
3279 * hack is also done in the Makefile
3281 if ((!strcmp(prefix
, "tutor10_1")) || (!strcmp(prefix
, "tutor10_2")) ||
3282 (!strcmp(prefix
, "tutor3_2")) || (!strcmp(prefix
, "307377")) ||
3283 (!strcmp(prefix
, "tutor8_2")))
3286 snprintf(pattern
, 499, "./test/relaxng/%s_?.xml", prefix
);
3289 globbuf
.gl_offs
= 0;
3290 glob(pattern
, GLOB_DOOFFS
, NULL
, &globbuf
);
3291 for (i
= 0;i
< globbuf
.gl_pathc
;i
++) {
3294 instance
= globbuf
.gl_pathv
[i
];
3295 base2
= baseFilename(instance
);
3296 len
= strlen(base2
);
3297 if ((len
> 6) && (base2
[len
- 6] == '_')) {
3298 count
= base2
[len
- 5];
3299 snprintf(result
, 499, "result/relaxng/%s_%c",
3302 snprintf(err
, 499, "result/relaxng/%s_%c.err",
3306 fprintf(stderr
, "don't know how to process %s\n", instance
);
3309 reader
= xmlReaderForFile(instance
, NULL
, options
);
3310 if (reader
== NULL
) {
3311 fprintf(stderr
, "Failed to build reder for %s\n", instance
);
3313 if (disable_err
== 1)
3314 ret
= streamProcessTest(instance
, result
, NULL
, reader
, filename
,
3317 ret
= streamProcessTest(instance
, result
, err
, reader
, filename
,
3319 xmlFreeTextReader(reader
);
3321 fprintf(stderr
, "instance %s failed\n", instance
);
3333 #ifdef LIBXML_PATTERN_ENABLED
3334 #ifdef LIBXML_READER_ENABLED
3335 /************************************************************************
3339 ************************************************************************/
3340 static void patternNode(FILE *out
, xmlTextReaderPtr reader
,
3341 const char *pattern
, xmlPatternPtr patternc
,
3342 xmlStreamCtxtPtr patstream
) {
3343 xmlChar
*path
= NULL
;
3347 type
= xmlTextReaderNodeType(reader
);
3348 empty
= xmlTextReaderIsEmptyElement(reader
);
3350 if (type
== XML_READER_TYPE_ELEMENT
) {
3351 /* do the check only on element start */
3352 match
= xmlPatternMatch(patternc
, xmlTextReaderCurrentNode(reader
));
3355 path
= xmlGetNodePath(xmlTextReaderCurrentNode(reader
));
3356 fprintf(out
, "Node %s matches pattern %s\n", path
, pattern
);
3359 if (patstream
!= NULL
) {
3362 if (type
== XML_READER_TYPE_ELEMENT
) {
3363 ret
= xmlStreamPush(patstream
,
3364 xmlTextReaderConstLocalName(reader
),
3365 xmlTextReaderConstNamespaceUri(reader
));
3367 fprintf(out
, "xmlStreamPush() failure\n");
3368 xmlFreeStreamCtxt(patstream
);
3370 } else if (ret
!= match
) {
3372 path
= xmlGetNodePath(
3373 xmlTextReaderCurrentNode(reader
));
3376 "xmlPatternMatch and xmlStreamPush disagree\n");
3378 " pattern %s node %s\n",
3384 if ((type
== XML_READER_TYPE_END_ELEMENT
) ||
3385 ((type
== XML_READER_TYPE_ELEMENT
) && (empty
))) {
3386 ret
= xmlStreamPop(patstream
);
3388 fprintf(out
, "xmlStreamPop() failure\n");
3389 xmlFreeStreamCtxt(patstream
);
3400 * @filename: the schemas file
3401 * @result: the file with expected result
3402 * @err: the file with error messages
3404 * Parse a set of files with streaming, applying an RNG schemas
3406 * Returns 0 in case of success, an error code otherwise
3409 patternTest(const char *filename
,
3410 const char *resul ATTRIBUTE_UNUSED
,
3411 const char *err ATTRIBUTE_UNUSED
,
3413 xmlPatternPtr patternc
= NULL
;
3414 xmlStreamCtxtPtr patstream
= NULL
;
3422 xmlTextReaderPtr reader
;
3425 len
= strlen(filename
);
3427 memcpy(xml
, filename
, len
);
3429 snprintf(result
, 499, "result/pattern/%s", baseFilename(xml
));
3431 memcpy(xml
+ len
, ".xml", 5);
3433 if (!checkTestFile(xml
)) {
3434 fprintf(stderr
, "Missing xml file %s\n", xml
);
3437 if (!checkTestFile(result
)) {
3438 fprintf(stderr
, "Missing result file %s\n", result
);
3441 f
= fopen(filename
, "rb");
3443 fprintf(stderr
, "Failed to open %s\n", filename
);
3446 temp
= resultFilename(filename
, "", ".res");
3448 fprintf(stderr
, "Out of memory\n");
3451 o
= fopen(temp
, "wb");
3453 fprintf(stderr
, "failed to open output file %s\n", temp
);
3460 * read one line in string buffer.
3462 if (fgets (&str
[0], sizeof (str
) - 1, f
) == NULL
)
3466 * remove the ending spaces
3470 ((str
[i
- 1] == '\n') || (str
[i
- 1] == '\r') ||
3471 (str
[i
- 1] == ' ') || (str
[i
- 1] == '\t'))) {
3475 doc
= xmlReadFile(xml
, NULL
, options
);
3477 fprintf(stderr
, "Failed to parse %s\n", xml
);
3481 const xmlChar
*namespaces
[22];
3485 root
= xmlDocGetRootElement(doc
);
3486 for (ns
= root
->nsDef
, j
= 0;ns
!= NULL
&& j
< 20;ns
=ns
->next
) {
3487 namespaces
[j
++] = ns
->href
;
3488 namespaces
[j
++] = ns
->prefix
;
3490 namespaces
[j
++] = NULL
;
3491 namespaces
[j
] = NULL
;
3493 patternc
= xmlPatterncompile((const xmlChar
*) str
, doc
->dict
,
3495 if (patternc
== NULL
) {
3496 testErrorHandler(NULL
,
3497 "Pattern %s failed to compile\n", str
);
3502 patstream
= xmlPatternGetStreamCtxt(patternc
);
3503 if (patstream
!= NULL
) {
3504 ret
= xmlStreamPush(patstream
, NULL
, NULL
);
3506 fprintf(stderr
, "xmlStreamPush() failure\n");
3507 xmlFreeStreamCtxt(patstream
);
3513 reader
= xmlReaderWalker(doc
);
3514 res
= xmlTextReaderRead(reader
);
3516 patternNode(o
, reader
, str
, patternc
, patstream
);
3517 res
= xmlTextReaderRead(reader
);
3520 fprintf(o
, "%s : failed to parse\n", filename
);
3522 xmlFreeTextReader(reader
);
3524 xmlFreeStreamCtxt(patstream
);
3526 xmlFreePattern(patternc
);
3534 ret
= compareFiles(temp
, result
);
3536 fprintf(stderr
, "Result for %s failed\n", filename
);
3546 #endif /* PATTERN */
3547 #ifdef LIBXML_C14N_ENABLED
3548 /************************************************************************
3550 * Canonicalization tests *
3552 ************************************************************************/
3553 static xmlXPathObjectPtr
3554 load_xpath_expr (xmlDocPtr parent_doc
, const char* filename
) {
3555 xmlXPathObjectPtr xpath
;
3558 xmlXPathContextPtr ctx
;
3563 * load XPath expr as a file
3565 xmlLoadExtDtdDefaultValue
= XML_DETECT_IDS
| XML_COMPLETE_ATTRS
;
3566 xmlSubstituteEntitiesDefault(1);
3568 doc
= xmlReadFile(filename
, NULL
, XML_PARSE_DTDATTR
| XML_PARSE_NOENT
);
3570 fprintf(stderr
, "Error: unable to parse file \"%s\"\n", filename
);
3575 * Check the document is of the right kind
3577 if(xmlDocGetRootElement(doc
) == NULL
) {
3578 fprintf(stderr
,"Error: empty document for file \"%s\"\n", filename
);
3583 node
= doc
->children
;
3584 while(node
!= NULL
&& !xmlStrEqual(node
->name
, (const xmlChar
*)"XPath")) {
3589 fprintf(stderr
,"Error: XPath element expected in the file \"%s\"\n", filename
);
3594 expr
= xmlNodeGetContent(node
);
3596 fprintf(stderr
,"Error: XPath content element is NULL \"%s\"\n", filename
);
3601 ctx
= xmlXPathNewContext(parent_doc
);
3603 fprintf(stderr
,"Error: unable to create new context\n");
3610 * Register namespaces
3614 if(xmlXPathRegisterNs(ctx
, ns
->prefix
, ns
->href
) != 0) {
3615 fprintf(stderr
,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns
->prefix
, ns
->href
);
3617 xmlXPathFreeContext(ctx
);
3627 xpath
= xmlXPathEvalExpression(expr
, ctx
);
3629 fprintf(stderr
,"Error: unable to evaluate xpath expression\n");
3631 xmlXPathFreeContext(ctx
);
3636 /* print_xpath_nodes(xpath->nodesetval); */
3639 xmlXPathFreeContext(ctx
);
3645 * Macro used to grow the current buffer.
3647 #define xxx_growBufferReentrant() { \
3649 buffer = (xmlChar **) \
3650 xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \
3651 if (buffer == NULL) { \
3652 perror("realloc failed"); \
3658 parse_list(xmlChar
*str
) {
3660 xmlChar
**out
= NULL
;
3661 int buffer_size
= 0;
3668 len
= xmlStrlen(str
);
3669 if((str
[0] == '\'') && (str
[len
- 1] == '\'')) {
3670 str
[len
- 1] = '\0';
3674 * allocate an translation buffer.
3677 buffer
= (xmlChar
**) xmlMalloc(buffer_size
* sizeof(xmlChar
*));
3678 if (buffer
== NULL
) {
3679 perror("malloc failed");
3684 while(*str
!= '\0') {
3685 if (out
- buffer
> buffer_size
- 10) {
3686 int indx
= out
- buffer
;
3688 xxx_growBufferReentrant();
3689 out
= &buffer
[indx
];
3692 while(*str
!= ',' && *str
!= '\0') ++str
;
3693 if(*str
== ',') *(str
++) = '\0';
3700 c14nRunTest(const char* xml_filename
, int with_comments
, int mode
,
3701 const char* xpath_filename
, const char *ns_filename
,
3702 const char* result_file
) {
3704 xmlXPathObjectPtr xpath
= NULL
;
3705 xmlChar
*result
= NULL
;
3707 xmlChar
**inclusive_namespaces
= NULL
;
3708 const char *nslist
= NULL
;
3713 * build an XML tree from a the file; we need to add default
3714 * attributes and resolve all character and entities references
3716 xmlLoadExtDtdDefaultValue
= XML_DETECT_IDS
| XML_COMPLETE_ATTRS
;
3717 xmlSubstituteEntitiesDefault(1);
3719 doc
= xmlReadFile(xml_filename
, NULL
, XML_PARSE_DTDATTR
| XML_PARSE_NOENT
);
3721 fprintf(stderr
, "Error: unable to parse file \"%s\"\n", xml_filename
);
3726 * Check the document is of the right kind
3728 if(xmlDocGetRootElement(doc
) == NULL
) {
3729 fprintf(stderr
,"Error: empty document for file \"%s\"\n", xml_filename
);
3735 * load xpath file if specified
3737 if(xpath_filename
) {
3738 xpath
= load_xpath_expr(doc
, xpath_filename
);
3740 fprintf(stderr
,"Error: unable to evaluate xpath expression\n");
3746 if (ns_filename
!= NULL
) {
3747 if (loadMem(ns_filename
, &nslist
, &nssize
)) {
3748 fprintf(stderr
,"Error: unable to evaluate xpath expression\n");
3749 if(xpath
!= NULL
) xmlXPathFreeObject(xpath
);
3753 inclusive_namespaces
= parse_list((xmlChar
*) nslist
);
3759 /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
3760 ret
= xmlC14NDocDumpMemory(doc
,
3761 (xpath
) ? xpath
->nodesetval
: NULL
,
3762 mode
, inclusive_namespaces
,
3763 with_comments
, &result
);
3765 if(result
!= NULL
) {
3766 if (compareFileMem(result_file
, (const char *) result
, ret
)) {
3767 fprintf(stderr
, "Result mismatch for %s\n", xml_filename
);
3768 fprintf(stderr
, "RESULT:\n%s\n", (const char*)result
);
3773 fprintf(stderr
,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename
, ret
);
3780 if (result
!= NULL
) xmlFree(result
);
3781 if(xpath
!= NULL
) xmlXPathFreeObject(xpath
);
3782 if (inclusive_namespaces
!= NULL
) xmlFree(inclusive_namespaces
);
3783 if (nslist
!= NULL
) free((char *) nslist
);
3790 c14nCommonTest(const char *filename
, int with_comments
, int mode
,
3791 const char *subdir
) {
3796 char *result
= NULL
;
3801 base
= baseFilename(filename
);
3804 memcpy(prefix
, base
, len
);
3807 snprintf(buf
, 499, "result/c14n/%s/%s", subdir
,prefix
);
3808 if (!checkTestFile(buf
)) {
3809 fprintf(stderr
, "Missing result file %s", buf
);
3812 result
= strdup(buf
);
3813 snprintf(buf
, 499, "test/c14n/%s/%s.xpath", subdir
,prefix
);
3814 if (checkTestFile(buf
)) {
3815 xpath
= strdup(buf
);
3817 snprintf(buf
, 499, "test/c14n/%s/%s.ns", subdir
,prefix
);
3818 if (checkTestFile(buf
)) {
3823 if (c14nRunTest(filename
, with_comments
, mode
,
3824 xpath
, ns
, result
) < 0)
3827 if (result
!= NULL
) free(result
);
3828 if (xpath
!= NULL
) free(xpath
);
3829 if (ns
!= NULL
) free(ns
);
3834 c14nWithCommentTest(const char *filename
,
3835 const char *resul ATTRIBUTE_UNUSED
,
3836 const char *err ATTRIBUTE_UNUSED
,
3837 int options ATTRIBUTE_UNUSED
) {
3838 return(c14nCommonTest(filename
, 1, XML_C14N_1_0
, "with-comments"));
3841 c14nWithoutCommentTest(const char *filename
,
3842 const char *resul ATTRIBUTE_UNUSED
,
3843 const char *err ATTRIBUTE_UNUSED
,
3844 int options ATTRIBUTE_UNUSED
) {
3845 return(c14nCommonTest(filename
, 0, XML_C14N_1_0
, "without-comments"));
3848 c14nExcWithoutCommentTest(const char *filename
,
3849 const char *resul ATTRIBUTE_UNUSED
,
3850 const char *err ATTRIBUTE_UNUSED
,
3851 int options ATTRIBUTE_UNUSED
) {
3852 return(c14nCommonTest(filename
, 0, XML_C14N_EXCLUSIVE_1_0
, "exc-without-comments"));
3855 c14n11WithoutCommentTest(const char *filename
,
3856 const char *resul ATTRIBUTE_UNUSED
,
3857 const char *err ATTRIBUTE_UNUSED
,
3858 int options ATTRIBUTE_UNUSED
) {
3859 return(c14nCommonTest(filename
, 0, XML_C14N_1_1
, "1-1-without-comments"));
3862 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined (LIBXML_SAX1_ENABLED)
3863 /************************************************************************
3865 * Catalog and threads test *
3867 ************************************************************************/
3870 * mostly a cut and paste from testThreads.c
3874 static const char *catalog
= "test/threads/complex.xml";
3875 static const char *testfiles
[] = {
3876 "test/threads/abc.xml",
3877 "test/threads/acb.xml",
3878 "test/threads/bac.xml",
3879 "test/threads/bca.xml",
3880 "test/threads/cab.xml",
3881 "test/threads/cba.xml",
3882 "test/threads/invalid.xml",
3885 static const char *Okay
= "OK";
3886 static const char *Failed
= "Failed";
3888 #ifndef xmlDoValidityCheckingDefaultValue
3889 #error xmlDoValidityCheckingDefaultValue is not a macro
3891 #ifndef xmlGenericErrorContext
3892 #error xmlGenericErrorContext is not a macro
3896 thread_specific_data(void *private_data
)
3899 const char *filename
= (const char *) private_data
;
3902 if (!strcmp(filename
, "test/threads/invalid.xml")) {
3903 xmlDoValidityCheckingDefaultValue
= 0;
3904 xmlGenericErrorContext
= stdout
;
3906 xmlDoValidityCheckingDefaultValue
= 1;
3907 xmlGenericErrorContext
= stderr
;
3909 myDoc
= xmlParseFile(filename
);
3913 printf("parse failed\n");
3916 if (!strcmp(filename
, "test/threads/invalid.xml")) {
3917 if (xmlDoValidityCheckingDefaultValue
!= 0) {
3918 printf("ValidityCheckingDefaultValue override failed\n");
3921 if (xmlGenericErrorContext
!= stdout
) {
3922 printf("xmlGenericErrorContext override failed\n");
3926 if (xmlDoValidityCheckingDefaultValue
!= 1) {
3927 printf("ValidityCheckingDefaultValue override failed\n");
3930 if (xmlGenericErrorContext
!= stderr
) {
3931 printf("xmlGenericErrorContext override failed\n");
3936 return ((void *) Failed
);
3937 return ((void *) Okay
);
3941 #include <windows.h>
3944 #define TEST_REPEAT_COUNT 500
3946 static HANDLE tid
[MAX_ARGC
];
3949 win32_thread_specific_data(void *private_data
)
3951 return((DWORD
) thread_specific_data(private_data
));
3957 unsigned int i
, repeat
;
3958 unsigned int num_threads
= sizeof(testfiles
) / sizeof(testfiles
[0]);
3959 DWORD results
[MAX_ARGC
];
3964 for (repeat
= 0; repeat
< TEST_REPEAT_COUNT
; repeat
++) {
3965 xmlLoadCatalog(catalog
);
3968 for (i
= 0; i
< num_threads
; i
++) {
3970 tid
[i
] = (HANDLE
) - 1;
3973 for (i
= 0; i
< num_threads
; i
++) {
3976 tid
[i
] = CreateThread(NULL
, 0,
3977 win32_thread_specific_data
,
3978 (void *) testfiles
[i
], 0,
3980 if (tid
[i
] == NULL
) {
3981 fprintf(stderr
, "CreateThread failed\n");
3986 if (WaitForMultipleObjects(num_threads
, tid
, TRUE
, INFINITE
) ==
3988 fprintf(stderr
, "WaitForMultipleObjects failed\n");
3992 for (i
= 0; i
< num_threads
; i
++) {
3993 ret
= GetExitCodeThread(tid
[i
], &results
[i
]);
3995 fprintf(stderr
, "GetExitCodeThread failed\n");
3998 CloseHandle(tid
[i
]);
4001 xmlCatalogCleanup();
4002 for (i
= 0; i
< num_threads
; i
++) {
4003 if (results
[i
] != (DWORD
) Okay
) {
4004 fprintf(stderr
, "Thread %d handling %s failed\n",
4014 #elif defined __BEOS__
4017 static thread_id tid
[MAX_ARGC
];
4022 unsigned int i
, repeat
;
4023 unsigned int num_threads
= sizeof(testfiles
) / sizeof(testfiles
[0]);
4024 void *results
[MAX_ARGC
];
4029 for (repeat
= 0; repeat
< 500; repeat
++) {
4030 xmlLoadCatalog(catalog
);
4031 for (i
= 0; i
< num_threads
; i
++) {
4033 tid
[i
] = (thread_id
) - 1;
4035 for (i
= 0; i
< num_threads
; i
++) {
4037 spawn_thread(thread_specific_data
, "xmlTestThread",
4038 B_NORMAL_PRIORITY
, (void *) testfiles
[i
]);
4039 if (tid
[i
] < B_OK
) {
4040 fprintf(stderr
, "beos_thread_create failed\n");
4043 printf("beos_thread_create %d -> %d\n", i
, tid
[i
]);
4045 for (i
= 0; i
< num_threads
; i
++) {
4046 ret
= wait_for_thread(tid
[i
], &results
[i
]);
4047 printf("beos_thread_wait %d -> %d\n", i
, ret
);
4049 fprintf(stderr
, "beos_thread_wait failed\n");
4054 xmlCatalogCleanup();
4056 for (i
= 0; i
< num_threads
; i
++)
4057 if (results
[i
] != (void *) Okay
) {
4058 printf("Thread %d handling %s failed\n", i
, testfiles
[i
]);
4067 #elif defined HAVE_PTHREAD_H
4068 #include <pthread.h>
4070 static pthread_t tid
[MAX_ARGC
];
4075 unsigned int i
, repeat
;
4076 unsigned int num_threads
= sizeof(testfiles
) / sizeof(testfiles
[0]);
4077 void *results
[MAX_ARGC
];
4083 for (repeat
= 0; repeat
< 500; repeat
++) {
4084 xmlLoadCatalog(catalog
);
4087 for (i
= 0; i
< num_threads
; i
++) {
4089 tid
[i
] = (pthread_t
) - 1;
4092 for (i
= 0; i
< num_threads
; i
++) {
4093 ret
= pthread_create(&tid
[i
], 0, thread_specific_data
,
4094 (void *) testfiles
[i
]);
4096 fprintf(stderr
, "pthread_create failed\n");
4100 for (i
= 0; i
< num_threads
; i
++) {
4101 ret
= pthread_join(tid
[i
], &results
[i
]);
4103 fprintf(stderr
, "pthread_join failed\n");
4108 xmlCatalogCleanup();
4109 for (i
= 0; i
< num_threads
; i
++)
4110 if (results
[i
] != (void *) Okay
) {
4111 fprintf(stderr
, "Thread %d handling %s failed\n",
4124 "Specific platform thread support not detected\n");
4129 threadsTest(const char *filename ATTRIBUTE_UNUSED
,
4130 const char *resul ATTRIBUTE_UNUSED
,
4131 const char *err ATTRIBUTE_UNUSED
,
4132 int options ATTRIBUTE_UNUSED
) {
4133 return(testThread());
4136 /************************************************************************
4138 * Tests Descriptions *
4140 ************************************************************************/
4143 testDesc testDescriptions
[] = {
4144 { "XML regression tests" ,
4145 oldParseTest
, "./test/*", "result/", "", NULL
,
4147 { "XML regression tests on memory" ,
4148 memParseTest
, "./test/*", "result/", "", NULL
,
4150 { "XML entity subst regression tests" ,
4151 noentParseTest
, "./test/*", "result/noent/", "", NULL
,
4153 { "XML Namespaces regression tests",
4154 errParseTest
, "./test/namespaces/*", "result/namespaces/", "", ".err",
4156 { "Error cases regression tests",
4157 errParseTest
, "./test/errors/*.xml", "result/errors/", "", ".err",
4159 #ifdef LIBXML_READER_ENABLED
4160 { "Error cases stream regression tests",
4161 streamParseTest
, "./test/errors/*.xml", "result/errors/", NULL
, ".str",
4163 { "Reader regression tests",
4164 streamParseTest
, "./test/*", "result/", ".rdr", NULL
,
4166 { "Reader entities substitution regression tests",
4167 streamParseTest
, "./test/*", "result/", ".rde", NULL
,
4169 { "Reader on memory regression tests",
4170 streamMemParseTest
, "./test/*", "result/", ".rdr", NULL
,
4172 { "Walker regression tests",
4173 walkerParseTest
, "./test/*", "result/", ".rdr", NULL
,
4176 #ifdef LIBXML_SAX1_ENABLED
4177 { "SAX1 callbacks regression tests" ,
4178 saxParseTest
, "./test/*", "result/", ".sax", NULL
,
4180 { "SAX2 callbacks regression tests" ,
4181 saxParseTest
, "./test/*", "result/", ".sax2", NULL
,
4184 #ifdef LIBXML_PUSH_ENABLED
4185 { "XML push regression tests" ,
4186 pushParseTest
, "./test/*", "result/", "", NULL
,
4189 #ifdef LIBXML_HTML_ENABLED
4190 { "HTML regression tests" ,
4191 errParseTest
, "./test/HTML/*", "result/HTML/", "", ".err",
4193 #ifdef LIBXML_PUSH_ENABLED
4194 { "Push HTML regression tests" ,
4195 pushParseTest
, "./test/HTML/*", "result/HTML/", "", ".err",
4198 #ifdef LIBXML_SAX1_ENABLED
4199 { "HTML SAX regression tests" ,
4200 saxParseTest
, "./test/HTML/*", "result/HTML/", ".sax", NULL
,
4204 #ifdef LIBXML_VALID_ENABLED
4205 { "Valid documents regression tests" ,
4206 errParseTest
, "./test/VCM/*", NULL
, NULL
, NULL
,
4207 XML_PARSE_DTDVALID
},
4208 { "Validity checking regression tests" ,
4209 errParseTest
, "./test/VC/*", "result/VC/", NULL
, "",
4210 XML_PARSE_DTDVALID
},
4211 #ifdef LIBXML_READER_ENABLED
4212 { "Streaming validity checking regression tests" ,
4213 streamParseTest
, "./test/valid/*.xml", "result/valid/", NULL
, ".err.rdr",
4214 XML_PARSE_DTDVALID
},
4215 { "Streaming validity error checking regression tests" ,
4216 streamParseTest
, "./test/VC/*", "result/VC/", NULL
, ".rdr",
4217 XML_PARSE_DTDVALID
},
4219 { "General documents valid regression tests" ,
4220 errParseTest
, "./test/valid/*", "result/valid/", "", ".err",
4221 XML_PARSE_DTDVALID
},
4223 #ifdef LIBXML_XINCLUDE_ENABLED
4224 { "XInclude regression tests" ,
4225 errParseTest
, "./test/XInclude/docs/*", "result/XInclude/", "", NULL
,
4226 /* Ignore errors at this point ".err", */
4227 XML_PARSE_XINCLUDE
},
4228 #ifdef LIBXML_READER_ENABLED
4229 { "XInclude xmlReader regression tests",
4230 streamParseTest
, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4231 /* Ignore errors at this point ".err", */
4232 NULL
, XML_PARSE_XINCLUDE
},
4234 { "XInclude regression tests stripping include nodes" ,
4235 errParseTest
, "./test/XInclude/docs/*", "result/XInclude/", "", NULL
,
4236 /* Ignore errors at this point ".err", */
4237 XML_PARSE_XINCLUDE
| XML_PARSE_NOXINCNODE
},
4238 #ifdef LIBXML_READER_ENABLED
4239 { "XInclude xmlReader regression tests stripping include nodes",
4240 streamParseTest
, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4241 /* Ignore errors at this point ".err", */
4242 NULL
, XML_PARSE_XINCLUDE
| XML_PARSE_NOXINCNODE
},
4245 #ifdef LIBXML_XPATH_ENABLED
4246 #ifdef LIBXML_DEBUG_ENABLED
4247 { "XPath expressions regression tests" ,
4248 xpathExprTest
, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL
,
4250 { "XPath document queries regression tests" ,
4251 xpathDocTest
, "./test/XPath/docs/*", NULL
, NULL
, NULL
,
4253 #ifdef LIBXML_XPTR_ENABLED
4254 { "XPointer document queries regression tests" ,
4255 xptrDocTest
, "./test/XPath/docs/*", NULL
, NULL
, NULL
,
4258 { "xml:id regression tests" ,
4259 xmlidDocTest
, "./test/xmlid/*", "result/xmlid/", "", ".err",
4263 { "URI parsing tests" ,
4264 uriParseTest
, "./test/URI/*.uri", "result/URI/", "", NULL
,
4266 { "URI base composition tests" ,
4267 uriBaseTest
, "./test/URI/*.data", "result/URI/", "", NULL
,
4269 { "Path URI conversion tests" ,
4270 uriPathTest
, NULL
, NULL
, NULL
, NULL
,
4272 #ifdef LIBXML_SCHEMAS_ENABLED
4273 { "Schemas regression tests" ,
4274 schemasTest
, "./test/schemas/*_*.xsd", NULL
, NULL
, NULL
,
4276 { "Relax-NG regression tests" ,
4277 rngTest
, "./test/relaxng/*.rng", NULL
, NULL
, NULL
,
4278 XML_PARSE_DTDATTR
| XML_PARSE_NOENT
},
4279 #ifdef LIBXML_READER_ENABLED
4280 { "Relax-NG streaming regression tests" ,
4281 rngStreamTest
, "./test/relaxng/*.rng", NULL
, NULL
, NULL
,
4282 XML_PARSE_DTDATTR
| XML_PARSE_NOENT
},
4285 #ifdef LIBXML_PATTERN_ENABLED
4286 #ifdef LIBXML_READER_ENABLED
4287 { "Pattern regression tests" ,
4288 patternTest
, "./test/pattern/*.pat", "result/pattern/", NULL
, NULL
,
4292 #ifdef LIBXML_C14N_ENABLED
4293 { "C14N with comments regression tests" ,
4294 c14nWithCommentTest
, "./test/c14n/with-comments/*.xml", NULL
, NULL
, NULL
,
4296 { "C14N without comments regression tests" ,
4297 c14nWithoutCommentTest
, "./test/c14n/without-comments/*.xml", NULL
, NULL
, NULL
,
4299 { "C14N exclusive without comments regression tests" ,
4300 c14nExcWithoutCommentTest
, "./test/c14n/exc-without-comments/*.xml", NULL
, NULL
, NULL
,
4302 { "C14N 1.1 without comments regression tests" ,
4303 c14n11WithoutCommentTest
, "./test/c14n/1-1-without-comments/*.xml", NULL
, NULL
, NULL
,
4306 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_SAX1_ENABLED)
4307 { "Catalog and Threads regression tests" ,
4308 threadsTest
, NULL
, NULL
, NULL
, NULL
,
4311 {NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, 0}
4314 /************************************************************************
4316 * The main code driving the tests *
4318 ************************************************************************/
4321 launchTests(testDescPtr tst
) {
4322 int res
= 0, err
= 0;
4328 if (tst
== NULL
) return(-1);
4329 if (tst
->in
!= NULL
) {
4332 globbuf
.gl_offs
= 0;
4333 glob(tst
->in
, GLOB_DOOFFS
, NULL
, &globbuf
);
4334 for (i
= 0;i
< globbuf
.gl_pathc
;i
++) {
4335 if (!checkTestFile(globbuf
.gl_pathv
[i
]))
4337 if (tst
->suffix
!= NULL
) {
4338 result
= resultFilename(globbuf
.gl_pathv
[i
], tst
->out
,
4340 if (result
== NULL
) {
4341 fprintf(stderr
, "Out of memory !\n");
4347 if (tst
->err
!= NULL
) {
4348 error
= resultFilename(globbuf
.gl_pathv
[i
], tst
->out
,
4350 if (error
== NULL
) {
4351 fprintf(stderr
, "Out of memory !\n");
4357 if ((result
) &&(!checkTestFile(result
))) {
4358 fprintf(stderr
, "Missing result file %s\n", result
);
4359 } else if ((error
) &&(!checkTestFile(error
))) {
4360 fprintf(stderr
, "Missing error file %s\n", error
);
4363 extraMemoryFromResolver
= 0;
4366 res
= tst
->func(globbuf
.gl_pathv
[i
], result
, error
,
4367 tst
->options
| XML_PARSE_COMPACT
);
4368 xmlResetLastError();
4370 fprintf(stderr
, "File %s generated an error\n",
4371 globbuf
.gl_pathv
[i
]);
4375 else if (xmlMemUsed() != mem
) {
4376 if ((xmlMemUsed() != mem
) &&
4377 (extraMemoryFromResolver
== 0)) {
4378 fprintf(stderr
, "File %s leaked %d bytes\n",
4379 globbuf
.gl_pathv
[i
], xmlMemUsed() - mem
);
4395 extraMemoryFromResolver
= 0;
4396 res
= tst
->func(NULL
, NULL
, NULL
, tst
->options
);
4405 static int verbose
= 0;
4406 static int tests_quiet
= 0;
4411 int old_errors
, old_tests
, old_leaks
;
4413 old_errors
= nb_errors
;
4414 old_tests
= nb_tests
;
4415 old_leaks
= nb_leaks
;
4416 if ((tests_quiet
== 0) && (testDescriptions
[i
].desc
!= NULL
))
4417 printf("## %s\n", testDescriptions
[i
].desc
);
4418 res
= launchTests(&testDescriptions
[i
]);
4422 if ((nb_errors
== old_errors
) && (nb_leaks
== old_leaks
))
4423 printf("Ran %d tests, no errors\n", nb_tests
- old_tests
);
4425 printf("Ran %d tests, %d errors, %d leaks\n",
4426 nb_tests
- old_tests
,
4427 nb_errors
- old_errors
,
4428 nb_leaks
- old_leaks
);
4434 main(int argc ATTRIBUTE_UNUSED
, char **argv ATTRIBUTE_UNUSED
) {
4438 initializeLibxml2();
4440 for (a
= 1; a
< argc
;a
++) {
4441 if (!strcmp(argv
[a
], "-v"))
4443 else if (!strcmp(argv
[a
], "-quiet"))
4446 for (i
= 0; testDescriptions
[i
].func
!= NULL
; i
++) {
4447 if (strstr(testDescriptions
[i
].desc
, argv
[a
])) {
4455 for (i
= 0; testDescriptions
[i
].func
!= NULL
; i
++) {
4459 if ((nb_errors
== 0) && (nb_leaks
== 0)) {
4461 printf("Total %d tests, no errors\n",
4465 printf("Total %d tests, %d errors, %d leaks\n",
4466 nb_tests
, nb_errors
, nb_leaks
);
4474 #else /* ! LIBXML_OUTPUT_ENABLED */
4476 main(int argc ATTRIBUTE_UNUSED
, char **argv ATTRIBUTE_UNUSED
) {
4477 fprintf(stderr
, "runtest requires output to be enabled in libxml2\n");