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