10161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/*
20161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * testrecurse.c: C program to run libxml2 regression tests checking entities
30161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *            recursions
40161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
50161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * To compile on Unixes:
60161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * cc -o testrecurse `xml2-config --cflags` testrecurse.c `xml2-config --libs` -lpthread
70161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
80161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * See Copyright for the status of this software.
90161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
100161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * daniel@veillard.com
110161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
120161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
130161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include "libxml.h"
140161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <stdio.h>
150161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
160161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#if !defined(_WIN32) || defined(__CYGWIN__)
170161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <unistd.h>
180161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#endif
190161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <string.h>
200161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <sys/types.h>
210161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <sys/stat.h>
220161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <fcntl.h>
230161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
240161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <libxml/parser.h>
250161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <libxml/tree.h>
260161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <libxml/uri.h>
270161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#ifdef LIBXML_READER_ENABLED
280161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <libxml/xmlreader.h>
290161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#endif
300161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
310161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/*
320161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * O_BINARY is just for Windows compatibility - if it isn't defined
330161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * on this system, avoid any compilation error
340161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
350161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#ifdef	O_BINARY
360161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#define RD_FLAGS	O_RDONLY | O_BINARY
370161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#else
380161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#define	RD_FLAGS	O_RDONLY
390161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#endif
400161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
410161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardtypedef int (*functest) (const char *filename, const char *result,
420161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                         const char *error, int options);
430161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
440161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardtypedef struct testDesc testDesc;
450161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardtypedef testDesc *testDescPtr;
460161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstruct testDesc {
470161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    const char *desc; /* descripton of the test */
480161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    functest    func; /* function implementing the test */
490161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    const char *in;   /* glob to path for input files */
500161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    const char *out;  /* output directory */
510161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    const char *suffix;/* suffix for output files */
520161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    const char *err;  /* suffix for error output files */
530161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int     options;  /* parser options for the test */
540161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard};
550161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
560161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int checkTestFile(const char *filename);
570161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
580161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
590161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#if defined(_WIN32) && !defined(__CYGWIN__)
600161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
610161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <windows.h>
620161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <io.h>
630161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
640161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardtypedef struct
650161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard{
660161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard      size_t gl_pathc;    /* Count of paths matched so far  */
670161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard      char **gl_pathv;    /* List of matched pathnames.  */
680161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard      size_t gl_offs;     /* Slots to reserve in 'gl_pathv'.  */
690161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard} glob_t;
700161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
710161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#define GLOB_DOOFFS 0
720161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int glob(const char *pattern, int flags,
730161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                int errfunc(const char *epath, int eerrno),
740161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                glob_t *pglob) {
750161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    glob_t *ret;
760161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    WIN32_FIND_DATA FindFileData;
770161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    HANDLE hFind;
780161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    unsigned int nb_paths = 0;
790161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    char directory[500];
800161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int len;
810161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
820161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((pattern == NULL) || (pglob == NULL)) return(-1);
830161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
840161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    strncpy(directory, pattern, 499);
850161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    for (len = strlen(directory);len >= 0;len--) {
860161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if (directory[len] == '/') {
870161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    len++;
880161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    directory[len] = 0;
890161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    break;
900161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	}
910161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
920161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (len <= 0)
930161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        len = 0;
940161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
950161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
960161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    ret = pglob;
970161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    memset(ret, 0, sizeof(glob_t));
980161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
990161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    hFind = FindFirstFileA(pattern, &FindFileData);
1000161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (hFind == INVALID_HANDLE_VALUE)
1010161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(0);
1020161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    nb_paths = 20;
1030161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
1040161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (ret->gl_pathv == NULL) {
1050161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	FindClose(hFind);
1060161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(-1);
1070161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
1080161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    strncpy(directory + len, FindFileData.cFileName, 499 - len);
1090161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    ret->gl_pathv[ret->gl_pathc] = strdup(directory);
1100161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (ret->gl_pathv[ret->gl_pathc] == NULL)
1110161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        goto done;
1120161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    ret->gl_pathc++;
1130161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    while(FindNextFileA(hFind, &FindFileData)) {
1140161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if (FindFileData.cFileName[0] == '.')
1150161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    continue;
1160161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if (ret->gl_pathc + 2 > nb_paths) {
1170161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
1180161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            if (tmp == NULL)
1190161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                break;
1200161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            ret->gl_pathv = tmp;
1210161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            nb_paths *= 2;
1220161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	}
1230161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	strncpy(directory + len, FindFileData.cFileName, 499 - len);
1240161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	ret->gl_pathv[ret->gl_pathc] = strdup(directory);
1250161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if (ret->gl_pathv[ret->gl_pathc] == NULL)
1260161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
1270161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        ret->gl_pathc++;
1280161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
1290161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    ret->gl_pathv[ret->gl_pathc] = NULL;
1300161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1310161e638c697890020c410dbedec9bb516d0fe49Daniel Veillarddone:
1320161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    FindClose(hFind);
1330161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(0);
1340161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
1350161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1360161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1370161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1380161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic void globfree(glob_t *pglob) {
1390161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    unsigned int i;
1400161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (pglob == NULL)
1410161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return;
1420161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1430161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    for (i = 0;i < pglob->gl_pathc;i++) {
1440161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard         if (pglob->gl_pathv[i] != NULL)
1450161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard             free(pglob->gl_pathv[i]);
1460161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
1470161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
14822030ef8888579b9ae8d8a63367e31b201eef4b5Daniel Veillard
1490161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#else
1500161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <glob.h>
1510161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#endif
1520161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1530161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/************************************************************************
1540161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
1550161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *		Huge document generator					*
1560161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
1570161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard ************************************************************************/
1580161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1590161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#include <libxml/xmlIO.h>
1600161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1610161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1620161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic const char *start = "<!DOCTYPE foo [\
1630161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard<!ENTITY f 'some internal data'> \
1640161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard<!ENTITY e '&f;&f;'> \
1650161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard<!ENTITY d '&e;&e;'> \
1660161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard]> \
1670161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard<foo>";
1680161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1690161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic const char *segment = "  <bar>&e; &f; &d;</bar>\n";
1700161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic const char *finish = "</foo>";
1710161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1720161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int curseg = 0;
1730161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic const char *current;
1740161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int rlen;
1750161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1760161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/**
1770161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * hugeMatch:
1780161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @URI: an URI to test
1790161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
1800161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Check for an huge: query
1810161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
1820161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Returns 1 if yes and 0 if another Input module should be used
1830161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
1840161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int
1850161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardhugeMatch(const char * URI) {
1860161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((URI != NULL) && (!strncmp(URI, "huge:", 4)))
1870161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(1);
1880161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(0);
1890161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
1900161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
1910161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/**
1920161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * hugeOpen:
1930161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @URI: an URI to test
1940161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
1950161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Return a pointer to the huge: query handler, in this example simply
1960161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * the current pointer...
1970161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
1980161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Returns an Input context or NULL in case or error
1990161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
2000161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic void *
2010161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardhugeOpen(const char * URI) {
2020161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((URI == NULL) || (strncmp(URI, "huge:", 4)))
2030161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(NULL);
2040161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    rlen = strlen(start);
2050161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    current = start;
2060161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return((void *) current);
2070161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
2080161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
2090161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/**
2100161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * hugeClose:
2110161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @context: the read context
2120161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
2130161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Close the huge: query handler
2140161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
2150161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Returns 0 or -1 in case of error
2160161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
2170161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int
2180161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardhugeClose(void * context) {
2190161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (context == NULL) return(-1);
2200161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(0);
2210161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
2220161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
2230161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#define MAX_NODES 1000000
2240161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
2250161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/**
2260161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * hugeRead:
2270161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @context: the read context
2280161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @buffer: where to store data
2290161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @len: number of bytes to read
2300161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
2310161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Implement an huge: query read.
2320161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
2330161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Returns the number of bytes read or -1 in case of error
2340161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
2350161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int
2360161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardhugeRead(void *context, char *buffer, int len)
2370161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard{
2380161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((context == NULL) || (buffer == NULL) || (len < 0))
2390161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return (-1);
2400161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
2410161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (len >= rlen) {
2420161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if (curseg >= MAX_NODES + 1) {
2430161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            rlen = 0;
2440161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            return(0);
2450161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        }
2460161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        len = rlen;
2470161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        rlen = 0;
2480161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	memcpy(buffer, current, len);
2490161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        curseg ++;
2500161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if (curseg == MAX_NODES) {
2510161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    fprintf(stderr, "\n");
2520161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            rlen = strlen(finish);
2530161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            current = finish;
2540161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	} else {
2550161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    if (curseg % (MAX_NODES / 10) == 0)
2560161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	        fprintf(stderr, ".");
2570161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            rlen = strlen(segment);
2580161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            current = segment;
2590161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	}
2600161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    } else {
2610161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	memcpy(buffer, current, len);
2620161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	rlen -= len;
2630161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        current += len;
2640161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
2650161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return (len);
2660161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
2670161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
2680161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/************************************************************************
2690161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
2700161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *		Libxml2 specific routines				*
2710161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
2720161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard ************************************************************************/
2730161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
2740161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int nb_tests = 0;
2750161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int nb_errors = 0;
2760161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int nb_leaks = 0;
2770161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int extraMemoryFromResolver = 0;
2780161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
2790161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int
2800161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardfatalError(void) {
2810161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    fprintf(stderr, "Exitting tests on fatal error\n");
2820161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    exit(1);
2830161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
2840161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
2850161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/*
2860161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * We need to trap calls to the resolver to not account memory for the catalog
2870161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * which is shared to the current running test. We also don't want to have
2880161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * network downloads modifying tests.
2890161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
2900161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic xmlParserInputPtr
2910161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardtestExternalEntityLoader(const char *URL, const char *ID,
2920161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard			 xmlParserCtxtPtr ctxt) {
2930161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlParserInputPtr ret;
2940161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
2950161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (checkTestFile(URL)) {
2960161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
2970161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    } else {
2980161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	int memused = xmlMemUsed();
2990161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
3000161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	extraMemoryFromResolver += xmlMemUsed() - memused;
3010161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
3020161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
3030161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(ret);
3040161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
3050161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
3060161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/*
3070161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Trapping the error messages at the generic level to grab the equivalent of
3080161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * stderr messages on CLI tools.
3090161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
3100161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic char testErrors[32769];
3110161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int testErrorsSize = 0;
3120161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
3130161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic void XMLCDECL
3140161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardchannel(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
3150161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    va_list args;
3160161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int res;
3170161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
3180161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (testErrorsSize >= 32768)
3190161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return;
3200161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    va_start(args, msg);
3210161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    res = vsnprintf(&testErrors[testErrorsSize],
3220161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                    32768 - testErrorsSize,
3230161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    msg, args);
3240161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    va_end(args);
3250161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (testErrorsSize + res >= 32768) {
3260161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        /* buffer is full */
3270161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	testErrorsSize = 32768;
3280161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	testErrors[testErrorsSize] = 0;
3290161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    } else {
3300161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        testErrorsSize += res;
3310161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
3320161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    testErrors[testErrorsSize] = 0;
3330161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
3340161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
3350161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/**
3360161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * xmlParserPrintFileContext:
3370161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @input:  an xmlParserInputPtr input
3380161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
3390161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Displays current context within the input content for error tracking
3400161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
3410161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
3420161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic void
3430161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardxmlParserPrintFileContextInternal(xmlParserInputPtr input ,
3440161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		xmlGenericErrorFunc chanl, void *data ) {
3450161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    const xmlChar *cur, *base;
3460161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    unsigned int n, col;	/* GCC warns if signed, because compared with sizeof() */
3470161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlChar  content[81]; /* space for 80 chars + line terminator */
3480161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlChar *ctnt;
3490161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
3500161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (input == NULL) return;
3510161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    cur = input->cur;
3520161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    base = input->base;
3530161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /* skip backwards over any end-of-lines */
3540161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
3550161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	cur--;
3560161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
3570161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    n = 0;
3580161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /* search backwards for beginning-of-line (to max buff size) */
3590161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    while ((n++ < (sizeof(content)-1)) && (cur > base) &&
3600161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard   (*(cur) != '\n') && (*(cur) != '\r'))
3610161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        cur--;
3620161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
3630161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /* calculate the error position in terms of the current position */
3640161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    col = input->cur - cur;
3650161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /* search forward for end-of-line (to max buff size) */
3660161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    n = 0;
3670161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    ctnt = content;
3680161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /* copy selected text to our buffer */
3690161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    while ((*cur != 0) && (*(cur) != '\n') &&
3700161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard   (*(cur) != '\r') && (n < sizeof(content)-1)) {
3710161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		*ctnt++ = *cur++;
3720161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	n++;
3730161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
3740161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    *ctnt = 0;
3750161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /* print out the selected text */
3760161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    chanl(data ,"%s\n", content);
3770161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /* create blank line with problem pointer */
3780161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    n = 0;
3790161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    ctnt = content;
3800161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /* (leave buffer space for pointer + line terminator) */
3810161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
3820161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	if (*(ctnt) != '\t')
3830161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    *(ctnt) = ' ';
3840161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	ctnt++;
3850161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
3860161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    *ctnt++ = '^';
3870161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    *ctnt = 0;
3880161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    chanl(data ,"%s\n", content);
3890161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
3900161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
3910161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic void
3920161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardtestStructuredErrorHandler(void *ctx  ATTRIBUTE_UNUSED, xmlErrorPtr err) {
3930161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    char *file = NULL;
3940161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int line = 0;
3950161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int code = -1;
3960161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int domain;
3970161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    void *data = NULL;
3980161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    const char *str;
3990161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    const xmlChar *name = NULL;
4000161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlNodePtr node;
4010161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlErrorLevel level;
4020161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlParserInputPtr input = NULL;
4030161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlParserInputPtr cur = NULL;
4040161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlParserCtxtPtr ctxt = NULL;
4050161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
4060161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (err == NULL)
4070161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return;
4080161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
4090161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    file = err->file;
4100161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    line = err->line;
4110161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    code = err->code;
4120161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    domain = err->domain;
4130161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    level = err->level;
4140161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    node = err->node;
4150161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
4160161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
4170161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
4180161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	ctxt = err->ctxt;
4190161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
4200161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    str = err->message;
4210161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
4220161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (code == XML_ERR_OK)
4230161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return;
4240161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
4250161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
4260161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        name = node->name;
4270161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
4280161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /*
4290161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard     * Maintain the compatibility with the legacy error handling
4300161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard     */
4310161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (ctxt != NULL) {
4320161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        input = ctxt->input;
4330161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if ((input != NULL) && (input->filename == NULL) &&
4340161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            (ctxt->inputNr > 1)) {
4350161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            cur = input;
4360161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            input = ctxt->inputTab[ctxt->inputNr - 2];
4370161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        }
4380161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if (input != NULL) {
4390161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            if (input->filename)
4400161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                channel(data, "%s:%d: ", input->filename, input->line);
4410161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            else if ((line != 0) && (domain == XML_FROM_PARSER))
4420161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                channel(data, "Entity: line %d: ", input->line);
4430161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        }
4440161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    } else {
4450161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if (file != NULL)
4460161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "%s:%d: ", file, line);
4470161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        else if ((line != 0) && (domain == XML_FROM_PARSER))
4480161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "Entity: line %d: ", line);
4490161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
4500161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (name != NULL) {
4510161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        channel(data, "element %s: ", name);
4520161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
4530161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (code == XML_ERR_OK)
4540161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return;
4550161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    switch (domain) {
4560161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_PARSER:
4570161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "parser ");
4580161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4590161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_NAMESPACE:
4600161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "namespace ");
4610161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4620161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_DTD:
4630161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_VALID:
4640161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "validity ");
4650161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4660161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_HTML:
4670161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "HTML parser ");
4680161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4690161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_MEMORY:
4700161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "memory ");
4710161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4720161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_OUTPUT:
4730161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "output ");
4740161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4750161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_IO:
4760161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "I/O ");
4770161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4780161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_XINCLUDE:
4790161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "XInclude ");
4800161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4810161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_XPATH:
4820161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "XPath ");
4830161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4840161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_XPOINTER:
4850161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "parser ");
4860161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4870161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_REGEXP:
4880161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "regexp ");
4890161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4900161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_MODULE:
4910161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "module ");
4920161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4930161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_SCHEMASV:
4940161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "Schemas validity ");
4950161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4960161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_SCHEMASP:
4970161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "Schemas parser ");
4980161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
4990161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_RELAXNGP:
5000161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "Relax-NG parser ");
5010161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
5020161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_RELAXNGV:
5030161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "Relax-NG validity ");
5040161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
5050161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_CATALOG:
5060161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "Catalog ");
5070161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
5080161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_C14N:
5090161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "C14N ");
5100161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
5110161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_FROM_XSLT:
5120161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "XSLT ");
5130161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
5140161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        default:
5150161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
5160161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
5170161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (code == XML_ERR_OK)
5180161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return;
5190161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    switch (level) {
5200161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_ERR_NONE:
5210161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, ": ");
5220161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
5230161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_ERR_WARNING:
5240161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "warning : ");
5250161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
5260161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_ERR_ERROR:
5270161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "error : ");
5280161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
5290161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        case XML_ERR_FATAL:
5300161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            channel(data, "error : ");
5310161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            break;
5320161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
5330161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (code == XML_ERR_OK)
5340161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return;
5350161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (str != NULL) {
5360161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        int len;
5370161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	len = xmlStrlen((const xmlChar *)str);
5380161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	if ((len > 0) && (str[len - 1] != '\n'))
5390161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    channel(data, "%s\n", str);
5400161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	else
5410161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    channel(data, "%s", str);
5420161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    } else {
5430161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        channel(data, "%s\n", "out of memory error");
5440161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
5450161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (code == XML_ERR_OK)
5460161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return;
5470161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
5480161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (ctxt != NULL) {
5490161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        xmlParserPrintFileContextInternal(input, channel, data);
5500161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if (cur != NULL) {
5510161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            if (cur->filename)
5520161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                channel(data, "%s:%d: \n", cur->filename, cur->line);
5530161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            else if ((line != 0) && (domain == XML_FROM_PARSER))
5540161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                channel(data, "Entity: line %d: \n", cur->line);
5550161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard            xmlParserPrintFileContextInternal(cur, channel, data);
5560161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        }
5570161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
5580161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
5590161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        (err->int1 < 100) &&
5600161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	(err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
5610161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	xmlChar buf[150];
5620161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	int i;
5630161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
5640161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	channel(data, "%s\n", err->str1);
5650161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	for (i=0;i < err->int1;i++)
5660161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	     buf[i] = ' ';
5670161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	buf[i++] = '^';
5680161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	buf[i] = 0;
5690161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	channel(data, "%s\n", buf);
5700161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
5710161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
5720161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
5730161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic void
5740161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardinitializeLibxml2(void) {
5750161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlGetWarningsDefaultValue = 0;
5760161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlPedanticParserDefault(0);
5770161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
5780161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
5790161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlInitParser();
5800161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlSetExternalEntityLoader(testExternalEntityLoader);
5810161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
5820161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /*
5830161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard     * register the new I/O handlers
5840161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard     */
5850161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (xmlRegisterInputCallbacks(hugeMatch, hugeOpen,
5860161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                                  hugeRead, hugeClose) < 0) {
5870161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        fprintf(stderr, "failed to register Huge handler\n");
5880161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	exit(1);
5890161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
5900161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
5910161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
5920161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/************************************************************************
5930161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
5940161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *		File name and path utilities				*
5950161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
5960161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard ************************************************************************/
5970161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
5980161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic const char *baseFilename(const char *filename) {
5990161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    const char *cur;
6000161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (filename == NULL)
6010161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(NULL);
6020161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    cur = &filename[strlen(filename)];
6030161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    while ((cur > filename) && (*cur != '/'))
6040161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        cur--;
6050161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (*cur == '/')
6060161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(cur + 1);
6070161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(cur);
6080161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
6090161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6100161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic char *resultFilename(const char *filename, const char *out,
6110161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                            const char *suffix) {
6120161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    const char *base;
6130161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    char res[500];
6140161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    char suffixbuff[500];
6150161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6160161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/*************
6170161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((filename[0] == 't') && (filename[1] == 'e') &&
6180161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        (filename[2] == 's') && (filename[3] == 't') &&
6190161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	(filename[4] == '/'))
6200161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	filename = &filename[5];
6210161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *************/
6220161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6230161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    base = baseFilename(filename);
6240161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (suffix == NULL)
6250161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        suffix = ".tmp";
6260161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (out == NULL)
6270161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        out = "";
6280161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6290161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    strncpy(suffixbuff,suffix,499);
6300161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#ifdef VMS
6310161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if(strstr(base,".") && suffixbuff[0]=='.')
6320161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard      suffixbuff[0]='_';
6330161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#endif
6340161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6350161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    snprintf(res, 499, "%s%s%s", out, base, suffixbuff);
6360161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    res[499] = 0;
6370161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(strdup(res));
6380161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
6390161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6400161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int checkTestFile(const char *filename) {
6410161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    struct stat buf;
6420161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6430161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (stat(filename, &buf) == -1)
6440161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(0);
6450161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6460161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#if defined(_WIN32) && !defined(__CYGWIN__)
6470161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (!(buf.st_mode & _S_IFREG))
6480161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(0);
6490161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#else
6500161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (!S_ISREG(buf.st_mode))
6510161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(0);
6520161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#endif
6530161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6540161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(1);
6550161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
6560161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6570161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6580161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6590161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/************************************************************************
6600161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
6610161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *		Test to detect or not recursive entities		*
6620161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
6630161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard ************************************************************************/
6640161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/**
6650161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * recursiveDetectTest:
6660161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @filename: the file to parse
6670161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @result: the file with expected result
6680161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @err: the file with error messages: unused
6690161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
6700161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Parse a file loading DTD and replacing entities check it fails for
6710161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * lol cases
6720161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
6730161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Returns 0 in case of success, an error code otherwise
6740161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
6750161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int
6760161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardrecursiveDetectTest(const char *filename,
6770161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard             const char *result ATTRIBUTE_UNUSED,
6780161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard             const char *err ATTRIBUTE_UNUSED,
6790161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	     int options ATTRIBUTE_UNUSED) {
6800161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlDocPtr doc;
6810161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlParserCtxtPtr ctxt;
6820161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int res = 0;
6830161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6840161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    nb_tests++;
6850161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
6860161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    ctxt = xmlNewParserCtxt();
6870161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /*
6880161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard     * base of the test, parse with the old API
6890161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard     */
6900161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    doc = xmlCtxtReadFile(ctxt, filename, NULL,
6910161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                          XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
6920161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((doc != NULL) || (ctxt->lastError.code != XML_ERR_ENTITY_LOOP)) {
6930161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        fprintf(stderr, "Failed to detect recursion in %s\n", filename);
6940161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	xmlFreeParserCtxt(ctxt);
6950161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	xmlFreeDoc(doc);
6960161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(1);
6970161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
6980161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlFreeParserCtxt(ctxt);
6990161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7000161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(res);
7010161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
7020161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7030161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/**
7040161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * notRecursiveDetectTest:
7050161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @filename: the file to parse
7060161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @result: the file with expected result
7070161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @err: the file with error messages: unused
7080161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
7090161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Parse a file loading DTD and replacing entities check it works for
7100161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * good cases
7110161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
7120161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Returns 0 in case of success, an error code otherwise
7130161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
7140161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int
7150161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardnotRecursiveDetectTest(const char *filename,
7160161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard             const char *result ATTRIBUTE_UNUSED,
7170161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard             const char *err ATTRIBUTE_UNUSED,
7180161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	     int options ATTRIBUTE_UNUSED) {
7190161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlDocPtr doc;
7200161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlParserCtxtPtr ctxt;
7210161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int res = 0;
7220161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7230161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    nb_tests++;
7240161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7250161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    ctxt = xmlNewParserCtxt();
7260161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    /*
7270161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard     * base of the test, parse with the old API
7280161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard     */
7290161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    doc = xmlCtxtReadFile(ctxt, filename, NULL,
7300161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                          XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
7310161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (doc == NULL) {
7320161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        fprintf(stderr, "Failed to parse correct file %s\n", filename);
7330161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	xmlFreeParserCtxt(ctxt);
7340161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        return(1);
7350161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
7360161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlFreeDoc(doc);
7370161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlFreeParserCtxt(ctxt);
7380161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7390161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(res);
7400161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
7410161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7420161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#ifdef LIBXML_READER_ENABLED
7430161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/**
7440161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * notRecursiveHugeTest:
7450161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @filename: the file to parse
7460161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @result: the file with expected result
7470161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * @err: the file with error messages: unused
7480161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
7490161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Parse a memory generated file
7500161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * good cases
7510161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *
7520161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard * Returns 0 in case of success, an error code otherwise
7530161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard */
7540161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int
7550161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardnotRecursiveHugeTest(const char *filename ATTRIBUTE_UNUSED,
7560161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard             const char *result ATTRIBUTE_UNUSED,
7570161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard             const char *err ATTRIBUTE_UNUSED,
7580161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	     int options ATTRIBUTE_UNUSED) {
7590161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlTextReaderPtr reader;
7600161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int res = 0;
7610161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int ret;
7620161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7630161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    nb_tests++;
7640161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7650161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    reader = xmlReaderForFile("huge:test" , NULL,
7660161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard                              XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
7670161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (reader == NULL) {
7680161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        fprintf(stderr, "Failed to open huge:test\n");
7690161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	return(1);
7700161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
7710161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    ret = xmlTextReaderRead(reader);
7720161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    while (ret == 1) {
7730161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        ret = xmlTextReaderRead(reader);
7740161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
7750161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (ret != 0) {
7760161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        fprintf(stderr, "Failed to parser huge:test with entities\n");
7770161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	res = 1;
7780161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
7790161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlFreeTextReader(reader);
7800161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7810161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(res);
7820161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
7830161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#endif
7840161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7850161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/************************************************************************
7860161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
7870161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *			Tests Descriptions				*
7880161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
7890161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard ************************************************************************/
7900161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
7910161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic
7920161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardtestDesc testDescriptions[] = {
7930161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    { "Parsing recursive test cases" ,
7940161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard      recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL,
7950161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard      0 },
7960161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    { "Parsing non-recursive test cases" ,
7970161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard      notRecursiveDetectTest, "./test/recurse/good*.xml", NULL, NULL, NULL,
7980161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard      0 },
7990161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#ifdef LIBXML_READER_ENABLED
8000161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    { "Parsing non-recursive huge case" ,
8010161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard      notRecursiveHugeTest, NULL, NULL, NULL, NULL,
8020161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard      0 },
8030161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard#endif
8040161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    {NULL, NULL, NULL, NULL, NULL, NULL, 0}
8050161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard};
8060161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
8070161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard/************************************************************************
8080161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
8090161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *		The main code driving the tests				*
8100161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard *									*
8110161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard ************************************************************************/
8120161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
8130161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int
8140161e638c697890020c410dbedec9bb516d0fe49Daniel VeillardlaunchTests(testDescPtr tst) {
8150161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int res = 0, err = 0;
8160161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    size_t i;
8170161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    char *result;
8180161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    char *error;
8190161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int mem;
8200161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
8210161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (tst == NULL) return(-1);
8220161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (tst->in != NULL) {
8230161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	glob_t globbuf;
8240161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
8250161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	globbuf.gl_offs = 0;
8260161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
8270161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	for (i = 0;i < globbuf.gl_pathc;i++) {
8280161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    if (!checkTestFile(globbuf.gl_pathv[i]))
8290161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	        continue;
8300161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    if (tst->suffix != NULL) {
8310161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		result = resultFilename(globbuf.gl_pathv[i], tst->out,
8320161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard					tst->suffix);
8330161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		if (result == NULL) {
8340161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    fprintf(stderr, "Out of memory !\n");
8350161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    fatalError();
8360161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		}
8370161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    } else {
8380161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	        result = NULL;
8390161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    }
8400161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    if (tst->err != NULL) {
8410161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		error = resultFilename(globbuf.gl_pathv[i], tst->out,
8420161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		                        tst->err);
8430161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		if (error == NULL) {
8440161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    fprintf(stderr, "Out of memory !\n");
8450161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    fatalError();
8460161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		}
8470161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    } else {
8480161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	        error = NULL;
8490161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    }
8500161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    if ((result) &&(!checkTestFile(result))) {
8510161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	        fprintf(stderr, "Missing result file %s\n", result);
8520161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    } else if ((error) &&(!checkTestFile(error))) {
8530161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	        fprintf(stderr, "Missing error file %s\n", error);
8540161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    } else {
8550161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		mem = xmlMemUsed();
8560161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		extraMemoryFromResolver = 0;
8570161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		testErrorsSize = 0;
8580161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		testErrors[0] = 0;
8590161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		res = tst->func(globbuf.gl_pathv[i], result, error,
8600161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		                tst->options | XML_PARSE_COMPACT);
8610161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		xmlResetLastError();
8620161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		if (res != 0) {
8630161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    fprintf(stderr, "File %s generated an error\n",
8640161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		            globbuf.gl_pathv[i]);
8650161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    nb_errors++;
8660161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    err++;
8670161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		}
8680161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		else if (xmlMemUsed() != mem) {
8690161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    if ((xmlMemUsed() != mem) &&
8700161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		        (extraMemoryFromResolver == 0)) {
8710161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard			fprintf(stderr, "File %s leaked %d bytes\n",
8720161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard				globbuf.gl_pathv[i], xmlMemUsed() - mem);
8730161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard			nb_leaks++;
8740161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard			err++;
8750161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    }
8760161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		}
8770161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		testErrorsSize = 0;
8780161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    }
8790161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    if (result)
8800161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		free(result);
8810161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    if (error)
8820161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		free(error);
8830161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	}
8840161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	globfree(&globbuf);
8850161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    } else {
8860161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        testErrorsSize = 0;
8870161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	testErrors[0] = 0;
8880161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	extraMemoryFromResolver = 0;
8890161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        res = tst->func(NULL, NULL, NULL, tst->options);
8900161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	if (res != 0) {
8910161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    nb_errors++;
8920161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    err++;
8930161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	}
8940161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
8950161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(err);
8960161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
8970161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
8980161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int verbose = 0;
8990161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int tests_quiet = 0;
9000161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
9010161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardstatic int
9020161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardruntest(int i) {
9030161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int ret = 0, res;
9040161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int old_errors, old_tests, old_leaks;
9050161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
9060161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    old_errors = nb_errors;
9070161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    old_tests = nb_tests;
9080161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    old_leaks = nb_leaks;
9090161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
9100161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	printf("## %s\n", testDescriptions[i].desc);
9110161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    res = launchTests(&testDescriptions[i]);
9120161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (res != 0)
9130161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	ret++;
9140161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (verbose) {
9150161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
9160161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    printf("Ran %d tests, no errors\n", nb_tests - old_tests);
9170161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	else
9180161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    printf("Ran %d tests, %d errors, %d leaks\n",
9190161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		   nb_tests - old_tests,
9200161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		   nb_errors - old_errors,
9210161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		   nb_leaks - old_leaks);
9220161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
9230161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(ret);
9240161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
9250161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
9260161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardint
9270161e638c697890020c410dbedec9bb516d0fe49Daniel Veillardmain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
9280161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int i, a, ret = 0;
9290161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    int subset = 0;
9300161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
9310161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    initializeLibxml2();
9320161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
9330161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    for (a = 1; a < argc;a++) {
9340161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        if (!strcmp(argv[a], "-v"))
9350161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    verbose = 1;
9360161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        else if (!strcmp(argv[a], "-quiet"))
9370161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    tests_quiet = 1;
9380161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	else {
9390161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    for (i = 0; testDescriptions[i].func != NULL; i++) {
9400161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	        if (strstr(testDescriptions[i].desc, argv[a])) {
9410161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    ret += runtest(i);
9420161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		    subset++;
9430161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard		}
9440161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    }
9450161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	}
9460161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
9470161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if (subset == 0) {
9480161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	for (i = 0; testDescriptions[i].func != NULL; i++) {
9490161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	    ret += runtest(i);
9500161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	}
9510161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
9520161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    if ((nb_errors == 0) && (nb_leaks == 0)) {
9530161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        ret = 0;
9540161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	printf("Total %d tests, no errors\n",
9550161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	       nb_tests);
9560161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    } else {
9570161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard        ret = 1;
9580161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	printf("Total %d tests, %d errors, %d leaks\n",
9590161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard	       nb_tests, nb_errors, nb_leaks);
9600161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    }
9610161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlCleanupParser();
9620161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    xmlMemoryDump();
9630161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard
9640161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard    return(ret);
9650161e638c697890020c410dbedec9bb516d0fe49Daniel Veillard}
966