aboutsummaryrefslogtreecommitdiffstats
path: root/runtest.c
diff options
context:
space:
mode:
authorWilliam M. Brack <wbrack@src.gnome.org>2005-07-06 20:41:33 +0000
committerWilliam M. Brack <wbrack@src.gnome.org>2005-07-06 20:41:33 +0000
commitca15a54652318d0a9572a3b1f881d2921b93264f (patch)
tree6093d65199d42f569b799b721643d14b8a19e3a5 /runtest.c
parent12baaecdb7a2b7ebd5d16aea9dd4fa3f4a4a978b (diff)
downloadandroid_external_libxml2-ca15a54652318d0a9572a3b1f881d2921b93264f.tar.gz
android_external_libxml2-ca15a54652318d0a9572a3b1f881d2921b93264f.tar.bz2
android_external_libxml2-ca15a54652318d0a9572a3b1f881d2921b93264f.zip
Reformatted on Windows, then re-committed to CVS
Diffstat (limited to 'runtest.c')
-rw-r--r--runtest.c8444
1 files changed, 4222 insertions, 4222 deletions
diff --git a/runtest.c b/runtest.c
index b05bfe6f..1923dc1c 100644
--- a/runtest.c
+++ b/runtest.c
@@ -1,4222 +1,4222 @@
-/*
- * runtest.c: C program to run libxml2 regression tests without
- * requiring make or Python, and reducing platform dependancies
- * to a strict minimum.
- *
- * To compile on Unixes:
- * cc -o runtest `xml2-config --cflags` runtest.c `xml2-config --libs` -lpthread
- *
- * See Copyright for the status of this software.
- *
- * daniel@veillard.com
- */
-
-#if !defined(_WIN32) || defined(__CYGWIN__)
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/uri.h>
-
-#ifdef LIBXML_OUTPUT_ENABLED
-#ifdef LIBXML_READER_ENABLED
-#include <libxml/xmlreader.h>
-#endif
-
-#ifdef LIBXML_XINCLUDE_ENABLED
-#include <libxml/xinclude.h>
-#endif
-
-#ifdef LIBXML_XPATH_ENABLED
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
-#ifdef LIBXML_XPTR_ENABLED
-#include <libxml/xpointer.h>
-#endif
-#endif
-
-#ifdef LIBXML_SCHEMAS_ENABLED
-#include <libxml/relaxng.h>
-#include <libxml/xmlschemas.h>
-#include <libxml/xmlschemastypes.h>
-#endif
-
-#ifdef LIBXML_PATTERN_ENABLED
-#include <libxml/pattern.h>
-#endif
-
-#ifdef LIBXML_C14N_ENABLED
-#include <libxml/c14n.h>
-#endif
-
-#ifdef LIBXML_HTML_ENABLED
-#include <libxml/HTMLparser.h>
-#include <libxml/HTMLtree.h>
-
-/*
- * pseudo flag for the unification of HTML and XML tests
- */
-#define XML_PARSE_HTML 1 << 24
-#endif
-
-#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
-#include <libxml/globals.h>
-#include <libxml/threads.h>
-#include <libxml/parser.h>
-#include <libxml/catalog.h>
-#include <string.h>
-#endif
-
-/*
- * O_BINARY is just for Windows compatibility - if it isn't defined
- * on this system, avoid any compilation error
- */
-#ifdef O_BINARY
-#define RD_FLAGS O_RDONLY | O_BINARY
-#else
-#define RD_FLAGS O_RDONLY
-#endif
-
-typedef int (*functest) (const char *filename, const char *result,
- const char *error, int options);
-
-typedef struct testDesc testDesc;
-typedef testDesc *testDescPtr;
-struct testDesc {
- const char *desc; /* descripton of the test */
- functest func; /* function implementing the test */
- const char *in; /* glob to path for input files */
- const char *out; /* output directory */
- const char *suffix;/* suffix for output files */
- const char *err; /* suffix for error output files */
- int options; /* parser options for the test */
-};
-
-static int checkTestFile(const char *filename);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
-
-#include <windows.h>
-#include <io.h>
-
-typedef struct
-{
- size_t gl_pathc; /* Count of paths matched so far */
- char **gl_pathv; /* List of matched pathnames. */
- size_t gl_offs; /* Slots to reserve in 'gl_pathv'. */
-} glob_t;
-
-#define GLOB_DOOFFS 0
-static int glob(const char *pattern, int flags,
- int errfunc(const char *epath, int eerrno),
- glob_t *pglob) {
- glob_t *ret;
- WIN32_FIND_DATA FindFileData;
- HANDLE hFind;
- unsigned int nb_paths = 0;
- char directory[500];
- int len;
-
- if ((pattern == NULL) || (pglob == NULL)) return(-1);
-
- strncpy(directory, pattern, 499);
- for (len = strlen(directory);len >= 0;len--) {
- if (directory[len] == '/') {
- len++;
- directory[len] = 0;
- break;
- }
- }
- if (len <= 0)
- len = 0;
-
-
- ret = pglob;
- memset(ret, 0, sizeof(glob_t));
-
- hFind = FindFirstFileA(pattern, &FindFileData);
- if (hFind == INVALID_HANDLE_VALUE)
- return(0);
- nb_paths = 20;
- ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
- if (ret->gl_pathv == NULL) {
- FindClose(hFind);
- return(-1);
- }
- strncpy(directory + len, FindFileData.cFileName, 499 - len);
- ret->gl_pathv[ret->gl_pathc] = strdup(directory);
- if (ret->gl_pathv[ret->gl_pathc] == NULL)
- goto done;
- ret->gl_pathc++;
- while(FindNextFileA(hFind, &FindFileData)) {
- if (FindFileData.cFileName[0] == '.')
- continue;
- if (ret->gl_pathc + 2 > nb_paths) {
- char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
- if (tmp == NULL)
- break;
- ret->gl_pathv = tmp;
- nb_paths *= 2;
- }
- strncpy(directory + len, FindFileData.cFileName, 499 - len);
- ret->gl_pathv[ret->gl_pathc] = strdup(directory);
- if (ret->gl_pathv[ret->gl_pathc] == NULL)
- break;
- ret->gl_pathc++;
- }
- ret->gl_pathv[ret->gl_pathc] = NULL;
-
-done:
- FindClose(hFind);
- return(0);
-}
-
-
-
-static void globfree(glob_t *pglob) {
- unsigned int i;
- if (pglob == NULL)
- return;
-
- for (i = 0;i < pglob->gl_pathc;i++) {
- if (pglob->gl_pathv[i] != NULL)
- free(pglob->gl_pathv[i]);
- }
-}
-#define vsnprintf _vsnprintf
-#define snprintf _snprintf
-#else
-#include <glob.h>
-#endif
-
-/************************************************************************
- * *
- * Libxml2 specific routines *
- * *
- ************************************************************************/
-
-static int nb_tests = 0;
-static int nb_errors = 0;
-static int nb_leaks = 0;
-static long libxmlMemoryAllocatedBase = 0;
-static int extraMemoryFromResolver = 0;
-
-static int
-fatalError(void) {
- fprintf(stderr, "Exitting tests on fatal error\n");
- exit(1);
-}
-
-/*
- * We need to trap calls to the resolver to not account memory for the catalog
- * which is shared to the current running test. We also don't want to have
- * network downloads modifying tests.
- */
-static xmlParserInputPtr
-testExternalEntityLoader(const char *URL, const char *ID,
- xmlParserCtxtPtr ctxt) {
- xmlParserInputPtr ret;
-
- if (checkTestFile(URL)) {
- ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
- } else {
- int memused = xmlMemUsed();
- ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
- extraMemoryFromResolver += xmlMemUsed() - memused;
- }
-
- return(ret);
-}
-
-/*
- * Trapping the error messages at the generic level to grab the equivalent of
- * stderr messages on CLI tools.
- */
-static char testErrors[32769];
-static int testErrorsSize = 0;
-
-static void
-testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
- va_list args;
- int res;
-
- if (testErrorsSize >= 32768)
- return;
- va_start(args, msg);
- res = vsnprintf(&testErrors[testErrorsSize],
- 32768 - testErrorsSize,
- msg, args);
- va_end(args);
- if (testErrorsSize + res >= 32768) {
- /* buffer is full */
- testErrorsSize = 32768;
- testErrors[testErrorsSize] = 0;
- } else {
- testErrorsSize += res;
- }
- testErrors[testErrorsSize] = 0;
-}
-
-static void
-channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
- va_list args;
- int res;
-
- if (testErrorsSize >= 32768)
- return;
- va_start(args, msg);
- res = vsnprintf(&testErrors[testErrorsSize],
- 32768 - testErrorsSize,
- msg, args);
- va_end(args);
- if (testErrorsSize + res >= 32768) {
- /* buffer is full */
- testErrorsSize = 32768;
- testErrors[testErrorsSize] = 0;
- } else {
- testErrorsSize += res;
- }
- testErrors[testErrorsSize] = 0;
-}
-
-/**
- * xmlParserPrintFileContext:
- * @input: an xmlParserInputPtr input
- *
- * Displays current context within the input content for error tracking
- */
-
-static void
-xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
- xmlGenericErrorFunc chanl, void *data ) {
- const xmlChar *cur, *base;
- unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
- xmlChar content[81]; /* space for 80 chars + line terminator */
- xmlChar *ctnt;
-
- if (input == NULL) return;
- cur = input->cur;
- base = input->base;
- /* skip backwards over any end-of-lines */
- while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
- cur--;
- }
- n = 0;
- /* search backwards for beginning-of-line (to max buff size) */
- while ((n++ < (sizeof(content)-1)) && (cur > base) &&
- (*(cur) != '\n') && (*(cur) != '\r'))
- cur--;
- if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
- /* calculate the error position in terms of the current position */
- col = input->cur - cur;
- /* search forward for end-of-line (to max buff size) */
- n = 0;
- ctnt = content;
- /* copy selected text to our buffer */
- while ((*cur != 0) && (*(cur) != '\n') &&
- (*(cur) != '\r') && (n < sizeof(content)-1)) {
- *ctnt++ = *cur++;
- n++;
- }
- *ctnt = 0;
- /* print out the selected text */
- chanl(data ,"%s\n", content);
- /* create blank line with problem pointer */
- n = 0;
- ctnt = content;
- /* (leave buffer space for pointer + line terminator) */
- while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
- if (*(ctnt) != '\t')
- *(ctnt) = ' ';
- ctnt++;
- }
- *ctnt++ = '^';
- *ctnt = 0;
- chanl(data ,"%s\n", content);
-}
-
-static void
-testStructuredErrorHandler(void *ctx ATTRIBUTE_UNUSED, xmlErrorPtr err) {
- char *file = NULL;
- int line = 0;
- int code = -1;
- int domain;
- void *data = NULL;
- const char *str;
- const xmlChar *name = NULL;
- xmlNodePtr node;
- xmlErrorLevel level;
- xmlParserInputPtr input = NULL;
- xmlParserInputPtr cur = NULL;
- xmlParserCtxtPtr ctxt = NULL;
-
- if (err == NULL)
- return;
-
- file = err->file;
- line = err->line;
- code = err->code;
- domain = err->domain;
- level = err->level;
- node = err->node;
- if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
- (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
- (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
- ctxt = err->ctxt;
- }
- str = err->message;
-
- if (code == XML_ERR_OK)
- return;
-
- if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
- name = node->name;
-
- /*
- * Maintain the compatibility with the legacy error handling
- */
- if (ctxt != NULL) {
- input = ctxt->input;
- if ((input != NULL) && (input->filename == NULL) &&
- (ctxt->inputNr > 1)) {
- cur = input;
- input = ctxt->inputTab[ctxt->inputNr - 2];
- }
- if (input != NULL) {
- if (input->filename)
- channel(data, "%s:%d: ", input->filename, input->line);
- else if ((line != 0) && (domain == XML_FROM_PARSER))
- channel(data, "Entity: line %d: ", input->line);
- }
- } else {
- if (file != NULL)
- channel(data, "%s:%d: ", file, line);
- else if ((line != 0) && (domain == XML_FROM_PARSER))
- channel(data, "Entity: line %d: ", line);
- }
- if (name != NULL) {
- channel(data, "element %s: ", name);
- }
- if (code == XML_ERR_OK)
- return;
- switch (domain) {
- case XML_FROM_PARSER:
- channel(data, "parser ");
- break;
- case XML_FROM_NAMESPACE:
- channel(data, "namespace ");
- break;
- case XML_FROM_DTD:
- case XML_FROM_VALID:
- channel(data, "validity ");
- break;
- case XML_FROM_HTML:
- channel(data, "HTML parser ");
- break;
- case XML_FROM_MEMORY:
- channel(data, "memory ");
- break;
- case XML_FROM_OUTPUT:
- channel(data, "output ");
- break;
- case XML_FROM_IO:
- channel(data, "I/O ");
- break;
- case XML_FROM_XINCLUDE:
- channel(data, "XInclude ");
- break;
- case XML_FROM_XPATH:
- channel(data, "XPath ");
- break;
- case XML_FROM_XPOINTER:
- channel(data, "parser ");
- break;
- case XML_FROM_REGEXP:
- channel(data, "regexp ");
- break;
- case XML_FROM_MODULE:
- channel(data, "module ");
- break;
- case XML_FROM_SCHEMASV:
- channel(data, "Schemas validity ");
- break;
- case XML_FROM_SCHEMASP:
- channel(data, "Schemas parser ");
- break;
- case XML_FROM_RELAXNGP:
- channel(data, "Relax-NG parser ");
- break;
- case XML_FROM_RELAXNGV:
- channel(data, "Relax-NG validity ");
- break;
- case XML_FROM_CATALOG:
- channel(data, "Catalog ");
- break;
- case XML_FROM_C14N:
- channel(data, "C14N ");
- break;
- case XML_FROM_XSLT:
- channel(data, "XSLT ");
- break;
- default:
- break;
- }
- if (code == XML_ERR_OK)
- return;
- switch (level) {
- case XML_ERR_NONE:
- channel(data, ": ");
- break;
- case XML_ERR_WARNING:
- channel(data, "warning : ");
- break;
- case XML_ERR_ERROR:
- channel(data, "error : ");
- break;
- case XML_ERR_FATAL:
- channel(data, "error : ");
- break;
- }
- if (code == XML_ERR_OK)
- return;
- if (str != NULL) {
- int len;
- len = xmlStrlen((const xmlChar *)str);
- if ((len > 0) && (str[len - 1] != '\n'))
- channel(data, "%s\n", str);
- else
- channel(data, "%s", str);
- } else {
- channel(data, "%s\n", "out of memory error");
- }
- if (code == XML_ERR_OK)
- return;
-
- if (ctxt != NULL) {
- xmlParserPrintFileContextInternal(input, channel, data);
- if (cur != NULL) {
- if (cur->filename)
- channel(data, "%s:%d: \n", cur->filename, cur->line);
- else if ((line != 0) && (domain == XML_FROM_PARSER))
- channel(data, "Entity: line %d: \n", cur->line);
- xmlParserPrintFileContextInternal(cur, channel, data);
- }
- }
- if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
- (err->int1 < 100) &&
- (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
- xmlChar buf[150];
- int i;
-
- channel(data, "%s\n", err->str1);
- for (i=0;i < err->int1;i++)
- buf[i] = ' ';
- buf[i++] = '^';
- buf[i] = 0;
- channel(data, "%s\n", buf);
- }
-}
-
-static void
-initializeLibxml2(void) {
- xmlGetWarningsDefaultValue = 0;
- xmlPedanticParserDefault(0);
-
- xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
- xmlInitParser();
- xmlSetExternalEntityLoader(testExternalEntityLoader);
- xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
-#ifdef LIBXML_SCHEMAS_ENABLED
- xmlSchemaInitTypes();
- xmlRelaxNGInitTypes();
-#endif
- libxmlMemoryAllocatedBase = xmlMemUsed();
-}
-
-
-/************************************************************************
- * *
- * File name and path utilities *
- * *
- ************************************************************************/
-
-static const char *baseFilename(const char *filename) {
- const char *cur;
- if (filename == NULL)
- return(NULL);
- cur = &filename[strlen(filename)];
- while ((cur > filename) && (*cur != '/'))
- cur--;
- if (*cur == '/')
- return(cur + 1);
- return(cur);
-}
-
-static char *resultFilename(const char *filename, const char *out,
- const char *suffix) {
- const char *base;
- char res[500];
-
-/*************
- if ((filename[0] == 't') && (filename[1] == 'e') &&
- (filename[2] == 's') && (filename[3] == 't') &&
- (filename[4] == '/'))
- filename = &filename[5];
- *************/
-
- base = baseFilename(filename);
- if (suffix == NULL)
- suffix = ".tmp";
- if (out == NULL)
- out = "";
- snprintf(res, 499, "%s%s%s", out, base, suffix);
- res[499] = 0;
- return(strdup(res));
-}
-
-static int checkTestFile(const char *filename) {
- struct stat buf;
-
- if (stat(filename, &buf) == -1)
- return(0);
-
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (!(buf.st_mode & _S_IFREG))
- return(0);
-#else
- if (!S_ISREG(buf.st_mode))
- return(0);
-#endif
-
- return(1);
-}
-
-static int compareFiles(const char *r1, const char *r2) {
- int res1, res2;
- int fd1, fd2;
- char bytes1[4096];
- char bytes2[4096];
-
- fd1 = open(r1, RD_FLAGS);
- if (fd1 < 0)
- return(-1);
- fd2 = open(r2, RD_FLAGS);
- if (fd2 < 0) {
- close(fd1);
- return(-1);
- }
- while (1) {
- res1 = read(fd1, bytes1, 4096);
- res2 = read(fd2, bytes2, 4096);
- if (res1 != res2) {
- close(fd1);
- close(fd2);
- return(1);
- }
- if (res1 == 0)
- break;
- if (memcmp(bytes1, bytes2, res1) != 0) {
- close(fd1);
- close(fd2);
- return(1);
- }
- }
- close(fd1);
- close(fd2);
- return(0);
-}
-
-static int compareFileMem(const char *filename, const char *mem, int size) {
- int res;
- int fd;
- char bytes[4096];
- int idx = 0;
- struct stat info;
-
- if (stat(filename, &info) < 0)
- return(-1);
- if (info.st_size != size)
- return(-1);
- fd = open(filename, RD_FLAGS);
- if (fd < 0)
- return(-1);
- while (idx < size) {
- res = read(fd, bytes, 4096);
- if (res <= 0)
- break;
- if (res + idx > size)
- break;
- if (memcmp(bytes, &mem[idx], res) != 0) {
- int ix;
- for (ix=0; ix<res; ix++)
- if (bytes[ix] != mem[idx+ix])
- break;
- fprintf(stderr,"Compare error at position %d\n", idx+ix);
- close(fd);
- return(1);
- }
- idx += res;
- }
- close(fd);
- return(idx != size);
-}
-
-static int loadMem(const char *filename, const char **mem, int *size) {
- int fd, res;
- struct stat info;
- char *base;
- int siz = 0;
- if (stat(filename, &info) < 0)
- return(-1);
- base = malloc(info.st_size + 1);
- if (base == NULL)
- return(-1);
- if ((fd = open(filename, RD_FLAGS)) < 0) {
- free(base);
- return(-1);
- }
- while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
- siz += res;
- }
- close(fd);
-#if !defined(_WIN32)
- if (siz != info.st_size) {
- free(base);
- return(-1);
- }
-#endif
- base[siz] = 0;
- *mem = base;
- *size = siz;
- return(0);
-}
-
-static int unloadMem(const char *mem) {
- free((char *)mem);
- return(0);
-}
-
-/************************************************************************
- * *
- * Tests implementations *
- * *
- ************************************************************************/
-
-/************************************************************************
- * *
- * Parse to SAX based tests *
- * *
- ************************************************************************/
-
-FILE *SAXdebug = NULL;
-
-/*
- * empty SAX block
- */
-xmlSAXHandler emptySAXHandlerStruct = {
- NULL, /* internalSubset */
- NULL, /* isStandalone */
- NULL, /* hasInternalSubset */
- NULL, /* hasExternalSubset */
- NULL, /* resolveEntity */
- NULL, /* getEntity */
- NULL, /* entityDecl */
- NULL, /* notationDecl */
- NULL, /* attributeDecl */
- NULL, /* elementDecl */
- NULL, /* unparsedEntityDecl */
- NULL, /* setDocumentLocator */
- NULL, /* startDocument */
- NULL, /* endDocument */
- NULL, /* startElement */
- NULL, /* endElement */
- NULL, /* reference */
- NULL, /* characters */
- NULL, /* ignorableWhitespace */
- NULL, /* processingInstruction */
- NULL, /* comment */
- NULL, /* xmlParserWarning */
- NULL, /* xmlParserError */
- NULL, /* xmlParserError */
- NULL, /* getParameterEntity */
- NULL, /* cdataBlock; */
- NULL, /* externalSubset; */
- 1,
- NULL,
- NULL, /* startElementNs */
- NULL, /* endElementNs */
- NULL /* xmlStructuredErrorFunc */
-};
-
-static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
-int callbacks = 0;
-int quiet = 0;
-
-/**
- * isStandaloneDebug:
- * @ctxt: An XML parser context
- *
- * Is this document tagged standalone ?
- *
- * Returns 1 if true
- */
-static int
-isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
-{
- callbacks++;
- if (quiet)
- return(0);
- fprintf(SAXdebug, "SAX.isStandalone()\n");
- return(0);
-}
-
-/**
- * hasInternalSubsetDebug:
- * @ctxt: An XML parser context
- *
- * Does this document has an internal subset
- *
- * Returns 1 if true
- */
-static int
-hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
-{
- callbacks++;
- if (quiet)
- return(0);
- fprintf(SAXdebug, "SAX.hasInternalSubset()\n");
- return(0);
-}
-
-/**
- * hasExternalSubsetDebug:
- * @ctxt: An XML parser context
- *
- * Does this document has an external subset
- *
- * Returns 1 if true
- */
-static int
-hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
-{
- callbacks++;
- if (quiet)
- return(0);
- fprintf(SAXdebug, "SAX.hasExternalSubset()\n");
- return(0);
-}
-
-/**
- * internalSubsetDebug:
- * @ctxt: An XML parser context
- *
- * Does this document has an internal subset
- */
-static void
-internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
- const xmlChar *ExternalID, const xmlChar *SystemID)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
- if (ExternalID == NULL)
- fprintf(SAXdebug, " ,");
- else
- fprintf(SAXdebug, " %s,", ExternalID);
- if (SystemID == NULL)
- fprintf(SAXdebug, " )\n");
- else
- fprintf(SAXdebug, " %s)\n", SystemID);
-}
-
-/**
- * externalSubsetDebug:
- * @ctxt: An XML parser context
- *
- * Does this document has an external subset
- */
-static void
-externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
- const xmlChar *ExternalID, const xmlChar *SystemID)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
- if (ExternalID == NULL)
- fprintf(SAXdebug, " ,");
- else
- fprintf(SAXdebug, " %s,", ExternalID);
- if (SystemID == NULL)
- fprintf(SAXdebug, " )\n");
- else
- fprintf(SAXdebug, " %s)\n", SystemID);
-}
-
-/**
- * resolveEntityDebug:
- * @ctxt: An XML parser context
- * @publicId: The public ID of the entity
- * @systemId: The system ID of the entity
- *
- * Special entity resolver, better left to the parser, it has
- * more context than the application layer.
- * The default behaviour is to NOT resolve the entities, in that case
- * the ENTITY_REF nodes are built in the structure (and the parameter
- * values).
- *
- * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
- */
-static xmlParserInputPtr
-resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
-{
- callbacks++;
- if (quiet)
- return(NULL);
- /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
-
-
- fprintf(SAXdebug, "SAX.resolveEntity(");
- if (publicId != NULL)
- fprintf(SAXdebug, "%s", (char *)publicId);
- else
- fprintf(SAXdebug, " ");
- if (systemId != NULL)
- fprintf(SAXdebug, ", %s)\n", (char *)systemId);
- else
- fprintf(SAXdebug, ", )\n");
-/*********
- if (systemId != NULL) {
- return(xmlNewInputFromFile(ctxt, (char *) systemId));
- }
- *********/
- return(NULL);
-}
-
-/**
- * getEntityDebug:
- * @ctxt: An XML parser context
- * @name: The entity name
- *
- * Get an entity by name
- *
- * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
- */
-static xmlEntityPtr
-getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
-{
- callbacks++;
- if (quiet)
- return(NULL);
- fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
- return(NULL);
-}
-
-/**
- * getParameterEntityDebug:
- * @ctxt: An XML parser context
- * @name: The entity name
- *
- * Get a parameter entity by name
- *
- * Returns the xmlParserInputPtr
- */
-static xmlEntityPtr
-getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
-{
- callbacks++;
- if (quiet)
- return(NULL);
- fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
- return(NULL);
-}
-
-
-/**
- * entityDeclDebug:
- * @ctxt: An XML parser context
- * @name: the entity name
- * @type: the entity type
- * @publicId: The public ID of the entity
- * @systemId: The system ID of the entity
- * @content: the entity value (without processing).
- *
- * An entity definition has been parsed
- */
-static void
-entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
- const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
-{
-const xmlChar *nullstr = BAD_CAST "(null)";
- /* not all libraries handle printing null pointers nicely */
- if (publicId == NULL)
- publicId = nullstr;
- if (systemId == NULL)
- systemId = nullstr;
- if (content == NULL)
- content = (xmlChar *)nullstr;
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
- name, type, publicId, systemId, content);
-}
-
-/**
- * attributeDeclDebug:
- * @ctxt: An XML parser context
- * @name: the attribute name
- * @type: the attribute type
- *
- * An attribute definition has been parsed
- */
-static void
-attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
- const xmlChar * name, int type, int def,
- const xmlChar * defaultValue, xmlEnumerationPtr tree)
-{
- callbacks++;
- if (quiet)
- return;
- if (defaultValue == NULL)
- fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
- elem, name, type, def);
- else
- fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
- elem, name, type, def, defaultValue);
- xmlFreeEnumeration(tree);
-}
-
-/**
- * elementDeclDebug:
- * @ctxt: An XML parser context
- * @name: the element name
- * @type: the element type
- * @content: the element value (without processing).
- *
- * An element definition has been parsed
- */
-static void
-elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
- xmlElementContentPtr content ATTRIBUTE_UNUSED)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n",
- name, type);
-}
-
-/**
- * notationDeclDebug:
- * @ctxt: An XML parser context
- * @name: The name of the notation
- * @publicId: The public ID of the entity
- * @systemId: The system ID of the entity
- *
- * What to do when a notation declaration has been parsed.
- */
-static void
-notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
- const xmlChar *publicId, const xmlChar *systemId)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n",
- (char *) name, (char *) publicId, (char *) systemId);
-}
-
-/**
- * unparsedEntityDeclDebug:
- * @ctxt: An XML parser context
- * @name: The name of the entity
- * @publicId: The public ID of the entity
- * @systemId: The system ID of the entity
- * @notationName: the name of the notation
- *
- * What to do when an unparsed entity declaration is parsed
- */
-static void
-unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
- const xmlChar *publicId, const xmlChar *systemId,
- const xmlChar *notationName)
-{
-const xmlChar *nullstr = BAD_CAST "(null)";
-
- if (publicId == NULL)
- publicId = nullstr;
- if (systemId == NULL)
- systemId = nullstr;
- if (notationName == NULL)
- notationName = nullstr;
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
- (char *) name, (char *) publicId, (char *) systemId,
- (char *) notationName);
-}
-
-/**
- * setDocumentLocatorDebug:
- * @ctxt: An XML parser context
- * @loc: A SAX Locator
- *
- * Receive the document locator at startup, actually xmlDefaultSAXLocator
- * Everything is available on the context, so this is useless in our case.
- */
-static void
-setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.setDocumentLocator()\n");
-}
-
-/**
- * startDocumentDebug:
- * @ctxt: An XML parser context
- *
- * called when the document start being processed.
- */
-static void
-startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.startDocument()\n");
-}
-
-/**
- * endDocumentDebug:
- * @ctxt: An XML parser context
- *
- * called when the document end has been detected.
- */
-static void
-endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.endDocument()\n");
-}
-
-/**
- * startElementDebug:
- * @ctxt: An XML parser context
- * @name: The element name
- *
- * called when an opening tag has been processed.
- */
-static void
-startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
-{
- int i;
-
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
- if (atts != NULL) {
- for (i = 0;(atts[i] != NULL);i++) {
- fprintf(SAXdebug, ", %s='", atts[i++]);
- if (atts[i] != NULL)
- fprintf(SAXdebug, "%s'", atts[i]);
- }
- }
- fprintf(SAXdebug, ")\n");
-}
-
-/**
- * endElementDebug:
- * @ctxt: An XML parser context
- * @name: The element name
- *
- * called when the end of an element has been detected.
- */
-static void
-endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name);
-}
-
-/**
- * charactersDebug:
- * @ctxt: An XML parser context
- * @ch: a xmlChar string
- * @len: the number of xmlChar
- *
- * receiving some chars from the parser.
- * Question: how much at a time ???
- */
-static void
-charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
-{
- char output[40];
- int i;
-
- callbacks++;
- if (quiet)
- return;
- for (i = 0;(i<len) && (i < 30);i++)
- output[i] = ch[i];
- output[i] = 0;
-
- fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
-}
-
-/**
- * referenceDebug:
- * @ctxt: An XML parser context
- * @name: The entity name
- *
- * called when an entity reference is detected.
- */
-static void
-referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.reference(%s)\n", name);
-}
-
-/**
- * ignorableWhitespaceDebug:
- * @ctxt: An XML parser context
- * @ch: a xmlChar string
- * @start: the first char in the string
- * @len: the number of xmlChar
- *
- * receiving some ignorable whitespaces from the parser.
- * Question: how much at a time ???
- */
-static void
-ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
-{
- char output[40];
- int i;
-
- callbacks++;
- if (quiet)
- return;
- for (i = 0;(i<len) && (i < 30);i++)
- output[i] = ch[i];
- output[i] = 0;
- fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
-}
-
-/**
- * processingInstructionDebug:
- * @ctxt: An XML parser context
- * @target: the target name
- * @data: the PI data's
- * @len: the number of xmlChar
- *
- * A processing instruction has been parsed.
- */
-static void
-processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
- const xmlChar *data)
-{
- callbacks++;
- if (quiet)
- return;
- if (data != NULL)
- fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
- (char *) target, (char *) data);
- else
- fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n",
- (char *) target);
-}
-
-/**
- * cdataBlockDebug:
- * @ctx: the user data (XML parser context)
- * @value: The pcdata content
- * @len: the block length
- *
- * called when a pcdata block has been parsed
- */
-static void
-cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n",
- (char *) value, len);
-}
-
-/**
- * commentDebug:
- * @ctxt: An XML parser context
- * @value: the comment content
- *
- * A comment has been parsed.
- */
-static void
-commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.comment(%s)\n", value);
-}
-
-/**
- * warningDebug:
- * @ctxt: An XML parser context
- * @msg: the message to display/transmit
- * @...: extra parameters for the message display
- *
- * Display and format a warning messages, gives file, line, position and
- * extra parameters.
- */
-static void
-warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
-{
- va_list args;
-
- callbacks++;
- if (quiet)
- return;
- va_start(args, msg);
- fprintf(SAXdebug, "SAX.warning: ");
- vfprintf(SAXdebug, msg, args);
- va_end(args);
-}
-
-/**
- * errorDebug:
- * @ctxt: An XML parser context
- * @msg: the message to display/transmit
- * @...: extra parameters for the message display
- *
- * Display and format a error messages, gives file, line, position and
- * extra parameters.
- */
-static void
-errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
-{
- va_list args;
-
- callbacks++;
- if (quiet)
- return;
- va_start(args, msg);
- fprintf(SAXdebug, "SAX.error: ");
- vfprintf(SAXdebug, msg, args);
- va_end(args);
-}
-
-/**
- * fatalErrorDebug:
- * @ctxt: An XML parser context
- * @msg: the message to display/transmit
- * @...: extra parameters for the message display
- *
- * Display and format a fatalError messages, gives file, line, position and
- * extra parameters.
- */
-static void
-fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
-{
- va_list args;
-
- callbacks++;
- if (quiet)
- return;
- va_start(args, msg);
- fprintf(SAXdebug, "SAX.fatalError: ");
- vfprintf(SAXdebug, msg, args);
- va_end(args);
-}
-
-xmlSAXHandler debugSAXHandlerStruct = {
- internalSubsetDebug,
- isStandaloneDebug,
- hasInternalSubsetDebug,
- hasExternalSubsetDebug,
- resolveEntityDebug,
- getEntityDebug,
- entityDeclDebug,
- notationDeclDebug,
- attributeDeclDebug,
- elementDeclDebug,
- unparsedEntityDeclDebug,
- setDocumentLocatorDebug,
- startDocumentDebug,
- endDocumentDebug,
- startElementDebug,
- endElementDebug,
- referenceDebug,
- charactersDebug,
- ignorableWhitespaceDebug,
- processingInstructionDebug,
- commentDebug,
- warningDebug,
- errorDebug,
- fatalErrorDebug,
- getParameterEntityDebug,
- cdataBlockDebug,
- externalSubsetDebug,
- 1,
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
-
-/*
- * SAX2 specific callbacks
- */
-/**
- * startElementNsDebug:
- * @ctxt: An XML parser context
- * @name: The element name
- *
- * called when an opening tag has been processed.
- */
-static void
-startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
- const xmlChar *localname,
- const xmlChar *prefix,
- const xmlChar *URI,
- int nb_namespaces,
- const xmlChar **namespaces,
- int nb_attributes,
- int nb_defaulted,
- const xmlChar **attributes)
-{
- int i;
-
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
- if (prefix == NULL)
- fprintf(SAXdebug, ", NULL");
- else
- fprintf(SAXdebug, ", %s", (char *) prefix);
- if (URI == NULL)
- fprintf(SAXdebug, ", NULL");
- else
- fprintf(SAXdebug, ", '%s'", (char *) URI);
- fprintf(SAXdebug, ", %d", nb_namespaces);
-
- if (namespaces != NULL) {
- for (i = 0;i < nb_namespaces * 2;i++) {
- fprintf(SAXdebug, ", xmlns");
- if (namespaces[i] != NULL)
- fprintf(SAXdebug, ":%s", namespaces[i]);
- i++;
- fprintf(SAXdebug, "='%s'", namespaces[i]);
- }
- }
- fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
- if (attributes != NULL) {
- for (i = 0;i < nb_attributes * 5;i += 5) {
- if (attributes[i + 1] != NULL)
- fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
- else
- fprintf(SAXdebug, ", %s='", attributes[i]);
- fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
- (int)(attributes[i + 4] - attributes[i + 3]));
- }
- }
- fprintf(SAXdebug, ")\n");
-}
-
-/**
- * endElementDebug:
- * @ctxt: An XML parser context
- * @name: The element name
- *
- * called when the end of an element has been detected.
- */
-static void
-endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
- const xmlChar *localname,
- const xmlChar *prefix,
- const xmlChar *URI)
-{
- callbacks++;
- if (quiet)
- return;
- fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
- if (prefix == NULL)
- fprintf(SAXdebug, ", NULL");
- else
- fprintf(SAXdebug, ", %s", (char *) prefix);
- if (URI == NULL)
- fprintf(SAXdebug, ", NULL)\n");
- else
- fprintf(SAXdebug, ", '%s')\n", (char *) URI);
-}
-
-xmlSAXHandler debugSAX2HandlerStruct = {
- internalSubsetDebug,
- isStandaloneDebug,
- hasInternalSubsetDebug,
- hasExternalSubsetDebug,
- resolveEntityDebug,
- getEntityDebug,
- entityDeclDebug,
- notationDeclDebug,
- attributeDeclDebug,
- elementDeclDebug,
- unparsedEntityDeclDebug,
- setDocumentLocatorDebug,
- startDocumentDebug,
- endDocumentDebug,
- NULL,
- NULL,
- referenceDebug,
- charactersDebug,
- ignorableWhitespaceDebug,
- processingInstructionDebug,
- commentDebug,
- warningDebug,
- errorDebug,
- fatalErrorDebug,
- getParameterEntityDebug,
- cdataBlockDebug,
- externalSubsetDebug,
- XML_SAX2_MAGIC,
- NULL,
- startElementNsDebug,
- endElementNsDebug,
- NULL
-};
-
-xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
-
-#ifdef LIBXML_HTML_ENABLED
-/**
- * htmlstartElementDebug:
- * @ctxt: An XML parser context
- * @name: The element name
- *
- * called when an opening tag has been processed.
- */
-static void
-htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
-{
- int i;
-
- fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
- if (atts != NULL) {
- for (i = 0;(atts[i] != NULL);i++) {
- fprintf(SAXdebug, ", %s", atts[i++]);
- if (atts[i] != NULL) {
- unsigned char output[40];
- const unsigned char *att = atts[i];
- int outlen, attlen;
- fprintf(SAXdebug, "='");
- while ((attlen = strlen((char*)att)) > 0) {
- outlen = sizeof output - 1;
- htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
- output[outlen] = 0;
- fprintf(SAXdebug, "%s", (char *) output);
- att += attlen;
- }
- fprintf(SAXdebug, "'");
- }
- }
- }
- fprintf(SAXdebug, ")\n");
-}
-
-/**
- * htmlcharactersDebug:
- * @ctxt: An XML parser context
- * @ch: a xmlChar string
- * @len: the number of xmlChar
- *
- * receiving some chars from the parser.
- * Question: how much at a time ???
- */
-static void
-htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
-{
- unsigned char output[40];
- int inlen = len, outlen = 30;
-
- htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
- output[outlen] = 0;
-
- fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
-}
-
-/**
- * htmlcdataDebug:
- * @ctxt: An XML parser context
- * @ch: a xmlChar string
- * @len: the number of xmlChar
- *
- * receiving some cdata chars from the parser.
- * Question: how much at a time ???
- */
-static void
-htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
-{
- unsigned char output[40];
- int inlen = len, outlen = 30;
-
- htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
- output[outlen] = 0;
-
- fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
-}
-
-xmlSAXHandler debugHTMLSAXHandlerStruct = {
- internalSubsetDebug,
- isStandaloneDebug,
- hasInternalSubsetDebug,
- hasExternalSubsetDebug,
- resolveEntityDebug,
- getEntityDebug,
- entityDeclDebug,
- notationDeclDebug,
- attributeDeclDebug,
- elementDeclDebug,
- unparsedEntityDeclDebug,
- setDocumentLocatorDebug,
- startDocumentDebug,
- endDocumentDebug,
- htmlstartElementDebug,
- endElementDebug,
- referenceDebug,
- htmlcharactersDebug,
- ignorableWhitespaceDebug,
- processingInstructionDebug,
- commentDebug,
- warningDebug,
- errorDebug,
- fatalErrorDebug,
- getParameterEntityDebug,
- htmlcdataDebug,
- externalSubsetDebug,
- 1,
- NULL,
- NULL,
- NULL,
- NULL
-};
-
-xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
-#endif /* LIBXML_HTML_ENABLED */
-
-#ifdef LIBXML_SAX1_ENABLED
-/**
- * saxParseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file using the SAX API and check for errors.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-saxParseTest(const char *filename, const char *result,
- const char *err ATTRIBUTE_UNUSED,
- int options) {
- int ret;
- char *temp;
-
- nb_tests++;
- temp = resultFilename(filename, "", ".res");
- if (temp == NULL) {
- fprintf(stderr, "out of memory\n");
- fatalError();
- }
- SAXdebug = fopen(temp, "wb");
- if (SAXdebug == NULL) {
- fprintf(stderr, "Failed to write to %s\n", temp);
- free(temp);
- return(-1);
- }
-
- /* for SAX we really want the callbacks though the context handlers */
- xmlSetStructuredErrorFunc(NULL, NULL);
- xmlSetGenericErrorFunc(NULL, testErrorHandler);
-
-#ifdef LIBXML_HTML_ENABLED
- if (options & XML_PARSE_HTML) {
- htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);
- ret = 0;
- } else
-#endif
- ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
- if (ret == XML_WAR_UNDECLARED_ENTITY) {
- fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
- ret = 0;
- }
- if (ret != 0) {
- fprintf(stderr, "Failed to parse %s\n", filename);
- return(1);
- }
-#ifdef LIBXML_HTML_ENABLED
- if (options & XML_PARSE_HTML) {
- htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
- ret = 0;
- } else
-#endif
- if (options & XML_PARSE_SAX1) {
- ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
- } else {
- ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
- }
- if (ret == XML_WAR_UNDECLARED_ENTITY) {
- fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
- ret = 0;
- }
- fclose(SAXdebug);
- if (compareFiles(temp, result)) {
- fprintf(stderr, "Got a difference for %s\n", filename);
- ret = 1;
- } else
- unlink(temp);
- free(temp);
-
- /* switch back to structured error handling */
- xmlSetGenericErrorFunc(NULL, NULL);
- xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
-
- return(ret);
-}
-#endif
-
-/************************************************************************
- * *
- * Parse to tree based tests *
- * *
- ************************************************************************/
-/**
- * oldParseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages: unused
- *
- * Parse a file using the old xmlParseFile API, then serialize back
- * reparse the result and serialize again, then check for deviation
- * in serialization.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-oldParseTest(const char *filename, const char *result,
- const char *err ATTRIBUTE_UNUSED,
- int options ATTRIBUTE_UNUSED) {
- xmlDocPtr doc;
- char *temp;
- int res = 0;
-
- nb_tests++;
- /*
- * base of the test, parse with the old API
- */
-#ifdef LIBXML_SAX1_ENABLED
- doc = xmlParseFile(filename);
-#else
- doc = xmlReadFile(filename, NULL, 0);
-#endif
- if (doc == NULL)
- return(1);
- temp = resultFilename(filename, "", ".res");
- if (temp == NULL) {
- fprintf(stderr, "out of memory\n");
- fatalError();
- }
- xmlSaveFile(temp, doc);
- if (compareFiles(temp, result)) {
- res = 1;
- }
- xmlFreeDoc(doc);
-
- /*
- * Parse the saved result to make sure the round trip is okay
- */
-#ifdef LIBXML_SAX1_ENABLED
- doc = xmlParseFile(temp);
-#else
- doc = xmlReadFile(temp, NULL, 0);
-#endif
- if (doc == NULL)
- return(1);
- xmlSaveFile(temp, doc);
- if (compareFiles(temp, result)) {
- res = 1;
- }
- xmlFreeDoc(doc);
-
- unlink(temp);
- free(temp);
- return(res);
-}
-
-#ifdef LIBXML_PUSH_ENABLED
-/**
- * pushParseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages: unused
- *
- * Parse a file using the Push API, then serialize back
- * to check for content.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-pushParseTest(const char *filename, const char *result,
- const char *err ATTRIBUTE_UNUSED,
- int options) {
- xmlParserCtxtPtr ctxt;
- xmlDocPtr doc;
- const char *base;
- int size, res;
- int cur = 0;
-
- nb_tests++;
- /*
- * load the document in memory and work from there.
- */
- if (loadMem(filename, &base, &size) != 0) {
- fprintf(stderr, "Failed to load %s\n", filename);
- return(-1);
- }
-
-#ifdef LIBXML_HTML_ENABLED
- if (options & XML_PARSE_HTML)
- ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,
- XML_CHAR_ENCODING_NONE);
- else
-#endif
- ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
- xmlCtxtUseOptions(ctxt, options);
- cur += 4;
- while (cur < size) {
- if (cur + 1024 >= size) {
-#ifdef LIBXML_HTML_ENABLED
- if (options & XML_PARSE_HTML)
- htmlParseChunk(ctxt, base + cur, size - cur, 1);
- else
-#endif
- xmlParseChunk(ctxt, base + cur, size - cur, 1);
- break;
- } else {
-#ifdef LIBXML_HTML_ENABLED
- if (options & XML_PARSE_HTML)
- htmlParseChunk(ctxt, base + cur, 1024, 0);
- else
-#endif
- xmlParseChunk(ctxt, base + cur, 1024, 0);
- cur += 1024;
- }
- }
- doc = ctxt->myDoc;
-#ifdef LIBXML_HTML_ENABLED
- if (options & XML_PARSE_HTML)
- res = 1;
- else
-#endif
- res = ctxt->wellFormed;
- xmlFreeParserCtxt(ctxt);
- free((char *)base);
- if (!res) {
- xmlFreeDoc(doc);
- fprintf(stderr, "Failed to parse %s\n", filename);
- return(-1);
- }
-#ifdef LIBXML_HTML_ENABLED
- if (options & XML_PARSE_HTML)
- htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
- else
-#endif
- xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
- xmlFreeDoc(doc);
- res = compareFileMem(result, base, size);
- if ((base == NULL) || (res != 0)) {
- if (base != NULL)
- xmlFree((char *)base);
- fprintf(stderr, "Result for %s failed\n", filename);
- return(-1);
- }
- xmlFree((char *)base);
- if (err != NULL) {
- res = compareFileMem(err, testErrors, testErrorsSize);
- if (res != 0) {
- fprintf(stderr, "Error for %s failed\n", filename);
- return(-1);
- }
- }
- return(0);
-}
-#endif
-
-/**
- * memParseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages: unused
- *
- * Parse a file using the old xmlReadMemory API, then serialize back
- * reparse the result and serialize again, then check for deviation
- * in serialization.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-memParseTest(const char *filename, const char *result,
- const char *err ATTRIBUTE_UNUSED,
- int options ATTRIBUTE_UNUSED) {
- xmlDocPtr doc;
- const char *base;
- int size, res;
-
- nb_tests++;
- /*
- * load and parse the memory
- */
- if (loadMem(filename, &base, &size) != 0) {
- fprintf(stderr, "Failed to load %s\n", filename);
- return(-1);
- }
-
- doc = xmlReadMemory(base, size, filename, NULL, 0);
- unloadMem(base);
- if (doc == NULL) {
- return(1);
- }
- xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
- xmlFreeDoc(doc);
- res = compareFileMem(result, base, size);
- if ((base == NULL) || (res != 0)) {
- if (base != NULL)
- xmlFree((char *)base);
- fprintf(stderr, "Result for %s failed\n", filename);
- return(-1);
- }
- xmlFree((char *)base);
- return(0);
-}
-
-/**
- * noentParseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages: unused
- *
- * Parse a file with entity resolution, then serialize back
- * reparse the result and serialize again, then check for deviation
- * in serialization.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-noentParseTest(const char *filename, const char *result,
- const char *err ATTRIBUTE_UNUSED,
- int options) {
- xmlDocPtr doc;
- char *temp;
- int res = 0;
-
- nb_tests++;
- /*
- * base of the test, parse with the old API
- */
- doc = xmlReadFile(filename, NULL, options);
- if (doc == NULL)
- return(1);
- temp = resultFilename(filename, "", ".res");
- if (temp == NULL) {
- fprintf(stderr, "Out of memory\n");
- fatalError();
- }
- xmlSaveFile(temp, doc);
- if (compareFiles(temp, result)) {
- res = 1;
- }
- xmlFreeDoc(doc);
-
- /*
- * Parse the saved result to make sure the round trip is okay
- */
- doc = xmlReadFile(filename, NULL, options);
- if (doc == NULL)
- return(1);
- xmlSaveFile(temp, doc);
- if (compareFiles(temp, result)) {
- res = 1;
- }
- xmlFreeDoc(doc);
-
- unlink(temp);
- free(temp);
- return(res);
-}
-
-/**
- * errParseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file using the xmlReadFile API and check for errors.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-errParseTest(const char *filename, const char *result, const char *err,
- int options) {
- xmlDocPtr doc;
- const char *base = NULL;
- int size, res = 0;
-
- nb_tests++;
-#ifdef LIBXML_HTML_ENABLED
- if (options & XML_PARSE_HTML) {
- doc = htmlReadFile(filename, NULL, options);
- } else
-#endif
-#ifdef LIBXML_XINCLUDE_ENABLED
- if (options & XML_PARSE_XINCLUDE) {
- doc = xmlReadFile(filename, NULL, options);
- xmlXIncludeProcessFlags(doc, options);
- } else
-#endif
- {
- xmlGetWarningsDefaultValue = 1;
- doc = xmlReadFile(filename, NULL, options);
- }
- xmlGetWarningsDefaultValue = 0;
- if (result) {
- if (doc == NULL) {
- base = "";
- size = 0;
- } else {
-#ifdef LIBXML_HTML_ENABLED
- if (options & XML_PARSE_HTML) {
- htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
- } else
-#endif
- xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
- }
- res = compareFileMem(result, base, size);
- }
- if (doc != NULL) {
- if (base != NULL)
- xmlFree((char *)base);
- xmlFreeDoc(doc);
- }
- if (res != 0) {
- fprintf(stderr, "Result for %s failed\n", filename);
- return(-1);
- }
- if (err != NULL) {
- res = compareFileMem(err, testErrors, testErrorsSize);
- if (res != 0) {
- fprintf(stderr, "Error for %s failed\n", filename);
- return(-1);
- }
- } else if (options & XML_PARSE_DTDVALID) {
- if (testErrorsSize != 0)
- fprintf(stderr, "Validation for %s failed\n", filename);
- }
-
- return(0);
-}
-
-#ifdef LIBXML_READER_ENABLED
-/************************************************************************
- * *
- * Reader based tests *
- * *
- ************************************************************************/
-
-static void processNode(FILE *out, xmlTextReaderPtr reader) {
- const xmlChar *name, *value;
- int type, empty;
-
- type = xmlTextReaderNodeType(reader);
- empty = xmlTextReaderIsEmptyElement(reader);
-
- name = xmlTextReaderConstName(reader);
- if (name == NULL)
- name = BAD_CAST "--";
-
- value = xmlTextReaderConstValue(reader);
-
-
- fprintf(out, "%d %d %s %d %d",
- xmlTextReaderDepth(reader),
- type,
- name,
- empty,
- xmlTextReaderHasValue(reader));
- if (value == NULL)
- fprintf(out, "\n");
- else {
- fprintf(out, " %s\n", value);
- }
-}
-static int
-streamProcessTest(const char *filename, const char *result, const char *err,
- xmlTextReaderPtr reader, const char *rng) {
- int ret;
- char *temp = NULL;
- FILE *t = NULL;
-
- if (reader == NULL)
- return(-1);
-
- nb_tests++;
- if (result != NULL) {
- temp = resultFilename(filename, "", ".res");
- if (temp == NULL) {
- fprintf(stderr, "Out of memory\n");
- fatalError();
- }
- t = fopen(temp, "wb");
- if (t == NULL) {
- fprintf(stderr, "Can't open temp file %s\n", temp);
- free(temp);
- return(-1);
- }
- }
-#ifdef LIBXML_SCHEMAS_ENABLED
- if (rng != NULL) {
- ret = xmlTextReaderRelaxNGValidate(reader, rng);
- if (ret < 0) {
- testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
- rng);
- fclose(t);
- unlink(temp);
- free(temp);
- return(0);
- }
- }
-#endif
- xmlGetWarningsDefaultValue = 1;
- ret = xmlTextReaderRead(reader);
- while (ret == 1) {
- if ((t != NULL) && (rng == NULL))
- processNode(t, reader);
- ret = xmlTextReaderRead(reader);
- }
- if (ret != 0) {
- testErrorHandler(NULL, "%s : failed to parse\n", filename);
- }
- if (rng != NULL) {
- if (xmlTextReaderIsValid(reader) != 1) {
- testErrorHandler(NULL, "%s fails to validate\n", filename);
- } else {
- testErrorHandler(NULL, "%s validates\n", filename);
- }
- }
- xmlGetWarningsDefaultValue = 0;
- if (t != NULL) {
- fclose(t);
- ret = compareFiles(temp, result);
- unlink(temp);
- free(temp);
- if (ret) {
- fprintf(stderr, "Result for %s failed\n", filename);
- return(-1);
- }
- }
- if (err != NULL) {
- ret = compareFileMem(err, testErrors, testErrorsSize);
- if (ret != 0) {
- fprintf(stderr, "Error for %s failed\n", filename);
- printf("%s", testErrors);
- return(-1);
- }
- }
-
- return(0);
-}
-
-/**
- * streamParseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file using the reader API and check for errors.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-streamParseTest(const char *filename, const char *result, const char *err,
- int options) {
- xmlTextReaderPtr reader;
- int ret;
-
- reader = xmlReaderForFile(filename, NULL, options);
- ret = streamProcessTest(filename, result, err, reader, NULL);
- xmlFreeTextReader(reader);
- return(ret);
-}
-
-/**
- * walkerParseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file using the walker, i.e. a reader built from a atree.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-walkerParseTest(const char *filename, const char *result, const char *err,
- int options) {
- xmlDocPtr doc;
- xmlTextReaderPtr reader;
- int ret;
-
- doc = xmlReadFile(filename, NULL, options);
- if (doc == NULL) {
- fprintf(stderr, "Failed to parse %s\n", filename);
- return(-1);
- }
- reader = xmlReaderWalker(doc);
- ret = streamProcessTest(filename, result, err, reader, NULL);
- xmlFreeTextReader(reader);
- xmlFreeDoc(doc);
- return(ret);
-}
-
-/**
- * streamMemParseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file using the reader API from memory and check for errors.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-streamMemParseTest(const char *filename, const char *result, const char *err,
- int options) {
- xmlTextReaderPtr reader;
- int ret;
- const char *base;
- int size;
-
- /*
- * load and parse the memory
- */
- if (loadMem(filename, &base, &size) != 0) {
- fprintf(stderr, "Failed to load %s\n", filename);
- return(-1);
- }
- reader = xmlReaderForMemory(base, size, filename, NULL, options);
- ret = streamProcessTest(filename, result, err, reader, NULL);
- free((char *)base);
- xmlFreeTextReader(reader);
- return(ret);
-}
-#endif
-
-#ifdef LIBXML_XPATH_ENABLED
-#ifdef LIBXML_DEBUG_ENABLED
-/************************************************************************
- * *
- * XPath and XPointer based tests *
- * *
- ************************************************************************/
-
-FILE *xpathOutput;
-xmlDocPtr xpathDocument;
-
-static void
-testXPath(const char *str, int xptr, int expr) {
- xmlXPathObjectPtr res;
- xmlXPathContextPtr ctxt;
-
- nb_tests++;
-#if defined(LIBXML_XPTR_ENABLED)
- if (xptr) {
- ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
- res = xmlXPtrEval(BAD_CAST str, ctxt);
- } else {
-#endif
- ctxt = xmlXPathNewContext(xpathDocument);
- ctxt->node = xmlDocGetRootElement(xpathDocument);
- if (expr)
- res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
- else {
- /* res = xmlXPathEval(BAD_CAST str, ctxt); */
- xmlXPathCompExprPtr comp;
-
- comp = xmlXPathCompile(BAD_CAST str);
- if (comp != NULL) {
- res = xmlXPathCompiledEval(comp, ctxt);
- xmlXPathFreeCompExpr(comp);
- } else
- res = NULL;
- }
-#if defined(LIBXML_XPTR_ENABLED)
- }
-#endif
- xmlXPathDebugDumpObject(xpathOutput, res, 0);
- xmlXPathFreeObject(res);
- xmlXPathFreeContext(ctxt);
-}
-
-/**
- * xpathExprTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file containing XPath standalone expressions and evaluate them
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-xpathCommonTest(const char *filename, const char *result,
- int xptr, int expr) {
- FILE *input;
- char expression[5000];
- int len, ret = 0;
- char *temp;
-
- temp = resultFilename(filename, "", ".res");
- if (temp == NULL) {
- fprintf(stderr, "Out of memory\n");
- fatalError();
- }
- xpathOutput = fopen(temp, "wb");
- if (xpathOutput == NULL) {
- fprintf(stderr, "failed to open output file %s\n", temp);
- free(temp);
- return(-1);
- }
-
- input = fopen(filename, "rb");
- if (input == NULL) {
- xmlGenericError(xmlGenericErrorContext,
- "Cannot open %s for reading\n", filename);
- free(temp);
- return(-1);
- }
- while (fgets(expression, 4500, input) != NULL) {
- len = strlen(expression);
- len--;
- while ((len >= 0) &&
- ((expression[len] == '\n') || (expression[len] == '\t') ||
- (expression[len] == '\r') || (expression[len] == ' '))) len--;
- expression[len + 1] = 0;
- if (len >= 0) {
- fprintf(xpathOutput,
- "\n========================\nExpression: %s\n",
- expression) ;
- testXPath(expression, xptr, expr);
- }
- }
-
- fclose(input);
- fclose(xpathOutput);
- if (result != NULL) {
- ret = compareFiles(temp, result);
- if (ret) {
- fprintf(stderr, "Result for %s failed\n", filename);
- }
- }
-
- unlink(temp);
- free(temp);
- return(ret);
-}
-
-/**
- * xpathExprTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file containing XPath standalone expressions and evaluate them
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-xpathExprTest(const char *filename, const char *result,
- const char *err ATTRIBUTE_UNUSED,
- int options ATTRIBUTE_UNUSED) {
- return(xpathCommonTest(filename, result, 0, 1));
-}
-
-/**
- * xpathDocTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file containing XPath expressions and evaluate them against
- * a set of corresponding documents.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-xpathDocTest(const char *filename,
- const char *resul ATTRIBUTE_UNUSED,
- const char *err ATTRIBUTE_UNUSED,
- int options) {
-
- char pattern[500];
- char result[500];
- glob_t globbuf;
- size_t i;
- int ret = 0, res;
-
- xpathDocument = xmlReadFile(filename, NULL,
- options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
- if (xpathDocument == NULL) {
- fprintf(stderr, "Failed to load %s\n", filename);
- return(-1);
- }
-
- snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
- pattern[499] = 0;
- globbuf.gl_offs = 0;
- glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
- for (i = 0;i < globbuf.gl_pathc;i++) {
- snprintf(result, 499, "result/XPath/tests/%s",
- baseFilename(globbuf.gl_pathv[i]));
- res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
- if (res != 0)
- ret = res;
- }
- globfree(&globbuf);
-
- xmlFreeDoc(xpathDocument);
- return(ret);
-}
-
-#ifdef LIBXML_XPTR_ENABLED
-/**
- * xptrDocTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file containing XPath expressions and evaluate them against
- * a set of corresponding documents.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-xptrDocTest(const char *filename,
- const char *resul ATTRIBUTE_UNUSED,
- const char *err ATTRIBUTE_UNUSED,
- int options) {
-
- char pattern[500];
- char result[500];
- glob_t globbuf;
- size_t i;
- int ret = 0, res;
-
- xpathDocument = xmlReadFile(filename, NULL,
- options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
- if (xpathDocument == NULL) {
- fprintf(stderr, "Failed to load %s\n", filename);
- return(-1);
- }
-
- snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
- pattern[499] = 0;
- globbuf.gl_offs = 0;
- glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
- for (i = 0;i < globbuf.gl_pathc;i++) {
- snprintf(result, 499, "result/XPath/xptr/%s",
- baseFilename(globbuf.gl_pathv[i]));
- res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
- if (res != 0)
- ret = res;
- }
- globfree(&globbuf);
-
- xmlFreeDoc(xpathDocument);
- return(ret);
-}
-#endif /* LIBXML_XPTR_ENABLED */
-
-/**
- * xmlidDocTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file containing xml:id and check for errors and verify
- * that XPath queries will work on them as expected.
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-xmlidDocTest(const char *filename,
- const char *result,
- const char *err,
- int options) {
-
- int res = 0;
- int ret = 0;
- char *temp;
-
- xpathDocument = xmlReadFile(filename, NULL,
- options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
- if (xpathDocument == NULL) {
- fprintf(stderr, "Failed to load %s\n", filename);
- return(-1);
- }
-
- temp = resultFilename(filename, "", ".res");
- if (temp == NULL) {
- fprintf(stderr, "Out of memory\n");
- fatalError();
- }
- xpathOutput = fopen(temp, "wb");
- if (xpathOutput == NULL) {
- fprintf(stderr, "failed to open output file %s\n", temp);
- xmlFreeDoc(xpathDocument);
- free(temp);
- return(-1);
- }
-
- testXPath("id('bar')", 0, 0);
-
- fclose(xpathOutput);
- if (result != NULL) {
- ret = compareFiles(temp, result);
- if (ret) {
- fprintf(stderr, "Result for %s failed\n", filename);
- res = 1;
- }
- }
-
- unlink(temp);
- free(temp);
- xmlFreeDoc(xpathDocument);
-
- if (err != NULL) {
- ret = compareFileMem(err, testErrors, testErrorsSize);
- if (ret != 0) {
- fprintf(stderr, "Error for %s failed\n", filename);
- res = 1;
- }
- }
- return(res);
-}
-
-#endif /* LIBXML_DEBUG_ENABLED */
-#endif /* XPATH */
-/************************************************************************
- * *
- * URI based tests *
- * *
- ************************************************************************/
-
-static void
-handleURI(const char *str, const char *base, FILE *o) {
- int ret;
- xmlURIPtr uri;
- xmlChar *res = NULL, *parsed = NULL;
-
- uri = xmlCreateURI();
-
- if (base == NULL) {
- ret = xmlParseURIReference(uri, str);
- if (ret != 0)
- fprintf(o, "%s : error %d\n", str, ret);
- else {
- xmlNormalizeURIPath(uri->path);
- xmlPrintURI(o, uri);
- fprintf(o, "\n");
- }
- } else {
- res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
- if (res != NULL) {
- fprintf(o, "%s\n", (char *) res);
- }
- else
- fprintf(o, "::ERROR::\n");
- }
- if (res != NULL)
- xmlFree(res);
- if (parsed != NULL)
- xmlFree(parsed);
- xmlFreeURI(uri);
-}
-
-/**
- * uriCommonTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file containing URI and check for errors
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-uriCommonTest(const char *filename,
- const char *result,
- const char *err,
- const char *base) {
- char *temp;
- FILE *o, *f;
- char str[1024];
- int res = 0, i, ret;
-
- temp = resultFilename(filename, "", ".res");
- if (temp == NULL) {
- fprintf(stderr, "Out of memory\n");
- fatalError();
- }
- o = fopen(temp, "wb");
- if (o == NULL) {
- fprintf(stderr, "failed to open output file %s\n", temp);
- free(temp);
- return(-1);
- }
- f = fopen(filename, "rb");
- if (f == NULL) {
- fprintf(stderr, "failed to open input file %s\n", filename);
- fclose(o);
- unlink(temp);
- free(temp);
- return(-1);
- }
-
- while (1) {
- /*
- * read one line in string buffer.
- */
- if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
- break;
-
- /*
- * remove the ending spaces
- */
- i = strlen(str);
- while ((i > 0) &&
- ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
- (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
- i--;
- str[i] = 0;
- }
- nb_tests++;
- handleURI(str, base, o);
- }
-
- fclose(f);
- fclose(o);
-
- if (result != NULL) {
- ret = compareFiles(temp, result);
- if (ret) {
- fprintf(stderr, "Result for %s failed\n", filename);
- res = 1;
- }
- }
- if (err != NULL) {
- ret = compareFileMem(err, testErrors, testErrorsSize);
- if (ret != 0) {
- fprintf(stderr, "Error for %s failed\n", filename);
- res = 1;
- }
- }
-
- unlink(temp);
- free(temp);
- return(res);
-}
-
-/**
- * uriParseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file containing URI and check for errors
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-uriParseTest(const char *filename,
- const char *result,
- const char *err,
- int options ATTRIBUTE_UNUSED) {
- return(uriCommonTest(filename, result, err, NULL));
-}
-
-/**
- * uriBaseTest:
- * @filename: the file to parse
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file containing URI, compose them against a fixed base and
- * check for errors
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-uriBaseTest(const char *filename,
- const char *result,
- const char *err,
- int options ATTRIBUTE_UNUSED) {
- return(uriCommonTest(filename, result, err,
- "http://foo.com/path/to/index.html?orig#help"));
-}
-
-#ifdef LIBXML_SCHEMAS_ENABLED
-/************************************************************************
- * *
- * Schemas tests *
- * *
- ************************************************************************/
-static int
-schemasOneTest(const char *sch,
- const char *filename,
- const char *result,
- const char *err,
- int options,
- xmlSchemaPtr schemas) {
- xmlDocPtr doc;
- xmlSchemaValidCtxtPtr ctxt;
- int ret = 0;
- char *temp;
- FILE *schemasOutput;
-
- doc = xmlReadFile(filename, NULL, options);
- if (doc == NULL) {
- fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
- return(-1);
- }
-
- temp = resultFilename(result, "", ".res");
- if (temp == NULL) {
- fprintf(stderr, "Out of memory\n");
- fatalError();
- }
- schemasOutput = fopen(temp, "wb");
- if (schemasOutput == NULL) {
- fprintf(stderr, "failed to open output file %s\n", temp);
- xmlFreeDoc(doc);
- free(temp);
- return(-1);
- }
-
- ctxt = xmlSchemaNewValidCtxt(schemas);
- xmlSchemaSetValidErrors(ctxt,
- (xmlSchemaValidityErrorFunc) testErrorHandler,
- (xmlSchemaValidityWarningFunc) testErrorHandler,
- ctxt);
- ret = xmlSchemaValidateDoc(ctxt, doc);
- if (ret == 0) {
- fprintf(schemasOutput, "%s validates\n", filename);
- } else if (ret > 0) {
- fprintf(schemasOutput, "%s fails to validate\n", filename);
- } else {
- fprintf(schemasOutput, "%s validation generated an internal error\n",
- filename);
- }
- fclose(schemasOutput);
- if (result) {
- if (compareFiles(temp, result)) {
- fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
- ret = 1;
- }
- }
- unlink(temp);
- free(temp);
-
- if (err != NULL) {
- if (compareFileMem(err, testErrors, testErrorsSize)) {
- fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
- ret = 1;
- }
- }
-
-
- xmlSchemaFreeValidCtxt(ctxt);
- xmlFreeDoc(doc);
- return(ret);
-}
-/**
- * schemasTest:
- * @filename: the schemas file
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a file containing URI, compose them against a fixed base and
- * check for errors
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-schemasTest(const char *filename,
- const char *resul ATTRIBUTE_UNUSED,
- const char *errr ATTRIBUTE_UNUSED,
- int options) {
- const char *base = baseFilename(filename);
- const char *base2;
- const char *instance;
- xmlSchemaParserCtxtPtr ctxt;
- xmlSchemaPtr schemas;
- int res = 0, len, ret;
- char pattern[500];
- char prefix[500];
- char result[500];
- char err[500];
- glob_t globbuf;
- size_t i;
- char count = 0;
-
- /* first compile the schemas if possible */
- ctxt = xmlSchemaNewParserCtxt(filename);
- xmlSchemaSetParserErrors(ctxt,
- (xmlSchemaValidityErrorFunc) testErrorHandler,
- (xmlSchemaValidityWarningFunc) testErrorHandler,
- ctxt);
- schemas = xmlSchemaParse(ctxt);
- xmlSchemaFreeParserCtxt(ctxt);
-
- /*
- * most of the mess is about the output filenames generated by the Makefile
- */
- len = strlen(base);
- if ((len > 499) || (len < 5)) {
- xmlSchemaFree(schemas);
- return(-1);
- }
- len -= 4; /* remove trailing .xsd */
- if (base[len - 2] == '_') {
- len -= 2; /* remove subtest number */
- }
- if (base[len - 2] == '_') {
- len -= 2; /* remove subtest number */
- }
- memcpy(prefix, base, len);
- prefix[len] = 0;
-
- snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
- pattern[499] = 0;
-
- if (base[len] == '_') {
- len += 2;
- memcpy(prefix, base, len);
- prefix[len] = 0;
- }
-
- globbuf.gl_offs = 0;
- glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
- for (i = 0;i < globbuf.gl_pathc;i++) {
- testErrorsSize = 0;
- testErrors[0] = 0;
- instance = globbuf.gl_pathv[i];
- base2 = baseFilename(instance);
- len = strlen(base2);
- if ((len > 6) && (base2[len - 6] == '_')) {
- count = base2[len - 5];
- snprintf(result, 499, "result/schemas/%s_%c",
- prefix, count);
- result[499] = 0;
- snprintf(err, 499, "result/schemas/%s_%c.err",
- prefix, count);
- err[499] = 0;
- } else {
- fprintf(stderr, "don't know how to process %s\n", instance);
- continue;
- }
- if (schemas == NULL) {
- } else {
- nb_tests++;
- ret = schemasOneTest(filename, instance, result, err,
- options, schemas);
- if (res != 0)
- ret = res;
- }
- }
- globfree(&globbuf);
- xmlSchemaFree(schemas);
-
- return(res);
-}
-
-/************************************************************************
- * *
- * Schemas tests *
- * *
- ************************************************************************/
-static int
-rngOneTest(const char *sch,
- const char *filename,
- const char *result,
- const char *err,
- int options,
- xmlRelaxNGPtr schemas) {
- xmlDocPtr doc;
- xmlRelaxNGValidCtxtPtr ctxt;
- int ret = 0;
- char *temp;
- FILE *schemasOutput;
-
- doc = xmlReadFile(filename, NULL, options);
- if (doc == NULL) {
- fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
- return(-1);
- }
-
- temp = resultFilename(result, "", ".res");
- if (temp == NULL) {
- fprintf(stderr, "Out of memory\n");
- fatalError();
- }
- schemasOutput = fopen(temp, "wb");
- if (schemasOutput == NULL) {
- fprintf(stderr, "failed to open output file %s\n", temp);
- xmlFreeDoc(doc);
- free(temp);
- return(-1);
- }
-
- ctxt = xmlRelaxNGNewValidCtxt(schemas);
- xmlRelaxNGSetValidErrors(ctxt,
- (xmlRelaxNGValidityErrorFunc) testErrorHandler,
- (xmlRelaxNGValidityWarningFunc) testErrorHandler,
- ctxt);
- ret = xmlRelaxNGValidateDoc(ctxt, doc);
- if (ret == 0) {
- testErrorHandler(NULL, "%s validates\n", filename);
- } else if (ret > 0) {
- testErrorHandler(NULL, "%s fails to validate\n", filename);
- } else {
- testErrorHandler(NULL, "%s validation generated an internal error\n",
- filename);
- }
- fclose(schemasOutput);
- if (result) {
- if (compareFiles(temp, result)) {
- fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
- ret = 1;
- }
- }
- unlink(temp);
- free(temp);
-
- if (err != NULL) {
- if (compareFileMem(err, testErrors, testErrorsSize)) {
- fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
- ret = 1;
- printf("%s", testErrors);
- }
- }
-
-
- xmlRelaxNGFreeValidCtxt(ctxt);
- xmlFreeDoc(doc);
- return(ret);
-}
-/**
- * rngTest:
- * @filename: the schemas file
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse an RNG schemas and then apply it to the related .xml
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-rngTest(const char *filename,
- const char *resul ATTRIBUTE_UNUSED,
- const char *errr ATTRIBUTE_UNUSED,
- int options) {
- const char *base = baseFilename(filename);
- const char *base2;
- const char *instance;
- xmlRelaxNGParserCtxtPtr ctxt;
- xmlRelaxNGPtr schemas;
- int res = 0, len, ret;
- char pattern[500];
- char prefix[500];
- char result[500];
- char err[500];
- glob_t globbuf;
- size_t i;
- char count = 0;
-
- /* first compile the schemas if possible */
- ctxt = xmlRelaxNGNewParserCtxt(filename);
- xmlRelaxNGSetParserErrors(ctxt,
- (xmlRelaxNGValidityErrorFunc) testErrorHandler,
- (xmlRelaxNGValidityWarningFunc) testErrorHandler,
- ctxt);
- schemas = xmlRelaxNGParse(ctxt);
- xmlRelaxNGFreeParserCtxt(ctxt);
-
- /*
- * most of the mess is about the output filenames generated by the Makefile
- */
- len = strlen(base);
- if ((len > 499) || (len < 5)) {
- xmlRelaxNGFree(schemas);
- return(-1);
- }
- len -= 4; /* remove trailing .rng */
- memcpy(prefix, base, len);
- prefix[len] = 0;
-
- snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
- pattern[499] = 0;
-
- globbuf.gl_offs = 0;
- glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
- for (i = 0;i < globbuf.gl_pathc;i++) {
- testErrorsSize = 0;
- testErrors[0] = 0;
- instance = globbuf.gl_pathv[i];
- base2 = baseFilename(instance);
- len = strlen(base2);
- if ((len > 6) && (base2[len - 6] == '_')) {
- count = base2[len - 5];
- snprintf(result, 499, "result/relaxng/%s_%c",
- prefix, count);
- result[499] = 0;
- snprintf(err, 499, "result/relaxng/%s_%c.err",
- prefix, count);
- err[499] = 0;
- } else {
- fprintf(stderr, "don't know how to process %s\n", instance);
- continue;
- }
- if (schemas == NULL) {
- } else {
- nb_tests++;
- ret = rngOneTest(filename, instance, result, err,
- options, schemas);
- if (res != 0)
- ret = res;
- }
- }
- globfree(&globbuf);
- xmlRelaxNGFree(schemas);
-
- return(res);
-}
-
-#ifdef LIBXML_READER_ENABLED
-/**
- * rngStreamTest:
- * @filename: the schemas file
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a set of files with streaming, applying an RNG schemas
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-rngStreamTest(const char *filename,
- const char *resul ATTRIBUTE_UNUSED,
- const char *errr ATTRIBUTE_UNUSED,
- int options) {
- const char *base = baseFilename(filename);
- const char *base2;
- const char *instance;
- int res = 0, len, ret;
- char pattern[500];
- char prefix[500];
- char result[500];
- char err[500];
- glob_t globbuf;
- size_t i;
- char count = 0;
- xmlTextReaderPtr reader;
- int disable_err = 0;
-
- /*
- * most of the mess is about the output filenames generated by the Makefile
- */
- len = strlen(base);
- if ((len > 499) || (len < 5)) {
- fprintf(stderr, "len(base) == %d !\n", len);
- return(-1);
- }
- len -= 4; /* remove trailing .rng */
- memcpy(prefix, base, len);
- prefix[len] = 0;
-
- /*
- * strictly unifying the error messages is nearly impossible this
- * hack is also done in the Makefile
- */
- if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
- (!strcmp(prefix, "tutor3_2")))
- disable_err = 1;
-
- snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
- pattern[499] = 0;
-
- globbuf.gl_offs = 0;
- glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
- for (i = 0;i < globbuf.gl_pathc;i++) {
- testErrorsSize = 0;
- testErrors[0] = 0;
- instance = globbuf.gl_pathv[i];
- base2 = baseFilename(instance);
- len = strlen(base2);
- if ((len > 6) && (base2[len - 6] == '_')) {
- count = base2[len - 5];
- snprintf(result, 499, "result/relaxng/%s_%c",
- prefix, count);
- result[499] = 0;
- snprintf(err, 499, "result/relaxng/%s_%c.err",
- prefix, count);
- err[499] = 0;
- } else {
- fprintf(stderr, "don't know how to process %s\n", instance);
- continue;
- }
- reader = xmlReaderForFile(instance, NULL, options);
- if (reader == NULL) {
- fprintf(stderr, "Failed to build reder for %s\n", instance);
- }
- if (disable_err == 1)
- ret = streamProcessTest(instance, result, NULL, reader, filename);
- else
- ret = streamProcessTest(instance, result, err, reader, filename);
- xmlFreeTextReader(reader);
- if (ret != 0) {
- fprintf(stderr, "instance %s failed\n", instance);
- res = ret;
- }
- }
- globfree(&globbuf);
-
- return(res);
-}
-#endif /* READER */
-
-#endif
-
-#ifdef LIBXML_PATTERN_ENABLED
-#ifdef LIBXML_READER_ENABLED
-/************************************************************************
- * *
- * Patterns tests *
- * *
- ************************************************************************/
-static void patternNode(FILE *out, xmlTextReaderPtr reader,
- const char *pattern, xmlPatternPtr patternc,
- xmlStreamCtxtPtr patstream) {
- xmlChar *path = NULL;
- int match = -1;
- int type, empty;
-
- type = xmlTextReaderNodeType(reader);
- empty = xmlTextReaderIsEmptyElement(reader);
-
- if (type == XML_READER_TYPE_ELEMENT) {
- /* do the check only on element start */
- match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
-
- if (match) {
- path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
- fprintf(out, "Node %s matches pattern %s\n", path, pattern);
- }
- }
- if (patstream != NULL) {
- int ret;
-
- if (type == XML_READER_TYPE_ELEMENT) {
- ret = xmlStreamPush(patstream,
- xmlTextReaderConstLocalName(reader),
- xmlTextReaderConstNamespaceUri(reader));
- if (ret < 0) {
- fprintf(out, "xmlStreamPush() failure\n");
- xmlFreeStreamCtxt(patstream);
- patstream = NULL;
- } else if (ret != match) {
- if (path == NULL) {
- path = xmlGetNodePath(
- xmlTextReaderCurrentNode(reader));
- }
- fprintf(out,
- "xmlPatternMatch and xmlStreamPush disagree\n");
- fprintf(out,
- " pattern %s node %s\n",
- pattern, path);
- }
-
-
- }
- if ((type == XML_READER_TYPE_END_ELEMENT) ||
- ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
- ret = xmlStreamPop(patstream);
- if (ret < 0) {
- fprintf(out, "xmlStreamPop() failure\n");
- xmlFreeStreamCtxt(patstream);
- patstream = NULL;
- }
- }
- }
- if (path != NULL)
- xmlFree(path);
-}
-
-/**
- * patternTest:
- * @filename: the schemas file
- * @result: the file with expected result
- * @err: the file with error messages
- *
- * Parse a set of files with streaming, applying an RNG schemas
- *
- * Returns 0 in case of success, an error code otherwise
- */
-static int
-patternTest(const char *filename,
- const char *resul ATTRIBUTE_UNUSED,
- const char *err ATTRIBUTE_UNUSED,
- int options) {
- xmlPatternPtr patternc = NULL;
- xmlStreamCtxtPtr patstream = NULL;
- FILE *o, *f;
- char str[1024];
- char xml[500];
- char result[500];
- int len, i;
- int ret = 0, res;
- char *temp;
- xmlTextReaderPtr reader;
- xmlDocPtr doc;
-
- len = strlen(filename);
- len -= 4;
- memcpy(xml, filename, len);
- xml[len] = 0;
- snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
- result[499] = 0;
- memcpy(xml + len, ".xml", 5);
-
- if (!checkTestFile(xml)) {
- fprintf(stderr, "Missing xml file %s\n", xml);
- return(-1);
- }
- if (!checkTestFile(result)) {
- fprintf(stderr, "Missing result file %s\n", result);
- return(-1);
- }
- f = fopen(filename, "rb");
- if (f == NULL) {
- fprintf(stderr, "Failed to open %s\n", filename);
- return(-1);
- }
- temp = resultFilename(filename, "", ".res");
- if (temp == NULL) {
- fprintf(stderr, "Out of memory\n");
- fatalError();
- }
- o = fopen(temp, "wb");
- if (o == NULL) {
- fprintf(stderr, "failed to open output file %s\n", temp);
- fclose(f);
- free(temp);
- return(-1);
- }
- while (1) {
- /*
- * read one line in string buffer.
- */
- if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
- break;
-
- /*
- * remove the ending spaces
- */
- i = strlen(str);
- while ((i > 0) &&
- ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
- (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
- i--;
- str[i] = 0;
- }
- doc = xmlReadFile(xml, NULL, options);
- if (doc == NULL) {
- fprintf(stderr, "Failed to parse %s\n", xml);
- ret = 1;
- } else {
- xmlNodePtr root;
- const xmlChar *namespaces[22];
- int j;
- xmlNsPtr ns;
-
- root = xmlDocGetRootElement(doc);
- for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
- namespaces[j++] = ns->href;
- namespaces[j++] = ns->prefix;
- }
- namespaces[j++] = NULL;
- namespaces[j++] = NULL;
-
- patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
- 0, &namespaces[0]);
- if (patternc == NULL) {
- testErrorHandler(NULL,
- "Pattern %s failed to compile\n", str);
- xmlFreeDoc(doc);
- ret = 1;
- continue;
- }
- patstream = xmlPatternGetStreamCtxt(patternc);
- if (patstream != NULL) {
- ret = xmlStreamPush(patstream, NULL, NULL);
- if (ret < 0) {
- fprintf(stderr, "xmlStreamPush() failure\n");
- xmlFreeStreamCtxt(patstream);
- patstream = NULL;
- }
- }
- nb_tests++;
-
- reader = xmlReaderWalker(doc);
- res = xmlTextReaderRead(reader);
- while (res == 1) {
- patternNode(o, reader, str, patternc, patstream);
- res = xmlTextReaderRead(reader);
- }
- if (res != 0) {
- fprintf(o, "%s : failed to parse\n", filename);
- }
- xmlFreeTextReader(reader);
- xmlFreeDoc(doc);
- xmlFreeStreamCtxt(patstream);
- patstream = NULL;
- xmlFreePattern(patternc);
-
- }
- }
-
- fclose(f);
- fclose(o);
-
- ret = compareFiles(temp, result);
- if (ret) {
- fprintf(stderr, "Result for %s failed\n", filename);
- ret = 1;
- }
- unlink(temp);
- free(temp);
- return(ret);
-}
-#endif /* READER */
-#endif /* PATTERN */
-#ifdef LIBXML_C14N_ENABLED
-/************************************************************************
- * *
- * Canonicalization tests *
- * *
- ************************************************************************/
-static xmlXPathObjectPtr
-load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
- xmlXPathObjectPtr xpath;
- xmlDocPtr doc;
- xmlChar *expr;
- xmlXPathContextPtr ctx;
- xmlNodePtr node;
- xmlNsPtr ns;
-
- /*
- * load XPath expr as a file
- */
- xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
- xmlSubstituteEntitiesDefault(1);
-
- doc = xmlParseFile(filename);
- if (doc == NULL) {
- fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
- return(NULL);
- }
-
- /*
- * Check the document is of the right kind
- */
- if(xmlDocGetRootElement(doc) == NULL) {
- fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
- xmlFreeDoc(doc);
- return(NULL);
- }
-
- node = doc->children;
- while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
- node = node->next;
- }
-
- if(node == NULL) {
- fprintf(stderr,"Error: XPath element expected in the file \"%s\"\n", filename);
- xmlFreeDoc(doc);
- return(NULL);
- }
-
- expr = xmlNodeGetContent(node);
- if(expr == NULL) {
- fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
- xmlFreeDoc(doc);
- return(NULL);
- }
-
- ctx = xmlXPathNewContext(parent_doc);
- if(ctx == NULL) {
- fprintf(stderr,"Error: unable to create new context\n");
- xmlFree(expr);
- xmlFreeDoc(doc);
- return(NULL);
- }
-
- /*
- * Register namespaces
- */
- ns = node->nsDef;
- while(ns != NULL) {
- if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
- fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
- xmlFree(expr);
- xmlXPathFreeContext(ctx);
- xmlFreeDoc(doc);
- return(NULL);
- }
- ns = ns->next;
- }
-
- /*
- * Evaluate xpath
- */
- xpath = xmlXPathEvalExpression(expr, ctx);
- if(xpath == NULL) {
- fprintf(stderr,"Error: unable to evaluate xpath expression\n");
- xmlFree(expr);
- xmlXPathFreeContext(ctx);
- xmlFreeDoc(doc);
- return(NULL);
- }
-
- /* print_xpath_nodes(xpath->nodesetval); */
-
- xmlFree(expr);
- xmlXPathFreeContext(ctx);
- xmlFreeDoc(doc);
- return(xpath);
-}
-
-/*
- * Macro used to grow the current buffer.
- */
-#define xxx_growBufferReentrant() { \
- buffer_size *= 2; \
- buffer = (xmlChar **) \
- xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \
- if (buffer == NULL) { \
- perror("realloc failed"); \
- return(NULL); \
- } \
-}
-
-static xmlChar **
-parse_list(xmlChar *str) {
- xmlChar **buffer;
- xmlChar **out = NULL;
- int buffer_size = 0;
- int len;
-
- if(str == NULL) {
- return(NULL);
- }
-
- len = xmlStrlen(str);
- if((str[0] == '\'') && (str[len - 1] == '\'')) {
- str[len - 1] = '\0';
- str++;
- len -= 2;
- }
- /*
- * allocate an translation buffer.
- */
- buffer_size = 1000;
- buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
- if (buffer == NULL) {
- perror("malloc failed");
- return(NULL);
- }
- out = buffer;
-
- while(*str != '\0') {
- if (out - buffer > buffer_size - 10) {
- int indx = out - buffer;
-
- xxx_growBufferReentrant();
- out = &buffer[indx];
- }
- (*out++) = str;
- while(*str != ',' && *str != '\0') ++str;
- if(*str == ',') *(str++) = '\0';
- }
- (*out) = NULL;
- return buffer;
-}
-
-static int
-c14nRunTest(const char* xml_filename, int with_comments, int exclusive,
- const char* xpath_filename, const char *ns_filename,
- const char* result_file) {
- xmlDocPtr doc;
- xmlXPathObjectPtr xpath = NULL;
- xmlChar *result = NULL;
- int ret;
- xmlChar **inclusive_namespaces = NULL;
- const char *nslist = NULL;
- int nssize;
-
-
- /*
- * build an XML tree from a the file; we need to add default
- * attributes and resolve all character and entities references
- */
- xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
- xmlSubstituteEntitiesDefault(1);
-
- doc = xmlParseFile(xml_filename);
- if (doc == NULL) {
- fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
- return(-1);
- }
-
- /*
- * Check the document is of the right kind
- */
- if(xmlDocGetRootElement(doc) == NULL) {
- fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
- xmlFreeDoc(doc);
- return(-1);
- }
-
- /*
- * load xpath file if specified
- */
- if(xpath_filename) {
- xpath = load_xpath_expr(doc, xpath_filename);
- if(xpath == NULL) {
- fprintf(stderr,"Error: unable to evaluate xpath expression\n");
- xmlFreeDoc(doc);
- return(-1);
- }
- }
-
- if (ns_filename != NULL) {
- if (loadMem(ns_filename, &nslist, &nssize)) {
- fprintf(stderr,"Error: unable to evaluate xpath expression\n");
- if(xpath != NULL) xmlXPathFreeObject(xpath);
- xmlFreeDoc(doc);
- return(-1);
- }
- inclusive_namespaces = parse_list((xmlChar *) nslist);
- }
-
- /*
- * Canonical form
- */
- /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
- ret = xmlC14NDocDumpMemory(doc,
- (xpath) ? xpath->nodesetval : NULL,
- exclusive, inclusive_namespaces,
- with_comments, &result);
- if (ret >= 0) {
- if(result != NULL) {
- if (compareFileMem(result_file, (const char *) result, ret)) {
- fprintf(stderr, "Result mismatch for %s\n", xml_filename);
- ret = -1;
- }
- }
- } else {
- fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
- ret = -1;
- }
-
- /*
- * Cleanup
- */
- if (result != NULL) xmlFree(result);
- if(xpath != NULL) xmlXPathFreeObject(xpath);
- if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
- if (nslist != NULL) free((char *) nslist);
- xmlFreeDoc(doc);
-
- return(ret);
-}
-
-static int
-c14nCommonTest(const char *filename, int with_comments, int exclusive,
- const char *subdir) {
- char buf[500];
- char prefix[500];
- const char *base;
- int len;
- char *result = NULL;
- char *xpath = NULL;
- char *ns = NULL;
- int ret = 0;
-
- base = baseFilename(filename);
- len = strlen(base);
- len -= 4;
- memcpy(prefix, base, len);
- prefix[len] = 0;
-
- snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
- if (!checkTestFile(buf)) {
- fprintf(stderr, "Missing result file %s", buf);
- return(-1);
- }
- result = strdup(buf);
- snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
- if (checkTestFile(buf)) {
- xpath = strdup(buf);
- }
- snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
- if (checkTestFile(buf)) {
- ns = strdup(buf);
- }
-
- nb_tests++;
- if (c14nRunTest(filename, with_comments, exclusive,
- xpath, ns, result) < 0)
- ret = 1;
-
- if (result != NULL) free(result);
- if (xpath != NULL) free(xpath);
- if (ns != NULL) free(ns);
- return(ret);
-}
-
-static int
-c14nWithCommentTest(const char *filename,
- const char *resul ATTRIBUTE_UNUSED,
- const char *err ATTRIBUTE_UNUSED,
- int options ATTRIBUTE_UNUSED) {
- return(c14nCommonTest(filename, 1, 0, "with-comments"));
-}
-static int
-c14nWithoutCommentTest(const char *filename,
- const char *resul ATTRIBUTE_UNUSED,
- const char *err ATTRIBUTE_UNUSED,
- int options ATTRIBUTE_UNUSED) {
- return(c14nCommonTest(filename, 0, 0, "without-comments"));
-}
-static int
-c14nExcWithoutCommentTest(const char *filename,
- const char *resul ATTRIBUTE_UNUSED,
- const char *err ATTRIBUTE_UNUSED,
- int options ATTRIBUTE_UNUSED) {
- return(c14nCommonTest(filename, 0, 1, "exc-without-comments"));
-}
-#endif
-#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
-/************************************************************************
- * *
- * Catalog and threads test *
- * *
- ************************************************************************/
-
-/*
- * mostly a cut and paste from testThreads.c
- */
-#define MAX_ARGC 20
-
-static const char *catalog = "test/threads/complex.xml";
-static const char *testfiles[] = {
- "test/threads/abc.xml",
- "test/threads/acb.xml",
- "test/threads/bac.xml",
- "test/threads/bca.xml",
- "test/threads/cab.xml",
- "test/threads/cba.xml",
- "test/threads/invalid.xml",
-};
-
-const char *Okay = "OK";
-const char *Failed = "Failed";
-
-#ifndef xmlDoValidityCheckingDefaultValue
-#error xmlDoValidityCheckingDefaultValue is not a macro
-#endif
-#ifndef xmlGenericErrorContext
-#error xmlGenericErrorContext is not a macro
-#endif
-
-static void *
-thread_specific_data(void *private_data)
-{
- xmlDocPtr myDoc;
- const char *filename = (const char *) private_data;
- int okay = 1;
-
- if (!strcmp(filename, "test/threads/invalid.xml")) {
- xmlDoValidityCheckingDefaultValue = 0;
- xmlGenericErrorContext = stdout;
- } else {
- xmlDoValidityCheckingDefaultValue = 1;
- xmlGenericErrorContext = stderr;
- }
- myDoc = xmlParseFile(filename);
- if (myDoc) {
- xmlFreeDoc(myDoc);
- } else {
- printf("parse failed\n");
- okay = 0;
- }
- if (!strcmp(filename, "test/threads/invalid.xml")) {
- if (xmlDoValidityCheckingDefaultValue != 0) {
- printf("ValidityCheckingDefaultValue override failed\n");
- okay = 0;
- }
- if (xmlGenericErrorContext != stdout) {
- printf("xmlGenericErrorContext override failed\n");
- okay = 0;
- }
- } else {
- if (xmlDoValidityCheckingDefaultValue != 1) {
- printf("ValidityCheckingDefaultValue override failed\n");
- okay = 0;
- }
- if (xmlGenericErrorContext != stderr) {
- printf("xmlGenericErrorContext override failed\n");
- okay = 0;
- }
- }
- if (okay == 0)
- return ((void *) Failed);
- return ((void *) Okay);
-}
-
-#if defined(linux) || defined(solaris)
-
-#include <pthread.h>
-
-static pthread_t tid[MAX_ARGC];
-
-static int
-testThread(void)
-{
- unsigned int i, repeat;
- unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
- void *results[MAX_ARGC];
- int ret;
- int res = 0;
-
- xmlInitParser();
-
- for (repeat = 0; repeat < 500; repeat++) {
- xmlLoadCatalog(catalog);
- nb_tests++;
-
- for (i = 0; i < num_threads; i++) {
- results[i] = NULL;
- tid[i] = (pthread_t) - 1;
- }
-
- for (i = 0; i < num_threads; i++) {
- ret = pthread_create(&tid[i], 0, thread_specific_data,
- (void *) testfiles[i]);
- if (ret != 0) {
- fprintf(stderr, "pthread_create failed\n");
- return (1);
- }
- }
- for (i = 0; i < num_threads; i++) {
- ret = pthread_join(tid[i], &results[i]);
- if (ret != 0) {
- fprintf(stderr, "pthread_join failed\n");
- return (1);
- }
- }
-
- xmlCatalogCleanup();
- for (i = 0; i < num_threads; i++)
- if (results[i] != (void *) Okay) {
- fprintf(stderr, "Thread %d handling %s failed\n",
- i, testfiles[i]);
- res = 1;
- }
- }
- return (res);
-}
-
-#elif defined WIN32
-#include <windows.h>
-#include <string.h>
-
-#define TEST_REPEAT_COUNT 500
-
-static HANDLE tid[MAX_ARGC];
-
-static DWORD WINAPI
-win32_thread_specific_data(void *private_data)
-{
- return((DWORD) thread_specific_data(private_data));
-}
-
-static int
-testThread(void)
-{
- unsigned int i, repeat;
- unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
- DWORD results[MAX_ARGC];
- BOOL ret;
- int res = 0;
-
- xmlInitParser();
- for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
- xmlLoadCatalog(catalog);
- nb_tests++;
-
- for (i = 0; i < num_threads; i++) {
- results[i] = 0;
- tid[i] = (HANDLE) - 1;
- }
-
- for (i = 0; i < num_threads; i++) {
- DWORD useless;
-
- tid[i] = CreateThread(NULL, 0,
- win32_thread_specific_data,
- (void *) testfiles[i], 0,
- &useless);
- if (tid[i] == NULL) {
- fprintf(stderr, "CreateThread failed\n");
- return(1);
- }
- }
-
- if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
- WAIT_FAILED) {
- fprintf(stderr, "WaitForMultipleObjects failed\n");
- return(1);
- }
-
- for (i = 0; i < num_threads; i++) {
- ret = GetExitCodeThread(tid[i], &results[i]);
- if (ret == 0) {
- fprintf(stderr, "GetExitCodeThread failed\n");
- return(1);
- }
- CloseHandle(tid[i]);
- }
-
- xmlCatalogCleanup();
- for (i = 0; i < num_threads; i++) {
- if (results[i] != (DWORD) Okay) {
- fprintf(stderr, "Thread %d handling %s failed\n",
- i, testfiles[i]);
- res = 1;
- }
- }
- }
-
- return (res);
-}
-
-#elif defined __BEOS__
-#include <OS.h>
-
-static thread_id tid[MAX_ARGC];
-
-static int
-testThread(void)
-{
- unsigned int i, repeat;
- unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
- void *results[MAX_ARGC];
- status_t ret;
- int res = 0;
-
- xmlInitParser();
- for (repeat = 0; repeat < 500; repeat++) {
- xmlLoadCatalog(catalog);
- for (i = 0; i < num_threads; i++) {
- results[i] = NULL;
- tid[i] = (thread_id) - 1;
- }
- for (i = 0; i < num_threads; i++) {
- tid[i] =
- spawn_thread(thread_specific_data, "xmlTestThread",
- B_NORMAL_PRIORITY, (void *) testfiles[i]);
- if (tid[i] < B_OK) {
- fprintf(stderr, "beos_thread_create failed\n");
- return (1);
- }
- printf("beos_thread_create %d -> %d\n", i, tid[i]);
- }
- for (i = 0; i < num_threads; i++) {
- ret = wait_for_thread(tid[i], &results[i]);
- printf("beos_thread_wait %d -> %d\n", i, ret);
- if (ret != B_OK) {
- fprintf(stderr, "beos_thread_wait failed\n");
- return (1);
- }
- }
-
- xmlCatalogCleanup();
- ret = B_OK;
- for (i = 0; i < num_threads; i++)
- if (results[i] != (void *) Okay) {
- printf("Thread %d handling %s failed\n", i, testfiles[i]);
- ret = B_ERROR;
- }
- }
- if (ret != B_OK)
- return(1);
- return (0);
-}
-#else
-static int
-testThread(void)
-{
- fprintf(stderr,
- "Specific platform thread support not detected\n");
- return (-1);
-}
-#endif
-static int
-threadsTest(const char *filename ATTRIBUTE_UNUSED,
- const char *resul ATTRIBUTE_UNUSED,
- const char *err ATTRIBUTE_UNUSED,
- int options ATTRIBUTE_UNUSED) {
- return(testThread());
-}
-#endif
-/************************************************************************
- * *
- * Tests Descriptions *
- * *
- ************************************************************************/
-
-static
-testDesc testDescriptions[] = {
- { "XML regression tests" ,
- oldParseTest, "./test/*", "result/", "", NULL,
- 0 },
- { "XML regression tests on memory" ,
- memParseTest, "./test/*", "result/", "", NULL,
- 0 },
- { "XML entity subst regression tests" ,
- noentParseTest, "./test/*", "result/noent/", "", NULL,
- XML_PARSE_NOENT },
- { "XML Namespaces regression tests",
- errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
- 0 },
- { "Error cases regression tests",
- errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
- 0 },
-#ifdef LIBXML_READER_ENABLED
- { "Error cases stream regression tests",
- streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
- 0 },
- { "Reader regression tests",
- streamParseTest, "./test/*", "result/", ".rdr", NULL,
- 0 },
- { "Reader entities substitution regression tests",
- streamParseTest, "./test/*", "result/", ".rde", NULL,
- XML_PARSE_NOENT },
- { "Reader on memory regression tests",
- streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
- 0 },
- { "Walker regression tests",
- walkerParseTest, "./test/*", "result/", ".rdr", NULL,
- 0 },
-#endif
-#ifdef LIBXML_SAX1_ENABLED
- { "SAX1 callbacks regression tests" ,
- saxParseTest, "./test/*", "result/", ".sax", NULL,
- XML_PARSE_SAX1 },
- { "SAX2 callbacks regression tests" ,
- saxParseTest, "./test/*", "result/", ".sax2", NULL,
- 0 },
-#endif
-#ifdef LIBXML_PUSH_ENABLED
- { "XML push regression tests" ,
- pushParseTest, "./test/*", "result/", "", NULL,
- 0 },
-#endif
-#ifdef LIBXML_HTML_ENABLED
- { "HTML regression tests" ,
- errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
- XML_PARSE_HTML },
-#ifdef LIBXML_PUSH_ENABLED
- { "Push HTML regression tests" ,
- pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
- XML_PARSE_HTML },
-#endif
-#ifdef LIBXML_SAX1_ENABLED
- { "HTML SAX regression tests" ,
- saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
- XML_PARSE_HTML },
-#endif
-#endif
-#ifdef LIBXML_VALID_ENABLED
- { "Valid documents regression tests" ,
- errParseTest, "./test/VCM/*", NULL, NULL, NULL,
- XML_PARSE_DTDVALID },
- { "Validity checking regression tests" ,
- errParseTest, "./test/VC/*", "result/VC/", NULL, "",
- XML_PARSE_DTDVALID },
- { "General documents valid regression tests" ,
- errParseTest, "./test/valid/*", "result/valid/", "", ".err",
- XML_PARSE_DTDVALID },
-#endif
-#ifdef LIBXML_XINCLUDE_ENABLED
- { "XInclude regression tests" ,
- errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
- /* Ignore errors at this point ".err", */
- XML_PARSE_XINCLUDE },
- { "XInclude xmlReader regression tests",
- streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
- /* Ignore errors at this point ".err", */
- NULL, XML_PARSE_XINCLUDE },
- { "XInclude regression tests stripping include nodes" ,
- errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
- /* Ignore errors at this point ".err", */
- XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
- { "XInclude xmlReader regression tests stripping include nodes",
- streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
- /* Ignore errors at this point ".err", */
- NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
-#endif
-#ifdef LIBXML_XPATH_ENABLED
-#ifdef LIBXML_DEBUG_ENABLED
- { "XPath expressions regression tests" ,
- xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
- 0 },
- { "XPath document queries regression tests" ,
- xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
- 0 },
-#ifdef LIBXML_XPTR_ENABLED
- { "XPointer document queries regression tests" ,
- xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
- 0 },
-#endif
- { "xml:id regression tests" ,
- xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
- 0 },
-#endif
-#endif
- { "URI parsing tests" ,
- uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
- 0 },
- { "URI base composition tests" ,
- uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
- 0 },
-#ifdef LIBXML_SCHEMAS_ENABLED
- { "Schemas regression tests" ,
- schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
- 0 },
- { "Relax-NG regression tests" ,
- rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
- XML_PARSE_DTDATTR | XML_PARSE_NOENT },
-#ifdef LIBXML_READER_ENABLED
- { "Relax-NG streaming regression tests" ,
- rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
- XML_PARSE_DTDATTR | XML_PARSE_NOENT },
-#endif
-#endif
-#ifdef LIBXML_PATTERN_ENABLED
-#ifdef LIBXML_READER_ENABLED
- { "Pattern regression tests" ,
- patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
- 0 },
-#endif
-#endif
-#ifdef LIBXML_C14N_ENABLED
- { "C14N with comments regression tests" ,
- c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
- 0 },
- { "C14N without comments regression tests" ,
- c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
- 0 },
- { "C14N exclusive without comments regression tests" ,
- c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
- 0 },
-#endif
-#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
- { "Catalog and Threads regression tests" ,
- threadsTest, NULL, NULL, NULL, NULL,
- 0 },
-#endif
- {NULL, NULL, NULL, NULL, NULL, NULL, 0}
-};
-
-/************************************************************************
- * *
- * The main code driving the tests *
- * *
- ************************************************************************/
-
-static int
-launchTests(testDescPtr tst) {
- int res = 0, err = 0;
- size_t i;
- char *result;
- char *error;
- int mem;
-
- if (tst == NULL) return(-1);
- if (tst->in != NULL) {
- glob_t globbuf;
-
- globbuf.gl_offs = 0;
- glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
- for (i = 0;i < globbuf.gl_pathc;i++) {
- if (!checkTestFile(globbuf.gl_pathv[i]))
- continue;
- if (tst->suffix != NULL) {
- result = resultFilename(globbuf.gl_pathv[i], tst->out,
- tst->suffix);
- if (result == NULL) {
- fprintf(stderr, "Out of memory !\n");
- fatalError();
- }
- } else {
- result = NULL;
- }
- if (tst->err != NULL) {
- error = resultFilename(globbuf.gl_pathv[i], tst->out,
- tst->err);
- if (error == NULL) {
- fprintf(stderr, "Out of memory !\n");
- fatalError();
- }
- } else {
- error = NULL;
- }
- if ((result) &&(!checkTestFile(result))) {
- fprintf(stderr, "Missing result file %s\n", result);
- } else if ((error) &&(!checkTestFile(error))) {
- fprintf(stderr, "Missing error file %s\n", error);
- } else {
- mem = xmlMemUsed();
- extraMemoryFromResolver = 0;
- testErrorsSize = 0;
- testErrors[0] = 0;
- res = tst->func(globbuf.gl_pathv[i], result, error,
- tst->options);
- xmlResetLastError();
- if (res != 0) {
- fprintf(stderr, "File %s generated an error\n",
- globbuf.gl_pathv[i]);
- nb_errors++;
- err++;
- }
- else if (xmlMemUsed() != mem) {
- if ((xmlMemUsed() != mem) &&
- (extraMemoryFromResolver == 0)) {
- fprintf(stderr, "File %s leaked %d bytes\n",
- globbuf.gl_pathv[i], xmlMemUsed() - mem);
- nb_leaks++;
- err++;
- }
- }
- testErrorsSize = 0;
- }
- if (result)
- free(result);
- if (error)
- free(error);
- }
- globfree(&globbuf);
- } else {
- testErrorsSize = 0;
- testErrors[0] = 0;
- extraMemoryFromResolver = 0;
- res = tst->func(NULL, NULL, NULL, tst->options);
- if (res != 0) {
- nb_errors++;
- err++;
- }
- }
- return(err);
-}
-
-int
-main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
- int i = 0, res, ret = 0;
- int verbose = 0;
- int old_errors, old_tests, old_leaks;
-
- initializeLibxml2();
-
- if ((argc >= 2) && (!strcmp(argv[1], "-v")))
- verbose = 1;
- for (i = 0; testDescriptions[i].func != NULL; i++) {
- old_errors = nb_errors;
- old_tests = nb_tests;
- old_leaks = nb_leaks;
- if (testDescriptions[i].desc != NULL)
- printf("## %s\n", testDescriptions[i].desc);
- res = launchTests(&testDescriptions[i]);
- if (res != 0)
- ret++;
- if (verbose) {
- if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
- printf("Ran %d tests, no errors\n", nb_tests - old_tests);
- else
- printf("Ran %d tests, %d errors, %d leaks\n",
- nb_tests - old_tests,
- nb_errors - old_errors,
- nb_leaks - old_leaks);
- }
- }
- if ((nb_errors == 0) && (nb_leaks == 0)) {
- ret = 0;
- printf("Total %d tests, no errors\n",
- nb_tests);
- } else {
- ret = 1;
- printf("Total %d tests, %d errors, %d leaks\n",
- nb_tests, nb_errors, nb_leaks);
- }
- xmlCleanupParser();
- xmlMemoryDump();
-
- return(ret);
-}
-
-#else /* ! LIBXML_OUTPUT_ENABLED */
-int
-main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
- fprintf(stderr, "runtest requires output to be enabled in libxml2\n");
- return(1);
-}
-#endif
+/*
+ * runtest.c: C program to run libxml2 regression tests without
+ * requiring make or Python, and reducing platform dependancies
+ * to a strict minimum.
+ *
+ * To compile on Unixes:
+ * cc -o runtest `xml2-config --cflags` runtest.c `xml2-config --libs` -lpthread
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#if !defined(_WIN32) || defined(__CYGWIN__)
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/uri.h>
+
+#ifdef LIBXML_OUTPUT_ENABLED
+#ifdef LIBXML_READER_ENABLED
+#include <libxml/xmlreader.h>
+#endif
+
+#ifdef LIBXML_XINCLUDE_ENABLED
+#include <libxml/xinclude.h>
+#endif
+
+#ifdef LIBXML_XPATH_ENABLED
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#ifdef LIBXML_XPTR_ENABLED
+#include <libxml/xpointer.h>
+#endif
+#endif
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/relaxng.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/xmlschemastypes.h>
+#endif
+
+#ifdef LIBXML_PATTERN_ENABLED
+#include <libxml/pattern.h>
+#endif
+
+#ifdef LIBXML_C14N_ENABLED
+#include <libxml/c14n.h>
+#endif
+
+#ifdef LIBXML_HTML_ENABLED
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+
+/*
+ * pseudo flag for the unification of HTML and XML tests
+ */
+#define XML_PARSE_HTML 1 << 24
+#endif
+
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
+#include <libxml/globals.h>
+#include <libxml/threads.h>
+#include <libxml/parser.h>
+#include <libxml/catalog.h>
+#include <string.h>
+#endif
+
+/*
+ * O_BINARY is just for Windows compatibility - if it isn't defined
+ * on this system, avoid any compilation error
+ */
+#ifdef O_BINARY
+#define RD_FLAGS O_RDONLY | O_BINARY
+#else
+#define RD_FLAGS O_RDONLY
+#endif
+
+typedef int (*functest) (const char *filename, const char *result,
+ const char *error, int options);
+
+typedef struct testDesc testDesc;
+typedef testDesc *testDescPtr;
+struct testDesc {
+ const char *desc; /* descripton of the test */
+ functest func; /* function implementing the test */
+ const char *in; /* glob to path for input files */
+ const char *out; /* output directory */
+ const char *suffix;/* suffix for output files */
+ const char *err; /* suffix for error output files */
+ int options; /* parser options for the test */
+};
+
+static int checkTestFile(const char *filename);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+
+#include <windows.h>
+#include <io.h>
+
+typedef struct
+{
+ size_t gl_pathc; /* Count of paths matched so far */
+ char **gl_pathv; /* List of matched pathnames. */
+ size_t gl_offs; /* Slots to reserve in 'gl_pathv'. */
+} glob_t;
+
+#define GLOB_DOOFFS 0
+static int glob(const char *pattern, int flags,
+ int errfunc(const char *epath, int eerrno),
+ glob_t *pglob) {
+ glob_t *ret;
+ WIN32_FIND_DATA FindFileData;
+ HANDLE hFind;
+ unsigned int nb_paths = 0;
+ char directory[500];
+ int len;
+
+ if ((pattern == NULL) || (pglob == NULL)) return(-1);
+
+ strncpy(directory, pattern, 499);
+ for (len = strlen(directory);len >= 0;len--) {
+ if (directory[len] == '/') {
+ len++;
+ directory[len] = 0;
+ break;
+ }
+ }
+ if (len <= 0)
+ len = 0;
+
+
+ ret = pglob;
+ memset(ret, 0, sizeof(glob_t));
+
+ hFind = FindFirstFileA(pattern, &FindFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ return(0);
+ nb_paths = 20;
+ ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
+ if (ret->gl_pathv == NULL) {
+ FindClose(hFind);
+ return(-1);
+ }
+ strncpy(directory + len, FindFileData.cFileName, 499 - len);
+ ret->gl_pathv[ret->gl_pathc] = strdup(directory);
+ if (ret->gl_pathv[ret->gl_pathc] == NULL)
+ goto done;
+ ret->gl_pathc++;
+ while(FindNextFileA(hFind, &FindFileData)) {
+ if (FindFileData.cFileName[0] == '.')
+ continue;
+ if (ret->gl_pathc + 2 > nb_paths) {
+ char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
+ if (tmp == NULL)
+ break;
+ ret->gl_pathv = tmp;
+ nb_paths *= 2;
+ }
+ strncpy(directory + len, FindFileData.cFileName, 499 - len);
+ ret->gl_pathv[ret->gl_pathc] = strdup(directory);
+ if (ret->gl_pathv[ret->gl_pathc] == NULL)
+ break;
+ ret->gl_pathc++;
+ }
+ ret->gl_pathv[ret->gl_pathc] = NULL;
+
+done:
+ FindClose(hFind);
+ return(0);
+}
+
+
+
+static void globfree(glob_t *pglob) {
+ unsigned int i;
+ if (pglob == NULL)
+ return;
+
+ for (i = 0;i < pglob->gl_pathc;i++) {
+ if (pglob->gl_pathv[i] != NULL)
+ free(pglob->gl_pathv[i]);
+ }
+}
+#define vsnprintf _vsnprintf
+#define snprintf _snprintf
+#else
+#include <glob.h>
+#endif
+
+/************************************************************************
+ * *
+ * Libxml2 specific routines *
+ * *
+ ************************************************************************/
+
+static int nb_tests = 0;
+static int nb_errors = 0;
+static int nb_leaks = 0;
+static long libxmlMemoryAllocatedBase = 0;
+static int extraMemoryFromResolver = 0;
+
+static int
+fatalError(void) {
+ fprintf(stderr, "Exitting tests on fatal error\n");
+ exit(1);
+}
+
+/*
+ * We need to trap calls to the resolver to not account memory for the catalog
+ * which is shared to the current running test. We also don't want to have
+ * network downloads modifying tests.
+ */
+static xmlParserInputPtr
+testExternalEntityLoader(const char *URL, const char *ID,
+ xmlParserCtxtPtr ctxt) {
+ xmlParserInputPtr ret;
+
+ if (checkTestFile(URL)) {
+ ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+ } else {
+ int memused = xmlMemUsed();
+ ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+ extraMemoryFromResolver += xmlMemUsed() - memused;
+ }
+
+ return(ret);
+}
+
+/*
+ * Trapping the error messages at the generic level to grab the equivalent of
+ * stderr messages on CLI tools.
+ */
+static char testErrors[32769];
+static int testErrorsSize = 0;
+
+static void
+testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
+ va_list args;
+ int res;
+
+ if (testErrorsSize >= 32768)
+ return;
+ va_start(args, msg);
+ res = vsnprintf(&testErrors[testErrorsSize],
+ 32768 - testErrorsSize,
+ msg, args);
+ va_end(args);
+ if (testErrorsSize + res >= 32768) {
+ /* buffer is full */
+ testErrorsSize = 32768;
+ testErrors[testErrorsSize] = 0;
+ } else {
+ testErrorsSize += res;
+ }
+ testErrors[testErrorsSize] = 0;
+}
+
+static void
+channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
+ va_list args;
+ int res;
+
+ if (testErrorsSize >= 32768)
+ return;
+ va_start(args, msg);
+ res = vsnprintf(&testErrors[testErrorsSize],
+ 32768 - testErrorsSize,
+ msg, args);
+ va_end(args);
+ if (testErrorsSize + res >= 32768) {
+ /* buffer is full */
+ testErrorsSize = 32768;
+ testErrors[testErrorsSize] = 0;
+ } else {
+ testErrorsSize += res;
+ }
+ testErrors[testErrorsSize] = 0;
+}
+
+/**
+ * xmlParserPrintFileContext:
+ * @input: an xmlParserInputPtr input
+ *
+ * Displays current context within the input content for error tracking
+ */
+
+static void
+xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
+ xmlGenericErrorFunc chanl, void *data ) {
+ const xmlChar *cur, *base;
+ unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
+ xmlChar content[81]; /* space for 80 chars + line terminator */
+ xmlChar *ctnt;
+
+ if (input == NULL) return;
+ cur = input->cur;
+ base = input->base;
+ /* skip backwards over any end-of-lines */
+ while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
+ cur--;
+ }
+ n = 0;
+ /* search backwards for beginning-of-line (to max buff size) */
+ while ((n++ < (sizeof(content)-1)) && (cur > base) &&
+ (*(cur) != '\n') && (*(cur) != '\r'))
+ cur--;
+ if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
+ /* calculate the error position in terms of the current position */
+ col = input->cur - cur;
+ /* search forward for end-of-line (to max buff size) */
+ n = 0;
+ ctnt = content;
+ /* copy selected text to our buffer */
+ while ((*cur != 0) && (*(cur) != '\n') &&
+ (*(cur) != '\r') && (n < sizeof(content)-1)) {
+ *ctnt++ = *cur++;
+ n++;
+ }
+ *ctnt = 0;
+ /* print out the selected text */
+ chanl(data ,"%s\n", content);
+ /* create blank line with problem pointer */
+ n = 0;
+ ctnt = content;
+ /* (leave buffer space for pointer + line terminator) */
+ while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
+ if (*(ctnt) != '\t')
+ *(ctnt) = ' ';
+ ctnt++;
+ }
+ *ctnt++ = '^';
+ *ctnt = 0;
+ chanl(data ,"%s\n", content);
+}
+
+static void
+testStructuredErrorHandler(void *ctx ATTRIBUTE_UNUSED, xmlErrorPtr err) {
+ char *file = NULL;
+ int line = 0;
+ int code = -1;
+ int domain;
+ void *data = NULL;
+ const char *str;
+ const xmlChar *name = NULL;
+ xmlNodePtr node;
+ xmlErrorLevel level;
+ xmlParserInputPtr input = NULL;
+ xmlParserInputPtr cur = NULL;
+ xmlParserCtxtPtr ctxt = NULL;
+
+ if (err == NULL)
+ return;
+
+ file = err->file;
+ line = err->line;
+ code = err->code;
+ domain = err->domain;
+ level = err->level;
+ node = err->node;
+ if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
+ (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
+ (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
+ ctxt = err->ctxt;
+ }
+ str = err->message;
+
+ if (code == XML_ERR_OK)
+ return;
+
+ if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
+ name = node->name;
+
+ /*
+ * Maintain the compatibility with the legacy error handling
+ */
+ if (ctxt != NULL) {
+ input = ctxt->input;
+ if ((input != NULL) && (input->filename == NULL) &&
+ (ctxt->inputNr > 1)) {
+ cur = input;
+ input = ctxt->inputTab[ctxt->inputNr - 2];
+ }
+ if (input != NULL) {
+ if (input->filename)
+ channel(data, "%s:%d: ", input->filename, input->line);
+ else if ((line != 0) && (domain == XML_FROM_PARSER))
+ channel(data, "Entity: line %d: ", input->line);
+ }
+ } else {
+ if (file != NULL)
+ channel(data, "%s:%d: ", file, line);
+ else if ((line != 0) && (domain == XML_FROM_PARSER))
+ channel(data, "Entity: line %d: ", line);
+ }
+ if (name != NULL) {
+ channel(data, "element %s: ", name);
+ }
+ if (code == XML_ERR_OK)
+ return;
+ switch (domain) {
+ case XML_FROM_PARSER:
+ channel(data, "parser ");
+ break;
+ case XML_FROM_NAMESPACE:
+ channel(data, "namespace ");
+ break;
+ case XML_FROM_DTD:
+ case XML_FROM_VALID:
+ channel(data, "validity ");
+ break;
+ case XML_FROM_HTML:
+ channel(data, "HTML parser ");
+ break;
+ case XML_FROM_MEMORY:
+ channel(data, "memory ");
+ break;
+ case XML_FROM_OUTPUT:
+ channel(data, "output ");
+ break;
+ case XML_FROM_IO:
+ channel(data, "I/O ");
+ break;
+ case XML_FROM_XINCLUDE:
+ channel(data, "XInclude ");
+ break;
+ case XML_FROM_XPATH:
+ channel(data, "XPath ");
+ break;
+ case XML_FROM_XPOINTER:
+ channel(data, "parser ");
+ break;
+ case XML_FROM_REGEXP:
+ channel(data, "regexp ");
+ break;
+ case XML_FROM_MODULE:
+ channel(data, "module ");
+ break;
+ case XML_FROM_SCHEMASV:
+ channel(data, "Schemas validity ");
+ break;
+ case XML_FROM_SCHEMASP:
+ channel(data, "Schemas parser ");
+ break;
+ case XML_FROM_RELAXNGP:
+ channel(data, "Relax-NG parser ");
+ break;
+ case XML_FROM_RELAXNGV:
+ channel(data, "Relax-NG validity ");
+ break;
+ case XML_FROM_CATALOG:
+ channel(data, "Catalog ");
+ break;
+ case XML_FROM_C14N:
+ channel(data, "C14N ");
+ break;
+ case XML_FROM_XSLT:
+ channel(data, "XSLT ");
+ break;
+ default:
+ break;
+ }
+ if (code == XML_ERR_OK)
+ return;
+ switch (level) {
+ case XML_ERR_NONE:
+ channel(data, ": ");
+ break;
+ case XML_ERR_WARNING:
+ channel(data, "warning : ");
+ break;
+ case XML_ERR_ERROR:
+ channel(data, "error : ");
+ break;
+ case XML_ERR_FATAL:
+ channel(data, "error : ");
+ break;
+ }
+ if (code == XML_ERR_OK)
+ return;
+ if (str != NULL) {
+ int len;
+ len = xmlStrlen((const xmlChar *)str);
+ if ((len > 0) && (str[len - 1] != '\n'))
+ channel(data, "%s\n", str);
+ else
+ channel(data, "%s", str);
+ } else {
+ channel(data, "%s\n", "out of memory error");
+ }
+ if (code == XML_ERR_OK)
+ return;
+
+ if (ctxt != NULL) {
+ xmlParserPrintFileContextInternal(input, channel, data);
+ if (cur != NULL) {
+ if (cur->filename)
+ channel(data, "%s:%d: \n", cur->filename, cur->line);
+ else if ((line != 0) && (domain == XML_FROM_PARSER))
+ channel(data, "Entity: line %d: \n", cur->line);
+ xmlParserPrintFileContextInternal(cur, channel, data);
+ }
+ }
+ if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
+ (err->int1 < 100) &&
+ (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
+ xmlChar buf[150];
+ int i;
+
+ channel(data, "%s\n", err->str1);
+ for (i=0;i < err->int1;i++)
+ buf[i] = ' ';
+ buf[i++] = '^';
+ buf[i] = 0;
+ channel(data, "%s\n", buf);
+ }
+}
+
+static void
+initializeLibxml2(void) {
+ xmlGetWarningsDefaultValue = 0;
+ xmlPedanticParserDefault(0);
+
+ xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
+ xmlInitParser();
+ xmlSetExternalEntityLoader(testExternalEntityLoader);
+ xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
+#ifdef LIBXML_SCHEMAS_ENABLED
+ xmlSchemaInitTypes();
+ xmlRelaxNGInitTypes();
+#endif
+ libxmlMemoryAllocatedBase = xmlMemUsed();
+}
+
+
+/************************************************************************
+ * *
+ * File name and path utilities *
+ * *
+ ************************************************************************/
+
+static const char *baseFilename(const char *filename) {
+ const char *cur;
+ if (filename == NULL)
+ return(NULL);
+ cur = &filename[strlen(filename)];
+ while ((cur > filename) && (*cur != '/'))
+ cur--;
+ if (*cur == '/')
+ return(cur + 1);
+ return(cur);
+}
+
+static char *resultFilename(const char *filename, const char *out,
+ const char *suffix) {
+ const char *base;
+ char res[500];
+
+/*************
+ if ((filename[0] == 't') && (filename[1] == 'e') &&
+ (filename[2] == 's') && (filename[3] == 't') &&
+ (filename[4] == '/'))
+ filename = &filename[5];
+ *************/
+
+ base = baseFilename(filename);
+ if (suffix == NULL)
+ suffix = ".tmp";
+ if (out == NULL)
+ out = "";
+ snprintf(res, 499, "%s%s%s", out, base, suffix);
+ res[499] = 0;
+ return(strdup(res));
+}
+
+static int checkTestFile(const char *filename) {
+ struct stat buf;
+
+ if (stat(filename, &buf) == -1)
+ return(0);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if (!(buf.st_mode & _S_IFREG))
+ return(0);
+#else
+ if (!S_ISREG(buf.st_mode))
+ return(0);
+#endif
+
+ return(1);
+}
+
+static int compareFiles(const char *r1, const char *r2) {
+ int res1, res2;
+ int fd1, fd2;
+ char bytes1[4096];
+ char bytes2[4096];
+
+ fd1 = open(r1, RD_FLAGS);
+ if (fd1 < 0)
+ return(-1);
+ fd2 = open(r2, RD_FLAGS);
+ if (fd2 < 0) {
+ close(fd1);
+ return(-1);
+ }
+ while (1) {
+ res1 = read(fd1, bytes1, 4096);
+ res2 = read(fd2, bytes2, 4096);
+ if (res1 != res2) {
+ close(fd1);
+ close(fd2);
+ return(1);
+ }
+ if (res1 == 0)
+ break;
+ if (memcmp(bytes1, bytes2, res1) != 0) {
+ close(fd1);
+ close(fd2);
+ return(1);
+ }
+ }
+ close(fd1);
+ close(fd2);
+ return(0);
+}
+
+static int compareFileMem(const char *filename, const char *mem, int size) {
+ int res;
+ int fd;
+ char bytes[4096];
+ int idx = 0;
+ struct stat info;
+
+ if (stat(filename, &info) < 0)
+ return(-1);
+ if (info.st_size != size)
+ return(-1);
+ fd = open(filename, RD_FLAGS);
+ if (fd < 0)
+ return(-1);
+ while (idx < size) {
+ res = read(fd, bytes, 4096);
+ if (res <= 0)
+ break;
+ if (res + idx > size)
+ break;
+ if (memcmp(bytes, &mem[idx], res) != 0) {
+ int ix;
+ for (ix=0; ix<res; ix++)
+ if (bytes[ix] != mem[idx+ix])
+ break;
+ fprintf(stderr,"Compare error at position %d\n", idx+ix);
+ close(fd);
+ return(1);
+ }
+ idx += res;
+ }
+ close(fd);
+ return(idx != size);
+}
+
+static int loadMem(const char *filename, const char **mem, int *size) {
+ int fd, res;
+ struct stat info;
+ char *base;
+ int siz = 0;
+ if (stat(filename, &info) < 0)
+ return(-1);
+ base = malloc(info.st_size + 1);
+ if (base == NULL)
+ return(-1);
+ if ((fd = open(filename, RD_FLAGS)) < 0) {
+ free(base);
+ return(-1);
+ }
+ while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
+ siz += res;
+ }
+ close(fd);
+#if !defined(_WIN32)
+ if (siz != info.st_size) {
+ free(base);
+ return(-1);
+ }
+#endif
+ base[siz] = 0;
+ *mem = base;
+ *size = siz;
+ return(0);
+}
+
+static int unloadMem(const char *mem) {
+ free((char *)mem);
+ return(0);
+}
+
+/************************************************************************
+ * *
+ * Tests implementations *
+ * *
+ ************************************************************************/
+
+/************************************************************************
+ * *
+ * Parse to SAX based tests *
+ * *
+ ************************************************************************/
+
+FILE *SAXdebug = NULL;
+
+/*
+ * empty SAX block
+ */
+xmlSAXHandler emptySAXHandlerStruct = {
+ NULL, /* internalSubset */
+ NULL, /* isStandalone */
+ NULL, /* hasInternalSubset */
+ NULL, /* hasExternalSubset */
+ NULL, /* resolveEntity */
+ NULL, /* getEntity */
+ NULL, /* entityDecl */
+ NULL, /* notationDecl */
+ NULL, /* attributeDecl */
+ NULL, /* elementDecl */
+ NULL, /* unparsedEntityDecl */
+ NULL, /* setDocumentLocator */
+ NULL, /* startDocument */
+ NULL, /* endDocument */
+ NULL, /* startElement */
+ NULL, /* endElement */
+ NULL, /* reference */
+ NULL, /* characters */
+ NULL, /* ignorableWhitespace */
+ NULL, /* processingInstruction */
+ NULL, /* comment */
+ NULL, /* xmlParserWarning */
+ NULL, /* xmlParserError */
+ NULL, /* xmlParserError */
+ NULL, /* getParameterEntity */
+ NULL, /* cdataBlock; */
+ NULL, /* externalSubset; */
+ 1,
+ NULL,
+ NULL, /* startElementNs */
+ NULL, /* endElementNs */
+ NULL /* xmlStructuredErrorFunc */
+};
+
+static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
+int callbacks = 0;
+int quiet = 0;
+
+/**
+ * isStandaloneDebug:
+ * @ctxt: An XML parser context
+ *
+ * Is this document tagged standalone ?
+ *
+ * Returns 1 if true
+ */
+static int
+isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+ callbacks++;
+ if (quiet)
+ return(0);
+ fprintf(SAXdebug, "SAX.isStandalone()\n");
+ return(0);
+}
+
+/**
+ * hasInternalSubsetDebug:
+ * @ctxt: An XML parser context
+ *
+ * Does this document has an internal subset
+ *
+ * Returns 1 if true
+ */
+static int
+hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+ callbacks++;
+ if (quiet)
+ return(0);
+ fprintf(SAXdebug, "SAX.hasInternalSubset()\n");
+ return(0);
+}
+
+/**
+ * hasExternalSubsetDebug:
+ * @ctxt: An XML parser context
+ *
+ * Does this document has an external subset
+ *
+ * Returns 1 if true
+ */
+static int
+hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+ callbacks++;
+ if (quiet)
+ return(0);
+ fprintf(SAXdebug, "SAX.hasExternalSubset()\n");
+ return(0);
+}
+
+/**
+ * internalSubsetDebug:
+ * @ctxt: An XML parser context
+ *
+ * Does this document has an internal subset
+ */
+static void
+internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+ const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
+ if (ExternalID == NULL)
+ fprintf(SAXdebug, " ,");
+ else
+ fprintf(SAXdebug, " %s,", ExternalID);
+ if (SystemID == NULL)
+ fprintf(SAXdebug, " )\n");
+ else
+ fprintf(SAXdebug, " %s)\n", SystemID);
+}
+
+/**
+ * externalSubsetDebug:
+ * @ctxt: An XML parser context
+ *
+ * Does this document has an external subset
+ */
+static void
+externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+ const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
+ if (ExternalID == NULL)
+ fprintf(SAXdebug, " ,");
+ else
+ fprintf(SAXdebug, " %s,", ExternalID);
+ if (SystemID == NULL)
+ fprintf(SAXdebug, " )\n");
+ else
+ fprintf(SAXdebug, " %s)\n", SystemID);
+}
+
+/**
+ * resolveEntityDebug:
+ * @ctxt: An XML parser context
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * Special entity resolver, better left to the parser, it has
+ * more context than the application layer.
+ * The default behaviour is to NOT resolve the entities, in that case
+ * the ENTITY_REF nodes are built in the structure (and the parameter
+ * values).
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+static xmlParserInputPtr
+resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
+{
+ callbacks++;
+ if (quiet)
+ return(NULL);
+ /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
+
+
+ fprintf(SAXdebug, "SAX.resolveEntity(");
+ if (publicId != NULL)
+ fprintf(SAXdebug, "%s", (char *)publicId);
+ else
+ fprintf(SAXdebug, " ");
+ if (systemId != NULL)
+ fprintf(SAXdebug, ", %s)\n", (char *)systemId);
+ else
+ fprintf(SAXdebug, ", )\n");
+/*********
+ if (systemId != NULL) {
+ return(xmlNewInputFromFile(ctxt, (char *) systemId));
+ }
+ *********/
+ return(NULL);
+}
+
+/**
+ * getEntityDebug:
+ * @ctxt: An XML parser context
+ * @name: The entity name
+ *
+ * Get an entity by name
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+static xmlEntityPtr
+getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+ callbacks++;
+ if (quiet)
+ return(NULL);
+ fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
+ return(NULL);
+}
+
+/**
+ * getParameterEntityDebug:
+ * @ctxt: An XML parser context
+ * @name: The entity name
+ *
+ * Get a parameter entity by name
+ *
+ * Returns the xmlParserInputPtr
+ */
+static xmlEntityPtr
+getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+ callbacks++;
+ if (quiet)
+ return(NULL);
+ fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
+ return(NULL);
+}
+
+
+/**
+ * entityDeclDebug:
+ * @ctxt: An XML parser context
+ * @name: the entity name
+ * @type: the entity type
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @content: the entity value (without processing).
+ *
+ * An entity definition has been parsed
+ */
+static void
+entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
+ const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
+{
+const xmlChar *nullstr = BAD_CAST "(null)";
+ /* not all libraries handle printing null pointers nicely */
+ if (publicId == NULL)
+ publicId = nullstr;
+ if (systemId == NULL)
+ systemId = nullstr;
+ if (content == NULL)
+ content = (xmlChar *)nullstr;
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
+ name, type, publicId, systemId, content);
+}
+
+/**
+ * attributeDeclDebug:
+ * @ctxt: An XML parser context
+ * @name: the attribute name
+ * @type: the attribute type
+ *
+ * An attribute definition has been parsed
+ */
+static void
+attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
+ const xmlChar * name, int type, int def,
+ const xmlChar * defaultValue, xmlEnumerationPtr tree)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ if (defaultValue == NULL)
+ fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
+ elem, name, type, def);
+ else
+ fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
+ elem, name, type, def, defaultValue);
+ xmlFreeEnumeration(tree);
+}
+
+/**
+ * elementDeclDebug:
+ * @ctxt: An XML parser context
+ * @name: the element name
+ * @type: the element type
+ * @content: the element value (without processing).
+ *
+ * An element definition has been parsed
+ */
+static void
+elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
+ xmlElementContentPtr content ATTRIBUTE_UNUSED)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n",
+ name, type);
+}
+
+/**
+ * notationDeclDebug:
+ * @ctxt: An XML parser context
+ * @name: The name of the notation
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * What to do when a notation declaration has been parsed.
+ */
+static void
+notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+ const xmlChar *publicId, const xmlChar *systemId)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n",
+ (char *) name, (char *) publicId, (char *) systemId);
+}
+
+/**
+ * unparsedEntityDeclDebug:
+ * @ctxt: An XML parser context
+ * @name: The name of the entity
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @notationName: the name of the notation
+ *
+ * What to do when an unparsed entity declaration is parsed
+ */
+static void
+unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
+ const xmlChar *publicId, const xmlChar *systemId,
+ const xmlChar *notationName)
+{
+const xmlChar *nullstr = BAD_CAST "(null)";
+
+ if (publicId == NULL)
+ publicId = nullstr;
+ if (systemId == NULL)
+ systemId = nullstr;
+ if (notationName == NULL)
+ notationName = nullstr;
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
+ (char *) name, (char *) publicId, (char *) systemId,
+ (char *) notationName);
+}
+
+/**
+ * setDocumentLocatorDebug:
+ * @ctxt: An XML parser context
+ * @loc: A SAX Locator
+ *
+ * Receive the document locator at startup, actually xmlDefaultSAXLocator
+ * Everything is available on the context, so this is useless in our case.
+ */
+static void
+setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.setDocumentLocator()\n");
+}
+
+/**
+ * startDocumentDebug:
+ * @ctxt: An XML parser context
+ *
+ * called when the document start being processed.
+ */
+static void
+startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.startDocument()\n");
+}
+
+/**
+ * endDocumentDebug:
+ * @ctxt: An XML parser context
+ *
+ * called when the document end has been detected.
+ */
+static void
+endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.endDocument()\n");
+}
+
+/**
+ * startElementDebug:
+ * @ctxt: An XML parser context
+ * @name: The element name
+ *
+ * called when an opening tag has been processed.
+ */
+static void
+startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
+{
+ int i;
+
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
+ if (atts != NULL) {
+ for (i = 0;(atts[i] != NULL);i++) {
+ fprintf(SAXdebug, ", %s='", atts[i++]);
+ if (atts[i] != NULL)
+ fprintf(SAXdebug, "%s'", atts[i]);
+ }
+ }
+ fprintf(SAXdebug, ")\n");
+}
+
+/**
+ * endElementDebug:
+ * @ctxt: An XML parser context
+ * @name: The element name
+ *
+ * called when the end of an element has been detected.
+ */
+static void
+endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name);
+}
+
+/**
+ * charactersDebug:
+ * @ctxt: An XML parser context
+ * @ch: a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some chars from the parser.
+ * Question: how much at a time ???
+ */
+static void
+charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+ char output[40];
+ int i;
+
+ callbacks++;
+ if (quiet)
+ return;
+ for (i = 0;(i<len) && (i < 30);i++)
+ output[i] = ch[i];
+ output[i] = 0;
+
+ fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
+}
+
+/**
+ * referenceDebug:
+ * @ctxt: An XML parser context
+ * @name: The entity name
+ *
+ * called when an entity reference is detected.
+ */
+static void
+referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.reference(%s)\n", name);
+}
+
+/**
+ * ignorableWhitespaceDebug:
+ * @ctxt: An XML parser context
+ * @ch: a xmlChar string
+ * @start: the first char in the string
+ * @len: the number of xmlChar
+ *
+ * receiving some ignorable whitespaces from the parser.
+ * Question: how much at a time ???
+ */
+static void
+ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+ char output[40];
+ int i;
+
+ callbacks++;
+ if (quiet)
+ return;
+ for (i = 0;(i<len) && (i < 30);i++)
+ output[i] = ch[i];
+ output[i] = 0;
+ fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
+}
+
+/**
+ * processingInstructionDebug:
+ * @ctxt: An XML parser context
+ * @target: the target name
+ * @data: the PI data's
+ * @len: the number of xmlChar
+ *
+ * A processing instruction has been parsed.
+ */
+static void
+processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
+ const xmlChar *data)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ if (data != NULL)
+ fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
+ (char *) target, (char *) data);
+ else
+ fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n",
+ (char *) target);
+}
+
+/**
+ * cdataBlockDebug:
+ * @ctx: the user data (XML parser context)
+ * @value: The pcdata content
+ * @len: the block length
+ *
+ * called when a pcdata block has been parsed
+ */
+static void
+cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n",
+ (char *) value, len);
+}
+
+/**
+ * commentDebug:
+ * @ctxt: An XML parser context
+ * @value: the comment content
+ *
+ * A comment has been parsed.
+ */
+static void
+commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.comment(%s)\n", value);
+}
+
+/**
+ * warningDebug:
+ * @ctxt: An XML parser context
+ * @msg: the message to display/transmit
+ * @...: extra parameters for the message display
+ *
+ * Display and format a warning messages, gives file, line, position and
+ * extra parameters.
+ */
+static void
+warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
+{
+ va_list args;
+
+ callbacks++;
+ if (quiet)
+ return;
+ va_start(args, msg);
+ fprintf(SAXdebug, "SAX.warning: ");
+ vfprintf(SAXdebug, msg, args);
+ va_end(args);
+}
+
+/**
+ * errorDebug:
+ * @ctxt: An XML parser context
+ * @msg: the message to display/transmit
+ * @...: extra parameters for the message display
+ *
+ * Display and format a error messages, gives file, line, position and
+ * extra parameters.
+ */
+static void
+errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
+{
+ va_list args;
+
+ callbacks++;
+ if (quiet)
+ return;
+ va_start(args, msg);
+ fprintf(SAXdebug, "SAX.error: ");
+ vfprintf(SAXdebug, msg, args);
+ va_end(args);
+}
+
+/**
+ * fatalErrorDebug:
+ * @ctxt: An XML parser context
+ * @msg: the message to display/transmit
+ * @...: extra parameters for the message display
+ *
+ * Display and format a fatalError messages, gives file, line, position and
+ * extra parameters.
+ */
+static void
+fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
+{
+ va_list args;
+
+ callbacks++;
+ if (quiet)
+ return;
+ va_start(args, msg);
+ fprintf(SAXdebug, "SAX.fatalError: ");
+ vfprintf(SAXdebug, msg, args);
+ va_end(args);
+}
+
+xmlSAXHandler debugSAXHandlerStruct = {
+ internalSubsetDebug,
+ isStandaloneDebug,
+ hasInternalSubsetDebug,
+ hasExternalSubsetDebug,
+ resolveEntityDebug,
+ getEntityDebug,
+ entityDeclDebug,
+ notationDeclDebug,
+ attributeDeclDebug,
+ elementDeclDebug,
+ unparsedEntityDeclDebug,
+ setDocumentLocatorDebug,
+ startDocumentDebug,
+ endDocumentDebug,
+ startElementDebug,
+ endElementDebug,
+ referenceDebug,
+ charactersDebug,
+ ignorableWhitespaceDebug,
+ processingInstructionDebug,
+ commentDebug,
+ warningDebug,
+ errorDebug,
+ fatalErrorDebug,
+ getParameterEntityDebug,
+ cdataBlockDebug,
+ externalSubsetDebug,
+ 1,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
+
+/*
+ * SAX2 specific callbacks
+ */
+/**
+ * startElementNsDebug:
+ * @ctxt: An XML parser context
+ * @name: The element name
+ *
+ * called when an opening tag has been processed.
+ */
+static void
+startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
+ const xmlChar *localname,
+ const xmlChar *prefix,
+ const xmlChar *URI,
+ int nb_namespaces,
+ const xmlChar **namespaces,
+ int nb_attributes,
+ int nb_defaulted,
+ const xmlChar **attributes)
+{
+ int i;
+
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
+ if (prefix == NULL)
+ fprintf(SAXdebug, ", NULL");
+ else
+ fprintf(SAXdebug, ", %s", (char *) prefix);
+ if (URI == NULL)
+ fprintf(SAXdebug, ", NULL");
+ else
+ fprintf(SAXdebug, ", '%s'", (char *) URI);
+ fprintf(SAXdebug, ", %d", nb_namespaces);
+
+ if (namespaces != NULL) {
+ for (i = 0;i < nb_namespaces * 2;i++) {
+ fprintf(SAXdebug, ", xmlns");
+ if (namespaces[i] != NULL)
+ fprintf(SAXdebug, ":%s", namespaces[i]);
+ i++;
+ fprintf(SAXdebug, "='%s'", namespaces[i]);
+ }
+ }
+ fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
+ if (attributes != NULL) {
+ for (i = 0;i < nb_attributes * 5;i += 5) {
+ if (attributes[i + 1] != NULL)
+ fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
+ else
+ fprintf(SAXdebug, ", %s='", attributes[i]);
+ fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
+ (int)(attributes[i + 4] - attributes[i + 3]));
+ }
+ }
+ fprintf(SAXdebug, ")\n");
+}
+
+/**
+ * endElementDebug:
+ * @ctxt: An XML parser context
+ * @name: The element name
+ *
+ * called when the end of an element has been detected.
+ */
+static void
+endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
+ const xmlChar *localname,
+ const xmlChar *prefix,
+ const xmlChar *URI)
+{
+ callbacks++;
+ if (quiet)
+ return;
+ fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
+ if (prefix == NULL)
+ fprintf(SAXdebug, ", NULL");
+ else
+ fprintf(SAXdebug, ", %s", (char *) prefix);
+ if (URI == NULL)
+ fprintf(SAXdebug, ", NULL)\n");
+ else
+ fprintf(SAXdebug, ", '%s')\n", (char *) URI);
+}
+
+xmlSAXHandler debugSAX2HandlerStruct = {
+ internalSubsetDebug,
+ isStandaloneDebug,
+ hasInternalSubsetDebug,
+ hasExternalSubsetDebug,
+ resolveEntityDebug,
+ getEntityDebug,
+ entityDeclDebug,
+ notationDeclDebug,
+ attributeDeclDebug,
+ elementDeclDebug,
+ unparsedEntityDeclDebug,
+ setDocumentLocatorDebug,
+ startDocumentDebug,
+ endDocumentDebug,
+ NULL,
+ NULL,
+ referenceDebug,
+ charactersDebug,
+ ignorableWhitespaceDebug,
+ processingInstructionDebug,
+ commentDebug,
+ warningDebug,
+ errorDebug,
+ fatalErrorDebug,
+ getParameterEntityDebug,
+ cdataBlockDebug,
+ externalSubsetDebug,
+ XML_SAX2_MAGIC,
+ NULL,
+ startElementNsDebug,
+ endElementNsDebug,
+ NULL
+};
+
+xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
+
+#ifdef LIBXML_HTML_ENABLED
+/**
+ * htmlstartElementDebug:
+ * @ctxt: An XML parser context
+ * @name: The element name
+ *
+ * called when an opening tag has been processed.
+ */
+static void
+htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
+{
+ int i;
+
+ fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
+ if (atts != NULL) {
+ for (i = 0;(atts[i] != NULL);i++) {
+ fprintf(SAXdebug, ", %s", atts[i++]);
+ if (atts[i] != NULL) {
+ unsigned char output[40];
+ const unsigned char *att = atts[i];
+ int outlen, attlen;
+ fprintf(SAXdebug, "='");
+ while ((attlen = strlen((char*)att)) > 0) {
+ outlen = sizeof output - 1;
+ htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
+ output[outlen] = 0;
+ fprintf(SAXdebug, "%s", (char *) output);
+ att += attlen;
+ }
+ fprintf(SAXdebug, "'");
+ }
+ }
+ }
+ fprintf(SAXdebug, ")\n");
+}
+
+/**
+ * htmlcharactersDebug:
+ * @ctxt: An XML parser context
+ * @ch: a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some chars from the parser.
+ * Question: how much at a time ???
+ */
+static void
+htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+ unsigned char output[40];
+ int inlen = len, outlen = 30;
+
+ htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
+ output[outlen] = 0;
+
+ fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
+}
+
+/**
+ * htmlcdataDebug:
+ * @ctxt: An XML parser context
+ * @ch: a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some cdata chars from the parser.
+ * Question: how much at a time ???
+ */
+static void
+htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
+{
+ unsigned char output[40];
+ int inlen = len, outlen = 30;
+
+ htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
+ output[outlen] = 0;
+
+ fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
+}
+
+xmlSAXHandler debugHTMLSAXHandlerStruct = {
+ internalSubsetDebug,
+ isStandaloneDebug,
+ hasInternalSubsetDebug,
+ hasExternalSubsetDebug,
+ resolveEntityDebug,
+ getEntityDebug,
+ entityDeclDebug,
+ notationDeclDebug,
+ attributeDeclDebug,
+ elementDeclDebug,
+ unparsedEntityDeclDebug,
+ setDocumentLocatorDebug,
+ startDocumentDebug,
+ endDocumentDebug,
+ htmlstartElementDebug,
+ endElementDebug,
+ referenceDebug,
+ htmlcharactersDebug,
+ ignorableWhitespaceDebug,
+ processingInstructionDebug,
+ commentDebug,
+ warningDebug,
+ errorDebug,
+ fatalErrorDebug,
+ getParameterEntityDebug,
+ htmlcdataDebug,
+ externalSubsetDebug,
+ 1,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
+#endif /* LIBXML_HTML_ENABLED */
+
+#ifdef LIBXML_SAX1_ENABLED
+/**
+ * saxParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the SAX API and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+saxParseTest(const char *filename, const char *result,
+ const char *err ATTRIBUTE_UNUSED,
+ int options) {
+ int ret;
+ char *temp;
+
+ nb_tests++;
+ temp = resultFilename(filename, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "out of memory\n");
+ fatalError();
+ }
+ SAXdebug = fopen(temp, "wb");
+ if (SAXdebug == NULL) {
+ fprintf(stderr, "Failed to write to %s\n", temp);
+ free(temp);
+ return(-1);
+ }
+
+ /* for SAX we really want the callbacks though the context handlers */
+ xmlSetStructuredErrorFunc(NULL, NULL);
+ xmlSetGenericErrorFunc(NULL, testErrorHandler);
+
+#ifdef LIBXML_HTML_ENABLED
+ if (options & XML_PARSE_HTML) {
+ htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);
+ ret = 0;
+ } else
+#endif
+ ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
+ if (ret == XML_WAR_UNDECLARED_ENTITY) {
+ fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
+ ret = 0;
+ }
+ if (ret != 0) {
+ fprintf(stderr, "Failed to parse %s\n", filename);
+ return(1);
+ }
+#ifdef LIBXML_HTML_ENABLED
+ if (options & XML_PARSE_HTML) {
+ htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
+ ret = 0;
+ } else
+#endif
+ if (options & XML_PARSE_SAX1) {
+ ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
+ } else {
+ ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
+ }
+ if (ret == XML_WAR_UNDECLARED_ENTITY) {
+ fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
+ ret = 0;
+ }
+ fclose(SAXdebug);
+ if (compareFiles(temp, result)) {
+ fprintf(stderr, "Got a difference for %s\n", filename);
+ ret = 1;
+ } else
+ unlink(temp);
+ free(temp);
+
+ /* switch back to structured error handling */
+ xmlSetGenericErrorFunc(NULL, NULL);
+ xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
+
+ return(ret);
+}
+#endif
+
+/************************************************************************
+ * *
+ * Parse to tree based tests *
+ * *
+ ************************************************************************/
+/**
+ * oldParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file using the old xmlParseFile API, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+oldParseTest(const char *filename, const char *result,
+ const char *err ATTRIBUTE_UNUSED,
+ int options ATTRIBUTE_UNUSED) {
+ xmlDocPtr doc;
+ char *temp;
+ int res = 0;
+
+ nb_tests++;
+ /*
+ * base of the test, parse with the old API
+ */
+#ifdef LIBXML_SAX1_ENABLED
+ doc = xmlParseFile(filename);
+#else
+ doc = xmlReadFile(filename, NULL, 0);
+#endif
+ if (doc == NULL)
+ return(1);
+ temp = resultFilename(filename, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "out of memory\n");
+ fatalError();
+ }
+ xmlSaveFile(temp, doc);
+ if (compareFiles(temp, result)) {
+ res = 1;
+ }
+ xmlFreeDoc(doc);
+
+ /*
+ * Parse the saved result to make sure the round trip is okay
+ */
+#ifdef LIBXML_SAX1_ENABLED
+ doc = xmlParseFile(temp);
+#else
+ doc = xmlReadFile(temp, NULL, 0);
+#endif
+ if (doc == NULL)
+ return(1);
+ xmlSaveFile(temp, doc);
+ if (compareFiles(temp, result)) {
+ res = 1;
+ }
+ xmlFreeDoc(doc);
+
+ unlink(temp);
+ free(temp);
+ return(res);
+}
+
+#ifdef LIBXML_PUSH_ENABLED
+/**
+ * pushParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file using the Push API, then serialize back
+ * to check for content.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+pushParseTest(const char *filename, const char *result,
+ const char *err ATTRIBUTE_UNUSED,
+ int options) {
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr doc;
+ const char *base;
+ int size, res;
+ int cur = 0;
+
+ nb_tests++;
+ /*
+ * load the document in memory and work from there.
+ */
+ if (loadMem(filename, &base, &size) != 0) {
+ fprintf(stderr, "Failed to load %s\n", filename);
+ return(-1);
+ }
+
+#ifdef LIBXML_HTML_ENABLED
+ if (options & XML_PARSE_HTML)
+ ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,
+ XML_CHAR_ENCODING_NONE);
+ else
+#endif
+ ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
+ xmlCtxtUseOptions(ctxt, options);
+ cur += 4;
+ while (cur < size) {
+ if (cur + 1024 >= size) {
+#ifdef LIBXML_HTML_ENABLED
+ if (options & XML_PARSE_HTML)
+ htmlParseChunk(ctxt, base + cur, size - cur, 1);
+ else
+#endif
+ xmlParseChunk(ctxt, base + cur, size - cur, 1);
+ break;
+ } else {
+#ifdef LIBXML_HTML_ENABLED
+ if (options & XML_PARSE_HTML)
+ htmlParseChunk(ctxt, base + cur, 1024, 0);
+ else
+#endif
+ xmlParseChunk(ctxt, base + cur, 1024, 0);
+ cur += 1024;
+ }
+ }
+ doc = ctxt->myDoc;
+#ifdef LIBXML_HTML_ENABLED
+ if (options & XML_PARSE_HTML)
+ res = 1;
+ else
+#endif
+ res = ctxt->wellFormed;
+ xmlFreeParserCtxt(ctxt);
+ free((char *)base);
+ if (!res) {
+ xmlFreeDoc(doc);
+ fprintf(stderr, "Failed to parse %s\n", filename);
+ return(-1);
+ }
+#ifdef LIBXML_HTML_ENABLED
+ if (options & XML_PARSE_HTML)
+ htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+ else
+#endif
+ xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+ xmlFreeDoc(doc);
+ res = compareFileMem(result, base, size);
+ if ((base == NULL) || (res != 0)) {
+ if (base != NULL)
+ xmlFree((char *)base);
+ fprintf(stderr, "Result for %s failed\n", filename);
+ return(-1);
+ }
+ xmlFree((char *)base);
+ if (err != NULL) {
+ res = compareFileMem(err, testErrors, testErrorsSize);
+ if (res != 0) {
+ fprintf(stderr, "Error for %s failed\n", filename);
+ return(-1);
+ }
+ }
+ return(0);
+}
+#endif
+
+/**
+ * memParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file using the old xmlReadMemory API, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+memParseTest(const char *filename, const char *result,
+ const char *err ATTRIBUTE_UNUSED,
+ int options ATTRIBUTE_UNUSED) {
+ xmlDocPtr doc;
+ const char *base;
+ int size, res;
+
+ nb_tests++;
+ /*
+ * load and parse the memory
+ */
+ if (loadMem(filename, &base, &size) != 0) {
+ fprintf(stderr, "Failed to load %s\n", filename);
+ return(-1);
+ }
+
+ doc = xmlReadMemory(base, size, filename, NULL, 0);
+ unloadMem(base);
+ if (doc == NULL) {
+ return(1);
+ }
+ xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+ xmlFreeDoc(doc);
+ res = compareFileMem(result, base, size);
+ if ((base == NULL) || (res != 0)) {
+ if (base != NULL)
+ xmlFree((char *)base);
+ fprintf(stderr, "Result for %s failed\n", filename);
+ return(-1);
+ }
+ xmlFree((char *)base);
+ return(0);
+}
+
+/**
+ * noentParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages: unused
+ *
+ * Parse a file with entity resolution, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+noentParseTest(const char *filename, const char *result,
+ const char *err ATTRIBUTE_UNUSED,
+ int options) {
+ xmlDocPtr doc;
+ char *temp;
+ int res = 0;
+
+ nb_tests++;
+ /*
+ * base of the test, parse with the old API
+ */
+ doc = xmlReadFile(filename, NULL, options);
+ if (doc == NULL)
+ return(1);
+ temp = resultFilename(filename, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ fatalError();
+ }
+ xmlSaveFile(temp, doc);
+ if (compareFiles(temp, result)) {
+ res = 1;
+ }
+ xmlFreeDoc(doc);
+
+ /*
+ * Parse the saved result to make sure the round trip is okay
+ */
+ doc = xmlReadFile(filename, NULL, options);
+ if (doc == NULL)
+ return(1);
+ xmlSaveFile(temp, doc);
+ if (compareFiles(temp, result)) {
+ res = 1;
+ }
+ xmlFreeDoc(doc);
+
+ unlink(temp);
+ free(temp);
+ return(res);
+}
+
+/**
+ * errParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the xmlReadFile API and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+errParseTest(const char *filename, const char *result, const char *err,
+ int options) {
+ xmlDocPtr doc;
+ const char *base = NULL;
+ int size, res = 0;
+
+ nb_tests++;
+#ifdef LIBXML_HTML_ENABLED
+ if (options & XML_PARSE_HTML) {
+ doc = htmlReadFile(filename, NULL, options);
+ } else
+#endif
+#ifdef LIBXML_XINCLUDE_ENABLED
+ if (options & XML_PARSE_XINCLUDE) {
+ doc = xmlReadFile(filename, NULL, options);
+ xmlXIncludeProcessFlags(doc, options);
+ } else
+#endif
+ {
+ xmlGetWarningsDefaultValue = 1;
+ doc = xmlReadFile(filename, NULL, options);
+ }
+ xmlGetWarningsDefaultValue = 0;
+ if (result) {
+ if (doc == NULL) {
+ base = "";
+ size = 0;
+ } else {
+#ifdef LIBXML_HTML_ENABLED
+ if (options & XML_PARSE_HTML) {
+ htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+ } else
+#endif
+ xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
+ }
+ res = compareFileMem(result, base, size);
+ }
+ if (doc != NULL) {
+ if (base != NULL)
+ xmlFree((char *)base);
+ xmlFreeDoc(doc);
+ }
+ if (res != 0) {
+ fprintf(stderr, "Result for %s failed\n", filename);
+ return(-1);
+ }
+ if (err != NULL) {
+ res = compareFileMem(err, testErrors, testErrorsSize);
+ if (res != 0) {
+ fprintf(stderr, "Error for %s failed\n", filename);
+ return(-1);
+ }
+ } else if (options & XML_PARSE_DTDVALID) {
+ if (testErrorsSize != 0)
+ fprintf(stderr, "Validation for %s failed\n", filename);
+ }
+
+ return(0);
+}
+
+#ifdef LIBXML_READER_ENABLED
+/************************************************************************
+ * *
+ * Reader based tests *
+ * *
+ ************************************************************************/
+
+static void processNode(FILE *out, xmlTextReaderPtr reader) {
+ const xmlChar *name, *value;
+ int type, empty;
+
+ type = xmlTextReaderNodeType(reader);
+ empty = xmlTextReaderIsEmptyElement(reader);
+
+ name = xmlTextReaderConstName(reader);
+ if (name == NULL)
+ name = BAD_CAST "--";
+
+ value = xmlTextReaderConstValue(reader);
+
+
+ fprintf(out, "%d %d %s %d %d",
+ xmlTextReaderDepth(reader),
+ type,
+ name,
+ empty,
+ xmlTextReaderHasValue(reader));
+ if (value == NULL)
+ fprintf(out, "\n");
+ else {
+ fprintf(out, " %s\n", value);
+ }
+}
+static int
+streamProcessTest(const char *filename, const char *result, const char *err,
+ xmlTextReaderPtr reader, const char *rng) {
+ int ret;
+ char *temp = NULL;
+ FILE *t = NULL;
+
+ if (reader == NULL)
+ return(-1);
+
+ nb_tests++;
+ if (result != NULL) {
+ temp = resultFilename(filename, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ fatalError();
+ }
+ t = fopen(temp, "wb");
+ if (t == NULL) {
+ fprintf(stderr, "Can't open temp file %s\n", temp);
+ free(temp);
+ return(-1);
+ }
+ }
+#ifdef LIBXML_SCHEMAS_ENABLED
+ if (rng != NULL) {
+ ret = xmlTextReaderRelaxNGValidate(reader, rng);
+ if (ret < 0) {
+ testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
+ rng);
+ fclose(t);
+ unlink(temp);
+ free(temp);
+ return(0);
+ }
+ }
+#endif
+ xmlGetWarningsDefaultValue = 1;
+ ret = xmlTextReaderRead(reader);
+ while (ret == 1) {
+ if ((t != NULL) && (rng == NULL))
+ processNode(t, reader);
+ ret = xmlTextReaderRead(reader);
+ }
+ if (ret != 0) {
+ testErrorHandler(NULL, "%s : failed to parse\n", filename);
+ }
+ if (rng != NULL) {
+ if (xmlTextReaderIsValid(reader) != 1) {
+ testErrorHandler(NULL, "%s fails to validate\n", filename);
+ } else {
+ testErrorHandler(NULL, "%s validates\n", filename);
+ }
+ }
+ xmlGetWarningsDefaultValue = 0;
+ if (t != NULL) {
+ fclose(t);
+ ret = compareFiles(temp, result);
+ unlink(temp);
+ free(temp);
+ if (ret) {
+ fprintf(stderr, "Result for %s failed\n", filename);
+ return(-1);
+ }
+ }
+ if (err != NULL) {
+ ret = compareFileMem(err, testErrors, testErrorsSize);
+ if (ret != 0) {
+ fprintf(stderr, "Error for %s failed\n", filename);
+ printf("%s", testErrors);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+/**
+ * streamParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the reader API and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+streamParseTest(const char *filename, const char *result, const char *err,
+ int options) {
+ xmlTextReaderPtr reader;
+ int ret;
+
+ reader = xmlReaderForFile(filename, NULL, options);
+ ret = streamProcessTest(filename, result, err, reader, NULL);
+ xmlFreeTextReader(reader);
+ return(ret);
+}
+
+/**
+ * walkerParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the walker, i.e. a reader built from a atree.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+walkerParseTest(const char *filename, const char *result, const char *err,
+ int options) {
+ xmlDocPtr doc;
+ xmlTextReaderPtr reader;
+ int ret;
+
+ doc = xmlReadFile(filename, NULL, options);
+ if (doc == NULL) {
+ fprintf(stderr, "Failed to parse %s\n", filename);
+ return(-1);
+ }
+ reader = xmlReaderWalker(doc);
+ ret = streamProcessTest(filename, result, err, reader, NULL);
+ xmlFreeTextReader(reader);
+ xmlFreeDoc(doc);
+ return(ret);
+}
+
+/**
+ * streamMemParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file using the reader API from memory and check for errors.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+streamMemParseTest(const char *filename, const char *result, const char *err,
+ int options) {
+ xmlTextReaderPtr reader;
+ int ret;
+ const char *base;
+ int size;
+
+ /*
+ * load and parse the memory
+ */
+ if (loadMem(filename, &base, &size) != 0) {
+ fprintf(stderr, "Failed to load %s\n", filename);
+ return(-1);
+ }
+ reader = xmlReaderForMemory(base, size, filename, NULL, options);
+ ret = streamProcessTest(filename, result, err, reader, NULL);
+ free((char *)base);
+ xmlFreeTextReader(reader);
+ return(ret);
+}
+#endif
+
+#ifdef LIBXML_XPATH_ENABLED
+#ifdef LIBXML_DEBUG_ENABLED
+/************************************************************************
+ * *
+ * XPath and XPointer based tests *
+ * *
+ ************************************************************************/
+
+FILE *xpathOutput;
+xmlDocPtr xpathDocument;
+
+static void
+testXPath(const char *str, int xptr, int expr) {
+ xmlXPathObjectPtr res;
+ xmlXPathContextPtr ctxt;
+
+ nb_tests++;
+#if defined(LIBXML_XPTR_ENABLED)
+ if (xptr) {
+ ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
+ res = xmlXPtrEval(BAD_CAST str, ctxt);
+ } else {
+#endif
+ ctxt = xmlXPathNewContext(xpathDocument);
+ ctxt->node = xmlDocGetRootElement(xpathDocument);
+ if (expr)
+ res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
+ else {
+ /* res = xmlXPathEval(BAD_CAST str, ctxt); */
+ xmlXPathCompExprPtr comp;
+
+ comp = xmlXPathCompile(BAD_CAST str);
+ if (comp != NULL) {
+ res = xmlXPathCompiledEval(comp, ctxt);
+ xmlXPathFreeCompExpr(comp);
+ } else
+ res = NULL;
+ }
+#if defined(LIBXML_XPTR_ENABLED)
+ }
+#endif
+ xmlXPathDebugDumpObject(xpathOutput, res, 0);
+ xmlXPathFreeObject(res);
+ xmlXPathFreeContext(ctxt);
+}
+
+/**
+ * xpathExprTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath standalone expressions and evaluate them
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xpathCommonTest(const char *filename, const char *result,
+ int xptr, int expr) {
+ FILE *input;
+ char expression[5000];
+ int len, ret = 0;
+ char *temp;
+
+ temp = resultFilename(filename, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ fatalError();
+ }
+ xpathOutput = fopen(temp, "wb");
+ if (xpathOutput == NULL) {
+ fprintf(stderr, "failed to open output file %s\n", temp);
+ free(temp);
+ return(-1);
+ }
+
+ input = fopen(filename, "rb");
+ if (input == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Cannot open %s for reading\n", filename);
+ free(temp);
+ return(-1);
+ }
+ while (fgets(expression, 4500, input) != NULL) {
+ len = strlen(expression);
+ len--;
+ while ((len >= 0) &&
+ ((expression[len] == '\n') || (expression[len] == '\t') ||
+ (expression[len] == '\r') || (expression[len] == ' '))) len--;
+ expression[len + 1] = 0;
+ if (len >= 0) {
+ fprintf(xpathOutput,
+ "\n========================\nExpression: %s\n",
+ expression) ;
+ testXPath(expression, xptr, expr);
+ }
+ }
+
+ fclose(input);
+ fclose(xpathOutput);
+ if (result != NULL) {
+ ret = compareFiles(temp, result);
+ if (ret) {
+ fprintf(stderr, "Result for %s failed\n", filename);
+ }
+ }
+
+ unlink(temp);
+ free(temp);
+ return(ret);
+}
+
+/**
+ * xpathExprTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath standalone expressions and evaluate them
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xpathExprTest(const char *filename, const char *result,
+ const char *err ATTRIBUTE_UNUSED,
+ int options ATTRIBUTE_UNUSED) {
+ return(xpathCommonTest(filename, result, 0, 1));
+}
+
+/**
+ * xpathDocTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath expressions and evaluate them against
+ * a set of corresponding documents.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xpathDocTest(const char *filename,
+ const char *resul ATTRIBUTE_UNUSED,
+ const char *err ATTRIBUTE_UNUSED,
+ int options) {
+
+ char pattern[500];
+ char result[500];
+ glob_t globbuf;
+ size_t i;
+ int ret = 0, res;
+
+ xpathDocument = xmlReadFile(filename, NULL,
+ options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
+ if (xpathDocument == NULL) {
+ fprintf(stderr, "Failed to load %s\n", filename);
+ return(-1);
+ }
+
+ snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
+ pattern[499] = 0;
+ globbuf.gl_offs = 0;
+ glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+ for (i = 0;i < globbuf.gl_pathc;i++) {
+ snprintf(result, 499, "result/XPath/tests/%s",
+ baseFilename(globbuf.gl_pathv[i]));
+ res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
+ if (res != 0)
+ ret = res;
+ }
+ globfree(&globbuf);
+
+ xmlFreeDoc(xpathDocument);
+ return(ret);
+}
+
+#ifdef LIBXML_XPTR_ENABLED
+/**
+ * xptrDocTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing XPath expressions and evaluate them against
+ * a set of corresponding documents.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xptrDocTest(const char *filename,
+ const char *resul ATTRIBUTE_UNUSED,
+ const char *err ATTRIBUTE_UNUSED,
+ int options) {
+
+ char pattern[500];
+ char result[500];
+ glob_t globbuf;
+ size_t i;
+ int ret = 0, res;
+
+ xpathDocument = xmlReadFile(filename, NULL,
+ options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
+ if (xpathDocument == NULL) {
+ fprintf(stderr, "Failed to load %s\n", filename);
+ return(-1);
+ }
+
+ snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
+ pattern[499] = 0;
+ globbuf.gl_offs = 0;
+ glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+ for (i = 0;i < globbuf.gl_pathc;i++) {
+ snprintf(result, 499, "result/XPath/xptr/%s",
+ baseFilename(globbuf.gl_pathv[i]));
+ res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
+ if (res != 0)
+ ret = res;
+ }
+ globfree(&globbuf);
+
+ xmlFreeDoc(xpathDocument);
+ return(ret);
+}
+#endif /* LIBXML_XPTR_ENABLED */
+
+/**
+ * xmlidDocTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing xml:id and check for errors and verify
+ * that XPath queries will work on them as expected.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+xmlidDocTest(const char *filename,
+ const char *result,
+ const char *err,
+ int options) {
+
+ int res = 0;
+ int ret = 0;
+ char *temp;
+
+ xpathDocument = xmlReadFile(filename, NULL,
+ options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
+ if (xpathDocument == NULL) {
+ fprintf(stderr, "Failed to load %s\n", filename);
+ return(-1);
+ }
+
+ temp = resultFilename(filename, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ fatalError();
+ }
+ xpathOutput = fopen(temp, "wb");
+ if (xpathOutput == NULL) {
+ fprintf(stderr, "failed to open output file %s\n", temp);
+ xmlFreeDoc(xpathDocument);
+ free(temp);
+ return(-1);
+ }
+
+ testXPath("id('bar')", 0, 0);
+
+ fclose(xpathOutput);
+ if (result != NULL) {
+ ret = compareFiles(temp, result);
+ if (ret) {
+ fprintf(stderr, "Result for %s failed\n", filename);
+ res = 1;
+ }
+ }
+
+ unlink(temp);
+ free(temp);
+ xmlFreeDoc(xpathDocument);
+
+ if (err != NULL) {
+ ret = compareFileMem(err, testErrors, testErrorsSize);
+ if (ret != 0) {
+ fprintf(stderr, "Error for %s failed\n", filename);
+ res = 1;
+ }
+ }
+ return(res);
+}
+
+#endif /* LIBXML_DEBUG_ENABLED */
+#endif /* XPATH */
+/************************************************************************
+ * *
+ * URI based tests *
+ * *
+ ************************************************************************/
+
+static void
+handleURI(const char *str, const char *base, FILE *o) {
+ int ret;
+ xmlURIPtr uri;
+ xmlChar *res = NULL, *parsed = NULL;
+
+ uri = xmlCreateURI();
+
+ if (base == NULL) {
+ ret = xmlParseURIReference(uri, str);
+ if (ret != 0)
+ fprintf(o, "%s : error %d\n", str, ret);
+ else {
+ xmlNormalizeURIPath(uri->path);
+ xmlPrintURI(o, uri);
+ fprintf(o, "\n");
+ }
+ } else {
+ res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
+ if (res != NULL) {
+ fprintf(o, "%s\n", (char *) res);
+ }
+ else
+ fprintf(o, "::ERROR::\n");
+ }
+ if (res != NULL)
+ xmlFree(res);
+ if (parsed != NULL)
+ xmlFree(parsed);
+ xmlFreeURI(uri);
+}
+
+/**
+ * uriCommonTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI and check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+uriCommonTest(const char *filename,
+ const char *result,
+ const char *err,
+ const char *base) {
+ char *temp;
+ FILE *o, *f;
+ char str[1024];
+ int res = 0, i, ret;
+
+ temp = resultFilename(filename, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ fatalError();
+ }
+ o = fopen(temp, "wb");
+ if (o == NULL) {
+ fprintf(stderr, "failed to open output file %s\n", temp);
+ free(temp);
+ return(-1);
+ }
+ f = fopen(filename, "rb");
+ if (f == NULL) {
+ fprintf(stderr, "failed to open input file %s\n", filename);
+ fclose(o);
+ unlink(temp);
+ free(temp);
+ return(-1);
+ }
+
+ while (1) {
+ /*
+ * read one line in string buffer.
+ */
+ if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
+ break;
+
+ /*
+ * remove the ending spaces
+ */
+ i = strlen(str);
+ while ((i > 0) &&
+ ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
+ (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
+ i--;
+ str[i] = 0;
+ }
+ nb_tests++;
+ handleURI(str, base, o);
+ }
+
+ fclose(f);
+ fclose(o);
+
+ if (result != NULL) {
+ ret = compareFiles(temp, result);
+ if (ret) {
+ fprintf(stderr, "Result for %s failed\n", filename);
+ res = 1;
+ }
+ }
+ if (err != NULL) {
+ ret = compareFileMem(err, testErrors, testErrorsSize);
+ if (ret != 0) {
+ fprintf(stderr, "Error for %s failed\n", filename);
+ res = 1;
+ }
+ }
+
+ unlink(temp);
+ free(temp);
+ return(res);
+}
+
+/**
+ * uriParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI and check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+uriParseTest(const char *filename,
+ const char *result,
+ const char *err,
+ int options ATTRIBUTE_UNUSED) {
+ return(uriCommonTest(filename, result, err, NULL));
+}
+
+/**
+ * uriBaseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI, compose them against a fixed base and
+ * check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+uriBaseTest(const char *filename,
+ const char *result,
+ const char *err,
+ int options ATTRIBUTE_UNUSED) {
+ return(uriCommonTest(filename, result, err,
+ "http://foo.com/path/to/index.html?orig#help"));
+}
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+/************************************************************************
+ * *
+ * Schemas tests *
+ * *
+ ************************************************************************/
+static int
+schemasOneTest(const char *sch,
+ const char *filename,
+ const char *result,
+ const char *err,
+ int options,
+ xmlSchemaPtr schemas) {
+ xmlDocPtr doc;
+ xmlSchemaValidCtxtPtr ctxt;
+ int ret = 0;
+ char *temp;
+ FILE *schemasOutput;
+
+ doc = xmlReadFile(filename, NULL, options);
+ if (doc == NULL) {
+ fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
+ return(-1);
+ }
+
+ temp = resultFilename(result, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ fatalError();
+ }
+ schemasOutput = fopen(temp, "wb");
+ if (schemasOutput == NULL) {
+ fprintf(stderr, "failed to open output file %s\n", temp);
+ xmlFreeDoc(doc);
+ free(temp);
+ return(-1);
+ }
+
+ ctxt = xmlSchemaNewValidCtxt(schemas);
+ xmlSchemaSetValidErrors(ctxt,
+ (xmlSchemaValidityErrorFunc) testErrorHandler,
+ (xmlSchemaValidityWarningFunc) testErrorHandler,
+ ctxt);
+ ret = xmlSchemaValidateDoc(ctxt, doc);
+ if (ret == 0) {
+ fprintf(schemasOutput, "%s validates\n", filename);
+ } else if (ret > 0) {
+ fprintf(schemasOutput, "%s fails to validate\n", filename);
+ } else {
+ fprintf(schemasOutput, "%s validation generated an internal error\n",
+ filename);
+ }
+ fclose(schemasOutput);
+ if (result) {
+ if (compareFiles(temp, result)) {
+ fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
+ ret = 1;
+ }
+ }
+ unlink(temp);
+ free(temp);
+
+ if (err != NULL) {
+ if (compareFileMem(err, testErrors, testErrorsSize)) {
+ fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
+ ret = 1;
+ }
+ }
+
+
+ xmlSchemaFreeValidCtxt(ctxt);
+ xmlFreeDoc(doc);
+ return(ret);
+}
+/**
+ * schemasTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a file containing URI, compose them against a fixed base and
+ * check for errors
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+schemasTest(const char *filename,
+ const char *resul ATTRIBUTE_UNUSED,
+ const char *errr ATTRIBUTE_UNUSED,
+ int options) {
+ const char *base = baseFilename(filename);
+ const char *base2;
+ const char *instance;
+ xmlSchemaParserCtxtPtr ctxt;
+ xmlSchemaPtr schemas;
+ int res = 0, len, ret;
+ char pattern[500];
+ char prefix[500];
+ char result[500];
+ char err[500];
+ glob_t globbuf;
+ size_t i;
+ char count = 0;
+
+ /* first compile the schemas if possible */
+ ctxt = xmlSchemaNewParserCtxt(filename);
+ xmlSchemaSetParserErrors(ctxt,
+ (xmlSchemaValidityErrorFunc) testErrorHandler,
+ (xmlSchemaValidityWarningFunc) testErrorHandler,
+ ctxt);
+ schemas = xmlSchemaParse(ctxt);
+ xmlSchemaFreeParserCtxt(ctxt);
+
+ /*
+ * most of the mess is about the output filenames generated by the Makefile
+ */
+ len = strlen(base);
+ if ((len > 499) || (len < 5)) {
+ xmlSchemaFree(schemas);
+ return(-1);
+ }
+ len -= 4; /* remove trailing .xsd */
+ if (base[len - 2] == '_') {
+ len -= 2; /* remove subtest number */
+ }
+ if (base[len - 2] == '_') {
+ len -= 2; /* remove subtest number */
+ }
+ memcpy(prefix, base, len);
+ prefix[len] = 0;
+
+ snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
+ pattern[499] = 0;
+
+ if (base[len] == '_') {
+ len += 2;
+ memcpy(prefix, base, len);
+ prefix[len] = 0;
+ }
+
+ globbuf.gl_offs = 0;
+ glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+ for (i = 0;i < globbuf.gl_pathc;i++) {
+ testErrorsSize = 0;
+ testErrors[0] = 0;
+ instance = globbuf.gl_pathv[i];
+ base2 = baseFilename(instance);
+ len = strlen(base2);
+ if ((len > 6) && (base2[len - 6] == '_')) {
+ count = base2[len - 5];
+ snprintf(result, 499, "result/schemas/%s_%c",
+ prefix, count);
+ result[499] = 0;
+ snprintf(err, 499, "result/schemas/%s_%c.err",
+ prefix, count);
+ err[499] = 0;
+ } else {
+ fprintf(stderr, "don't know how to process %s\n", instance);
+ continue;
+ }
+ if (schemas == NULL) {
+ } else {
+ nb_tests++;
+ ret = schemasOneTest(filename, instance, result, err,
+ options, schemas);
+ if (res != 0)
+ ret = res;
+ }
+ }
+ globfree(&globbuf);
+ xmlSchemaFree(schemas);
+
+ return(res);
+}
+
+/************************************************************************
+ * *
+ * Schemas tests *
+ * *
+ ************************************************************************/
+static int
+rngOneTest(const char *sch,
+ const char *filename,
+ const char *result,
+ const char *err,
+ int options,
+ xmlRelaxNGPtr schemas) {
+ xmlDocPtr doc;
+ xmlRelaxNGValidCtxtPtr ctxt;
+ int ret = 0;
+ char *temp;
+ FILE *schemasOutput;
+
+ doc = xmlReadFile(filename, NULL, options);
+ if (doc == NULL) {
+ fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
+ return(-1);
+ }
+
+ temp = resultFilename(result, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ fatalError();
+ }
+ schemasOutput = fopen(temp, "wb");
+ if (schemasOutput == NULL) {
+ fprintf(stderr, "failed to open output file %s\n", temp);
+ xmlFreeDoc(doc);
+ free(temp);
+ return(-1);
+ }
+
+ ctxt = xmlRelaxNGNewValidCtxt(schemas);
+ xmlRelaxNGSetValidErrors(ctxt,
+ (xmlRelaxNGValidityErrorFunc) testErrorHandler,
+ (xmlRelaxNGValidityWarningFunc) testErrorHandler,
+ ctxt);
+ ret = xmlRelaxNGValidateDoc(ctxt, doc);
+ if (ret == 0) {
+ testErrorHandler(NULL, "%s validates\n", filename);
+ } else if (ret > 0) {
+ testErrorHandler(NULL, "%s fails to validate\n", filename);
+ } else {
+ testErrorHandler(NULL, "%s validation generated an internal error\n",
+ filename);
+ }
+ fclose(schemasOutput);
+ if (result) {
+ if (compareFiles(temp, result)) {
+ fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
+ ret = 1;
+ }
+ }
+ unlink(temp);
+ free(temp);
+
+ if (err != NULL) {
+ if (compareFileMem(err, testErrors, testErrorsSize)) {
+ fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
+ ret = 1;
+ printf("%s", testErrors);
+ }
+ }
+
+
+ xmlRelaxNGFreeValidCtxt(ctxt);
+ xmlFreeDoc(doc);
+ return(ret);
+}
+/**
+ * rngTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse an RNG schemas and then apply it to the related .xml
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+rngTest(const char *filename,
+ const char *resul ATTRIBUTE_UNUSED,
+ const char *errr ATTRIBUTE_UNUSED,
+ int options) {
+ const char *base = baseFilename(filename);
+ const char *base2;
+ const char *instance;
+ xmlRelaxNGParserCtxtPtr ctxt;
+ xmlRelaxNGPtr schemas;
+ int res = 0, len, ret;
+ char pattern[500];
+ char prefix[500];
+ char result[500];
+ char err[500];
+ glob_t globbuf;
+ size_t i;
+ char count = 0;
+
+ /* first compile the schemas if possible */
+ ctxt = xmlRelaxNGNewParserCtxt(filename);
+ xmlRelaxNGSetParserErrors(ctxt,
+ (xmlRelaxNGValidityErrorFunc) testErrorHandler,
+ (xmlRelaxNGValidityWarningFunc) testErrorHandler,
+ ctxt);
+ schemas = xmlRelaxNGParse(ctxt);
+ xmlRelaxNGFreeParserCtxt(ctxt);
+
+ /*
+ * most of the mess is about the output filenames generated by the Makefile
+ */
+ len = strlen(base);
+ if ((len > 499) || (len < 5)) {
+ xmlRelaxNGFree(schemas);
+ return(-1);
+ }
+ len -= 4; /* remove trailing .rng */
+ memcpy(prefix, base, len);
+ prefix[len] = 0;
+
+ snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
+ pattern[499] = 0;
+
+ globbuf.gl_offs = 0;
+ glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+ for (i = 0;i < globbuf.gl_pathc;i++) {
+ testErrorsSize = 0;
+ testErrors[0] = 0;
+ instance = globbuf.gl_pathv[i];
+ base2 = baseFilename(instance);
+ len = strlen(base2);
+ if ((len > 6) && (base2[len - 6] == '_')) {
+ count = base2[len - 5];
+ snprintf(result, 499, "result/relaxng/%s_%c",
+ prefix, count);
+ result[499] = 0;
+ snprintf(err, 499, "result/relaxng/%s_%c.err",
+ prefix, count);
+ err[499] = 0;
+ } else {
+ fprintf(stderr, "don't know how to process %s\n", instance);
+ continue;
+ }
+ if (schemas == NULL) {
+ } else {
+ nb_tests++;
+ ret = rngOneTest(filename, instance, result, err,
+ options, schemas);
+ if (res != 0)
+ ret = res;
+ }
+ }
+ globfree(&globbuf);
+ xmlRelaxNGFree(schemas);
+
+ return(res);
+}
+
+#ifdef LIBXML_READER_ENABLED
+/**
+ * rngStreamTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a set of files with streaming, applying an RNG schemas
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+rngStreamTest(const char *filename,
+ const char *resul ATTRIBUTE_UNUSED,
+ const char *errr ATTRIBUTE_UNUSED,
+ int options) {
+ const char *base = baseFilename(filename);
+ const char *base2;
+ const char *instance;
+ int res = 0, len, ret;
+ char pattern[500];
+ char prefix[500];
+ char result[500];
+ char err[500];
+ glob_t globbuf;
+ size_t i;
+ char count = 0;
+ xmlTextReaderPtr reader;
+ int disable_err = 0;
+
+ /*
+ * most of the mess is about the output filenames generated by the Makefile
+ */
+ len = strlen(base);
+ if ((len > 499) || (len < 5)) {
+ fprintf(stderr, "len(base) == %d !\n", len);
+ return(-1);
+ }
+ len -= 4; /* remove trailing .rng */
+ memcpy(prefix, base, len);
+ prefix[len] = 0;
+
+ /*
+ * strictly unifying the error messages is nearly impossible this
+ * hack is also done in the Makefile
+ */
+ if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
+ (!strcmp(prefix, "tutor3_2")))
+ disable_err = 1;
+
+ snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
+ pattern[499] = 0;
+
+ globbuf.gl_offs = 0;
+ glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
+ for (i = 0;i < globbuf.gl_pathc;i++) {
+ testErrorsSize = 0;
+ testErrors[0] = 0;
+ instance = globbuf.gl_pathv[i];
+ base2 = baseFilename(instance);
+ len = strlen(base2);
+ if ((len > 6) && (base2[len - 6] == '_')) {
+ count = base2[len - 5];
+ snprintf(result, 499, "result/relaxng/%s_%c",
+ prefix, count);
+ result[499] = 0;
+ snprintf(err, 499, "result/relaxng/%s_%c.err",
+ prefix, count);
+ err[499] = 0;
+ } else {
+ fprintf(stderr, "don't know how to process %s\n", instance);
+ continue;
+ }
+ reader = xmlReaderForFile(instance, NULL, options);
+ if (reader == NULL) {
+ fprintf(stderr, "Failed to build reder for %s\n", instance);
+ }
+ if (disable_err == 1)
+ ret = streamProcessTest(instance, result, NULL, reader, filename);
+ else
+ ret = streamProcessTest(instance, result, err, reader, filename);
+ xmlFreeTextReader(reader);
+ if (ret != 0) {
+ fprintf(stderr, "instance %s failed\n", instance);
+ res = ret;
+ }
+ }
+ globfree(&globbuf);
+
+ return(res);
+}
+#endif /* READER */
+
+#endif
+
+#ifdef LIBXML_PATTERN_ENABLED
+#ifdef LIBXML_READER_ENABLED
+/************************************************************************
+ * *
+ * Patterns tests *
+ * *
+ ************************************************************************/
+static void patternNode(FILE *out, xmlTextReaderPtr reader,
+ const char *pattern, xmlPatternPtr patternc,
+ xmlStreamCtxtPtr patstream) {
+ xmlChar *path = NULL;
+ int match = -1;
+ int type, empty;
+
+ type = xmlTextReaderNodeType(reader);
+ empty = xmlTextReaderIsEmptyElement(reader);
+
+ if (type == XML_READER_TYPE_ELEMENT) {
+ /* do the check only on element start */
+ match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
+
+ if (match) {
+ path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
+ fprintf(out, "Node %s matches pattern %s\n", path, pattern);
+ }
+ }
+ if (patstream != NULL) {
+ int ret;
+
+ if (type == XML_READER_TYPE_ELEMENT) {
+ ret = xmlStreamPush(patstream,
+ xmlTextReaderConstLocalName(reader),
+ xmlTextReaderConstNamespaceUri(reader));
+ if (ret < 0) {
+ fprintf(out, "xmlStreamPush() failure\n");
+ xmlFreeStreamCtxt(patstream);
+ patstream = NULL;
+ } else if (ret != match) {
+ if (path == NULL) {
+ path = xmlGetNodePath(
+ xmlTextReaderCurrentNode(reader));
+ }
+ fprintf(out,
+ "xmlPatternMatch and xmlStreamPush disagree\n");
+ fprintf(out,
+ " pattern %s node %s\n",
+ pattern, path);
+ }
+
+
+ }
+ if ((type == XML_READER_TYPE_END_ELEMENT) ||
+ ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
+ ret = xmlStreamPop(patstream);
+ if (ret < 0) {
+ fprintf(out, "xmlStreamPop() failure\n");
+ xmlFreeStreamCtxt(patstream);
+ patstream = NULL;
+ }
+ }
+ }
+ if (path != NULL)
+ xmlFree(path);
+}
+
+/**
+ * patternTest:
+ * @filename: the schemas file
+ * @result: the file with expected result
+ * @err: the file with error messages
+ *
+ * Parse a set of files with streaming, applying an RNG schemas
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+patternTest(const char *filename,
+ const char *resul ATTRIBUTE_UNUSED,
+ const char *err ATTRIBUTE_UNUSED,
+ int options) {
+ xmlPatternPtr patternc = NULL;
+ xmlStreamCtxtPtr patstream = NULL;
+ FILE *o, *f;
+ char str[1024];
+ char xml[500];
+ char result[500];
+ int len, i;
+ int ret = 0, res;
+ char *temp;
+ xmlTextReaderPtr reader;
+ xmlDocPtr doc;
+
+ len = strlen(filename);
+ len -= 4;
+ memcpy(xml, filename, len);
+ xml[len] = 0;
+ snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
+ result[499] = 0;
+ memcpy(xml + len, ".xml", 5);
+
+ if (!checkTestFile(xml)) {
+ fprintf(stderr, "Missing xml file %s\n", xml);
+ return(-1);
+ }
+ if (!checkTestFile(result)) {
+ fprintf(stderr, "Missing result file %s\n", result);
+ return(-1);
+ }
+ f = fopen(filename, "rb");
+ if (f == NULL) {
+ fprintf(stderr, "Failed to open %s\n", filename);
+ return(-1);
+ }
+ temp = resultFilename(filename, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ fatalError();
+ }
+ o = fopen(temp, "wb");
+ if (o == NULL) {
+ fprintf(stderr, "failed to open output file %s\n", temp);
+ fclose(f);
+ free(temp);
+ return(-1);
+ }
+ while (1) {
+ /*
+ * read one line in string buffer.
+ */
+ if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
+ break;
+
+ /*
+ * remove the ending spaces
+ */
+ i = strlen(str);
+ while ((i > 0) &&
+ ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
+ (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
+ i--;
+ str[i] = 0;
+ }
+ doc = xmlReadFile(xml, NULL, options);
+ if (doc == NULL) {
+ fprintf(stderr, "Failed to parse %s\n", xml);
+ ret = 1;
+ } else {
+ xmlNodePtr root;
+ const xmlChar *namespaces[22];
+ int j;
+ xmlNsPtr ns;
+
+ root = xmlDocGetRootElement(doc);
+ for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
+ namespaces[j++] = ns->href;
+ namespaces[j++] = ns->prefix;
+ }
+ namespaces[j++] = NULL;
+ namespaces[j++] = NULL;
+
+ patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
+ 0, &namespaces[0]);
+ if (patternc == NULL) {
+ testErrorHandler(NULL,
+ "Pattern %s failed to compile\n", str);
+ xmlFreeDoc(doc);
+ ret = 1;
+ continue;
+ }
+ patstream = xmlPatternGetStreamCtxt(patternc);
+ if (patstream != NULL) {
+ ret = xmlStreamPush(patstream, NULL, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "xmlStreamPush() failure\n");
+ xmlFreeStreamCtxt(patstream);
+ patstream = NULL;
+ }
+ }
+ nb_tests++;
+
+ reader = xmlReaderWalker(doc);
+ res = xmlTextReaderRead(reader);
+ while (res == 1) {
+ patternNode(o, reader, str, patternc, patstream);
+ res = xmlTextReaderRead(reader);
+ }
+ if (res != 0) {
+ fprintf(o, "%s : failed to parse\n", filename);
+ }
+ xmlFreeTextReader(reader);
+ xmlFreeDoc(doc);
+ xmlFreeStreamCtxt(patstream);
+ patstream = NULL;
+ xmlFreePattern(patternc);
+
+ }
+ }
+
+ fclose(f);
+ fclose(o);
+
+ ret = compareFiles(temp, result);
+ if (ret) {
+ fprintf(stderr, "Result for %s failed\n", filename);
+ ret = 1;
+ }
+ unlink(temp);
+ free(temp);
+ return(ret);
+}
+#endif /* READER */
+#endif /* PATTERN */
+#ifdef LIBXML_C14N_ENABLED
+/************************************************************************
+ * *
+ * Canonicalization tests *
+ * *
+ ************************************************************************/
+static xmlXPathObjectPtr
+load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
+ xmlXPathObjectPtr xpath;
+ xmlDocPtr doc;
+ xmlChar *expr;
+ xmlXPathContextPtr ctx;
+ xmlNodePtr node;
+ xmlNsPtr ns;
+
+ /*
+ * load XPath expr as a file
+ */
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+
+ doc = xmlParseFile(filename);
+ if (doc == NULL) {
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
+ return(NULL);
+ }
+
+ /*
+ * Check the document is of the right kind
+ */
+ if(xmlDocGetRootElement(doc) == NULL) {
+ fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
+ xmlFreeDoc(doc);
+ return(NULL);
+ }
+
+ node = doc->children;
+ while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
+ node = node->next;
+ }
+
+ if(node == NULL) {
+ fprintf(stderr,"Error: XPath element expected in the file \"%s\"\n", filename);
+ xmlFreeDoc(doc);
+ return(NULL);
+ }
+
+ expr = xmlNodeGetContent(node);
+ if(expr == NULL) {
+ fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
+ xmlFreeDoc(doc);
+ return(NULL);
+ }
+
+ ctx = xmlXPathNewContext(parent_doc);
+ if(ctx == NULL) {
+ fprintf(stderr,"Error: unable to create new context\n");
+ xmlFree(expr);
+ xmlFreeDoc(doc);
+ return(NULL);
+ }
+
+ /*
+ * Register namespaces
+ */
+ ns = node->nsDef;
+ while(ns != NULL) {
+ if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
+ fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
+ xmlFree(expr);
+ xmlXPathFreeContext(ctx);
+ xmlFreeDoc(doc);
+ return(NULL);
+ }
+ ns = ns->next;
+ }
+
+ /*
+ * Evaluate xpath
+ */
+ xpath = xmlXPathEvalExpression(expr, ctx);
+ if(xpath == NULL) {
+ fprintf(stderr,"Error: unable to evaluate xpath expression\n");
+ xmlFree(expr);
+ xmlXPathFreeContext(ctx);
+ xmlFreeDoc(doc);
+ return(NULL);
+ }
+
+ /* print_xpath_nodes(xpath->nodesetval); */
+
+ xmlFree(expr);
+ xmlXPathFreeContext(ctx);
+ xmlFreeDoc(doc);
+ return(xpath);
+}
+
+/*
+ * Macro used to grow the current buffer.
+ */
+#define xxx_growBufferReentrant() { \
+ buffer_size *= 2; \
+ buffer = (xmlChar **) \
+ xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \
+ if (buffer == NULL) { \
+ perror("realloc failed"); \
+ return(NULL); \
+ } \
+}
+
+static xmlChar **
+parse_list(xmlChar *str) {
+ xmlChar **buffer;
+ xmlChar **out = NULL;
+ int buffer_size = 0;
+ int len;
+
+ if(str == NULL) {
+ return(NULL);
+ }
+
+ len = xmlStrlen(str);
+ if((str[0] == '\'') && (str[len - 1] == '\'')) {
+ str[len - 1] = '\0';
+ str++;
+ len -= 2;
+ }
+ /*
+ * allocate an translation buffer.
+ */
+ buffer_size = 1000;
+ buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
+ if (buffer == NULL) {
+ perror("malloc failed");
+ return(NULL);
+ }
+ out = buffer;
+
+ while(*str != '\0') {
+ if (out - buffer > buffer_size - 10) {
+ int indx = out - buffer;
+
+ xxx_growBufferReentrant();
+ out = &buffer[indx];
+ }
+ (*out++) = str;
+ while(*str != ',' && *str != '\0') ++str;
+ if(*str == ',') *(str++) = '\0';
+ }
+ (*out) = NULL;
+ return buffer;
+}
+
+static int
+c14nRunTest(const char* xml_filename, int with_comments, int exclusive,
+ const char* xpath_filename, const char *ns_filename,
+ const char* result_file) {
+ xmlDocPtr doc;
+ xmlXPathObjectPtr xpath = NULL;
+ xmlChar *result = NULL;
+ int ret;
+ xmlChar **inclusive_namespaces = NULL;
+ const char *nslist = NULL;
+ int nssize;
+
+
+ /*
+ * build an XML tree from a the file; we need to add default
+ * attributes and resolve all character and entities references
+ */
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlSubstituteEntitiesDefault(1);
+
+ doc = xmlParseFile(xml_filename);
+ if (doc == NULL) {
+ fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
+ return(-1);
+ }
+
+ /*
+ * Check the document is of the right kind
+ */
+ if(xmlDocGetRootElement(doc) == NULL) {
+ fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+
+ /*
+ * load xpath file if specified
+ */
+ if(xpath_filename) {
+ xpath = load_xpath_expr(doc, xpath_filename);
+ if(xpath == NULL) {
+ fprintf(stderr,"Error: unable to evaluate xpath expression\n");
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ }
+
+ if (ns_filename != NULL) {
+ if (loadMem(ns_filename, &nslist, &nssize)) {
+ fprintf(stderr,"Error: unable to evaluate xpath expression\n");
+ if(xpath != NULL) xmlXPathFreeObject(xpath);
+ xmlFreeDoc(doc);
+ return(-1);
+ }
+ inclusive_namespaces = parse_list((xmlChar *) nslist);
+ }
+
+ /*
+ * Canonical form
+ */
+ /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
+ ret = xmlC14NDocDumpMemory(doc,
+ (xpath) ? xpath->nodesetval : NULL,
+ exclusive, inclusive_namespaces,
+ with_comments, &result);
+ if (ret >= 0) {
+ if(result != NULL) {
+ if (compareFileMem(result_file, (const char *) result, ret)) {
+ fprintf(stderr, "Result mismatch for %s\n", xml_filename);
+ ret = -1;
+ }
+ }
+ } else {
+ fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
+ ret = -1;
+ }
+
+ /*
+ * Cleanup
+ */
+ if (result != NULL) xmlFree(result);
+ if(xpath != NULL) xmlXPathFreeObject(xpath);
+ if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
+ if (nslist != NULL) free((char *) nslist);
+ xmlFreeDoc(doc);
+
+ return(ret);
+}
+
+static int
+c14nCommonTest(const char *filename, int with_comments, int exclusive,
+ const char *subdir) {
+ char buf[500];
+ char prefix[500];
+ const char *base;
+ int len;
+ char *result = NULL;
+ char *xpath = NULL;
+ char *ns = NULL;
+ int ret = 0;
+
+ base = baseFilename(filename);
+ len = strlen(base);
+ len -= 4;
+ memcpy(prefix, base, len);
+ prefix[len] = 0;
+
+ snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
+ if (!checkTestFile(buf)) {
+ fprintf(stderr, "Missing result file %s", buf);
+ return(-1);
+ }
+ result = strdup(buf);
+ snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
+ if (checkTestFile(buf)) {
+ xpath = strdup(buf);
+ }
+ snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
+ if (checkTestFile(buf)) {
+ ns = strdup(buf);
+ }
+
+ nb_tests++;
+ if (c14nRunTest(filename, with_comments, exclusive,
+ xpath, ns, result) < 0)
+ ret = 1;
+
+ if (result != NULL) free(result);
+ if (xpath != NULL) free(xpath);
+ if (ns != NULL) free(ns);
+ return(ret);
+}
+
+static int
+c14nWithCommentTest(const char *filename,
+ const char *resul ATTRIBUTE_UNUSED,
+ const char *err ATTRIBUTE_UNUSED,
+ int options ATTRIBUTE_UNUSED) {
+ return(c14nCommonTest(filename, 1, 0, "with-comments"));
+}
+static int
+c14nWithoutCommentTest(const char *filename,
+ const char *resul ATTRIBUTE_UNUSED,
+ const char *err ATTRIBUTE_UNUSED,
+ int options ATTRIBUTE_UNUSED) {
+ return(c14nCommonTest(filename, 0, 0, "without-comments"));
+}
+static int
+c14nExcWithoutCommentTest(const char *filename,
+ const char *resul ATTRIBUTE_UNUSED,
+ const char *err ATTRIBUTE_UNUSED,
+ int options ATTRIBUTE_UNUSED) {
+ return(c14nCommonTest(filename, 0, 1, "exc-without-comments"));
+}
+#endif
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
+/************************************************************************
+ * *
+ * Catalog and threads test *
+ * *
+ ************************************************************************/
+
+/*
+ * mostly a cut and paste from testThreads.c
+ */
+#define MAX_ARGC 20
+
+static const char *catalog = "test/threads/complex.xml";
+static const char *testfiles[] = {
+ "test/threads/abc.xml",
+ "test/threads/acb.xml",
+ "test/threads/bac.xml",
+ "test/threads/bca.xml",
+ "test/threads/cab.xml",
+ "test/threads/cba.xml",
+ "test/threads/invalid.xml",
+};
+
+const char *Okay = "OK";
+const char *Failed = "Failed";
+
+#ifndef xmlDoValidityCheckingDefaultValue
+#error xmlDoValidityCheckingDefaultValue is not a macro
+#endif
+#ifndef xmlGenericErrorContext
+#error xmlGenericErrorContext is not a macro
+#endif
+
+static void *
+thread_specific_data(void *private_data)
+{
+ xmlDocPtr myDoc;
+ const char *filename = (const char *) private_data;
+ int okay = 1;
+
+ if (!strcmp(filename, "test/threads/invalid.xml")) {
+ xmlDoValidityCheckingDefaultValue = 0;
+ xmlGenericErrorContext = stdout;
+ } else {
+ xmlDoValidityCheckingDefaultValue = 1;
+ xmlGenericErrorContext = stderr;
+ }
+ myDoc = xmlParseFile(filename);
+ if (myDoc) {
+ xmlFreeDoc(myDoc);
+ } else {
+ printf("parse failed\n");
+ okay = 0;
+ }
+ if (!strcmp(filename, "test/threads/invalid.xml")) {
+ if (xmlDoValidityCheckingDefaultValue != 0) {
+ printf("ValidityCheckingDefaultValue override failed\n");
+ okay = 0;
+ }
+ if (xmlGenericErrorContext != stdout) {
+ printf("xmlGenericErrorContext override failed\n");
+ okay = 0;
+ }
+ } else {
+ if (xmlDoValidityCheckingDefaultValue != 1) {
+ printf("ValidityCheckingDefaultValue override failed\n");
+ okay = 0;
+ }
+ if (xmlGenericErrorContext != stderr) {
+ printf("xmlGenericErrorContext override failed\n");
+ okay = 0;
+ }
+ }
+ if (okay == 0)
+ return ((void *) Failed);
+ return ((void *) Okay);
+}
+
+#if defined(linux) || defined(solaris)
+
+#include <pthread.h>
+
+static pthread_t tid[MAX_ARGC];
+
+static int
+testThread(void)
+{
+ unsigned int i, repeat;
+ unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
+ void *results[MAX_ARGC];
+ int ret;
+ int res = 0;
+
+ xmlInitParser();
+
+ for (repeat = 0; repeat < 500; repeat++) {
+ xmlLoadCatalog(catalog);
+ nb_tests++;
+
+ for (i = 0; i < num_threads; i++) {
+ results[i] = NULL;
+ tid[i] = (pthread_t) - 1;
+ }
+
+ for (i = 0; i < num_threads; i++) {
+ ret = pthread_create(&tid[i], 0, thread_specific_data,
+ (void *) testfiles[i]);
+ if (ret != 0) {
+ fprintf(stderr, "pthread_create failed\n");
+ return (1);
+ }
+ }
+ for (i = 0; i < num_threads; i++) {
+ ret = pthread_join(tid[i], &results[i]);
+ if (ret != 0) {
+ fprintf(stderr, "pthread_join failed\n");
+ return (1);
+ }
+ }
+
+ xmlCatalogCleanup();
+ for (i = 0; i < num_threads; i++)
+ if (results[i] != (void *) Okay) {
+ fprintf(stderr, "Thread %d handling %s failed\n",
+ i, testfiles[i]);
+ res = 1;
+ }
+ }
+ return (res);
+}
+
+#elif defined WIN32
+#include <windows.h>
+#include <string.h>
+
+#define TEST_REPEAT_COUNT 500
+
+static HANDLE tid[MAX_ARGC];
+
+static DWORD WINAPI
+win32_thread_specific_data(void *private_data)
+{
+ return((DWORD) thread_specific_data(private_data));
+}
+
+static int
+testThread(void)
+{
+ unsigned int i, repeat;
+ unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
+ DWORD results[MAX_ARGC];
+ BOOL ret;
+ int res = 0;
+
+ xmlInitParser();
+ for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
+ xmlLoadCatalog(catalog);
+ nb_tests++;
+
+ for (i = 0; i < num_threads; i++) {
+ results[i] = 0;
+ tid[i] = (HANDLE) - 1;
+ }
+
+ for (i = 0; i < num_threads; i++) {
+ DWORD useless;
+
+ tid[i] = CreateThread(NULL, 0,
+ win32_thread_specific_data,
+ (void *) testfiles[i], 0,
+ &useless);
+ if (tid[i] == NULL) {
+ fprintf(stderr, "CreateThread failed\n");
+ return(1);
+ }
+ }
+
+ if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
+ WAIT_FAILED) {
+ fprintf(stderr, "WaitForMultipleObjects failed\n");
+ return(1);
+ }
+
+ for (i = 0; i < num_threads; i++) {
+ ret = GetExitCodeThread(tid[i], &results[i]);
+ if (ret == 0) {
+ fprintf(stderr, "GetExitCodeThread failed\n");
+ return(1);
+ }
+ CloseHandle(tid[i]);
+ }
+
+ xmlCatalogCleanup();
+ for (i = 0; i < num_threads; i++) {
+ if (results[i] != (DWORD) Okay) {
+ fprintf(stderr, "Thread %d handling %s failed\n",
+ i, testfiles[i]);
+ res = 1;
+ }
+ }
+ }
+
+ return (res);
+}
+
+#elif defined __BEOS__
+#include <OS.h>
+
+static thread_id tid[MAX_ARGC];
+
+static int
+testThread(void)
+{
+ unsigned int i, repeat;
+ unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
+ void *results[MAX_ARGC];
+ status_t ret;
+ int res = 0;
+
+ xmlInitParser();
+ for (repeat = 0; repeat < 500; repeat++) {
+ xmlLoadCatalog(catalog);
+ for (i = 0; i < num_threads; i++) {
+ results[i] = NULL;
+ tid[i] = (thread_id) - 1;
+ }
+ for (i = 0; i < num_threads; i++) {
+ tid[i] =
+ spawn_thread(thread_specific_data, "xmlTestThread",
+ B_NORMAL_PRIORITY, (void *) testfiles[i]);
+ if (tid[i] < B_OK) {
+ fprintf(stderr, "beos_thread_create failed\n");
+ return (1);
+ }
+ printf("beos_thread_create %d -> %d\n", i, tid[i]);
+ }
+ for (i = 0; i < num_threads; i++) {
+ ret = wait_for_thread(tid[i], &results[i]);
+ printf("beos_thread_wait %d -> %d\n", i, ret);
+ if (ret != B_OK) {
+ fprintf(stderr, "beos_thread_wait failed\n");
+ return (1);
+ }
+ }
+
+ xmlCatalogCleanup();
+ ret = B_OK;
+ for (i = 0; i < num_threads; i++)
+ if (results[i] != (void *) Okay) {
+ printf("Thread %d handling %s failed\n", i, testfiles[i]);
+ ret = B_ERROR;
+ }
+ }
+ if (ret != B_OK)
+ return(1);
+ return (0);
+}
+#else
+static int
+testThread(void)
+{
+ fprintf(stderr,
+ "Specific platform thread support not detected\n");
+ return (-1);
+}
+#endif
+static int
+threadsTest(const char *filename ATTRIBUTE_UNUSED,
+ const char *resul ATTRIBUTE_UNUSED,
+ const char *err ATTRIBUTE_UNUSED,
+ int options ATTRIBUTE_UNUSED) {
+ return(testThread());
+}
+#endif
+/************************************************************************
+ * *
+ * Tests Descriptions *
+ * *
+ ************************************************************************/
+
+static
+testDesc testDescriptions[] = {
+ { "XML regression tests" ,
+ oldParseTest, "./test/*", "result/", "", NULL,
+ 0 },
+ { "XML regression tests on memory" ,
+ memParseTest, "./test/*", "result/", "", NULL,
+ 0 },
+ { "XML entity subst regression tests" ,
+ noentParseTest, "./test/*", "result/noent/", "", NULL,
+ XML_PARSE_NOENT },
+ { "XML Namespaces regression tests",
+ errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
+ 0 },
+ { "Error cases regression tests",
+ errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
+ 0 },
+#ifdef LIBXML_READER_ENABLED
+ { "Error cases stream regression tests",
+ streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
+ 0 },
+ { "Reader regression tests",
+ streamParseTest, "./test/*", "result/", ".rdr", NULL,
+ 0 },
+ { "Reader entities substitution regression tests",
+ streamParseTest, "./test/*", "result/", ".rde", NULL,
+ XML_PARSE_NOENT },
+ { "Reader on memory regression tests",
+ streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
+ 0 },
+ { "Walker regression tests",
+ walkerParseTest, "./test/*", "result/", ".rdr", NULL,
+ 0 },
+#endif
+#ifdef LIBXML_SAX1_ENABLED
+ { "SAX1 callbacks regression tests" ,
+ saxParseTest, "./test/*", "result/", ".sax", NULL,
+ XML_PARSE_SAX1 },
+ { "SAX2 callbacks regression tests" ,
+ saxParseTest, "./test/*", "result/", ".sax2", NULL,
+ 0 },
+#endif
+#ifdef LIBXML_PUSH_ENABLED
+ { "XML push regression tests" ,
+ pushParseTest, "./test/*", "result/", "", NULL,
+ 0 },
+#endif
+#ifdef LIBXML_HTML_ENABLED
+ { "HTML regression tests" ,
+ errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
+ XML_PARSE_HTML },
+#ifdef LIBXML_PUSH_ENABLED
+ { "Push HTML regression tests" ,
+ pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
+ XML_PARSE_HTML },
+#endif
+#ifdef LIBXML_SAX1_ENABLED
+ { "HTML SAX regression tests" ,
+ saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
+ XML_PARSE_HTML },
+#endif
+#endif
+#ifdef LIBXML_VALID_ENABLED
+ { "Valid documents regression tests" ,
+ errParseTest, "./test/VCM/*", NULL, NULL, NULL,
+ XML_PARSE_DTDVALID },
+ { "Validity checking regression tests" ,
+ errParseTest, "./test/VC/*", "result/VC/", NULL, "",
+ XML_PARSE_DTDVALID },
+ { "General documents valid regression tests" ,
+ errParseTest, "./test/valid/*", "result/valid/", "", ".err",
+ XML_PARSE_DTDVALID },
+#endif
+#ifdef LIBXML_XINCLUDE_ENABLED
+ { "XInclude regression tests" ,
+ errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
+ /* Ignore errors at this point ".err", */
+ XML_PARSE_XINCLUDE },
+ { "XInclude xmlReader regression tests",
+ streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
+ /* Ignore errors at this point ".err", */
+ NULL, XML_PARSE_XINCLUDE },
+ { "XInclude regression tests stripping include nodes" ,
+ errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
+ /* Ignore errors at this point ".err", */
+ XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
+ { "XInclude xmlReader regression tests stripping include nodes",
+ streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
+ /* Ignore errors at this point ".err", */
+ NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
+#endif
+#ifdef LIBXML_XPATH_ENABLED
+#ifdef LIBXML_DEBUG_ENABLED
+ { "XPath expressions regression tests" ,
+ xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
+ 0 },
+ { "XPath document queries regression tests" ,
+ xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
+ 0 },
+#ifdef LIBXML_XPTR_ENABLED
+ { "XPointer document queries regression tests" ,
+ xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
+ 0 },
+#endif
+ { "xml:id regression tests" ,
+ xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
+ 0 },
+#endif
+#endif
+ { "URI parsing tests" ,
+ uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
+ 0 },
+ { "URI base composition tests" ,
+ uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
+ 0 },
+#ifdef LIBXML_SCHEMAS_ENABLED
+ { "Schemas regression tests" ,
+ schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
+ 0 },
+ { "Relax-NG regression tests" ,
+ rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
+ XML_PARSE_DTDATTR | XML_PARSE_NOENT },
+#ifdef LIBXML_READER_ENABLED
+ { "Relax-NG streaming regression tests" ,
+ rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
+ XML_PARSE_DTDATTR | XML_PARSE_NOENT },
+#endif
+#endif
+#ifdef LIBXML_PATTERN_ENABLED
+#ifdef LIBXML_READER_ENABLED
+ { "Pattern regression tests" ,
+ patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
+ 0 },
+#endif
+#endif
+#ifdef LIBXML_C14N_ENABLED
+ { "C14N with comments regression tests" ,
+ c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
+ 0 },
+ { "C14N without comments regression tests" ,
+ c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
+ 0 },
+ { "C14N exclusive without comments regression tests" ,
+ c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
+ 0 },
+#endif
+#if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
+ { "Catalog and Threads regression tests" ,
+ threadsTest, NULL, NULL, NULL, NULL,
+ 0 },
+#endif
+ {NULL, NULL, NULL, NULL, NULL, NULL, 0}
+};
+
+/************************************************************************
+ * *
+ * The main code driving the tests *
+ * *
+ ************************************************************************/
+
+static int
+launchTests(testDescPtr tst) {
+ int res = 0, err = 0;
+ size_t i;
+ char *result;
+ char *error;
+ int mem;
+
+ if (tst == NULL) return(-1);
+ if (tst->in != NULL) {
+ glob_t globbuf;
+
+ globbuf.gl_offs = 0;
+ glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
+ for (i = 0;i < globbuf.gl_pathc;i++) {
+ if (!checkTestFile(globbuf.gl_pathv[i]))
+ continue;
+ if (tst->suffix != NULL) {
+ result = resultFilename(globbuf.gl_pathv[i], tst->out,
+ tst->suffix);
+ if (result == NULL) {
+ fprintf(stderr, "Out of memory !\n");
+ fatalError();
+ }
+ } else {
+ result = NULL;
+ }
+ if (tst->err != NULL) {
+ error = resultFilename(globbuf.gl_pathv[i], tst->out,
+ tst->err);
+ if (error == NULL) {
+ fprintf(stderr, "Out of memory !\n");
+ fatalError();
+ }
+ } else {
+ error = NULL;
+ }
+ if ((result) &&(!checkTestFile(result))) {
+ fprintf(stderr, "Missing result file %s\n", result);
+ } else if ((error) &&(!checkTestFile(error))) {
+ fprintf(stderr, "Missing error file %s\n", error);
+ } else {
+ mem = xmlMemUsed();
+ extraMemoryFromResolver = 0;
+ testErrorsSize = 0;
+ testErrors[0] = 0;
+ res = tst->func(globbuf.gl_pathv[i], result, error,
+ tst->options);
+ xmlResetLastError();
+ if (res != 0) {
+ fprintf(stderr, "File %s generated an error\n",
+ globbuf.gl_pathv[i]);
+ nb_errors++;
+ err++;
+ }
+ else if (xmlMemUsed() != mem) {
+ if ((xmlMemUsed() != mem) &&
+ (extraMemoryFromResolver == 0)) {
+ fprintf(stderr, "File %s leaked %d bytes\n",
+ globbuf.gl_pathv[i], xmlMemUsed() - mem);
+ nb_leaks++;
+ err++;
+ }
+ }
+ testErrorsSize = 0;
+ }
+ if (result)
+ free(result);
+ if (error)
+ free(error);
+ }
+ globfree(&globbuf);
+ } else {
+ testErrorsSize = 0;
+ testErrors[0] = 0;
+ extraMemoryFromResolver = 0;
+ res = tst->func(NULL, NULL, NULL, tst->options);
+ if (res != 0) {
+ nb_errors++;
+ err++;
+ }
+ }
+ return(err);
+}
+
+int
+main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+ int i = 0, res, ret = 0;
+ int verbose = 0;
+ int old_errors, old_tests, old_leaks;
+
+ initializeLibxml2();
+
+ if ((argc >= 2) && (!strcmp(argv[1], "-v")))
+ verbose = 1;
+ for (i = 0; testDescriptions[i].func != NULL; i++) {
+ old_errors = nb_errors;
+ old_tests = nb_tests;
+ old_leaks = nb_leaks;
+ if (testDescriptions[i].desc != NULL)
+ printf("## %s\n", testDescriptions[i].desc);
+ res = launchTests(&testDescriptions[i]);
+ if (res != 0)
+ ret++;
+ if (verbose) {
+ if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
+ printf("Ran %d tests, no errors\n", nb_tests - old_tests);
+ else
+ printf("Ran %d tests, %d errors, %d leaks\n",
+ nb_tests - old_tests,
+ nb_errors - old_errors,
+ nb_leaks - old_leaks);
+ }
+ }
+ if ((nb_errors == 0) && (nb_leaks == 0)) {
+ ret = 0;
+ printf("Total %d tests, no errors\n",
+ nb_tests);
+ } else {
+ ret = 1;
+ printf("Total %d tests, %d errors, %d leaks\n",
+ nb_tests, nb_errors, nb_leaks);
+ }
+ xmlCleanupParser();
+ xmlMemoryDump();
+
+ return(ret);
+}
+
+#else /* ! LIBXML_OUTPUT_ENABLED */
+int
+main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
+ fprintf(stderr, "runtest requires output to be enabled in libxml2\n");
+ return(1);
+}
+#endif