Blame testlimits.c

Packit 423ecb
/*
Packit 423ecb
 * testlimits.c: C program to run libxml2 regression tests checking various
Packit 423ecb
 *       limits in document size. Will consume a lot of RAM and CPU cycles
Packit 423ecb
 *
Packit 423ecb
 * To compile on Unixes:
Packit 423ecb
 * cc -o testlimits `xml2-config --cflags` testlimits.c `xml2-config --libs` -lpthread
Packit 423ecb
 *
Packit 423ecb
 * See Copyright for the status of this software.
Packit 423ecb
 *
Packit 423ecb
 * daniel@veillard.com
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
#include "libxml.h"
Packit 423ecb
#include <stdio.h>
Packit 423ecb
Packit 423ecb
#if !defined(_WIN32) || defined(__CYGWIN__)
Packit 423ecb
#include <unistd.h>
Packit 423ecb
#endif
Packit 423ecb
#include <string.h>
Packit 423ecb
#include <sys/types.h>
Packit 423ecb
#include <sys/stat.h>
Packit 423ecb
#include <fcntl.h>
Packit 423ecb
#include <time.h>
Packit 423ecb
Packit 423ecb
#include <libxml/parser.h>
Packit 423ecb
#include <libxml/parserInternals.h>
Packit 423ecb
#include <libxml/tree.h>
Packit 423ecb
#include <libxml/uri.h>
Packit 423ecb
#ifdef LIBXML_READER_ENABLED
Packit 423ecb
#include <libxml/xmlreader.h>
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
static int verbose = 0;
Packit 423ecb
static int tests_quiet = 0;
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		time handling                                           *
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
/* maximum time for one parsing before declaring a timeout */
Packit 423ecb
#define MAX_TIME 2 /* seconds */
Packit 423ecb
Packit 423ecb
static clock_t t0;
Packit 423ecb
int timeout = 0;
Packit 423ecb
Packit 423ecb
static void reset_timout(void) {
Packit 423ecb
    timeout = 0;
Packit 423ecb
    t0 = clock();
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static int check_time(void) {
Packit 423ecb
    clock_t tnow = clock();
Packit 423ecb
    if (((tnow - t0) / CLOCKS_PER_SEC) > MAX_TIME) {
Packit 423ecb
        timeout = 1;
Packit 423ecb
        return(0);
Packit 423ecb
    }
Packit 423ecb
    return(1);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		Huge document generator					*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
#include <libxml/xmlIO.h>
Packit 423ecb
Packit 423ecb
/*
Packit 423ecb
 * Huge documents are built using fixed start and end chunks
Packit 423ecb
 * and filling between the two an unconventional amount of char data
Packit 423ecb
 */
Packit 423ecb
typedef struct hugeTest hugeTest;
Packit 423ecb
typedef hugeTest *hugeTestPtr;
Packit 423ecb
struct hugeTest {
Packit 423ecb
    const char *description;
Packit 423ecb
    const char *name;
Packit 423ecb
    const char *start;
Packit 423ecb
    const char *end;
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
static struct hugeTest hugeTests[] = {
Packit 423ecb
    { "Huge text node", "huge:textNode", "<foo>", "</foo>" },
Packit 423ecb
    { "Huge attribute node", "huge:attrNode", "<foo bar='", "'/>" },
Packit 423ecb
    { "Huge comment node", "huge:commentNode", "<foo></foo>" },
Packit 423ecb
    { "Huge PI node", "huge:piNode", "<foo></foo>" },
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
static const char *current;
Packit 423ecb
static int rlen;
Packit 423ecb
static unsigned int currentTest = 0;
Packit 423ecb
static int instate = 0;
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * hugeMatch:
Packit 423ecb
 * @URI: an URI to test
Packit 423ecb
 *
Packit 423ecb
 * Check for an huge: query
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if yes and 0 if another Input module should be used
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
hugeMatch(const char * URI) {
Packit 423ecb
    if ((URI != NULL) && (!strncmp(URI, "huge:", 5)))
Packit 423ecb
        return(1);
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * hugeOpen:
Packit 423ecb
 * @URI: an URI to test
Packit 423ecb
 *
Packit 423ecb
 * Return a pointer to the huge: query handler, in this example simply
Packit 423ecb
 * the current pointer...
Packit 423ecb
 *
Packit 423ecb
 * Returns an Input context or NULL in case or error
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
hugeOpen(const char * URI) {
Packit 423ecb
    if ((URI == NULL) || (strncmp(URI, "huge:", 5)))
Packit 423ecb
        return(NULL);
Packit 423ecb
Packit 423ecb
    for (currentTest = 0;currentTest < sizeof(hugeTests)/sizeof(hugeTests[0]);
Packit 423ecb
         currentTest++)
Packit 423ecb
         if (!strcmp(hugeTests[currentTest].name, URI))
Packit 423ecb
             goto found;
Packit 423ecb
Packit 423ecb
    return(NULL);
Packit 423ecb
Packit 423ecb
found:
Packit 423ecb
    rlen = strlen(hugeTests[currentTest].start);
Packit 423ecb
    current = hugeTests[currentTest].start;
Packit 423ecb
    instate = 0;
Packit 423ecb
    return((void *) current);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * hugeClose:
Packit 423ecb
 * @context: the read context
Packit 423ecb
 *
Packit 423ecb
 * Close the huge: query handler
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 or -1 in case of error
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
hugeClose(void * context) {
Packit 423ecb
    if (context == NULL) return(-1);
Packit 423ecb
    fprintf(stderr, "\n");
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#define CHUNK 4096
Packit 423ecb
Packit 423ecb
char filling[CHUNK + 1];
Packit 423ecb
Packit 423ecb
static void fillFilling(void) {
Packit 423ecb
    int i;
Packit 423ecb
Packit 423ecb
    for (i = 0;i < CHUNK;i++) {
Packit 423ecb
        filling[i] = 'a';
Packit 423ecb
    }
Packit 423ecb
    filling[CHUNK] = 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
size_t maxlen = 64 * 1024 * 1024;
Packit 423ecb
size_t curlen = 0;
Packit 423ecb
size_t dotlen;
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * hugeRead:
Packit 423ecb
 * @context: the read context
Packit 423ecb
 * @buffer: where to store data
Packit 423ecb
 * @len: number of bytes to read
Packit 423ecb
 *
Packit 423ecb
 * Implement an huge: query read.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes read or -1 in case of error
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
hugeRead(void *context, char *buffer, int len)
Packit 423ecb
{
Packit 423ecb
    if ((context == NULL) || (buffer == NULL) || (len < 0))
Packit 423ecb
        return (-1);
Packit 423ecb
Packit 423ecb
    if (instate == 0) {
Packit 423ecb
        if (len >= rlen) {
Packit 423ecb
            len = rlen;
Packit 423ecb
            rlen = 0;
Packit 423ecb
            memcpy(buffer, current, len);
Packit 423ecb
            instate = 1;
Packit 423ecb
            curlen = 0;
Packit 423ecb
            dotlen = maxlen / 10;
Packit 423ecb
        } else {
Packit 423ecb
            memcpy(buffer, current, len);
Packit 423ecb
            rlen -= len;
Packit 423ecb
            current += len;
Packit 423ecb
        }
Packit 423ecb
    } else if (instate == 2) {
Packit 423ecb
        if (len >= rlen) {
Packit 423ecb
            len = rlen;
Packit 423ecb
            rlen = 0;
Packit 423ecb
            memcpy(buffer, current, len);
Packit 423ecb
            instate = 3;
Packit 423ecb
            curlen = 0;
Packit 423ecb
        } else {
Packit 423ecb
            memcpy(buffer, current, len);
Packit 423ecb
            rlen -= len;
Packit 423ecb
            current += len;
Packit 423ecb
        }
Packit 423ecb
    } else if (instate == 1) {
Packit 423ecb
        if (len > CHUNK) len = CHUNK;
Packit 423ecb
        memcpy(buffer, &filling[0], len);
Packit 423ecb
        curlen += len;
Packit 423ecb
        if (curlen >= maxlen) {
Packit 423ecb
            rlen = strlen(hugeTests[currentTest].end);
Packit 423ecb
            current = hugeTests[currentTest].end;
Packit 423ecb
            instate = 2;
Packit 423ecb
	} else {
Packit 423ecb
            if (curlen > dotlen) {
Packit 423ecb
                fprintf(stderr, ".");
Packit 423ecb
                dotlen += maxlen / 10;
Packit 423ecb
            }
Packit 423ecb
        }
Packit 423ecb
    } else
Packit 423ecb
      len = 0;
Packit 423ecb
    return (len);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		Crazy document generator				*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
unsigned int crazy_indx = 0;
Packit 423ecb
Packit 423ecb
const char *crazy = "\
Packit 423ecb
\
Packit 423ecb
\
Packit 423ecb
Packit 423ecb
\
Packit 423ecb
\
Packit 423ecb
\
Packit 423ecb
\
Packit 423ecb
]>\
Packit 423ecb
\
Packit 423ecb
\
Packit 423ecb
<foo bar='foo'>\
Packit 423ecb
\
Packit 423ecb
\
Packit 423ecb
foo\
Packit 423ecb
\
Packit 423ecb
</foo>\
Packit 423ecb
\
Packit 423ecb
";
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * crazyMatch:
Packit 423ecb
 * @URI: an URI to test
Packit 423ecb
 *
Packit 423ecb
 * Check for a crazy: query
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if yes and 0 if another Input module should be used
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
crazyMatch(const char * URI) {
Packit 423ecb
    if ((URI != NULL) && (!strncmp(URI, "crazy:", 6)))
Packit 423ecb
        return(1);
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * crazyOpen:
Packit 423ecb
 * @URI: an URI to test
Packit 423ecb
 *
Packit 423ecb
 * Return a pointer to the crazy: query handler, in this example simply
Packit 423ecb
 * the current pointer...
Packit 423ecb
 *
Packit 423ecb
 * Returns an Input context or NULL in case or error
Packit 423ecb
 */
Packit 423ecb
static void *
Packit 423ecb
crazyOpen(const char * URI) {
Packit 423ecb
    if ((URI == NULL) || (strncmp(URI, "crazy:", 6)))
Packit 423ecb
        return(NULL);
Packit 423ecb
Packit 423ecb
    if (crazy_indx > strlen(crazy))
Packit 423ecb
        return(NULL);
Packit 423ecb
    reset_timout();
Packit 423ecb
    rlen = crazy_indx;
Packit 423ecb
    current = &crazy[0];
Packit 423ecb
    instate = 0;
Packit 423ecb
    return((void *) current);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * crazyClose:
Packit 423ecb
 * @context: the read context
Packit 423ecb
 *
Packit 423ecb
 * Close the crazy: query handler
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 or -1 in case of error
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
crazyClose(void * context) {
Packit 423ecb
    if (context == NULL) return(-1);
Packit 423ecb
    return(0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * crazyRead:
Packit 423ecb
 * @context: the read context
Packit 423ecb
 * @buffer: where to store data
Packit 423ecb
 * @len: number of bytes to read
Packit 423ecb
 *
Packit 423ecb
 * Implement an crazy: query read.
Packit 423ecb
 *
Packit 423ecb
 * Returns the number of bytes read or -1 in case of error
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
crazyRead(void *context, char *buffer, int len)
Packit 423ecb
{
Packit 423ecb
    if ((context == NULL) || (buffer == NULL) || (len < 0))
Packit 423ecb
        return (-1);
Packit 423ecb
Packit 423ecb
    if ((check_time() <= 0) && (instate == 1)) {
Packit 423ecb
        fprintf(stderr, "\ntimeout in crazy(%d)\n", crazy_indx);
Packit 423ecb
        rlen = strlen(crazy) - crazy_indx;
Packit 423ecb
        current = &crazy[crazy_indx];
Packit 423ecb
        instate = 2;
Packit 423ecb
    }
Packit 423ecb
    if (instate == 0) {
Packit 423ecb
        if (len >= rlen) {
Packit 423ecb
            len = rlen;
Packit 423ecb
            rlen = 0;
Packit 423ecb
            memcpy(buffer, current, len);
Packit 423ecb
            instate = 1;
Packit 423ecb
            curlen = 0;
Packit 423ecb
        } else {
Packit 423ecb
            memcpy(buffer, current, len);
Packit 423ecb
            rlen -= len;
Packit 423ecb
            current += len;
Packit 423ecb
        }
Packit 423ecb
    } else if (instate == 2) {
Packit 423ecb
        if (len >= rlen) {
Packit 423ecb
            len = rlen;
Packit 423ecb
            rlen = 0;
Packit 423ecb
            memcpy(buffer, current, len);
Packit 423ecb
            instate = 3;
Packit 423ecb
            curlen = 0;
Packit 423ecb
        } else {
Packit 423ecb
            memcpy(buffer, current, len);
Packit 423ecb
            rlen -= len;
Packit 423ecb
            current += len;
Packit 423ecb
        }
Packit 423ecb
    } else if (instate == 1) {
Packit 423ecb
        if (len > CHUNK) len = CHUNK;
Packit 423ecb
        memcpy(buffer, &filling[0], len);
Packit 423ecb
        curlen += len;
Packit 423ecb
        if (curlen >= maxlen) {
Packit 423ecb
            rlen = strlen(crazy) - crazy_indx;
Packit 423ecb
            current = &crazy[crazy_indx];
Packit 423ecb
            instate = 2;
Packit 423ecb
        }
Packit 423ecb
    } else
Packit 423ecb
      len = 0;
Packit 423ecb
    return (len);
Packit 423ecb
}
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		Libxml2 specific routines				*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
static int nb_tests = 0;
Packit 423ecb
static int nb_errors = 0;
Packit 423ecb
static int nb_leaks = 0;
Packit 423ecb
static int extraMemoryFromResolver = 0;
Packit 423ecb
Packit 423ecb
/*
Packit 423ecb
 * We need to trap calls to the resolver to not account memory for the catalog
Packit 423ecb
 * which is shared to the current running test. We also don't want to have
Packit 423ecb
 * network downloads modifying tests.
Packit 423ecb
 */
Packit 423ecb
static xmlParserInputPtr
Packit 423ecb
testExternalEntityLoader(const char *URL, const char *ID,
Packit 423ecb
			 xmlParserCtxtPtr ctxt) {
Packit 423ecb
    xmlParserInputPtr ret;
Packit 423ecb
    int memused = xmlMemUsed();
Packit 423ecb
Packit 423ecb
    ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
Packit 423ecb
    extraMemoryFromResolver += xmlMemUsed() - memused;
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/*
Packit 423ecb
 * Trapping the error messages at the generic level to grab the equivalent of
Packit 423ecb
 * stderr messages on CLI tools.
Packit 423ecb
 */
Packit 423ecb
static char testErrors[32769];
Packit 423ecb
static int testErrorsSize = 0;
Packit 423ecb
Packit 423ecb
static void XMLCDECL
Packit 423ecb
channel(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
Packit 423ecb
    va_list args;
Packit 423ecb
    int res;
Packit 423ecb
Packit 423ecb
    if (testErrorsSize >= 32768)
Packit 423ecb
        return;
Packit 423ecb
    va_start(args, msg);
Packit 423ecb
    res = vsnprintf(&testErrors[testErrorsSize],
Packit 423ecb
                    32768 - testErrorsSize,
Packit 423ecb
		    msg, args);
Packit 423ecb
    va_end(args);
Packit 423ecb
    if (testErrorsSize + res >= 32768) {
Packit 423ecb
        /* buffer is full */
Packit 423ecb
	testErrorsSize = 32768;
Packit 423ecb
	testErrors[testErrorsSize] = 0;
Packit 423ecb
    } else {
Packit 423ecb
        testErrorsSize += res;
Packit 423ecb
    }
Packit 423ecb
    testErrors[testErrorsSize] = 0;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * xmlParserPrintFileContext:
Packit 423ecb
 * @input:  an xmlParserInputPtr input
Packit 423ecb
 *
Packit 423ecb
 * Displays current context within the input content for error tracking
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
static void
Packit 423ecb
xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
Packit 423ecb
		xmlGenericErrorFunc chanl, void *data ) {
Packit 423ecb
    const xmlChar *cur, *base;
Packit 423ecb
    unsigned int n, col;	/* GCC warns if signed, because compared with sizeof() */
Packit 423ecb
    xmlChar  content[81]; /* space for 80 chars + line terminator */
Packit 423ecb
    xmlChar *ctnt;
Packit 423ecb
Packit 423ecb
    if (input == NULL) return;
Packit 423ecb
    cur = input->cur;
Packit 423ecb
    base = input->base;
Packit 423ecb
    /* skip backwards over any end-of-lines */
Packit 423ecb
    while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
Packit 423ecb
	cur--;
Packit 423ecb
    }
Packit 423ecb
    n = 0;
Packit 423ecb
    /* search backwards for beginning-of-line (to max buff size) */
Packit 423ecb
    while ((n++ < (sizeof(content)-1)) && (cur > base) &&
Packit 423ecb
   (*(cur) != '\n') && (*(cur) != '\r'))
Packit 423ecb
        cur--;
Packit 423ecb
    if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
Packit 423ecb
    /* calculate the error position in terms of the current position */
Packit 423ecb
    col = input->cur - cur;
Packit 423ecb
    /* search forward for end-of-line (to max buff size) */
Packit 423ecb
    n = 0;
Packit 423ecb
    ctnt = content;
Packit 423ecb
    /* copy selected text to our buffer */
Packit 423ecb
    while ((*cur != 0) && (*(cur) != '\n') &&
Packit 423ecb
   (*(cur) != '\r') && (n < sizeof(content)-1)) {
Packit 423ecb
		*ctnt++ = *cur++;
Packit 423ecb
	n++;
Packit 423ecb
    }
Packit 423ecb
    *ctnt = 0;
Packit 423ecb
    /* print out the selected text */
Packit 423ecb
    chanl(data ,"%s\n", content);
Packit 423ecb
    /* create blank line with problem pointer */
Packit 423ecb
    n = 0;
Packit 423ecb
    ctnt = content;
Packit 423ecb
    /* (leave buffer space for pointer + line terminator) */
Packit 423ecb
    while ((n
Packit 423ecb
	if (*(ctnt) != '\t')
Packit 423ecb
	    *(ctnt) = ' ';
Packit 423ecb
	ctnt++;
Packit 423ecb
    }
Packit 423ecb
    *ctnt++ = '^';
Packit 423ecb
    *ctnt = 0;
Packit 423ecb
    chanl(data ,"%s\n", content);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static void
Packit 423ecb
testStructuredErrorHandler(void *ctx  ATTRIBUTE_UNUSED, xmlErrorPtr err) {
Packit 423ecb
    char *file = NULL;
Packit 423ecb
    int line = 0;
Packit 423ecb
    int code = -1;
Packit 423ecb
    int domain;
Packit 423ecb
    void *data = NULL;
Packit 423ecb
    const char *str;
Packit 423ecb
    const xmlChar *name = NULL;
Packit 423ecb
    xmlNodePtr node;
Packit 423ecb
    xmlErrorLevel level;
Packit 423ecb
    xmlParserInputPtr input = NULL;
Packit 423ecb
    xmlParserInputPtr cur = NULL;
Packit 423ecb
    xmlParserCtxtPtr ctxt = NULL;
Packit 423ecb
Packit 423ecb
    if (err == NULL)
Packit 423ecb
        return;
Packit 423ecb
Packit 423ecb
    file = err->file;
Packit 423ecb
    line = err->line;
Packit 423ecb
    code = err->code;
Packit 423ecb
    domain = err->domain;
Packit 423ecb
    level = err->level;
Packit 423ecb
    node = err->node;
Packit 423ecb
    if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
Packit 423ecb
        (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
Packit 423ecb
	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
Packit 423ecb
	ctxt = err->ctxt;
Packit 423ecb
    }
Packit 423ecb
    str = err->message;
Packit 423ecb
Packit 423ecb
    if (code == XML_ERR_OK)
Packit 423ecb
        return;
Packit 423ecb
Packit 423ecb
    if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
Packit 423ecb
        name = node->name;
Packit 423ecb
Packit 423ecb
    /*
Packit 423ecb
     * Maintain the compatibility with the legacy error handling
Packit 423ecb
     */
Packit 423ecb
    if (ctxt != NULL) {
Packit 423ecb
        input = ctxt->input;
Packit 423ecb
        if ((input != NULL) && (input->filename == NULL) &&
Packit 423ecb
            (ctxt->inputNr > 1)) {
Packit 423ecb
            cur = input;
Packit 423ecb
            input = ctxt->inputTab[ctxt->inputNr - 2];
Packit 423ecb
        }
Packit 423ecb
        if (input != NULL) {
Packit 423ecb
            if (input->filename)
Packit 423ecb
                channel(data, "%s:%d: ", input->filename, input->line);
Packit 423ecb
            else if ((line != 0) && (domain == XML_FROM_PARSER))
Packit 423ecb
                channel(data, "Entity: line %d: ", input->line);
Packit 423ecb
        }
Packit 423ecb
    } else {
Packit 423ecb
        if (file != NULL)
Packit 423ecb
            channel(data, "%s:%d: ", file, line);
Packit 423ecb
        else if ((line != 0) && (domain == XML_FROM_PARSER))
Packit 423ecb
            channel(data, "Entity: line %d: ", line);
Packit 423ecb
    }
Packit 423ecb
    if (name != NULL) {
Packit 423ecb
        channel(data, "element %s: ", name);
Packit 423ecb
    }
Packit 423ecb
    if (code == XML_ERR_OK)
Packit 423ecb
        return;
Packit 423ecb
    switch (domain) {
Packit 423ecb
        case XML_FROM_PARSER:
Packit 423ecb
            channel(data, "parser ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_NAMESPACE:
Packit 423ecb
            channel(data, "namespace ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_DTD:
Packit 423ecb
        case XML_FROM_VALID:
Packit 423ecb
            channel(data, "validity ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_HTML:
Packit 423ecb
            channel(data, "HTML parser ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_MEMORY:
Packit 423ecb
            channel(data, "memory ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_OUTPUT:
Packit 423ecb
            channel(data, "output ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_IO:
Packit 423ecb
            channel(data, "I/O ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_XINCLUDE:
Packit 423ecb
            channel(data, "XInclude ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_XPATH:
Packit 423ecb
            channel(data, "XPath ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_XPOINTER:
Packit 423ecb
            channel(data, "parser ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_REGEXP:
Packit 423ecb
            channel(data, "regexp ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_MODULE:
Packit 423ecb
            channel(data, "module ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_SCHEMASV:
Packit 423ecb
            channel(data, "Schemas validity ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_SCHEMASP:
Packit 423ecb
            channel(data, "Schemas parser ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_RELAXNGP:
Packit 423ecb
            channel(data, "Relax-NG parser ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_RELAXNGV:
Packit 423ecb
            channel(data, "Relax-NG validity ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_CATALOG:
Packit 423ecb
            channel(data, "Catalog ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_C14N:
Packit 423ecb
            channel(data, "C14N ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_FROM_XSLT:
Packit 423ecb
            channel(data, "XSLT ");
Packit 423ecb
            break;
Packit 423ecb
        default:
Packit 423ecb
            break;
Packit 423ecb
    }
Packit 423ecb
    if (code == XML_ERR_OK)
Packit 423ecb
        return;
Packit 423ecb
    switch (level) {
Packit 423ecb
        case XML_ERR_NONE:
Packit 423ecb
            channel(data, ": ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_ERR_WARNING:
Packit 423ecb
            channel(data, "warning : ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_ERR_ERROR:
Packit 423ecb
            channel(data, "error : ");
Packit 423ecb
            break;
Packit 423ecb
        case XML_ERR_FATAL:
Packit 423ecb
            channel(data, "error : ");
Packit 423ecb
            break;
Packit 423ecb
    }
Packit 423ecb
    if (code == XML_ERR_OK)
Packit 423ecb
        return;
Packit 423ecb
    if (str != NULL) {
Packit 423ecb
        int len;
Packit 423ecb
	len = xmlStrlen((const xmlChar *)str);
Packit 423ecb
	if ((len > 0) && (str[len - 1] != '\n'))
Packit 423ecb
	    channel(data, "%s\n", str);
Packit 423ecb
	else
Packit 423ecb
	    channel(data, "%s", str);
Packit 423ecb
    } else {
Packit 423ecb
        channel(data, "%s\n", "out of memory error");
Packit 423ecb
    }
Packit 423ecb
    if (code == XML_ERR_OK)
Packit 423ecb
        return;
Packit 423ecb
Packit 423ecb
    if (ctxt != NULL) {
Packit 423ecb
        xmlParserPrintFileContextInternal(input, channel, data);
Packit 423ecb
        if (cur != NULL) {
Packit 423ecb
            if (cur->filename)
Packit 423ecb
                channel(data, "%s:%d: \n", cur->filename, cur->line);
Packit 423ecb
            else if ((line != 0) && (domain == XML_FROM_PARSER))
Packit 423ecb
                channel(data, "Entity: line %d: \n", cur->line);
Packit 423ecb
            xmlParserPrintFileContextInternal(cur, channel, data);
Packit 423ecb
        }
Packit 423ecb
    }
Packit 423ecb
    if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
Packit 423ecb
        (err->int1 < 100) &&
Packit 423ecb
	(err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
Packit 423ecb
	xmlChar buf[150];
Packit 423ecb
	int i;
Packit 423ecb
Packit 423ecb
	channel(data, "%s\n", err->str1);
Packit 423ecb
	for (i=0;i < err->int1;i++)
Packit 423ecb
	     buf[i] = ' ';
Packit 423ecb
	buf[i++] = '^';
Packit 423ecb
	buf[i] = 0;
Packit 423ecb
	channel(data, "%s\n", buf);
Packit 423ecb
    }
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static void
Packit 423ecb
initializeLibxml2(void) {
Packit 423ecb
    xmlGetWarningsDefaultValue = 0;
Packit 423ecb
    xmlPedanticParserDefault(0);
Packit 423ecb
Packit 423ecb
    xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
Packit 423ecb
    xmlInitParser();
Packit 423ecb
    xmlSetExternalEntityLoader(testExternalEntityLoader);
Packit 423ecb
    xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
Packit 423ecb
    /*
Packit 423ecb
     * register the new I/O handlers
Packit 423ecb
     */
Packit 423ecb
    if (xmlRegisterInputCallbacks(hugeMatch, hugeOpen,
Packit 423ecb
                                  hugeRead, hugeClose) < 0) {
Packit 423ecb
        fprintf(stderr, "failed to register Huge handlers\n");
Packit 423ecb
	exit(1);
Packit 423ecb
    }
Packit 423ecb
    if (xmlRegisterInputCallbacks(crazyMatch, crazyOpen,
Packit 423ecb
                                  crazyRead, crazyClose) < 0) {
Packit 423ecb
        fprintf(stderr, "failed to register Crazy handlers\n");
Packit 423ecb
	exit(1);
Packit 423ecb
    }
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		SAX empty callbacks                                     *
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
unsigned long callbacks = 0;
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * isStandaloneCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 *
Packit 423ecb
 * Is this document tagged standalone ?
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if true
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
isStandaloneCallback(void *ctx ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return (0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * hasInternalSubsetCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 *
Packit 423ecb
 * Does this document has an internal subset
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if true
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
hasInternalSubsetCallback(void *ctx ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return (0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * hasExternalSubsetCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 *
Packit 423ecb
 * Does this document has an external subset
Packit 423ecb
 *
Packit 423ecb
 * Returns 1 if true
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
hasExternalSubsetCallback(void *ctx ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return (0);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * internalSubsetCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 *
Packit 423ecb
 * Does this document has an internal subset
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
internalSubsetCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar * name ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar * ExternalID ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar * SystemID ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * externalSubsetCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 *
Packit 423ecb
 * Does this document has an external subset
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
externalSubsetCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar * name ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar * ExternalID ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar * SystemID ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * resolveEntityCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @publicId: The public ID of the entity
Packit 423ecb
 * @systemId: The system ID of the entity
Packit 423ecb
 *
Packit 423ecb
 * Special entity resolver, better left to the parser, it has
Packit 423ecb
 * more context than the application layer.
Packit 423ecb
 * The default behaviour is to NOT resolve the entities, in that case
Packit 423ecb
 * the ENTITY_REF nodes are built in the structure (and the parameter
Packit 423ecb
 * values).
Packit 423ecb
 *
Packit 423ecb
 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Packit 423ecb
 */
Packit 423ecb
static xmlParserInputPtr
Packit 423ecb
resolveEntityCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                      const xmlChar * publicId ATTRIBUTE_UNUSED,
Packit 423ecb
                      const xmlChar * systemId ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return (NULL);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * getEntityCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name: The entity name
Packit 423ecb
 *
Packit 423ecb
 * Get an entity by name
Packit 423ecb
 *
Packit 423ecb
 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Packit 423ecb
 */
Packit 423ecb
static xmlEntityPtr
Packit 423ecb
getEntityCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                  const xmlChar * name ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return (NULL);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * getParameterEntityCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name: The entity name
Packit 423ecb
 *
Packit 423ecb
 * Get a parameter entity by name
Packit 423ecb
 *
Packit 423ecb
 * Returns the xmlParserInputPtr
Packit 423ecb
 */
Packit 423ecb
static xmlEntityPtr
Packit 423ecb
getParameterEntityCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                           const xmlChar * name ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return (NULL);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * entityDeclCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name:  the entity name
Packit 423ecb
 * @type:  the entity type
Packit 423ecb
 * @publicId: The public ID of the entity
Packit 423ecb
 * @systemId: The system ID of the entity
Packit 423ecb
 * @content: the entity value (without processing).
Packit 423ecb
 *
Packit 423ecb
 * An entity definition has been parsed
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
entityDeclCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                   const xmlChar * name ATTRIBUTE_UNUSED,
Packit 423ecb
                   int type ATTRIBUTE_UNUSED,
Packit 423ecb
                   const xmlChar * publicId ATTRIBUTE_UNUSED,
Packit 423ecb
                   const xmlChar * systemId ATTRIBUTE_UNUSED,
Packit 423ecb
                   xmlChar * content ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * attributeDeclCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name:  the attribute name
Packit 423ecb
 * @type:  the attribute type
Packit 423ecb
 *
Packit 423ecb
 * An attribute definition has been parsed
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
attributeDeclCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                      const xmlChar * elem ATTRIBUTE_UNUSED,
Packit 423ecb
                      const xmlChar * name ATTRIBUTE_UNUSED,
Packit 423ecb
                      int type ATTRIBUTE_UNUSED, int def ATTRIBUTE_UNUSED,
Packit 423ecb
                      const xmlChar * defaultValue ATTRIBUTE_UNUSED,
Packit 423ecb
                      xmlEnumerationPtr tree ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * elementDeclCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name:  the element name
Packit 423ecb
 * @type:  the element type
Packit 423ecb
 * @content: the element value (without processing).
Packit 423ecb
 *
Packit 423ecb
 * An element definition has been parsed
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
elementDeclCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                    const xmlChar * name ATTRIBUTE_UNUSED,
Packit 423ecb
                    int type ATTRIBUTE_UNUSED,
Packit 423ecb
                    xmlElementContentPtr content ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * notationDeclCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name: The name of the notation
Packit 423ecb
 * @publicId: The public ID of the entity
Packit 423ecb
 * @systemId: The system ID of the entity
Packit 423ecb
 *
Packit 423ecb
 * What to do when a notation declaration has been parsed.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
notationDeclCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                     const xmlChar * name ATTRIBUTE_UNUSED,
Packit 423ecb
                     const xmlChar * publicId ATTRIBUTE_UNUSED,
Packit 423ecb
                     const xmlChar * systemId ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * unparsedEntityDeclCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name: The name of the entity
Packit 423ecb
 * @publicId: The public ID of the entity
Packit 423ecb
 * @systemId: The system ID of the entity
Packit 423ecb
 * @notationName: the name of the notation
Packit 423ecb
 *
Packit 423ecb
 * What to do when an unparsed entity declaration is parsed
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
unparsedEntityDeclCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                           const xmlChar * name ATTRIBUTE_UNUSED,
Packit 423ecb
                           const xmlChar * publicId ATTRIBUTE_UNUSED,
Packit 423ecb
                           const xmlChar * systemId ATTRIBUTE_UNUSED,
Packit 423ecb
                           const xmlChar * notationName ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * setDocumentLocatorCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @loc: A SAX Locator
Packit 423ecb
 *
Packit 423ecb
 * Receive the document locator at startup, actually xmlDefaultSAXLocator
Packit 423ecb
 * Everything is available on the context, so this is useless in our case.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
setDocumentLocatorCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                           xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * startDocumentCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 *
Packit 423ecb
 * called when the document start being processed.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
startDocumentCallback(void *ctx ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * endDocumentCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 *
Packit 423ecb
 * called when the document end has been detected.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
endDocumentCallback(void *ctx ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#if 0
Packit 423ecb
/**
Packit 423ecb
 * startElementCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name:  The element name
Packit 423ecb
 *
Packit 423ecb
 * called when an opening tag has been processed.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
startElementCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                     const xmlChar * name ATTRIBUTE_UNUSED,
Packit 423ecb
                     const xmlChar ** atts ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * endElementCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name:  The element name
Packit 423ecb
 *
Packit 423ecb
 * called when the end of an element has been detected.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
endElementCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                   const xmlChar * name ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * charactersCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @ch:  a xmlChar string
Packit 423ecb
 * @len: the number of xmlChar
Packit 423ecb
 *
Packit 423ecb
 * receiving some chars from the parser.
Packit 423ecb
 * Question: how much at a time ???
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
charactersCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                   const xmlChar * ch ATTRIBUTE_UNUSED,
Packit 423ecb
                   int len ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * referenceCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name:  The entity name
Packit 423ecb
 *
Packit 423ecb
 * called when an entity reference is detected.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
referenceCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                  const xmlChar * name ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * ignorableWhitespaceCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @ch:  a xmlChar string
Packit 423ecb
 * @start: the first char in the string
Packit 423ecb
 * @len: the number of xmlChar
Packit 423ecb
 *
Packit 423ecb
 * receiving some ignorable whitespaces from the parser.
Packit 423ecb
 * Question: how much at a time ???
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
ignorableWhitespaceCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                            const xmlChar * ch ATTRIBUTE_UNUSED,
Packit 423ecb
                            int len ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * processingInstructionCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @target:  the target name
Packit 423ecb
 * @data: the PI data's
Packit 423ecb
 * @len: the number of xmlChar
Packit 423ecb
 *
Packit 423ecb
 * A processing instruction has been parsed.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
processingInstructionCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                              const xmlChar * target ATTRIBUTE_UNUSED,
Packit 423ecb
                              const xmlChar * data ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * cdataBlockCallback:
Packit 423ecb
 * @ctx: the user data (XML parser context)
Packit 423ecb
 * @value:  The pcdata content
Packit 423ecb
 * @len:  the block length
Packit 423ecb
 *
Packit 423ecb
 * called when a pcdata block has been parsed
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
cdataBlockCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                   const xmlChar * value ATTRIBUTE_UNUSED,
Packit 423ecb
                   int len ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * commentCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @value:  the comment content
Packit 423ecb
 *
Packit 423ecb
 * A comment has been parsed.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
commentCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                const xmlChar * value ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * warningCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @msg:  the message to display/transmit
Packit 423ecb
 * @...:  extra parameters for the message display
Packit 423ecb
 *
Packit 423ecb
 * Display and format a warning messages, gives file, line, position and
Packit 423ecb
 * extra parameters.
Packit 423ecb
 */
Packit 423ecb
static void XMLCDECL
Packit 423ecb
warningCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                const char *msg ATTRIBUTE_UNUSED, ...)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * errorCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @msg:  the message to display/transmit
Packit 423ecb
 * @...:  extra parameters for the message display
Packit 423ecb
 *
Packit 423ecb
 * Display and format a error messages, gives file, line, position and
Packit 423ecb
 * extra parameters.
Packit 423ecb
 */
Packit 423ecb
static void XMLCDECL
Packit 423ecb
errorCallback(void *ctx ATTRIBUTE_UNUSED, const char *msg ATTRIBUTE_UNUSED,
Packit 423ecb
              ...)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * fatalErrorCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @msg:  the message to display/transmit
Packit 423ecb
 * @...:  extra parameters for the message display
Packit 423ecb
 *
Packit 423ecb
 * Display and format a fatalError messages, gives file, line, position and
Packit 423ecb
 * extra parameters.
Packit 423ecb
 */
Packit 423ecb
static void XMLCDECL
Packit 423ecb
fatalErrorCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                   const char *msg ATTRIBUTE_UNUSED, ...)
Packit 423ecb
{
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
/*
Packit 423ecb
 * SAX2 specific callbacks
Packit 423ecb
 */
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * startElementNsCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name:  The element name
Packit 423ecb
 *
Packit 423ecb
 * called when an opening tag has been processed.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
startElementNsCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar * localname ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar * prefix ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar * URI ATTRIBUTE_UNUSED,
Packit 423ecb
                       int nb_namespaces ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar ** namespaces ATTRIBUTE_UNUSED,
Packit 423ecb
                       int nb_attributes ATTRIBUTE_UNUSED,
Packit 423ecb
                       int nb_defaulted ATTRIBUTE_UNUSED,
Packit 423ecb
                       const xmlChar ** attributes ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * endElementCallback:
Packit 423ecb
 * @ctxt:  An XML parser context
Packit 423ecb
 * @name:  The element name
Packit 423ecb
 *
Packit 423ecb
 * called when the end of an element has been detected.
Packit 423ecb
 */
Packit 423ecb
static void
Packit 423ecb
endElementNsCallback(void *ctx ATTRIBUTE_UNUSED,
Packit 423ecb
                     const xmlChar * localname ATTRIBUTE_UNUSED,
Packit 423ecb
                     const xmlChar * prefix ATTRIBUTE_UNUSED,
Packit 423ecb
                     const xmlChar * URI ATTRIBUTE_UNUSED)
Packit 423ecb
{
Packit 423ecb
    callbacks++;
Packit 423ecb
    return;
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static xmlSAXHandler callbackSAX2HandlerStruct = {
Packit 423ecb
    internalSubsetCallback,
Packit 423ecb
    isStandaloneCallback,
Packit 423ecb
    hasInternalSubsetCallback,
Packit 423ecb
    hasExternalSubsetCallback,
Packit 423ecb
    resolveEntityCallback,
Packit 423ecb
    getEntityCallback,
Packit 423ecb
    entityDeclCallback,
Packit 423ecb
    notationDeclCallback,
Packit 423ecb
    attributeDeclCallback,
Packit 423ecb
    elementDeclCallback,
Packit 423ecb
    unparsedEntityDeclCallback,
Packit 423ecb
    setDocumentLocatorCallback,
Packit 423ecb
    startDocumentCallback,
Packit 423ecb
    endDocumentCallback,
Packit 423ecb
    NULL,
Packit 423ecb
    NULL,
Packit 423ecb
    referenceCallback,
Packit 423ecb
    charactersCallback,
Packit 423ecb
    ignorableWhitespaceCallback,
Packit 423ecb
    processingInstructionCallback,
Packit 423ecb
    commentCallback,
Packit 423ecb
    warningCallback,
Packit 423ecb
    errorCallback,
Packit 423ecb
    fatalErrorCallback,
Packit 423ecb
    getParameterEntityCallback,
Packit 423ecb
    cdataBlockCallback,
Packit 423ecb
    externalSubsetCallback,
Packit 423ecb
    XML_SAX2_MAGIC,
Packit 423ecb
    NULL,
Packit 423ecb
    startElementNsCallback,
Packit 423ecb
    endElementNsCallback,
Packit 423ecb
    NULL
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
static xmlSAXHandlerPtr callbackSAX2Handler = &callbackSAX2HandlerStruct;
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *		The tests front-ends                                     *
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
/**
Packit 423ecb
 * readerTest:
Packit 423ecb
 * @filename: the file to parse
Packit 423ecb
 * @max_size: size of the limit to test
Packit 423ecb
 * @options: parsing options
Packit 423ecb
 * @fail: should a failure be reported
Packit 423ecb
 *
Packit 423ecb
 * Parse a memory generated file using SAX
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 in case of success, an error code otherwise
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
saxTest(const char *filename, size_t limit, int options, int fail) {
Packit 423ecb
    int res = 0;
Packit 423ecb
    xmlParserCtxtPtr ctxt;
Packit 423ecb
    xmlDocPtr doc;
Packit 423ecb
    xmlSAXHandlerPtr old_sax;
Packit 423ecb
Packit 423ecb
    nb_tests++;
Packit 423ecb
Packit 423ecb
    maxlen = limit;
Packit 423ecb
    ctxt = xmlNewParserCtxt();
Packit 423ecb
    if (ctxt == NULL) {
Packit 423ecb
        fprintf(stderr, "Failed to create parser context\n");
Packit 423ecb
	return(1);
Packit 423ecb
    }
Packit 423ecb
    old_sax = ctxt->sax;
Packit 423ecb
    ctxt->sax = callbackSAX2Handler;
Packit 423ecb
    ctxt->userData = NULL;
Packit 423ecb
    doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
Packit 423ecb
Packit 423ecb
    if (doc != NULL) {
Packit 423ecb
        fprintf(stderr, "SAX parsing generated a document !\n");
Packit 423ecb
        xmlFreeDoc(doc);
Packit 423ecb
        res = 0;
Packit 423ecb
    } else if (ctxt->wellFormed == 0) {
Packit 423ecb
        if (fail)
Packit 423ecb
            res = 0;
Packit 423ecb
        else {
Packit 423ecb
            fprintf(stderr, "Failed to parse '%s' %lu\n", filename,
Packit 423ecb
                    (unsigned long) limit);
Packit 423ecb
            res = 1;
Packit 423ecb
        }
Packit 423ecb
    } else {
Packit 423ecb
        if (fail) {
Packit 423ecb
            fprintf(stderr, "Failed to get failure for '%s' %lu\n",
Packit 423ecb
                    filename, (unsigned long) limit);
Packit 423ecb
            res = 1;
Packit 423ecb
        } else
Packit 423ecb
            res = 0;
Packit 423ecb
    }
Packit 423ecb
    ctxt->sax = old_sax;
Packit 423ecb
    xmlFreeParserCtxt(ctxt);
Packit 423ecb
Packit 423ecb
    return(res);
Packit 423ecb
}
Packit 423ecb
#ifdef LIBXML_READER_ENABLED
Packit 423ecb
/**
Packit 423ecb
 * readerTest:
Packit 423ecb
 * @filename: the file to parse
Packit 423ecb
 * @max_size: size of the limit to test
Packit 423ecb
 * @options: parsing options
Packit 423ecb
 * @fail: should a failure be reported
Packit 423ecb
 *
Packit 423ecb
 * Parse a memory generated file using the xmlReader
Packit 423ecb
 *
Packit 423ecb
 * Returns 0 in case of success, an error code otherwise
Packit 423ecb
 */
Packit 423ecb
static int
Packit 423ecb
readerTest(const char *filename, size_t limit, int options, int fail) {
Packit 423ecb
    xmlTextReaderPtr reader;
Packit 423ecb
    int res = 0;
Packit 423ecb
    int ret;
Packit 423ecb
Packit 423ecb
    nb_tests++;
Packit 423ecb
Packit 423ecb
    maxlen = limit;
Packit 423ecb
    reader = xmlReaderForFile(filename , NULL, options);
Packit 423ecb
    if (reader == NULL) {
Packit 423ecb
        fprintf(stderr, "Failed to open '%s' test\n", filename);
Packit 423ecb
	return(1);
Packit 423ecb
    }
Packit 423ecb
    ret = xmlTextReaderRead(reader);
Packit 423ecb
    while (ret == 1) {
Packit 423ecb
        ret = xmlTextReaderRead(reader);
Packit 423ecb
    }
Packit 423ecb
    if (ret != 0) {
Packit 423ecb
        if (fail)
Packit 423ecb
            res = 0;
Packit 423ecb
        else {
Packit 423ecb
            if (strncmp(filename, "crazy:", 6) == 0)
Packit 423ecb
                fprintf(stderr, "Failed to parse '%s' %u\n",
Packit 423ecb
                        filename, crazy_indx);
Packit 423ecb
            else
Packit 423ecb
                fprintf(stderr, "Failed to parse '%s' %lu\n",
Packit 423ecb
                        filename, (unsigned long) limit);
Packit 423ecb
            res = 1;
Packit 423ecb
        }
Packit 423ecb
    } else {
Packit 423ecb
        if (fail) {
Packit 423ecb
            if (strncmp(filename, "crazy:", 6) == 0)
Packit 423ecb
                fprintf(stderr, "Failed to get failure for '%s' %u\n",
Packit 423ecb
                        filename, crazy_indx);
Packit 423ecb
            else
Packit 423ecb
                fprintf(stderr, "Failed to get failure for '%s' %lu\n",
Packit 423ecb
                        filename, (unsigned long) limit);
Packit 423ecb
            res = 1;
Packit 423ecb
        } else
Packit 423ecb
            res = 0;
Packit 423ecb
    }
Packit 423ecb
    if (timeout)
Packit 423ecb
        res = 1;
Packit 423ecb
    xmlFreeTextReader(reader);
Packit 423ecb
Packit 423ecb
    return(res);
Packit 423ecb
}
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
/************************************************************************
Packit 423ecb
 *									*
Packit 423ecb
 *			Tests descriptions				*
Packit 423ecb
 *									*
Packit 423ecb
 ************************************************************************/
Packit 423ecb
Packit 423ecb
typedef int (*functest) (const char *filename, size_t limit, int options,
Packit 423ecb
                         int fail);
Packit 423ecb
Packit 423ecb
typedef struct limitDesc limitDesc;
Packit 423ecb
typedef limitDesc *limitDescPtr;
Packit 423ecb
struct limitDesc {
Packit 423ecb
    const char *name; /* the huge generator name */
Packit 423ecb
    size_t limit;     /* the limit to test */
Packit 423ecb
    int options;      /* extra parser options */
Packit 423ecb
    int fail;         /* whether the test should fail */
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
static limitDesc limitDescriptions[] = {
Packit 423ecb
    /* max length of a text node in content */
Packit 423ecb
    {"huge:textNode", XML_MAX_TEXT_LENGTH - CHUNK, 0, 0},
Packit 423ecb
    {"huge:textNode", XML_MAX_TEXT_LENGTH + CHUNK, 0, 1},
Packit 423ecb
    {"huge:textNode", XML_MAX_TEXT_LENGTH + CHUNK, XML_PARSE_HUGE, 0},
Packit 423ecb
    /* max length of a text node in content */
Packit 423ecb
    {"huge:attrNode", XML_MAX_TEXT_LENGTH - CHUNK, 0, 0},
Packit 423ecb
    {"huge:attrNode", XML_MAX_TEXT_LENGTH + CHUNK, 0, 1},
Packit 423ecb
    {"huge:attrNode", XML_MAX_TEXT_LENGTH + CHUNK, XML_PARSE_HUGE, 0},
Packit 423ecb
    /* max length of a comment node */
Packit 423ecb
    {"huge:commentNode", XML_MAX_TEXT_LENGTH - CHUNK, 0, 0},
Packit 423ecb
    {"huge:commentNode", XML_MAX_TEXT_LENGTH + CHUNK, 0, 1},
Packit 423ecb
    {"huge:commentNode", XML_MAX_TEXT_LENGTH + CHUNK, XML_PARSE_HUGE, 0},
Packit 423ecb
    /* max length of a PI node */
Packit 423ecb
    {"huge:piNode", XML_MAX_TEXT_LENGTH - CHUNK, 0, 0},
Packit 423ecb
    {"huge:piNode", XML_MAX_TEXT_LENGTH + CHUNK, 0, 1},
Packit 423ecb
    {"huge:piNode", XML_MAX_TEXT_LENGTH + CHUNK, XML_PARSE_HUGE, 0},
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
typedef struct testDesc testDesc;
Packit 423ecb
typedef testDesc *testDescPtr;
Packit 423ecb
struct testDesc {
Packit 423ecb
    const char *desc; /* descripton of the test */
Packit 423ecb
    functest    func; /* function implementing the test */
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
static
Packit 423ecb
testDesc testDescriptions[] = {
Packit 423ecb
    { "Parsing of huge files with the sax parser", saxTest},
Packit 423ecb
/*    { "Parsing of huge files with the tree parser", treeTest}, */
Packit 423ecb
#ifdef LIBXML_READER_ENABLED
Packit 423ecb
    { "Parsing of huge files with the reader", readerTest},
Packit 423ecb
#endif
Packit 423ecb
    {NULL, NULL}
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
typedef struct testException testException;
Packit 423ecb
typedef testException *testExceptionPtr;
Packit 423ecb
struct testException {
Packit 423ecb
    unsigned int test;  /* the parser test number */
Packit 423ecb
    unsigned int limit; /* the limit test number */
Packit 423ecb
    int fail;           /* new fail value or -1*/
Packit 423ecb
    size_t size;        /* new limit value or 0 */
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
static
Packit 423ecb
testException testExceptions[] = {
Packit 423ecb
    /* the SAX parser doesn't hit a limit of XML_MAX_TEXT_LENGTH text nodes */
Packit 423ecb
    { 0, 1, 0, 0},
Packit 423ecb
};
Packit 423ecb
Packit 423ecb
static int
Packit 423ecb
launchTests(testDescPtr tst, unsigned int test) {
Packit 423ecb
    int res = 0, err = 0;
Packit 423ecb
    unsigned int i, j;
Packit 423ecb
    size_t limit;
Packit 423ecb
    int fail;
Packit 423ecb
Packit 423ecb
    if (tst == NULL) return(-1);
Packit 423ecb
Packit 423ecb
    for (i = 0;i < sizeof(limitDescriptions)/sizeof(limitDescriptions[0]);i++) {
Packit 423ecb
        limit = limitDescriptions[i].limit;
Packit 423ecb
        fail = limitDescriptions[i].fail;
Packit 423ecb
        /*
Packit 423ecb
         * Handle exceptions if any
Packit 423ecb
         */
Packit 423ecb
        for (j = 0;j < sizeof(testExceptions)/sizeof(testExceptions[0]);j++) {
Packit 423ecb
            if ((testExceptions[j].test == test) &&
Packit 423ecb
                (testExceptions[j].limit == i)) {
Packit 423ecb
                if (testExceptions[j].fail != -1)
Packit 423ecb
                    fail = testExceptions[j].fail;
Packit 423ecb
                if (testExceptions[j].size != 0)
Packit 423ecb
                    limit = testExceptions[j].size;
Packit 423ecb
                break;
Packit 423ecb
            }
Packit 423ecb
        }
Packit 423ecb
        res = tst->func(limitDescriptions[i].name, limit,
Packit 423ecb
                        limitDescriptions[i].options, fail);
Packit 423ecb
        if (res != 0) {
Packit 423ecb
            nb_errors++;
Packit 423ecb
            err++;
Packit 423ecb
        }
Packit 423ecb
    }
Packit 423ecb
    return(err);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
static int
Packit 423ecb
runtest(unsigned int i) {
Packit 423ecb
    int ret = 0, res;
Packit 423ecb
    int old_errors, old_tests, old_leaks;
Packit 423ecb
Packit 423ecb
    old_errors = nb_errors;
Packit 423ecb
    old_tests = nb_tests;
Packit 423ecb
    old_leaks = nb_leaks;
Packit 423ecb
    if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
Packit 423ecb
	printf("## %s\n", testDescriptions[i].desc);
Packit 423ecb
    res = launchTests(&testDescriptions[i], i);
Packit 423ecb
    if (res != 0)
Packit 423ecb
	ret++;
Packit 423ecb
    if (verbose) {
Packit 423ecb
	if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
Packit 423ecb
	    printf("Ran %d tests, no errors\n", nb_tests - old_tests);
Packit 423ecb
	else
Packit 423ecb
	    printf("Ran %d tests, %d errors, %d leaks\n",
Packit 423ecb
		   nb_tests - old_tests,
Packit 423ecb
		   nb_errors - old_errors,
Packit 423ecb
		   nb_leaks - old_leaks);
Packit 423ecb
    }
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static int
Packit 423ecb
launchCrazySAX(unsigned int test, int fail) {
Packit 423ecb
    int res = 0, err = 0;
Packit 423ecb
Packit 423ecb
    crazy_indx = test;
Packit 423ecb
Packit 423ecb
    res = saxTest("crazy::test", XML_MAX_LOOKUP_LIMIT - CHUNK, 0, fail);
Packit 423ecb
    if (res != 0) {
Packit 423ecb
        nb_errors++;
Packit 423ecb
        err++;
Packit 423ecb
    }
Packit 423ecb
    if (tests_quiet == 0)
Packit 423ecb
        fprintf(stderr, "%c", crazy[test]);
Packit 423ecb
Packit 423ecb
    return(err);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_READER_ENABLED
Packit 423ecb
static int
Packit 423ecb
launchCrazy(unsigned int test, int fail) {
Packit 423ecb
    int res = 0, err = 0;
Packit 423ecb
Packit 423ecb
    crazy_indx = test;
Packit 423ecb
Packit 423ecb
    res = readerTest("crazy::test", XML_MAX_LOOKUP_LIMIT - CHUNK, 0, fail);
Packit 423ecb
    if (res != 0) {
Packit 423ecb
        nb_errors++;
Packit 423ecb
        err++;
Packit 423ecb
    }
Packit 423ecb
    if (tests_quiet == 0)
Packit 423ecb
        fprintf(stderr, "%c", crazy[test]);
Packit 423ecb
Packit 423ecb
    return(err);
Packit 423ecb
}
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
static int get_crazy_fail(int test) {
Packit 423ecb
    /*
Packit 423ecb
     * adding 1000000 of character 'a' leads to parser failure mostly
Packit 423ecb
     * everywhere except in those special spots. Need to be updated
Packit 423ecb
     * each time crazy is updated
Packit 423ecb
     */
Packit 423ecb
    int fail = 1;
Packit 423ecb
    if ((test == 44) || /* PI in Misc */
Packit 423ecb
        ((test >= 50) && (test <= 55)) || /* Comment in Misc */
Packit 423ecb
        (test == 79) || /* PI in DTD */
Packit 423ecb
        ((test >= 85) && (test <= 90)) || /* Comment in DTD */
Packit 423ecb
        (test == 154) || /* PI in Misc */
Packit 423ecb
        ((test >= 160) && (test <= 165)) || /* Comment in Misc */
Packit 423ecb
        ((test >= 178) && (test <= 181)) || /* attribute value */
Packit 423ecb
        (test == 183) || /* Text */
Packit 423ecb
        (test == 189) || /* PI in Content */
Packit 423ecb
        (test == 191) || /* Text */
Packit 423ecb
        ((test >= 195) && (test <= 200)) || /* Comment in Content */
Packit 423ecb
        ((test >= 203) && (test <= 206)) || /* Text */
Packit 423ecb
        (test == 215) || (test == 216) || /* in CDATA */
Packit 423ecb
        (test == 219) || /* Text */
Packit 423ecb
        (test == 231) || /* PI in Misc */
Packit 423ecb
        ((test >= 237) && (test <= 242))) /* Comment in Misc */
Packit 423ecb
        fail = 0;
Packit 423ecb
    return(fail);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
static int
Packit 423ecb
runcrazy(void) {
Packit 423ecb
    int ret = 0, res = 0;
Packit 423ecb
    int old_errors, old_tests, old_leaks;
Packit 423ecb
    unsigned int i;
Packit 423ecb
Packit 423ecb
    old_errors = nb_errors;
Packit 423ecb
    old_tests = nb_tests;
Packit 423ecb
    old_leaks = nb_leaks;
Packit 423ecb
Packit 423ecb
#ifdef LIBXML_READER_ENABLED
Packit 423ecb
    if (tests_quiet == 0) {
Packit 423ecb
	printf("## Crazy tests on reader\n");
Packit 423ecb
    }
Packit 423ecb
    for (i = 0;i < strlen(crazy);i++) {
Packit 423ecb
        res += launchCrazy(i, get_crazy_fail(i));
Packit 423ecb
        if (res != 0)
Packit 423ecb
            ret++;
Packit 423ecb
    }
Packit 423ecb
#endif
Packit 423ecb
Packit 423ecb
    if (tests_quiet == 0) {
Packit 423ecb
	printf("\n## Crazy tests on SAX\n");
Packit 423ecb
    }
Packit 423ecb
    for (i = 0;i < strlen(crazy);i++) {
Packit 423ecb
        res += launchCrazySAX(i, get_crazy_fail(i));
Packit 423ecb
        if (res != 0)
Packit 423ecb
            ret++;
Packit 423ecb
    }
Packit 423ecb
    if (tests_quiet == 0)
Packit 423ecb
        fprintf(stderr, "\n");
Packit 423ecb
    if (verbose) {
Packit 423ecb
	if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
Packit 423ecb
	    printf("Ran %d tests, no errors\n", nb_tests - old_tests);
Packit 423ecb
	else
Packit 423ecb
	    printf("Ran %d tests, %d errors, %d leaks\n",
Packit 423ecb
		   nb_tests - old_tests,
Packit 423ecb
		   nb_errors - old_errors,
Packit 423ecb
		   nb_leaks - old_leaks);
Packit 423ecb
    }
Packit 423ecb
    return(ret);
Packit 423ecb
}
Packit 423ecb
Packit 423ecb
Packit 423ecb
int
Packit 423ecb
main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
Packit 423ecb
    int i, a, ret = 0;
Packit 423ecb
    int subset = 0;
Packit 423ecb
Packit 423ecb
    fillFilling();
Packit 423ecb
    initializeLibxml2();
Packit 423ecb
Packit 423ecb
    for (a = 1; a < argc;a++) {
Packit 423ecb
        if (!strcmp(argv[a], "-v"))
Packit 423ecb
	    verbose = 1;
Packit 423ecb
        else if (!strcmp(argv[a], "-quiet"))
Packit 423ecb
	    tests_quiet = 1;
Packit 423ecb
        else if (!strcmp(argv[a], "-crazy"))
Packit 423ecb
	    subset = 1;
Packit 423ecb
    }
Packit 423ecb
    if (subset == 0) {
Packit 423ecb
	for (i = 0; testDescriptions[i].func != NULL; i++) {
Packit 423ecb
	    ret += runtest(i);
Packit 423ecb
	}
Packit 423ecb
    }
Packit 423ecb
    ret += runcrazy();
Packit 423ecb
    if ((nb_errors == 0) && (nb_leaks == 0)) {
Packit 423ecb
        ret = 0;
Packit 423ecb
	printf("Total %d tests, no errors\n",
Packit 423ecb
	       nb_tests);
Packit 423ecb
    } else {
Packit 423ecb
        ret = 1;
Packit 423ecb
	printf("Total %d tests, %d errors, %d leaks\n",
Packit 423ecb
	       nb_tests, nb_errors, nb_leaks);
Packit 423ecb
    }
Packit 423ecb
    xmlCleanupParser();
Packit 423ecb
    xmlMemoryDump();
Packit 423ecb
Packit 423ecb
    return(ret);
Packit 423ecb
}