File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / runtest.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:37:58 2012 UTC (12 years, 5 months ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_7_8, HEAD
libxml2

    1: /*
    2:  * runtest.c: C program to run libxml2 regression tests without
    3:  *            requiring make or Python, and reducing platform dependancies
    4:  *            to a strict minimum.
    5:  *
    6:  * To compile on Unixes:
    7:  * cc -o runtest `xml2-config --cflags` runtest.c `xml2-config --libs` -lpthread
    8:  *
    9:  * See Copyright for the status of this software.
   10:  *
   11:  * daniel@veillard.com
   12:  */
   13: 
   14: #ifdef HAVE_CONFIG_H
   15: #include "libxml.h"
   16: #else
   17: #include <stdio.h>
   18: #endif
   19: 
   20: #if !defined(_WIN32) || defined(__CYGWIN__)
   21: #include <unistd.h>
   22: #endif
   23: #include <string.h>
   24: #include <sys/types.h>
   25: #include <sys/stat.h>
   26: #include <fcntl.h>
   27: 
   28: #include <libxml/parser.h>
   29: #include <libxml/tree.h>
   30: #include <libxml/uri.h>
   31: 
   32: #ifdef LIBXML_OUTPUT_ENABLED
   33: #ifdef LIBXML_READER_ENABLED
   34: #include <libxml/xmlreader.h>
   35: #endif
   36: 
   37: #ifdef LIBXML_XINCLUDE_ENABLED
   38: #include <libxml/xinclude.h>
   39: #endif
   40: 
   41: #ifdef LIBXML_XPATH_ENABLED
   42: #include <libxml/xpath.h>
   43: #include <libxml/xpathInternals.h>
   44: #ifdef LIBXML_XPTR_ENABLED
   45: #include <libxml/xpointer.h>
   46: #endif
   47: #endif
   48: 
   49: #ifdef LIBXML_SCHEMAS_ENABLED
   50: #include <libxml/relaxng.h>
   51: #include <libxml/xmlschemas.h>
   52: #include <libxml/xmlschemastypes.h>
   53: #endif
   54: 
   55: #ifdef LIBXML_PATTERN_ENABLED
   56: #include <libxml/pattern.h>
   57: #endif
   58: 
   59: #ifdef LIBXML_C14N_ENABLED
   60: #include <libxml/c14n.h>
   61: #endif
   62: 
   63: #ifdef LIBXML_HTML_ENABLED
   64: #include <libxml/HTMLparser.h>
   65: #include <libxml/HTMLtree.h>
   66: 
   67: /*
   68:  * pseudo flag for the unification of HTML and XML tests
   69:  */
   70: #define XML_PARSE_HTML 1 << 24
   71: #endif
   72: 
   73: #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
   74: #include <libxml/globals.h>
   75: #include <libxml/threads.h>
   76: #include <libxml/parser.h>
   77: #include <libxml/catalog.h>
   78: #include <string.h>
   79: #endif
   80: 
   81: /*
   82:  * O_BINARY is just for Windows compatibility - if it isn't defined
   83:  * on this system, avoid any compilation error
   84:  */
   85: #ifdef	O_BINARY
   86: #define RD_FLAGS	O_RDONLY | O_BINARY
   87: #else
   88: #define	RD_FLAGS	O_RDONLY
   89: #endif
   90: 
   91: typedef int (*functest) (const char *filename, const char *result,
   92:                          const char *error, int options);
   93: 
   94: typedef struct testDesc testDesc;
   95: typedef testDesc *testDescPtr;
   96: struct testDesc {
   97:     const char *desc; /* descripton of the test */
   98:     functest    func; /* function implementing the test */
   99:     const char *in;   /* glob to path for input files */
  100:     const char *out;  /* output directory */
  101:     const char *suffix;/* suffix for output files */
  102:     const char *err;  /* suffix for error output files */
  103:     int     options;  /* parser options for the test */
  104: };
  105: 
  106: static int checkTestFile(const char *filename);
  107: 
  108: #if defined(_WIN32) && !defined(__CYGWIN__)
  109: 
  110: #include <windows.h>
  111: #include <io.h>
  112: 
  113: typedef struct
  114: {
  115:       size_t gl_pathc;    /* Count of paths matched so far  */
  116:       char **gl_pathv;    /* List of matched pathnames.  */
  117:       size_t gl_offs;     /* Slots to reserve in 'gl_pathv'.  */
  118: } glob_t;
  119: 
  120: #define GLOB_DOOFFS 0
  121: static int glob(const char *pattern, int flags,
  122:                 int errfunc(const char *epath, int eerrno),
  123:                 glob_t *pglob) {
  124:     glob_t *ret;
  125:     WIN32_FIND_DATA FindFileData;
  126:     HANDLE hFind;
  127:     unsigned int nb_paths = 0;
  128:     char directory[500];
  129:     int len;
  130: 
  131:     if ((pattern == NULL) || (pglob == NULL)) return(-1);
  132: 
  133:     strncpy(directory, pattern, 499);
  134:     for (len = strlen(directory);len >= 0;len--) {
  135:         if (directory[len] == '/') {
  136: 	    len++;
  137: 	    directory[len] = 0;
  138: 	    break;
  139: 	}
  140:     }
  141:     if (len <= 0)
  142:         len = 0;
  143: 
  144: 
  145:     ret = pglob;
  146:     memset(ret, 0, sizeof(glob_t));
  147: 
  148:     hFind = FindFirstFileA(pattern, &FindFileData);
  149:     if (hFind == INVALID_HANDLE_VALUE)
  150:         return(0);
  151:     nb_paths = 20;
  152:     ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
  153:     if (ret->gl_pathv == NULL) {
  154: 	FindClose(hFind);
  155:         return(-1);
  156:     }
  157:     strncpy(directory + len, FindFileData.cFileName, 499 - len);
  158:     ret->gl_pathv[ret->gl_pathc] = strdup(directory);
  159:     if (ret->gl_pathv[ret->gl_pathc] == NULL)
  160:         goto done;
  161:     ret->gl_pathc++;
  162:     while(FindNextFileA(hFind, &FindFileData)) {
  163:         if (FindFileData.cFileName[0] == '.')
  164: 	    continue;
  165:         if (ret->gl_pathc + 2 > nb_paths) {
  166:             char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
  167:             if (tmp == NULL)
  168:                 break;
  169:             ret->gl_pathv = tmp;
  170:             nb_paths *= 2;
  171: 	}
  172: 	strncpy(directory + len, FindFileData.cFileName, 499 - len);
  173: 	ret->gl_pathv[ret->gl_pathc] = strdup(directory);
  174:         if (ret->gl_pathv[ret->gl_pathc] == NULL)
  175:             break;
  176:         ret->gl_pathc++;
  177:     }
  178:     ret->gl_pathv[ret->gl_pathc] = NULL;
  179: 
  180: done:
  181:     FindClose(hFind);
  182:     return(0);
  183: }
  184: 
  185: 
  186: 
  187: static void globfree(glob_t *pglob) {
  188:     unsigned int i;
  189:     if (pglob == NULL)
  190:         return;
  191: 
  192:     for (i = 0;i < pglob->gl_pathc;i++) {
  193:          if (pglob->gl_pathv[i] != NULL)
  194:              free(pglob->gl_pathv[i]);
  195:     }
  196: }
  197: #define vsnprintf _vsnprintf
  198: #define snprintf _snprintf
  199: #else
  200: #include <glob.h>
  201: #endif
  202: 
  203: /************************************************************************
  204:  *									*
  205:  *		Libxml2 specific routines				*
  206:  *									*
  207:  ************************************************************************/
  208: 
  209: static int nb_tests = 0;
  210: static int nb_errors = 0;
  211: static int nb_leaks = 0;
  212: static int extraMemoryFromResolver = 0;
  213: 
  214: static int
  215: fatalError(void) {
  216:     fprintf(stderr, "Exitting tests on fatal error\n");
  217:     exit(1);
  218: }
  219: 
  220: /*
  221:  * We need to trap calls to the resolver to not account memory for the catalog
  222:  * which is shared to the current running test. We also don't want to have
  223:  * network downloads modifying tests.
  224:  */
  225: static xmlParserInputPtr
  226: testExternalEntityLoader(const char *URL, const char *ID,
  227: 			 xmlParserCtxtPtr ctxt) {
  228:     xmlParserInputPtr ret;
  229: 
  230:     if (checkTestFile(URL)) {
  231: 	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
  232:     } else {
  233: 	int memused = xmlMemUsed();
  234: 	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
  235: 	extraMemoryFromResolver += xmlMemUsed() - memused;
  236:     }
  237: 
  238:     return(ret);
  239: }
  240: 
  241: /*
  242:  * Trapping the error messages at the generic level to grab the equivalent of
  243:  * stderr messages on CLI tools.
  244:  */
  245: static char testErrors[32769];
  246: static int testErrorsSize = 0;
  247: 
  248: static void XMLCDECL
  249: testErrorHandler(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
  250:     va_list args;
  251:     int res;
  252: 
  253:     if (testErrorsSize >= 32768)
  254:         return;
  255:     va_start(args, msg);
  256:     res = vsnprintf(&testErrors[testErrorsSize],
  257:                     32768 - testErrorsSize,
  258: 		    msg, args);
  259:     va_end(args);
  260:     if (testErrorsSize + res >= 32768) {
  261:         /* buffer is full */
  262: 	testErrorsSize = 32768;
  263: 	testErrors[testErrorsSize] = 0;
  264:     } else {
  265:         testErrorsSize += res;
  266:     }
  267:     testErrors[testErrorsSize] = 0;
  268: }
  269: 
  270: static void XMLCDECL
  271: channel(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
  272:     va_list args;
  273:     int res;
  274: 
  275:     if (testErrorsSize >= 32768)
  276:         return;
  277:     va_start(args, msg);
  278:     res = vsnprintf(&testErrors[testErrorsSize],
  279:                     32768 - testErrorsSize,
  280: 		    msg, args);
  281:     va_end(args);
  282:     if (testErrorsSize + res >= 32768) {
  283:         /* buffer is full */
  284: 	testErrorsSize = 32768;
  285: 	testErrors[testErrorsSize] = 0;
  286:     } else {
  287:         testErrorsSize += res;
  288:     }
  289:     testErrors[testErrorsSize] = 0;
  290: }
  291: 
  292: /**
  293:  * xmlParserPrintFileContext:
  294:  * @input:  an xmlParserInputPtr input
  295:  *
  296:  * Displays current context within the input content for error tracking
  297:  */
  298: 
  299: static void
  300: xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
  301: 		xmlGenericErrorFunc chanl, void *data ) {
  302:     const xmlChar *cur, *base;
  303:     unsigned int n, col;	/* GCC warns if signed, because compared with sizeof() */
  304:     xmlChar  content[81]; /* space for 80 chars + line terminator */
  305:     xmlChar *ctnt;
  306: 
  307:     if (input == NULL) return;
  308:     cur = input->cur;
  309:     base = input->base;
  310:     /* skip backwards over any end-of-lines */
  311:     while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
  312: 	cur--;
  313:     }
  314:     n = 0;
  315:     /* search backwards for beginning-of-line (to max buff size) */
  316:     while ((n++ < (sizeof(content)-1)) && (cur > base) &&
  317:    (*(cur) != '\n') && (*(cur) != '\r'))
  318:         cur--;
  319:     if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
  320:     /* calculate the error position in terms of the current position */
  321:     col = input->cur - cur;
  322:     /* search forward for end-of-line (to max buff size) */
  323:     n = 0;
  324:     ctnt = content;
  325:     /* copy selected text to our buffer */
  326:     while ((*cur != 0) && (*(cur) != '\n') &&
  327:    (*(cur) != '\r') && (n < sizeof(content)-1)) {
  328: 		*ctnt++ = *cur++;
  329: 	n++;
  330:     }
  331:     *ctnt = 0;
  332:     /* print out the selected text */
  333:     chanl(data ,"%s\n", content);
  334:     /* create blank line with problem pointer */
  335:     n = 0;
  336:     ctnt = content;
  337:     /* (leave buffer space for pointer + line terminator) */
  338:     while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
  339: 	if (*(ctnt) != '\t')
  340: 	    *(ctnt) = ' ';
  341: 	ctnt++;
  342:     }
  343:     *ctnt++ = '^';
  344:     *ctnt = 0;
  345:     chanl(data ,"%s\n", content);
  346: }
  347: 
  348: static void
  349: testStructuredErrorHandler(void *ctx  ATTRIBUTE_UNUSED, xmlErrorPtr err) {
  350:     char *file = NULL;
  351:     int line = 0;
  352:     int code = -1;
  353:     int domain;
  354:     void *data = NULL;
  355:     const char *str;
  356:     const xmlChar *name = NULL;
  357:     xmlNodePtr node;
  358:     xmlErrorLevel level;
  359:     xmlParserInputPtr input = NULL;
  360:     xmlParserInputPtr cur = NULL;
  361:     xmlParserCtxtPtr ctxt = NULL;
  362: 
  363:     if (err == NULL)
  364:         return;
  365: 
  366:     file = err->file;
  367:     line = err->line;
  368:     code = err->code;
  369:     domain = err->domain;
  370:     level = err->level;
  371:     node = err->node;
  372:     if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
  373:         (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
  374: 	(domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
  375: 	ctxt = err->ctxt;
  376:     }
  377:     str = err->message;
  378: 
  379:     if (code == XML_ERR_OK)
  380:         return;
  381: 
  382:     if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
  383:         name = node->name;
  384: 
  385:     /*
  386:      * Maintain the compatibility with the legacy error handling
  387:      */
  388:     if (ctxt != NULL) {
  389:         input = ctxt->input;
  390:         if ((input != NULL) && (input->filename == NULL) &&
  391:             (ctxt->inputNr > 1)) {
  392:             cur = input;
  393:             input = ctxt->inputTab[ctxt->inputNr - 2];
  394:         }
  395:         if (input != NULL) {
  396:             if (input->filename)
  397:                 channel(data, "%s:%d: ", input->filename, input->line);
  398:             else if ((line != 0) && (domain == XML_FROM_PARSER))
  399:                 channel(data, "Entity: line %d: ", input->line);
  400:         }
  401:     } else {
  402:         if (file != NULL)
  403:             channel(data, "%s:%d: ", file, line);
  404:         else if ((line != 0) && (domain == XML_FROM_PARSER))
  405:             channel(data, "Entity: line %d: ", line);
  406:     }
  407:     if (name != NULL) {
  408:         channel(data, "element %s: ", name);
  409:     }
  410:     if (code == XML_ERR_OK)
  411:         return;
  412:     switch (domain) {
  413:         case XML_FROM_PARSER:
  414:             channel(data, "parser ");
  415:             break;
  416:         case XML_FROM_NAMESPACE:
  417:             channel(data, "namespace ");
  418:             break;
  419:         case XML_FROM_DTD:
  420:         case XML_FROM_VALID:
  421:             channel(data, "validity ");
  422:             break;
  423:         case XML_FROM_HTML:
  424:             channel(data, "HTML parser ");
  425:             break;
  426:         case XML_FROM_MEMORY:
  427:             channel(data, "memory ");
  428:             break;
  429:         case XML_FROM_OUTPUT:
  430:             channel(data, "output ");
  431:             break;
  432:         case XML_FROM_IO:
  433:             channel(data, "I/O ");
  434:             break;
  435:         case XML_FROM_XINCLUDE:
  436:             channel(data, "XInclude ");
  437:             break;
  438:         case XML_FROM_XPATH:
  439:             channel(data, "XPath ");
  440:             break;
  441:         case XML_FROM_XPOINTER:
  442:             channel(data, "parser ");
  443:             break;
  444:         case XML_FROM_REGEXP:
  445:             channel(data, "regexp ");
  446:             break;
  447:         case XML_FROM_MODULE:
  448:             channel(data, "module ");
  449:             break;
  450:         case XML_FROM_SCHEMASV:
  451:             channel(data, "Schemas validity ");
  452:             break;
  453:         case XML_FROM_SCHEMASP:
  454:             channel(data, "Schemas parser ");
  455:             break;
  456:         case XML_FROM_RELAXNGP:
  457:             channel(data, "Relax-NG parser ");
  458:             break;
  459:         case XML_FROM_RELAXNGV:
  460:             channel(data, "Relax-NG validity ");
  461:             break;
  462:         case XML_FROM_CATALOG:
  463:             channel(data, "Catalog ");
  464:             break;
  465:         case XML_FROM_C14N:
  466:             channel(data, "C14N ");
  467:             break;
  468:         case XML_FROM_XSLT:
  469:             channel(data, "XSLT ");
  470:             break;
  471:         default:
  472:             break;
  473:     }
  474:     if (code == XML_ERR_OK)
  475:         return;
  476:     switch (level) {
  477:         case XML_ERR_NONE:
  478:             channel(data, ": ");
  479:             break;
  480:         case XML_ERR_WARNING:
  481:             channel(data, "warning : ");
  482:             break;
  483:         case XML_ERR_ERROR:
  484:             channel(data, "error : ");
  485:             break;
  486:         case XML_ERR_FATAL:
  487:             channel(data, "error : ");
  488:             break;
  489:     }
  490:     if (code == XML_ERR_OK)
  491:         return;
  492:     if (str != NULL) {
  493:         int len;
  494: 	len = xmlStrlen((const xmlChar *)str);
  495: 	if ((len > 0) && (str[len - 1] != '\n'))
  496: 	    channel(data, "%s\n", str);
  497: 	else
  498: 	    channel(data, "%s", str);
  499:     } else {
  500:         channel(data, "%s\n", "out of memory error");
  501:     }
  502:     if (code == XML_ERR_OK)
  503:         return;
  504: 
  505:     if (ctxt != NULL) {
  506:         xmlParserPrintFileContextInternal(input, channel, data);
  507:         if (cur != NULL) {
  508:             if (cur->filename)
  509:                 channel(data, "%s:%d: \n", cur->filename, cur->line);
  510:             else if ((line != 0) && (domain == XML_FROM_PARSER))
  511:                 channel(data, "Entity: line %d: \n", cur->line);
  512:             xmlParserPrintFileContextInternal(cur, channel, data);
  513:         }
  514:     }
  515:     if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
  516:         (err->int1 < 100) &&
  517: 	(err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
  518: 	xmlChar buf[150];
  519: 	int i;
  520: 
  521: 	channel(data, "%s\n", err->str1);
  522: 	for (i=0;i < err->int1;i++)
  523: 	     buf[i] = ' ';
  524: 	buf[i++] = '^';
  525: 	buf[i] = 0;
  526: 	channel(data, "%s\n", buf);
  527:     }
  528: }
  529: 
  530: static void
  531: initializeLibxml2(void) {
  532:     xmlGetWarningsDefaultValue = 0;
  533:     xmlPedanticParserDefault(0);
  534: 
  535:     xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
  536:     xmlInitParser();
  537:     xmlSetExternalEntityLoader(testExternalEntityLoader);
  538:     xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
  539: #ifdef LIBXML_SCHEMAS_ENABLED
  540:     xmlSchemaInitTypes();
  541:     xmlRelaxNGInitTypes();
  542: #endif
  543: }
  544: 
  545: 
  546: /************************************************************************
  547:  *									*
  548:  *		File name and path utilities				*
  549:  *									*
  550:  ************************************************************************/
  551: 
  552: static const char *baseFilename(const char *filename) {
  553:     const char *cur;
  554:     if (filename == NULL)
  555:         return(NULL);
  556:     cur = &filename[strlen(filename)];
  557:     while ((cur > filename) && (*cur != '/'))
  558:         cur--;
  559:     if (*cur == '/')
  560:         return(cur + 1);
  561:     return(cur);
  562: }
  563: 
  564: static char *resultFilename(const char *filename, const char *out,
  565:                             const char *suffix) {
  566:     const char *base;
  567:     char res[500];
  568:     char suffixbuff[500];
  569: 
  570: /*************
  571:     if ((filename[0] == 't') && (filename[1] == 'e') &&
  572:         (filename[2] == 's') && (filename[3] == 't') &&
  573: 	(filename[4] == '/'))
  574: 	filename = &filename[5];
  575:  *************/
  576: 
  577:     base = baseFilename(filename);
  578:     if (suffix == NULL)
  579:         suffix = ".tmp";
  580:     if (out == NULL)
  581:         out = "";
  582: 
  583:     strncpy(suffixbuff,suffix,499);
  584: #ifdef VMS
  585:     if(strstr(base,".") && suffixbuff[0]=='.')
  586:       suffixbuff[0]='_';
  587: #endif
  588: 
  589:     snprintf(res, 499, "%s%s%s", out, base, suffixbuff);
  590:     res[499] = 0;
  591:     return(strdup(res));
  592: }
  593: 
  594: static int checkTestFile(const char *filename) {
  595:     struct stat buf;
  596: 
  597:     if (stat(filename, &buf) == -1)
  598:         return(0);
  599: 
  600: #if defined(_WIN32) && !defined(__CYGWIN__)
  601:     if (!(buf.st_mode & _S_IFREG))
  602:         return(0);
  603: #else
  604:     if (!S_ISREG(buf.st_mode))
  605:         return(0);
  606: #endif
  607: 
  608:     return(1);
  609: }
  610: 
  611: static int compareFiles(const char *r1, const char *r2) {
  612:     int res1, res2;
  613:     int fd1, fd2;
  614:     char bytes1[4096];
  615:     char bytes2[4096];
  616: 
  617:     fd1 = open(r1, RD_FLAGS);
  618:     if (fd1 < 0)
  619:         return(-1);
  620:     fd2 = open(r2, RD_FLAGS);
  621:     if (fd2 < 0) {
  622:         close(fd1);
  623:         return(-1);
  624:     }
  625:     while (1) {
  626:         res1 = read(fd1, bytes1, 4096);
  627:         res2 = read(fd2, bytes2, 4096);
  628: 	if ((res1 != res2) || (res1 < 0)) {
  629: 	    close(fd1);
  630: 	    close(fd2);
  631: 	    return(1);
  632: 	}
  633: 	if (res1 == 0)
  634: 	    break;
  635: 	if (memcmp(bytes1, bytes2, res1) != 0) {
  636: 	    close(fd1);
  637: 	    close(fd2);
  638: 	    return(1);
  639: 	}
  640:     }
  641:     close(fd1);
  642:     close(fd2);
  643:     return(0);
  644: }
  645: 
  646: static int compareFileMem(const char *filename, const char *mem, int size) {
  647:     int res;
  648:     int fd;
  649:     char bytes[4096];
  650:     int idx = 0;
  651:     struct stat info;
  652: 
  653:     if (stat(filename, &info) < 0)
  654: 	return(-1);
  655:     if (info.st_size != size)
  656:         return(-1);
  657:     fd = open(filename, RD_FLAGS);
  658:     if (fd < 0)
  659:         return(-1);
  660:     while (idx < size) {
  661:         res = read(fd, bytes, 4096);
  662: 	if (res <= 0)
  663: 	    break;
  664: 	if (res + idx > size)
  665: 	    break;
  666: 	if (memcmp(bytes, &mem[idx], res) != 0) {
  667: 	    int ix;
  668: 	    for (ix=0; ix<res; ix++)
  669: 		if (bytes[ix] != mem[idx+ix])
  670: 			break;
  671: 	    fprintf(stderr,"Compare error at position %d\n", idx+ix);
  672: 	    close(fd);
  673: 	    return(1);
  674: 	}
  675: 	idx += res;
  676:     }
  677:     close(fd);
  678:     return(idx != size);
  679: }
  680: 
  681: static int loadMem(const char *filename, const char **mem, int *size) {
  682:     int fd, res;
  683:     struct stat info;
  684:     char *base;
  685:     int siz = 0;
  686:     if (stat(filename, &info) < 0)
  687: 	return(-1);
  688:     base = malloc(info.st_size + 1);
  689:     if (base == NULL)
  690: 	return(-1);
  691:     if ((fd = open(filename, RD_FLAGS)) < 0) {
  692:         free(base);
  693: 	return(-1);
  694:     }
  695:     while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
  696:         siz += res;
  697:     }
  698:     close(fd);
  699: #if !defined(_WIN32)
  700:     if (siz != info.st_size) {
  701:         free(base);
  702: 	return(-1);
  703:     }
  704: #endif
  705:     base[siz] = 0;
  706:     *mem = base;
  707:     *size = siz;
  708:     return(0);
  709: }
  710: 
  711: static int unloadMem(const char *mem) {
  712:     free((char *)mem);
  713:     return(0);
  714: }
  715: 
  716: /************************************************************************
  717:  *									*
  718:  *		Tests implementations					*
  719:  *									*
  720:  ************************************************************************/
  721: 
  722: /************************************************************************
  723:  *									*
  724:  *		Parse to SAX based tests				*
  725:  *									*
  726:  ************************************************************************/
  727: 
  728: static FILE *SAXdebug = NULL;
  729: 
  730: /*
  731:  * empty SAX block
  732:  */
  733: static xmlSAXHandler emptySAXHandlerStruct = {
  734:     NULL, /* internalSubset */
  735:     NULL, /* isStandalone */
  736:     NULL, /* hasInternalSubset */
  737:     NULL, /* hasExternalSubset */
  738:     NULL, /* resolveEntity */
  739:     NULL, /* getEntity */
  740:     NULL, /* entityDecl */
  741:     NULL, /* notationDecl */
  742:     NULL, /* attributeDecl */
  743:     NULL, /* elementDecl */
  744:     NULL, /* unparsedEntityDecl */
  745:     NULL, /* setDocumentLocator */
  746:     NULL, /* startDocument */
  747:     NULL, /* endDocument */
  748:     NULL, /* startElement */
  749:     NULL, /* endElement */
  750:     NULL, /* reference */
  751:     NULL, /* characters */
  752:     NULL, /* ignorableWhitespace */
  753:     NULL, /* processingInstruction */
  754:     NULL, /* comment */
  755:     NULL, /* xmlParserWarning */
  756:     NULL, /* xmlParserError */
  757:     NULL, /* xmlParserError */
  758:     NULL, /* getParameterEntity */
  759:     NULL, /* cdataBlock; */
  760:     NULL, /* externalSubset; */
  761:     1,
  762:     NULL,
  763:     NULL, /* startElementNs */
  764:     NULL, /* endElementNs */
  765:     NULL  /* xmlStructuredErrorFunc */
  766: };
  767: 
  768: static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
  769: static int callbacks = 0;
  770: static int quiet = 0;
  771: 
  772: /**
  773:  * isStandaloneDebug:
  774:  * @ctxt:  An XML parser context
  775:  *
  776:  * Is this document tagged standalone ?
  777:  *
  778:  * Returns 1 if true
  779:  */
  780: static int
  781: isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
  782: {
  783:     callbacks++;
  784:     if (quiet)
  785: 	return(0);
  786:     fprintf(SAXdebug, "SAX.isStandalone()\n");
  787:     return(0);
  788: }
  789: 
  790: /**
  791:  * hasInternalSubsetDebug:
  792:  * @ctxt:  An XML parser context
  793:  *
  794:  * Does this document has an internal subset
  795:  *
  796:  * Returns 1 if true
  797:  */
  798: static int
  799: hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
  800: {
  801:     callbacks++;
  802:     if (quiet)
  803: 	return(0);
  804:     fprintf(SAXdebug, "SAX.hasInternalSubset()\n");
  805:     return(0);
  806: }
  807: 
  808: /**
  809:  * hasExternalSubsetDebug:
  810:  * @ctxt:  An XML parser context
  811:  *
  812:  * Does this document has an external subset
  813:  *
  814:  * Returns 1 if true
  815:  */
  816: static int
  817: hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
  818: {
  819:     callbacks++;
  820:     if (quiet)
  821: 	return(0);
  822:     fprintf(SAXdebug, "SAX.hasExternalSubset()\n");
  823:     return(0);
  824: }
  825: 
  826: /**
  827:  * internalSubsetDebug:
  828:  * @ctxt:  An XML parser context
  829:  *
  830:  * Does this document has an internal subset
  831:  */
  832: static void
  833: internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
  834: 	       const xmlChar *ExternalID, const xmlChar *SystemID)
  835: {
  836:     callbacks++;
  837:     if (quiet)
  838: 	return;
  839:     fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
  840:     if (ExternalID == NULL)
  841: 	fprintf(SAXdebug, " ,");
  842:     else
  843: 	fprintf(SAXdebug, " %s,", ExternalID);
  844:     if (SystemID == NULL)
  845: 	fprintf(SAXdebug, " )\n");
  846:     else
  847: 	fprintf(SAXdebug, " %s)\n", SystemID);
  848: }
  849: 
  850: /**
  851:  * externalSubsetDebug:
  852:  * @ctxt:  An XML parser context
  853:  *
  854:  * Does this document has an external subset
  855:  */
  856: static void
  857: externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
  858: 	       const xmlChar *ExternalID, const xmlChar *SystemID)
  859: {
  860:     callbacks++;
  861:     if (quiet)
  862: 	return;
  863:     fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
  864:     if (ExternalID == NULL)
  865: 	fprintf(SAXdebug, " ,");
  866:     else
  867: 	fprintf(SAXdebug, " %s,", ExternalID);
  868:     if (SystemID == NULL)
  869: 	fprintf(SAXdebug, " )\n");
  870:     else
  871: 	fprintf(SAXdebug, " %s)\n", SystemID);
  872: }
  873: 
  874: /**
  875:  * resolveEntityDebug:
  876:  * @ctxt:  An XML parser context
  877:  * @publicId: The public ID of the entity
  878:  * @systemId: The system ID of the entity
  879:  *
  880:  * Special entity resolver, better left to the parser, it has
  881:  * more context than the application layer.
  882:  * The default behaviour is to NOT resolve the entities, in that case
  883:  * the ENTITY_REF nodes are built in the structure (and the parameter
  884:  * values).
  885:  *
  886:  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
  887:  */
  888: static xmlParserInputPtr
  889: resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
  890: {
  891:     callbacks++;
  892:     if (quiet)
  893: 	return(NULL);
  894:     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
  895: 
  896: 
  897:     fprintf(SAXdebug, "SAX.resolveEntity(");
  898:     if (publicId != NULL)
  899: 	fprintf(SAXdebug, "%s", (char *)publicId);
  900:     else
  901: 	fprintf(SAXdebug, " ");
  902:     if (systemId != NULL)
  903: 	fprintf(SAXdebug, ", %s)\n", (char *)systemId);
  904:     else
  905: 	fprintf(SAXdebug, ", )\n");
  906: /*********
  907:     if (systemId != NULL) {
  908:         return(xmlNewInputFromFile(ctxt, (char *) systemId));
  909:     }
  910:  *********/
  911:     return(NULL);
  912: }
  913: 
  914: /**
  915:  * getEntityDebug:
  916:  * @ctxt:  An XML parser context
  917:  * @name: The entity name
  918:  *
  919:  * Get an entity by name
  920:  *
  921:  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
  922:  */
  923: static xmlEntityPtr
  924: getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
  925: {
  926:     callbacks++;
  927:     if (quiet)
  928: 	return(NULL);
  929:     fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
  930:     return(NULL);
  931: }
  932: 
  933: /**
  934:  * getParameterEntityDebug:
  935:  * @ctxt:  An XML parser context
  936:  * @name: The entity name
  937:  *
  938:  * Get a parameter entity by name
  939:  *
  940:  * Returns the xmlParserInputPtr
  941:  */
  942: static xmlEntityPtr
  943: getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
  944: {
  945:     callbacks++;
  946:     if (quiet)
  947: 	return(NULL);
  948:     fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
  949:     return(NULL);
  950: }
  951: 
  952: 
  953: /**
  954:  * entityDeclDebug:
  955:  * @ctxt:  An XML parser context
  956:  * @name:  the entity name
  957:  * @type:  the entity type
  958:  * @publicId: The public ID of the entity
  959:  * @systemId: The system ID of the entity
  960:  * @content: the entity value (without processing).
  961:  *
  962:  * An entity definition has been parsed
  963:  */
  964: static void
  965: entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
  966:           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
  967: {
  968: const xmlChar *nullstr = BAD_CAST "(null)";
  969:     /* not all libraries handle printing null pointers nicely */
  970:     if (publicId == NULL)
  971:         publicId = nullstr;
  972:     if (systemId == NULL)
  973:         systemId = nullstr;
  974:     if (content == NULL)
  975:         content = (xmlChar *)nullstr;
  976:     callbacks++;
  977:     if (quiet)
  978: 	return;
  979:     fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
  980:             name, type, publicId, systemId, content);
  981: }
  982: 
  983: /**
  984:  * attributeDeclDebug:
  985:  * @ctxt:  An XML parser context
  986:  * @name:  the attribute name
  987:  * @type:  the attribute type
  988:  *
  989:  * An attribute definition has been parsed
  990:  */
  991: static void
  992: attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
  993:                    const xmlChar * name, int type, int def,
  994:                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
  995: {
  996:     callbacks++;
  997:     if (quiet)
  998:         return;
  999:     if (defaultValue == NULL)
 1000:         fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
 1001:                 elem, name, type, def);
 1002:     else
 1003:         fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
 1004:                 elem, name, type, def, defaultValue);
 1005:     xmlFreeEnumeration(tree);
 1006: }
 1007: 
 1008: /**
 1009:  * elementDeclDebug:
 1010:  * @ctxt:  An XML parser context
 1011:  * @name:  the element name
 1012:  * @type:  the element type
 1013:  * @content: the element value (without processing).
 1014:  *
 1015:  * An element definition has been parsed
 1016:  */
 1017: static void
 1018: elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
 1019: 	    xmlElementContentPtr content ATTRIBUTE_UNUSED)
 1020: {
 1021:     callbacks++;
 1022:     if (quiet)
 1023: 	return;
 1024:     fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n",
 1025:             name, type);
 1026: }
 1027: 
 1028: /**
 1029:  * notationDeclDebug:
 1030:  * @ctxt:  An XML parser context
 1031:  * @name: The name of the notation
 1032:  * @publicId: The public ID of the entity
 1033:  * @systemId: The system ID of the entity
 1034:  *
 1035:  * What to do when a notation declaration has been parsed.
 1036:  */
 1037: static void
 1038: notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
 1039: 	     const xmlChar *publicId, const xmlChar *systemId)
 1040: {
 1041:     callbacks++;
 1042:     if (quiet)
 1043: 	return;
 1044:     fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n",
 1045:             (char *) name, (char *) publicId, (char *) systemId);
 1046: }
 1047: 
 1048: /**
 1049:  * unparsedEntityDeclDebug:
 1050:  * @ctxt:  An XML parser context
 1051:  * @name: The name of the entity
 1052:  * @publicId: The public ID of the entity
 1053:  * @systemId: The system ID of the entity
 1054:  * @notationName: the name of the notation
 1055:  *
 1056:  * What to do when an unparsed entity declaration is parsed
 1057:  */
 1058: static void
 1059: unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
 1060: 		   const xmlChar *publicId, const xmlChar *systemId,
 1061: 		   const xmlChar *notationName)
 1062: {
 1063: const xmlChar *nullstr = BAD_CAST "(null)";
 1064: 
 1065:     if (publicId == NULL)
 1066:         publicId = nullstr;
 1067:     if (systemId == NULL)
 1068:         systemId = nullstr;
 1069:     if (notationName == NULL)
 1070:         notationName = nullstr;
 1071:     callbacks++;
 1072:     if (quiet)
 1073: 	return;
 1074:     fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
 1075:             (char *) name, (char *) publicId, (char *) systemId,
 1076: 	    (char *) notationName);
 1077: }
 1078: 
 1079: /**
 1080:  * setDocumentLocatorDebug:
 1081:  * @ctxt:  An XML parser context
 1082:  * @loc: A SAX Locator
 1083:  *
 1084:  * Receive the document locator at startup, actually xmlDefaultSAXLocator
 1085:  * Everything is available on the context, so this is useless in our case.
 1086:  */
 1087: static void
 1088: setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
 1089: {
 1090:     callbacks++;
 1091:     if (quiet)
 1092: 	return;
 1093:     fprintf(SAXdebug, "SAX.setDocumentLocator()\n");
 1094: }
 1095: 
 1096: /**
 1097:  * startDocumentDebug:
 1098:  * @ctxt:  An XML parser context
 1099:  *
 1100:  * called when the document start being processed.
 1101:  */
 1102: static void
 1103: startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
 1104: {
 1105:     callbacks++;
 1106:     if (quiet)
 1107: 	return;
 1108:     fprintf(SAXdebug, "SAX.startDocument()\n");
 1109: }
 1110: 
 1111: /**
 1112:  * endDocumentDebug:
 1113:  * @ctxt:  An XML parser context
 1114:  *
 1115:  * called when the document end has been detected.
 1116:  */
 1117: static void
 1118: endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
 1119: {
 1120:     callbacks++;
 1121:     if (quiet)
 1122: 	return;
 1123:     fprintf(SAXdebug, "SAX.endDocument()\n");
 1124: }
 1125: 
 1126: /**
 1127:  * startElementDebug:
 1128:  * @ctxt:  An XML parser context
 1129:  * @name:  The element name
 1130:  *
 1131:  * called when an opening tag has been processed.
 1132:  */
 1133: static void
 1134: startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
 1135: {
 1136:     int i;
 1137: 
 1138:     callbacks++;
 1139:     if (quiet)
 1140: 	return;
 1141:     fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
 1142:     if (atts != NULL) {
 1143:         for (i = 0;(atts[i] != NULL);i++) {
 1144: 	    fprintf(SAXdebug, ", %s='", atts[i++]);
 1145: 	    if (atts[i] != NULL)
 1146: 	        fprintf(SAXdebug, "%s'", atts[i]);
 1147: 	}
 1148:     }
 1149:     fprintf(SAXdebug, ")\n");
 1150: }
 1151: 
 1152: /**
 1153:  * endElementDebug:
 1154:  * @ctxt:  An XML parser context
 1155:  * @name:  The element name
 1156:  *
 1157:  * called when the end of an element has been detected.
 1158:  */
 1159: static void
 1160: endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
 1161: {
 1162:     callbacks++;
 1163:     if (quiet)
 1164: 	return;
 1165:     fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name);
 1166: }
 1167: 
 1168: /**
 1169:  * charactersDebug:
 1170:  * @ctxt:  An XML parser context
 1171:  * @ch:  a xmlChar string
 1172:  * @len: the number of xmlChar
 1173:  *
 1174:  * receiving some chars from the parser.
 1175:  * Question: how much at a time ???
 1176:  */
 1177: static void
 1178: charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
 1179: {
 1180:     char output[40];
 1181:     int i;
 1182: 
 1183:     callbacks++;
 1184:     if (quiet)
 1185: 	return;
 1186:     for (i = 0;(i<len) && (i < 30);i++)
 1187: 	output[i] = ch[i];
 1188:     output[i] = 0;
 1189: 
 1190:     fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
 1191: }
 1192: 
 1193: /**
 1194:  * referenceDebug:
 1195:  * @ctxt:  An XML parser context
 1196:  * @name:  The entity name
 1197:  *
 1198:  * called when an entity reference is detected.
 1199:  */
 1200: static void
 1201: referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
 1202: {
 1203:     callbacks++;
 1204:     if (quiet)
 1205: 	return;
 1206:     fprintf(SAXdebug, "SAX.reference(%s)\n", name);
 1207: }
 1208: 
 1209: /**
 1210:  * ignorableWhitespaceDebug:
 1211:  * @ctxt:  An XML parser context
 1212:  * @ch:  a xmlChar string
 1213:  * @start: the first char in the string
 1214:  * @len: the number of xmlChar
 1215:  *
 1216:  * receiving some ignorable whitespaces from the parser.
 1217:  * Question: how much at a time ???
 1218:  */
 1219: static void
 1220: ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
 1221: {
 1222:     char output[40];
 1223:     int i;
 1224: 
 1225:     callbacks++;
 1226:     if (quiet)
 1227: 	return;
 1228:     for (i = 0;(i<len) && (i < 30);i++)
 1229: 	output[i] = ch[i];
 1230:     output[i] = 0;
 1231:     fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
 1232: }
 1233: 
 1234: /**
 1235:  * processingInstructionDebug:
 1236:  * @ctxt:  An XML parser context
 1237:  * @target:  the target name
 1238:  * @data: the PI data's
 1239:  * @len: the number of xmlChar
 1240:  *
 1241:  * A processing instruction has been parsed.
 1242:  */
 1243: static void
 1244: processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
 1245:                       const xmlChar *data)
 1246: {
 1247:     callbacks++;
 1248:     if (quiet)
 1249: 	return;
 1250:     if (data != NULL)
 1251: 	fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
 1252: 		(char *) target, (char *) data);
 1253:     else
 1254: 	fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n",
 1255: 		(char *) target);
 1256: }
 1257: 
 1258: /**
 1259:  * cdataBlockDebug:
 1260:  * @ctx: the user data (XML parser context)
 1261:  * @value:  The pcdata content
 1262:  * @len:  the block length
 1263:  *
 1264:  * called when a pcdata block has been parsed
 1265:  */
 1266: static void
 1267: cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
 1268: {
 1269:     callbacks++;
 1270:     if (quiet)
 1271: 	return;
 1272:     fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n",
 1273: 	    (char *) value, len);
 1274: }
 1275: 
 1276: /**
 1277:  * commentDebug:
 1278:  * @ctxt:  An XML parser context
 1279:  * @value:  the comment content
 1280:  *
 1281:  * A comment has been parsed.
 1282:  */
 1283: static void
 1284: commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
 1285: {
 1286:     callbacks++;
 1287:     if (quiet)
 1288: 	return;
 1289:     fprintf(SAXdebug, "SAX.comment(%s)\n", value);
 1290: }
 1291: 
 1292: /**
 1293:  * warningDebug:
 1294:  * @ctxt:  An XML parser context
 1295:  * @msg:  the message to display/transmit
 1296:  * @...:  extra parameters for the message display
 1297:  *
 1298:  * Display and format a warning messages, gives file, line, position and
 1299:  * extra parameters.
 1300:  */
 1301: static void XMLCDECL
 1302: warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
 1303: {
 1304:     va_list args;
 1305: 
 1306:     callbacks++;
 1307:     if (quiet)
 1308: 	return;
 1309:     va_start(args, msg);
 1310:     fprintf(SAXdebug, "SAX.warning: ");
 1311:     vfprintf(SAXdebug, msg, args);
 1312:     va_end(args);
 1313: }
 1314: 
 1315: /**
 1316:  * errorDebug:
 1317:  * @ctxt:  An XML parser context
 1318:  * @msg:  the message to display/transmit
 1319:  * @...:  extra parameters for the message display
 1320:  *
 1321:  * Display and format a error messages, gives file, line, position and
 1322:  * extra parameters.
 1323:  */
 1324: static void XMLCDECL
 1325: errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
 1326: {
 1327:     va_list args;
 1328: 
 1329:     callbacks++;
 1330:     if (quiet)
 1331: 	return;
 1332:     va_start(args, msg);
 1333:     fprintf(SAXdebug, "SAX.error: ");
 1334:     vfprintf(SAXdebug, msg, args);
 1335:     va_end(args);
 1336: }
 1337: 
 1338: /**
 1339:  * fatalErrorDebug:
 1340:  * @ctxt:  An XML parser context
 1341:  * @msg:  the message to display/transmit
 1342:  * @...:  extra parameters for the message display
 1343:  *
 1344:  * Display and format a fatalError messages, gives file, line, position and
 1345:  * extra parameters.
 1346:  */
 1347: static void XMLCDECL
 1348: fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
 1349: {
 1350:     va_list args;
 1351: 
 1352:     callbacks++;
 1353:     if (quiet)
 1354: 	return;
 1355:     va_start(args, msg);
 1356:     fprintf(SAXdebug, "SAX.fatalError: ");
 1357:     vfprintf(SAXdebug, msg, args);
 1358:     va_end(args);
 1359: }
 1360: 
 1361: static xmlSAXHandler debugSAXHandlerStruct = {
 1362:     internalSubsetDebug,
 1363:     isStandaloneDebug,
 1364:     hasInternalSubsetDebug,
 1365:     hasExternalSubsetDebug,
 1366:     resolveEntityDebug,
 1367:     getEntityDebug,
 1368:     entityDeclDebug,
 1369:     notationDeclDebug,
 1370:     attributeDeclDebug,
 1371:     elementDeclDebug,
 1372:     unparsedEntityDeclDebug,
 1373:     setDocumentLocatorDebug,
 1374:     startDocumentDebug,
 1375:     endDocumentDebug,
 1376:     startElementDebug,
 1377:     endElementDebug,
 1378:     referenceDebug,
 1379:     charactersDebug,
 1380:     ignorableWhitespaceDebug,
 1381:     processingInstructionDebug,
 1382:     commentDebug,
 1383:     warningDebug,
 1384:     errorDebug,
 1385:     fatalErrorDebug,
 1386:     getParameterEntityDebug,
 1387:     cdataBlockDebug,
 1388:     externalSubsetDebug,
 1389:     1,
 1390:     NULL,
 1391:     NULL,
 1392:     NULL,
 1393:     NULL
 1394: };
 1395: 
 1396: static xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
 1397: 
 1398: /*
 1399:  * SAX2 specific callbacks
 1400:  */
 1401: /**
 1402:  * startElementNsDebug:
 1403:  * @ctxt:  An XML parser context
 1404:  * @name:  The element name
 1405:  *
 1406:  * called when an opening tag has been processed.
 1407:  */
 1408: static void
 1409: startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
 1410:                     const xmlChar *localname,
 1411:                     const xmlChar *prefix,
 1412:                     const xmlChar *URI,
 1413: 		    int nb_namespaces,
 1414: 		    const xmlChar **namespaces,
 1415: 		    int nb_attributes,
 1416: 		    int nb_defaulted,
 1417: 		    const xmlChar **attributes)
 1418: {
 1419:     int i;
 1420: 
 1421:     callbacks++;
 1422:     if (quiet)
 1423: 	return;
 1424:     fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
 1425:     if (prefix == NULL)
 1426: 	fprintf(SAXdebug, ", NULL");
 1427:     else
 1428: 	fprintf(SAXdebug, ", %s", (char *) prefix);
 1429:     if (URI == NULL)
 1430: 	fprintf(SAXdebug, ", NULL");
 1431:     else
 1432: 	fprintf(SAXdebug, ", '%s'", (char *) URI);
 1433:     fprintf(SAXdebug, ", %d", nb_namespaces);
 1434: 
 1435:     if (namespaces != NULL) {
 1436:         for (i = 0;i < nb_namespaces * 2;i++) {
 1437: 	    fprintf(SAXdebug, ", xmlns");
 1438: 	    if (namespaces[i] != NULL)
 1439: 	        fprintf(SAXdebug, ":%s", namespaces[i]);
 1440: 	    i++;
 1441: 	    fprintf(SAXdebug, "='%s'", namespaces[i]);
 1442: 	}
 1443:     }
 1444:     fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
 1445:     if (attributes != NULL) {
 1446:         for (i = 0;i < nb_attributes * 5;i += 5) {
 1447: 	    if (attributes[i + 1] != NULL)
 1448: 		fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
 1449: 	    else
 1450: 		fprintf(SAXdebug, ", %s='", attributes[i]);
 1451: 	    fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
 1452: 		    (int)(attributes[i + 4] - attributes[i + 3]));
 1453: 	}
 1454:     }
 1455:     fprintf(SAXdebug, ")\n");
 1456: }
 1457: 
 1458: /**
 1459:  * endElementDebug:
 1460:  * @ctxt:  An XML parser context
 1461:  * @name:  The element name
 1462:  *
 1463:  * called when the end of an element has been detected.
 1464:  */
 1465: static void
 1466: endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
 1467:                   const xmlChar *localname,
 1468:                   const xmlChar *prefix,
 1469:                   const xmlChar *URI)
 1470: {
 1471:     callbacks++;
 1472:     if (quiet)
 1473: 	return;
 1474:     fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
 1475:     if (prefix == NULL)
 1476: 	fprintf(SAXdebug, ", NULL");
 1477:     else
 1478: 	fprintf(SAXdebug, ", %s", (char *) prefix);
 1479:     if (URI == NULL)
 1480: 	fprintf(SAXdebug, ", NULL)\n");
 1481:     else
 1482: 	fprintf(SAXdebug, ", '%s')\n", (char *) URI);
 1483: }
 1484: 
 1485: static xmlSAXHandler debugSAX2HandlerStruct = {
 1486:     internalSubsetDebug,
 1487:     isStandaloneDebug,
 1488:     hasInternalSubsetDebug,
 1489:     hasExternalSubsetDebug,
 1490:     resolveEntityDebug,
 1491:     getEntityDebug,
 1492:     entityDeclDebug,
 1493:     notationDeclDebug,
 1494:     attributeDeclDebug,
 1495:     elementDeclDebug,
 1496:     unparsedEntityDeclDebug,
 1497:     setDocumentLocatorDebug,
 1498:     startDocumentDebug,
 1499:     endDocumentDebug,
 1500:     NULL,
 1501:     NULL,
 1502:     referenceDebug,
 1503:     charactersDebug,
 1504:     ignorableWhitespaceDebug,
 1505:     processingInstructionDebug,
 1506:     commentDebug,
 1507:     warningDebug,
 1508:     errorDebug,
 1509:     fatalErrorDebug,
 1510:     getParameterEntityDebug,
 1511:     cdataBlockDebug,
 1512:     externalSubsetDebug,
 1513:     XML_SAX2_MAGIC,
 1514:     NULL,
 1515:     startElementNsDebug,
 1516:     endElementNsDebug,
 1517:     NULL
 1518: };
 1519: 
 1520: static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
 1521: 
 1522: #ifdef LIBXML_HTML_ENABLED
 1523: /**
 1524:  * htmlstartElementDebug:
 1525:  * @ctxt:  An XML parser context
 1526:  * @name:  The element name
 1527:  *
 1528:  * called when an opening tag has been processed.
 1529:  */
 1530: static void
 1531: htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
 1532: {
 1533:     int i;
 1534: 
 1535:     fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
 1536:     if (atts != NULL) {
 1537:         for (i = 0;(atts[i] != NULL);i++) {
 1538: 	    fprintf(SAXdebug, ", %s", atts[i++]);
 1539: 	    if (atts[i] != NULL) {
 1540: 		unsigned char output[40];
 1541: 		const unsigned char *att = atts[i];
 1542: 		int outlen, attlen;
 1543: 	        fprintf(SAXdebug, "='");
 1544: 		while ((attlen = strlen((char*)att)) > 0) {
 1545: 		    outlen = sizeof output - 1;
 1546: 		    htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
 1547: 		    output[outlen] = 0;
 1548: 		    fprintf(SAXdebug, "%s", (char *) output);
 1549: 		    att += attlen;
 1550: 		}
 1551: 		fprintf(SAXdebug, "'");
 1552: 	    }
 1553: 	}
 1554:     }
 1555:     fprintf(SAXdebug, ")\n");
 1556: }
 1557: 
 1558: /**
 1559:  * htmlcharactersDebug:
 1560:  * @ctxt:  An XML parser context
 1561:  * @ch:  a xmlChar string
 1562:  * @len: the number of xmlChar
 1563:  *
 1564:  * receiving some chars from the parser.
 1565:  * Question: how much at a time ???
 1566:  */
 1567: static void
 1568: htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
 1569: {
 1570:     unsigned char output[40];
 1571:     int inlen = len, outlen = 30;
 1572: 
 1573:     htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
 1574:     output[outlen] = 0;
 1575: 
 1576:     fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
 1577: }
 1578: 
 1579: /**
 1580:  * htmlcdataDebug:
 1581:  * @ctxt:  An XML parser context
 1582:  * @ch:  a xmlChar string
 1583:  * @len: the number of xmlChar
 1584:  *
 1585:  * receiving some cdata chars from the parser.
 1586:  * Question: how much at a time ???
 1587:  */
 1588: static void
 1589: htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
 1590: {
 1591:     unsigned char output[40];
 1592:     int inlen = len, outlen = 30;
 1593: 
 1594:     htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
 1595:     output[outlen] = 0;
 1596: 
 1597:     fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
 1598: }
 1599: 
 1600: static xmlSAXHandler debugHTMLSAXHandlerStruct = {
 1601:     internalSubsetDebug,
 1602:     isStandaloneDebug,
 1603:     hasInternalSubsetDebug,
 1604:     hasExternalSubsetDebug,
 1605:     resolveEntityDebug,
 1606:     getEntityDebug,
 1607:     entityDeclDebug,
 1608:     notationDeclDebug,
 1609:     attributeDeclDebug,
 1610:     elementDeclDebug,
 1611:     unparsedEntityDeclDebug,
 1612:     setDocumentLocatorDebug,
 1613:     startDocumentDebug,
 1614:     endDocumentDebug,
 1615:     htmlstartElementDebug,
 1616:     endElementDebug,
 1617:     referenceDebug,
 1618:     htmlcharactersDebug,
 1619:     ignorableWhitespaceDebug,
 1620:     processingInstructionDebug,
 1621:     commentDebug,
 1622:     warningDebug,
 1623:     errorDebug,
 1624:     fatalErrorDebug,
 1625:     getParameterEntityDebug,
 1626:     htmlcdataDebug,
 1627:     externalSubsetDebug,
 1628:     1,
 1629:     NULL,
 1630:     NULL,
 1631:     NULL,
 1632:     NULL
 1633: };
 1634: 
 1635: static xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
 1636: #endif /* LIBXML_HTML_ENABLED */
 1637: 
 1638: #ifdef LIBXML_SAX1_ENABLED
 1639: /**
 1640:  * saxParseTest:
 1641:  * @filename: the file to parse
 1642:  * @result: the file with expected result
 1643:  * @err: the file with error messages
 1644:  *
 1645:  * Parse a file using the SAX API and check for errors.
 1646:  *
 1647:  * Returns 0 in case of success, an error code otherwise
 1648:  */
 1649: static int
 1650: saxParseTest(const char *filename, const char *result,
 1651:              const char *err ATTRIBUTE_UNUSED,
 1652:              int options) {
 1653:     int ret;
 1654:     char *temp;
 1655: 
 1656:     nb_tests++;
 1657:     temp = resultFilename(filename, "", ".res");
 1658:     if (temp == NULL) {
 1659:         fprintf(stderr, "out of memory\n");
 1660:         fatalError();
 1661:     }
 1662:     SAXdebug = fopen(temp, "wb");
 1663:     if (SAXdebug == NULL) {
 1664:         fprintf(stderr, "Failed to write to %s\n", temp);
 1665: 	free(temp);
 1666: 	return(-1);
 1667:     }
 1668: 
 1669:     /* for SAX we really want the callbacks though the context handlers */
 1670:     xmlSetStructuredErrorFunc(NULL, NULL);
 1671:     xmlSetGenericErrorFunc(NULL, testErrorHandler);
 1672: 
 1673: #ifdef LIBXML_HTML_ENABLED
 1674:     if (options & XML_PARSE_HTML) {
 1675: 	htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);
 1676: 	ret = 0;
 1677:     } else
 1678: #endif
 1679:     ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
 1680:     if (ret == XML_WAR_UNDECLARED_ENTITY) {
 1681:         fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
 1682:         ret = 0;
 1683:     }
 1684:     if (ret != 0) {
 1685:         fprintf(stderr, "Failed to parse %s\n", filename);
 1686: 	return(1);
 1687:     }
 1688: #ifdef LIBXML_HTML_ENABLED
 1689:     if (options & XML_PARSE_HTML) {
 1690: 	htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
 1691: 	ret = 0;
 1692:     } else
 1693: #endif
 1694:     if (options & XML_PARSE_SAX1) {
 1695: 	ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
 1696:     } else {
 1697: 	ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
 1698:     }
 1699:     if (ret == XML_WAR_UNDECLARED_ENTITY) {
 1700:         fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
 1701:         ret = 0;
 1702:     }
 1703:     fclose(SAXdebug);
 1704:     if (compareFiles(temp, result)) {
 1705:         fprintf(stderr, "Got a difference for %s\n", filename);
 1706:         ret = 1;
 1707:     }
 1708:     if (temp != NULL) {
 1709:         unlink(temp);
 1710:         free(temp);
 1711:     }
 1712: 
 1713:     /* switch back to structured error handling */
 1714:     xmlSetGenericErrorFunc(NULL, NULL);
 1715:     xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
 1716: 
 1717:     return(ret);
 1718: }
 1719: #endif
 1720: 
 1721: /************************************************************************
 1722:  *									*
 1723:  *		Parse to tree based tests				*
 1724:  *									*
 1725:  ************************************************************************/
 1726: /**
 1727:  * oldParseTest:
 1728:  * @filename: the file to parse
 1729:  * @result: the file with expected result
 1730:  * @err: the file with error messages: unused
 1731:  *
 1732:  * Parse a file using the old xmlParseFile API, then serialize back
 1733:  * reparse the result and serialize again, then check for deviation
 1734:  * in serialization.
 1735:  *
 1736:  * Returns 0 in case of success, an error code otherwise
 1737:  */
 1738: static int
 1739: oldParseTest(const char *filename, const char *result,
 1740:              const char *err ATTRIBUTE_UNUSED,
 1741: 	     int options ATTRIBUTE_UNUSED) {
 1742:     xmlDocPtr doc;
 1743:     char *temp;
 1744:     int res = 0;
 1745: 
 1746:     nb_tests++;
 1747:     /*
 1748:      * base of the test, parse with the old API
 1749:      */
 1750: #ifdef LIBXML_SAX1_ENABLED
 1751:     doc = xmlParseFile(filename);
 1752: #else
 1753:     doc = xmlReadFile(filename, NULL, 0);
 1754: #endif
 1755:     if (doc == NULL)
 1756:         return(1);
 1757:     temp = resultFilename(filename, "", ".res");
 1758:     if (temp == NULL) {
 1759:         fprintf(stderr, "out of memory\n");
 1760:         fatalError();
 1761:     }
 1762:     xmlSaveFile(temp, doc);
 1763:     if (compareFiles(temp, result)) {
 1764:         res = 1;
 1765:     }
 1766:     xmlFreeDoc(doc);
 1767: 
 1768:     /*
 1769:      * Parse the saved result to make sure the round trip is okay
 1770:      */
 1771: #ifdef LIBXML_SAX1_ENABLED
 1772:     doc = xmlParseFile(temp);
 1773: #else
 1774:     doc = xmlReadFile(temp, NULL, 0);
 1775: #endif
 1776:     if (doc == NULL)
 1777:         return(1);
 1778:     xmlSaveFile(temp, doc);
 1779:     if (compareFiles(temp, result)) {
 1780:         res = 1;
 1781:     }
 1782:     xmlFreeDoc(doc);
 1783: 
 1784:     if (temp != NULL) {
 1785:         unlink(temp);
 1786:         free(temp);
 1787:     }
 1788:     return(res);
 1789: }
 1790: 
 1791: #ifdef LIBXML_PUSH_ENABLED
 1792: /**
 1793:  * pushParseTest:
 1794:  * @filename: the file to parse
 1795:  * @result: the file with expected result
 1796:  * @err: the file with error messages: unused
 1797:  *
 1798:  * Parse a file using the Push API, then serialize back
 1799:  * to check for content.
 1800:  *
 1801:  * Returns 0 in case of success, an error code otherwise
 1802:  */
 1803: static int
 1804: pushParseTest(const char *filename, const char *result,
 1805:              const char *err ATTRIBUTE_UNUSED,
 1806: 	     int options) {
 1807:     xmlParserCtxtPtr ctxt;
 1808:     xmlDocPtr doc;
 1809:     const char *base;
 1810:     int size, res;
 1811:     int cur = 0;
 1812: 
 1813:     nb_tests++;
 1814:     /*
 1815:      * load the document in memory and work from there.
 1816:      */
 1817:     if (loadMem(filename, &base, &size) != 0) {
 1818:         fprintf(stderr, "Failed to load %s\n", filename);
 1819: 	return(-1);
 1820:     }
 1821: 
 1822: #ifdef LIBXML_HTML_ENABLED
 1823:     if (options & XML_PARSE_HTML)
 1824: 	ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,
 1825: 	                                XML_CHAR_ENCODING_NONE);
 1826:     else
 1827: #endif
 1828:     ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
 1829:     xmlCtxtUseOptions(ctxt, options);
 1830:     cur += 4;
 1831:     while (cur < size) {
 1832:         if (cur + 1024 >= size) {
 1833: #ifdef LIBXML_HTML_ENABLED
 1834: 	    if (options & XML_PARSE_HTML)
 1835: 		htmlParseChunk(ctxt, base + cur, size - cur, 1);
 1836: 	    else
 1837: #endif
 1838: 	    xmlParseChunk(ctxt, base + cur, size - cur, 1);
 1839: 	    break;
 1840: 	} else {
 1841: #ifdef LIBXML_HTML_ENABLED
 1842: 	    if (options & XML_PARSE_HTML)
 1843: 		htmlParseChunk(ctxt, base + cur, 1024, 0);
 1844: 	    else
 1845: #endif
 1846: 	    xmlParseChunk(ctxt, base + cur, 1024, 0);
 1847: 	    cur += 1024;
 1848: 	}
 1849:     }
 1850:     doc = ctxt->myDoc;
 1851: #ifdef LIBXML_HTML_ENABLED
 1852:     if (options & XML_PARSE_HTML)
 1853:         res = 1;
 1854:     else
 1855: #endif
 1856:     res = ctxt->wellFormed;
 1857:     xmlFreeParserCtxt(ctxt);
 1858:     free((char *)base);
 1859:     if (!res) {
 1860: 	xmlFreeDoc(doc);
 1861: 	fprintf(stderr, "Failed to parse %s\n", filename);
 1862: 	return(-1);
 1863:     }
 1864: #ifdef LIBXML_HTML_ENABLED
 1865:     if (options & XML_PARSE_HTML)
 1866: 	htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
 1867:     else
 1868: #endif
 1869:     xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
 1870:     xmlFreeDoc(doc);
 1871:     res = compareFileMem(result, base, size);
 1872:     if ((base == NULL) || (res != 0)) {
 1873: 	if (base != NULL)
 1874: 	    xmlFree((char *)base);
 1875:         fprintf(stderr, "Result for %s failed\n", filename);
 1876: 	return(-1);
 1877:     }
 1878:     xmlFree((char *)base);
 1879:     if (err != NULL) {
 1880: 	res = compareFileMem(err, testErrors, testErrorsSize);
 1881: 	if (res != 0) {
 1882: 	    fprintf(stderr, "Error for %s failed\n", filename);
 1883: 	    return(-1);
 1884: 	}
 1885:     }
 1886:     return(0);
 1887: }
 1888: #endif
 1889: 
 1890: /**
 1891:  * memParseTest:
 1892:  * @filename: the file to parse
 1893:  * @result: the file with expected result
 1894:  * @err: the file with error messages: unused
 1895:  *
 1896:  * Parse a file using the old xmlReadMemory API, then serialize back
 1897:  * reparse the result and serialize again, then check for deviation
 1898:  * in serialization.
 1899:  *
 1900:  * Returns 0 in case of success, an error code otherwise
 1901:  */
 1902: static int
 1903: memParseTest(const char *filename, const char *result,
 1904:              const char *err ATTRIBUTE_UNUSED,
 1905: 	     int options ATTRIBUTE_UNUSED) {
 1906:     xmlDocPtr doc;
 1907:     const char *base;
 1908:     int size, res;
 1909: 
 1910:     nb_tests++;
 1911:     /*
 1912:      * load and parse the memory
 1913:      */
 1914:     if (loadMem(filename, &base, &size) != 0) {
 1915:         fprintf(stderr, "Failed to load %s\n", filename);
 1916: 	return(-1);
 1917:     }
 1918: 
 1919:     doc = xmlReadMemory(base, size, filename, NULL, 0);
 1920:     unloadMem(base);
 1921:     if (doc == NULL) {
 1922:         return(1);
 1923:     }
 1924:     xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
 1925:     xmlFreeDoc(doc);
 1926:     res = compareFileMem(result, base, size);
 1927:     if ((base == NULL) || (res != 0)) {
 1928: 	if (base != NULL)
 1929: 	    xmlFree((char *)base);
 1930:         fprintf(stderr, "Result for %s failed\n", filename);
 1931: 	return(-1);
 1932:     }
 1933:     xmlFree((char *)base);
 1934:     return(0);
 1935: }
 1936: 
 1937: /**
 1938:  * noentParseTest:
 1939:  * @filename: the file to parse
 1940:  * @result: the file with expected result
 1941:  * @err: the file with error messages: unused
 1942:  *
 1943:  * Parse a file with entity resolution, then serialize back
 1944:  * reparse the result and serialize again, then check for deviation
 1945:  * in serialization.
 1946:  *
 1947:  * Returns 0 in case of success, an error code otherwise
 1948:  */
 1949: static int
 1950: noentParseTest(const char *filename, const char *result,
 1951:                const char *err  ATTRIBUTE_UNUSED,
 1952: 	       int options) {
 1953:     xmlDocPtr doc;
 1954:     char *temp;
 1955:     int res = 0;
 1956: 
 1957:     nb_tests++;
 1958:     /*
 1959:      * base of the test, parse with the old API
 1960:      */
 1961:     doc = xmlReadFile(filename, NULL, options);
 1962:     if (doc == NULL)
 1963:         return(1);
 1964:     temp = resultFilename(filename, "", ".res");
 1965:     if (temp == NULL) {
 1966:         fprintf(stderr, "Out of memory\n");
 1967:         fatalError();
 1968:     }
 1969:     xmlSaveFile(temp, doc);
 1970:     if (compareFiles(temp, result)) {
 1971:         res = 1;
 1972:     }
 1973:     xmlFreeDoc(doc);
 1974: 
 1975:     /*
 1976:      * Parse the saved result to make sure the round trip is okay
 1977:      */
 1978:     doc = xmlReadFile(filename, NULL, options);
 1979:     if (doc == NULL)
 1980:         return(1);
 1981:     xmlSaveFile(temp, doc);
 1982:     if (compareFiles(temp, result)) {
 1983:         res = 1;
 1984:     }
 1985:     xmlFreeDoc(doc);
 1986: 
 1987:     if (temp != NULL) {
 1988:         unlink(temp);
 1989:         free(temp);
 1990:     }
 1991:     return(res);
 1992: }
 1993: 
 1994: /**
 1995:  * errParseTest:
 1996:  * @filename: the file to parse
 1997:  * @result: the file with expected result
 1998:  * @err: the file with error messages
 1999:  *
 2000:  * Parse a file using the xmlReadFile API and check for errors.
 2001:  *
 2002:  * Returns 0 in case of success, an error code otherwise
 2003:  */
 2004: static int
 2005: errParseTest(const char *filename, const char *result, const char *err,
 2006:              int options) {
 2007:     xmlDocPtr doc;
 2008:     const char *base = NULL;
 2009:     int size, res = 0;
 2010: 
 2011:     nb_tests++;
 2012: #ifdef LIBXML_HTML_ENABLED
 2013:     if (options & XML_PARSE_HTML) {
 2014:         doc = htmlReadFile(filename, NULL, options);
 2015:     } else
 2016: #endif
 2017: #ifdef LIBXML_XINCLUDE_ENABLED
 2018:     if (options & XML_PARSE_XINCLUDE) {
 2019: 	doc = xmlReadFile(filename, NULL, options);
 2020: 	xmlXIncludeProcessFlags(doc, options);
 2021:     } else
 2022: #endif
 2023:     {
 2024: 	xmlGetWarningsDefaultValue = 1;
 2025: 	doc = xmlReadFile(filename, NULL, options);
 2026:     }
 2027:     xmlGetWarningsDefaultValue = 0;
 2028:     if (result) {
 2029: 	if (doc == NULL) {
 2030: 	    base = "";
 2031: 	    size = 0;
 2032: 	} else {
 2033: #ifdef LIBXML_HTML_ENABLED
 2034: 	    if (options & XML_PARSE_HTML) {
 2035: 		htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
 2036: 	    } else
 2037: #endif
 2038: 	    xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
 2039: 	}
 2040: 	res = compareFileMem(result, base, size);
 2041:     }
 2042:     if (doc != NULL) {
 2043: 	if (base != NULL)
 2044: 	    xmlFree((char *)base);
 2045: 	xmlFreeDoc(doc);
 2046:     }
 2047:     if (res != 0) {
 2048:         fprintf(stderr, "Result for %s failed\n", filename);
 2049: 	return(-1);
 2050:     }
 2051:     if (err != NULL) {
 2052: 	res = compareFileMem(err, testErrors, testErrorsSize);
 2053: 	if (res != 0) {
 2054: 	    fprintf(stderr, "Error for %s failed\n", filename);
 2055: 	    return(-1);
 2056: 	}
 2057:     } else if (options & XML_PARSE_DTDVALID) {
 2058:         if (testErrorsSize != 0)
 2059: 	    fprintf(stderr, "Validation for %s failed\n", filename);
 2060:     }
 2061: 
 2062:     return(0);
 2063: }
 2064: 
 2065: #ifdef LIBXML_READER_ENABLED
 2066: /************************************************************************
 2067:  *									*
 2068:  *		Reader based tests					*
 2069:  *									*
 2070:  ************************************************************************/
 2071: 
 2072: static void processNode(FILE *out, xmlTextReaderPtr reader) {
 2073:     const xmlChar *name, *value;
 2074:     int type, empty;
 2075: 
 2076:     type = xmlTextReaderNodeType(reader);
 2077:     empty = xmlTextReaderIsEmptyElement(reader);
 2078: 
 2079:     name = xmlTextReaderConstName(reader);
 2080:     if (name == NULL)
 2081: 	name = BAD_CAST "--";
 2082: 
 2083:     value = xmlTextReaderConstValue(reader);
 2084: 
 2085: 
 2086:     fprintf(out, "%d %d %s %d %d",
 2087: 	    xmlTextReaderDepth(reader),
 2088: 	    type,
 2089: 	    name,
 2090: 	    empty,
 2091: 	    xmlTextReaderHasValue(reader));
 2092:     if (value == NULL)
 2093: 	fprintf(out, "\n");
 2094:     else {
 2095: 	fprintf(out, " %s\n", value);
 2096:     }
 2097: }
 2098: static int
 2099: streamProcessTest(const char *filename, const char *result, const char *err,
 2100:                   xmlTextReaderPtr reader, const char *rng) {
 2101:     int ret;
 2102:     char *temp = NULL;
 2103:     FILE *t = NULL;
 2104: 
 2105:     if (reader == NULL)
 2106:         return(-1);
 2107: 
 2108:     nb_tests++;
 2109:     if (result != NULL) {
 2110: 	temp = resultFilename(filename, "", ".res");
 2111: 	if (temp == NULL) {
 2112: 	    fprintf(stderr, "Out of memory\n");
 2113: 	    fatalError();
 2114: 	}
 2115: 	t = fopen(temp, "wb");
 2116: 	if (t == NULL) {
 2117: 	    fprintf(stderr, "Can't open temp file %s\n", temp);
 2118: 	    free(temp);
 2119: 	    return(-1);
 2120: 	}
 2121:     }
 2122: #ifdef LIBXML_SCHEMAS_ENABLED
 2123:     if (rng != NULL) {
 2124: 	ret = xmlTextReaderRelaxNGValidate(reader, rng);
 2125: 	if (ret < 0) {
 2126: 	    testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
 2127: 	                     rng);
 2128: 	    fclose(t);
 2129:             if (temp != NULL) {
 2130:                 unlink(temp);
 2131:                 free(temp);
 2132:             }
 2133: 	    return(0);
 2134: 	}
 2135:     }
 2136: #endif
 2137:     xmlGetWarningsDefaultValue = 1;
 2138:     ret = xmlTextReaderRead(reader);
 2139:     while (ret == 1) {
 2140: 	if ((t != NULL) && (rng == NULL))
 2141: 	    processNode(t, reader);
 2142:         ret = xmlTextReaderRead(reader);
 2143:     }
 2144:     if (ret != 0) {
 2145:         testErrorHandler(NULL, "%s : failed to parse\n", filename);
 2146:     }
 2147:     if (rng != NULL) {
 2148:         if (xmlTextReaderIsValid(reader) != 1) {
 2149: 	    testErrorHandler(NULL, "%s fails to validate\n", filename);
 2150: 	} else {
 2151: 	    testErrorHandler(NULL, "%s validates\n", filename);
 2152: 	}
 2153:     }
 2154:     xmlGetWarningsDefaultValue = 0;
 2155:     if (t != NULL) {
 2156:         fclose(t);
 2157: 	ret = compareFiles(temp, result);
 2158:         if (temp != NULL) {
 2159:             unlink(temp);
 2160:             free(temp);
 2161:         }
 2162: 	if (ret) {
 2163: 	    fprintf(stderr, "Result for %s failed\n", filename);
 2164: 	    return(-1);
 2165: 	}
 2166:     }
 2167:     if (err != NULL) {
 2168: 	ret = compareFileMem(err, testErrors, testErrorsSize);
 2169: 	if (ret != 0) {
 2170: 	    fprintf(stderr, "Error for %s failed\n", filename);
 2171: 	    printf("%s", testErrors);
 2172: 	    return(-1);
 2173: 	}
 2174:     }
 2175: 
 2176:     return(0);
 2177: }
 2178: 
 2179: /**
 2180:  * streamParseTest:
 2181:  * @filename: the file to parse
 2182:  * @result: the file with expected result
 2183:  * @err: the file with error messages
 2184:  *
 2185:  * Parse a file using the reader API and check for errors.
 2186:  *
 2187:  * Returns 0 in case of success, an error code otherwise
 2188:  */
 2189: static int
 2190: streamParseTest(const char *filename, const char *result, const char *err,
 2191:                 int options) {
 2192:     xmlTextReaderPtr reader;
 2193:     int ret;
 2194: 
 2195:     reader = xmlReaderForFile(filename, NULL, options);
 2196:     ret = streamProcessTest(filename, result, err, reader, NULL);
 2197:     xmlFreeTextReader(reader);
 2198:     return(ret);
 2199: }
 2200: 
 2201: /**
 2202:  * walkerParseTest:
 2203:  * @filename: the file to parse
 2204:  * @result: the file with expected result
 2205:  * @err: the file with error messages
 2206:  *
 2207:  * Parse a file using the walker, i.e. a reader built from a atree.
 2208:  *
 2209:  * Returns 0 in case of success, an error code otherwise
 2210:  */
 2211: static int
 2212: walkerParseTest(const char *filename, const char *result, const char *err,
 2213:                 int options) {
 2214:     xmlDocPtr doc;
 2215:     xmlTextReaderPtr reader;
 2216:     int ret;
 2217: 
 2218:     doc = xmlReadFile(filename, NULL, options);
 2219:     if (doc == NULL) {
 2220:         fprintf(stderr, "Failed to parse %s\n", filename);
 2221: 	return(-1);
 2222:     }
 2223:     reader = xmlReaderWalker(doc);
 2224:     ret = streamProcessTest(filename, result, err, reader, NULL);
 2225:     xmlFreeTextReader(reader);
 2226:     xmlFreeDoc(doc);
 2227:     return(ret);
 2228: }
 2229: 
 2230: /**
 2231:  * streamMemParseTest:
 2232:  * @filename: the file to parse
 2233:  * @result: the file with expected result
 2234:  * @err: the file with error messages
 2235:  *
 2236:  * Parse a file using the reader API from memory and check for errors.
 2237:  *
 2238:  * Returns 0 in case of success, an error code otherwise
 2239:  */
 2240: static int
 2241: streamMemParseTest(const char *filename, const char *result, const char *err,
 2242:                    int options) {
 2243:     xmlTextReaderPtr reader;
 2244:     int ret;
 2245:     const char *base;
 2246:     int size;
 2247: 
 2248:     /*
 2249:      * load and parse the memory
 2250:      */
 2251:     if (loadMem(filename, &base, &size) != 0) {
 2252:         fprintf(stderr, "Failed to load %s\n", filename);
 2253: 	return(-1);
 2254:     }
 2255:     reader = xmlReaderForMemory(base, size, filename, NULL, options);
 2256:     ret = streamProcessTest(filename, result, err, reader, NULL);
 2257:     free((char *)base);
 2258:     xmlFreeTextReader(reader);
 2259:     return(ret);
 2260: }
 2261: #endif
 2262: 
 2263: #ifdef LIBXML_XPATH_ENABLED
 2264: #ifdef LIBXML_DEBUG_ENABLED
 2265: /************************************************************************
 2266:  *									*
 2267:  *		XPath and XPointer based tests				*
 2268:  *									*
 2269:  ************************************************************************/
 2270: 
 2271: static FILE *xpathOutput;
 2272: static xmlDocPtr xpathDocument;
 2273: 
 2274: static void
 2275: testXPath(const char *str, int xptr, int expr) {
 2276:     xmlXPathObjectPtr res;
 2277:     xmlXPathContextPtr ctxt;
 2278: 
 2279:     nb_tests++;
 2280: #if defined(LIBXML_XPTR_ENABLED)
 2281:     if (xptr) {
 2282: 	ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
 2283: 	res = xmlXPtrEval(BAD_CAST str, ctxt);
 2284:     } else {
 2285: #endif
 2286: 	ctxt = xmlXPathNewContext(xpathDocument);
 2287: 	ctxt->node = xmlDocGetRootElement(xpathDocument);
 2288: 	if (expr)
 2289: 	    res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
 2290: 	else {
 2291: 	    /* res = xmlXPathEval(BAD_CAST str, ctxt); */
 2292: 	    xmlXPathCompExprPtr comp;
 2293: 
 2294: 	    comp = xmlXPathCompile(BAD_CAST str);
 2295: 	    if (comp != NULL) {
 2296: 		res = xmlXPathCompiledEval(comp, ctxt);
 2297: 		xmlXPathFreeCompExpr(comp);
 2298: 	    } else
 2299: 		res = NULL;
 2300: 	}
 2301: #if defined(LIBXML_XPTR_ENABLED)
 2302:     }
 2303: #endif
 2304:     xmlXPathDebugDumpObject(xpathOutput, res, 0);
 2305:     xmlXPathFreeObject(res);
 2306:     xmlXPathFreeContext(ctxt);
 2307: }
 2308: 
 2309: /**
 2310:  * xpathExprTest:
 2311:  * @filename: the file to parse
 2312:  * @result: the file with expected result
 2313:  * @err: the file with error messages
 2314:  *
 2315:  * Parse a file containing XPath standalone expressions and evaluate them
 2316:  *
 2317:  * Returns 0 in case of success, an error code otherwise
 2318:  */
 2319: static int
 2320: xpathCommonTest(const char *filename, const char *result,
 2321:                 int xptr, int expr) {
 2322:     FILE *input;
 2323:     char expression[5000];
 2324:     int len, ret = 0;
 2325:     char *temp;
 2326: 
 2327:     temp = resultFilename(filename, "", ".res");
 2328:     if (temp == NULL) {
 2329:         fprintf(stderr, "Out of memory\n");
 2330:         fatalError();
 2331:     }
 2332:     xpathOutput = fopen(temp, "wb");
 2333:     if (xpathOutput == NULL) {
 2334: 	fprintf(stderr, "failed to open output file %s\n", temp);
 2335:         free(temp);
 2336: 	return(-1);
 2337:     }
 2338: 
 2339:     input = fopen(filename, "rb");
 2340:     if (input == NULL) {
 2341:         xmlGenericError(xmlGenericErrorContext,
 2342: 		"Cannot open %s for reading\n", filename);
 2343:         free(temp);
 2344: 	return(-1);
 2345:     }
 2346:     while (fgets(expression, 4500, input) != NULL) {
 2347: 	len = strlen(expression);
 2348: 	len--;
 2349: 	while ((len >= 0) &&
 2350: 	       ((expression[len] == '\n') || (expression[len] == '\t') ||
 2351: 		(expression[len] == '\r') || (expression[len] == ' '))) len--;
 2352: 	expression[len + 1] = 0;
 2353: 	if (len >= 0) {
 2354: 	    fprintf(xpathOutput,
 2355: 	            "\n========================\nExpression: %s\n",
 2356: 		    expression) ;
 2357: 	    testXPath(expression, xptr, expr);
 2358: 	}
 2359:     }
 2360: 
 2361:     fclose(input);
 2362:     fclose(xpathOutput);
 2363:     if (result != NULL) {
 2364: 	ret = compareFiles(temp, result);
 2365: 	if (ret) {
 2366: 	    fprintf(stderr, "Result for %s failed\n", filename);
 2367: 	}
 2368:     }
 2369: 
 2370:     if (temp != NULL) {
 2371:         unlink(temp);
 2372:         free(temp);
 2373:     }
 2374:     return(ret);
 2375: }
 2376: 
 2377: /**
 2378:  * xpathExprTest:
 2379:  * @filename: the file to parse
 2380:  * @result: the file with expected result
 2381:  * @err: the file with error messages
 2382:  *
 2383:  * Parse a file containing XPath standalone expressions and evaluate them
 2384:  *
 2385:  * Returns 0 in case of success, an error code otherwise
 2386:  */
 2387: static int
 2388: xpathExprTest(const char *filename, const char *result,
 2389:               const char *err ATTRIBUTE_UNUSED,
 2390:               int options ATTRIBUTE_UNUSED) {
 2391:     return(xpathCommonTest(filename, result, 0, 1));
 2392: }
 2393: 
 2394: /**
 2395:  * xpathDocTest:
 2396:  * @filename: the file to parse
 2397:  * @result: the file with expected result
 2398:  * @err: the file with error messages
 2399:  *
 2400:  * Parse a file containing XPath expressions and evaluate them against
 2401:  * a set of corresponding documents.
 2402:  *
 2403:  * Returns 0 in case of success, an error code otherwise
 2404:  */
 2405: static int
 2406: xpathDocTest(const char *filename,
 2407:              const char *resul ATTRIBUTE_UNUSED,
 2408:              const char *err ATTRIBUTE_UNUSED,
 2409:              int options) {
 2410: 
 2411:     char pattern[500];
 2412:     char result[500];
 2413:     glob_t globbuf;
 2414:     size_t i;
 2415:     int ret = 0, res;
 2416: 
 2417:     xpathDocument = xmlReadFile(filename, NULL,
 2418:                                 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
 2419:     if (xpathDocument == NULL) {
 2420:         fprintf(stderr, "Failed to load %s\n", filename);
 2421: 	return(-1);
 2422:     }
 2423: 
 2424:     snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
 2425:     pattern[499] = 0;
 2426:     globbuf.gl_offs = 0;
 2427:     glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
 2428:     for (i = 0;i < globbuf.gl_pathc;i++) {
 2429:         snprintf(result, 499, "result/XPath/tests/%s",
 2430: 	         baseFilename(globbuf.gl_pathv[i]));
 2431: 	res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
 2432: 	if (res != 0)
 2433: 	    ret = res;
 2434:     }
 2435:     globfree(&globbuf);
 2436: 
 2437:     xmlFreeDoc(xpathDocument);
 2438:     return(ret);
 2439: }
 2440: 
 2441: #ifdef LIBXML_XPTR_ENABLED
 2442: /**
 2443:  * xptrDocTest:
 2444:  * @filename: the file to parse
 2445:  * @result: the file with expected result
 2446:  * @err: the file with error messages
 2447:  *
 2448:  * Parse a file containing XPath expressions and evaluate them against
 2449:  * a set of corresponding documents.
 2450:  *
 2451:  * Returns 0 in case of success, an error code otherwise
 2452:  */
 2453: static int
 2454: xptrDocTest(const char *filename,
 2455:             const char *resul ATTRIBUTE_UNUSED,
 2456:             const char *err ATTRIBUTE_UNUSED,
 2457:             int options) {
 2458: 
 2459:     char pattern[500];
 2460:     char result[500];
 2461:     glob_t globbuf;
 2462:     size_t i;
 2463:     int ret = 0, res;
 2464: 
 2465:     xpathDocument = xmlReadFile(filename, NULL,
 2466:                                 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
 2467:     if (xpathDocument == NULL) {
 2468:         fprintf(stderr, "Failed to load %s\n", filename);
 2469: 	return(-1);
 2470:     }
 2471: 
 2472:     snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
 2473:     pattern[499] = 0;
 2474:     globbuf.gl_offs = 0;
 2475:     glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
 2476:     for (i = 0;i < globbuf.gl_pathc;i++) {
 2477:         snprintf(result, 499, "result/XPath/xptr/%s",
 2478: 	         baseFilename(globbuf.gl_pathv[i]));
 2479: 	res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
 2480: 	if (res != 0)
 2481: 	    ret = res;
 2482:     }
 2483:     globfree(&globbuf);
 2484: 
 2485:     xmlFreeDoc(xpathDocument);
 2486:     return(ret);
 2487: }
 2488: #endif /* LIBXML_XPTR_ENABLED */
 2489: 
 2490: /**
 2491:  * xmlidDocTest:
 2492:  * @filename: the file to parse
 2493:  * @result: the file with expected result
 2494:  * @err: the file with error messages
 2495:  *
 2496:  * Parse a file containing xml:id and check for errors and verify
 2497:  * that XPath queries will work on them as expected.
 2498:  *
 2499:  * Returns 0 in case of success, an error code otherwise
 2500:  */
 2501: static int
 2502: xmlidDocTest(const char *filename,
 2503:              const char *result,
 2504:              const char *err,
 2505:              int options) {
 2506: 
 2507:     int res = 0;
 2508:     int ret = 0;
 2509:     char *temp;
 2510: 
 2511:     xpathDocument = xmlReadFile(filename, NULL,
 2512:                                 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
 2513:     if (xpathDocument == NULL) {
 2514:         fprintf(stderr, "Failed to load %s\n", filename);
 2515: 	return(-1);
 2516:     }
 2517: 
 2518:     temp = resultFilename(filename, "", ".res");
 2519:     if (temp == NULL) {
 2520:         fprintf(stderr, "Out of memory\n");
 2521:         fatalError();
 2522:     }
 2523:     xpathOutput = fopen(temp, "wb");
 2524:     if (xpathOutput == NULL) {
 2525: 	fprintf(stderr, "failed to open output file %s\n", temp);
 2526:         xmlFreeDoc(xpathDocument);
 2527:         free(temp);
 2528: 	return(-1);
 2529:     }
 2530: 
 2531:     testXPath("id('bar')", 0, 0);
 2532: 
 2533:     fclose(xpathOutput);
 2534:     if (result != NULL) {
 2535: 	ret = compareFiles(temp, result);
 2536: 	if (ret) {
 2537: 	    fprintf(stderr, "Result for %s failed\n", filename);
 2538: 	    res = 1;
 2539: 	}
 2540:     }
 2541: 
 2542:     if (temp != NULL) {
 2543:         unlink(temp);
 2544:         free(temp);
 2545:     }
 2546:     xmlFreeDoc(xpathDocument);
 2547: 
 2548:     if (err != NULL) {
 2549: 	ret = compareFileMem(err, testErrors, testErrorsSize);
 2550: 	if (ret != 0) {
 2551: 	    fprintf(stderr, "Error for %s failed\n", filename);
 2552: 	    res = 1;
 2553: 	}
 2554:     }
 2555:     return(res);
 2556: }
 2557: 
 2558: #endif /* LIBXML_DEBUG_ENABLED */
 2559: #endif /* XPATH */
 2560: /************************************************************************
 2561:  *									*
 2562:  *			URI based tests					*
 2563:  *									*
 2564:  ************************************************************************/
 2565: 
 2566: static void
 2567: handleURI(const char *str, const char *base, FILE *o) {
 2568:     int ret;
 2569:     xmlURIPtr uri;
 2570:     xmlChar *res = NULL;
 2571: 
 2572:     uri = xmlCreateURI();
 2573: 
 2574:     if (base == NULL) {
 2575: 	ret = xmlParseURIReference(uri, str);
 2576: 	if (ret != 0)
 2577: 	    fprintf(o, "%s : error %d\n", str, ret);
 2578: 	else {
 2579: 	    xmlNormalizeURIPath(uri->path);
 2580: 	    xmlPrintURI(o, uri);
 2581: 	    fprintf(o, "\n");
 2582: 	}
 2583:     } else {
 2584: 	res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
 2585: 	if (res != NULL) {
 2586: 	    fprintf(o, "%s\n", (char *) res);
 2587: 	}
 2588: 	else
 2589: 	    fprintf(o, "::ERROR::\n");
 2590:     }
 2591:     if (res != NULL)
 2592: 	xmlFree(res);
 2593:     xmlFreeURI(uri);
 2594: }
 2595: 
 2596: /**
 2597:  * uriCommonTest:
 2598:  * @filename: the file to parse
 2599:  * @result: the file with expected result
 2600:  * @err: the file with error messages
 2601:  *
 2602:  * Parse a file containing URI and check for errors
 2603:  *
 2604:  * Returns 0 in case of success, an error code otherwise
 2605:  */
 2606: static int
 2607: uriCommonTest(const char *filename,
 2608:              const char *result,
 2609:              const char *err,
 2610:              const char *base) {
 2611:     char *temp;
 2612:     FILE *o, *f;
 2613:     char str[1024];
 2614:     int res = 0, i, ret;
 2615: 
 2616:     temp = resultFilename(filename, "", ".res");
 2617:     if (temp == NULL) {
 2618:         fprintf(stderr, "Out of memory\n");
 2619:         fatalError();
 2620:     }
 2621:     o = fopen(temp, "wb");
 2622:     if (o == NULL) {
 2623: 	fprintf(stderr, "failed to open output file %s\n", temp);
 2624:         free(temp);
 2625: 	return(-1);
 2626:     }
 2627:     f = fopen(filename, "rb");
 2628:     if (f == NULL) {
 2629: 	fprintf(stderr, "failed to open input file %s\n", filename);
 2630: 	fclose(o);
 2631:         if (temp != NULL) {
 2632:             unlink(temp);
 2633:             free(temp);
 2634:         }
 2635: 	return(-1);
 2636:     }
 2637: 
 2638:     while (1) {
 2639: 	/*
 2640: 	 * read one line in string buffer.
 2641: 	 */
 2642: 	if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
 2643: 	   break;
 2644: 
 2645: 	/*
 2646: 	 * remove the ending spaces
 2647: 	 */
 2648: 	i = strlen(str);
 2649: 	while ((i > 0) &&
 2650: 	       ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
 2651: 		(str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
 2652: 	    i--;
 2653: 	    str[i] = 0;
 2654: 	}
 2655: 	nb_tests++;
 2656: 	handleURI(str, base, o);
 2657:     }
 2658: 
 2659:     fclose(f);
 2660:     fclose(o);
 2661: 
 2662:     if (result != NULL) {
 2663: 	ret = compareFiles(temp, result);
 2664: 	if (ret) {
 2665: 	    fprintf(stderr, "Result for %s failed\n", filename);
 2666: 	    res = 1;
 2667: 	}
 2668:     }
 2669:     if (err != NULL) {
 2670: 	ret = compareFileMem(err, testErrors, testErrorsSize);
 2671: 	if (ret != 0) {
 2672: 	    fprintf(stderr, "Error for %s failed\n", filename);
 2673: 	    res = 1;
 2674: 	}
 2675:     }
 2676: 
 2677:     if (temp != NULL) {
 2678:         unlink(temp);
 2679:         free(temp);
 2680:     }
 2681:     return(res);
 2682: }
 2683: 
 2684: /**
 2685:  * uriParseTest:
 2686:  * @filename: the file to parse
 2687:  * @result: the file with expected result
 2688:  * @err: the file with error messages
 2689:  *
 2690:  * Parse a file containing URI and check for errors
 2691:  *
 2692:  * Returns 0 in case of success, an error code otherwise
 2693:  */
 2694: static int
 2695: uriParseTest(const char *filename,
 2696:              const char *result,
 2697:              const char *err,
 2698:              int options ATTRIBUTE_UNUSED) {
 2699:     return(uriCommonTest(filename, result, err, NULL));
 2700: }
 2701: 
 2702: /**
 2703:  * uriBaseTest:
 2704:  * @filename: the file to parse
 2705:  * @result: the file with expected result
 2706:  * @err: the file with error messages
 2707:  *
 2708:  * Parse a file containing URI, compose them against a fixed base and
 2709:  * check for errors
 2710:  *
 2711:  * Returns 0 in case of success, an error code otherwise
 2712:  */
 2713: static int
 2714: uriBaseTest(const char *filename,
 2715:              const char *result,
 2716:              const char *err,
 2717:              int options ATTRIBUTE_UNUSED) {
 2718:     return(uriCommonTest(filename, result, err,
 2719:                          "http://foo.com/path/to/index.html?orig#help"));
 2720: }
 2721: 
 2722: static int urip_success = 1;
 2723: static int urip_current = 0;
 2724: static const char *urip_testURLs[] = {
 2725:     "urip://example.com/a b.html",
 2726:     "urip://example.com/a%20b.html",
 2727:     "file:///path/to/a b.html",
 2728:     "file:///path/to/a%20b.html",
 2729:     "/path/to/a b.html",
 2730:     "/path/to/a%20b.html",
 2731:     "urip://example.com/résumé.html",
 2732:     "urip://example.com/test?a=1&b=2%263&c=4#foo",
 2733:     NULL
 2734: };
 2735: static const char *urip_rcvsURLs[] = {
 2736:     /* it is an URI the strings must be escaped */
 2737:     "urip://example.com/a%20b.html",
 2738:     /* check that % escaping is not broken */
 2739:     "urip://example.com/a%20b.html",
 2740:     /* it's an URI path the strings must be escaped */
 2741:     "file:///path/to/a%20b.html",
 2742:     /* check that % escaping is not broken */
 2743:     "file:///path/to/a%20b.html",
 2744:     /* this is not an URI, this is a path, so this should not be escaped */
 2745:     "/path/to/a b.html",
 2746:     /* check that paths with % are not broken */
 2747:     "/path/to/a%20b.html",
 2748:     /* out of context the encoding can't be guessed byte by byte conversion */
 2749:     "urip://example.com/r%E9sum%E9.html",
 2750:     /* verify we don't destroy URIs especially the query part */
 2751:     "urip://example.com/test?a=1&b=2%263&c=4#foo",
 2752:     NULL
 2753: };
 2754: static const char *urip_res = "<list/>";
 2755: static const char *urip_cur = NULL;
 2756: static int urip_rlen;
 2757: 
 2758: /**
 2759:  * uripMatch:
 2760:  * @URI: an URI to test
 2761:  *
 2762:  * Check for an urip: query
 2763:  *
 2764:  * Returns 1 if yes and 0 if another Input module should be used
 2765:  */
 2766: static int
 2767: uripMatch(const char * URI) {
 2768:     if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
 2769:         return(0);
 2770:     /* Verify we received the escaped URL */
 2771:     if (strcmp(urip_rcvsURLs[urip_current], URI))
 2772: 	urip_success = 0;
 2773:     return(1);
 2774: }
 2775: 
 2776: /**
 2777:  * uripOpen:
 2778:  * @URI: an URI to test
 2779:  *
 2780:  * Return a pointer to the urip: query handler, in this example simply
 2781:  * the urip_current pointer...
 2782:  *
 2783:  * Returns an Input context or NULL in case or error
 2784:  */
 2785: static void *
 2786: uripOpen(const char * URI) {
 2787:     if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
 2788:         return(NULL);
 2789:     /* Verify we received the escaped URL */
 2790:     if (strcmp(urip_rcvsURLs[urip_current], URI))
 2791: 	urip_success = 0;
 2792:     urip_cur = urip_res;
 2793:     urip_rlen = strlen(urip_res);
 2794:     return((void *) urip_cur);
 2795: }
 2796: 
 2797: /**
 2798:  * uripClose:
 2799:  * @context: the read context
 2800:  *
 2801:  * Close the urip: query handler
 2802:  *
 2803:  * Returns 0 or -1 in case of error
 2804:  */
 2805: static int
 2806: uripClose(void * context) {
 2807:     if (context == NULL) return(-1);
 2808:     urip_cur = NULL;
 2809:     urip_rlen = 0;
 2810:     return(0);
 2811: }
 2812: 
 2813: /**
 2814:  * uripRead:
 2815:  * @context: the read context
 2816:  * @buffer: where to store data
 2817:  * @len: number of bytes to read
 2818:  *
 2819:  * Implement an urip: query read.
 2820:  *
 2821:  * Returns the number of bytes read or -1 in case of error
 2822:  */
 2823: static int
 2824: uripRead(void * context, char * buffer, int len) {
 2825:    const char *ptr = (const char *) context;
 2826: 
 2827:    if ((context == NULL) || (buffer == NULL) || (len < 0))
 2828:        return(-1);
 2829: 
 2830:    if (len > urip_rlen) len = urip_rlen;
 2831:    memcpy(buffer, ptr, len);
 2832:    urip_rlen -= len;
 2833:    return(len);
 2834: }
 2835: 
 2836: static int
 2837: urip_checkURL(const char *URL) {
 2838:     xmlDocPtr doc;
 2839: 
 2840:     doc = xmlReadFile(URL, NULL, 0);
 2841:     if (doc == NULL)
 2842:         return(-1);
 2843:     xmlFreeDoc(doc);
 2844:     return(1);
 2845: }
 2846: 
 2847: /**
 2848:  * uriPathTest:
 2849:  * @filename: ignored
 2850:  * @result: ignored
 2851:  * @err: ignored
 2852:  *
 2853:  * Run a set of tests to check how Path and URI are handled before
 2854:  * being passed to the I/O layer
 2855:  *
 2856:  * Returns 0 in case of success, an error code otherwise
 2857:  */
 2858: static int
 2859: uriPathTest(const char *filename ATTRIBUTE_UNUSED,
 2860:              const char *result ATTRIBUTE_UNUSED,
 2861:              const char *err ATTRIBUTE_UNUSED,
 2862:              int options ATTRIBUTE_UNUSED) {
 2863:     int parsed;
 2864:     int failures = 0;
 2865: 
 2866:     /*
 2867:      * register the new I/O handlers
 2868:      */
 2869:     if (xmlRegisterInputCallbacks(uripMatch, uripOpen, uripRead, uripClose) < 0)
 2870:     {
 2871:         fprintf(stderr, "failed to register HTTP handler\n");
 2872: 	return(-1);
 2873:     }
 2874: 
 2875:     for (urip_current = 0;urip_testURLs[urip_current] != NULL;urip_current++) {
 2876:         urip_success = 1;
 2877:         parsed = urip_checkURL(urip_testURLs[urip_current]);
 2878: 	if (urip_success != 1) {
 2879: 	    fprintf(stderr, "failed the URL passing test for %s",
 2880: 	            urip_testURLs[urip_current]);
 2881: 	    failures++;
 2882: 	} else if (parsed != 1) {
 2883: 	    fprintf(stderr, "failed the parsing test for %s",
 2884: 	            urip_testURLs[urip_current]);
 2885: 	    failures++;
 2886: 	}
 2887: 	nb_tests++;
 2888:     }
 2889: 
 2890:     xmlPopInputCallbacks();
 2891:     return(failures);
 2892: }
 2893: 
 2894: #ifdef LIBXML_SCHEMAS_ENABLED
 2895: /************************************************************************
 2896:  *									*
 2897:  *			Schemas tests					*
 2898:  *									*
 2899:  ************************************************************************/
 2900: static int
 2901: schemasOneTest(const char *sch,
 2902:                const char *filename,
 2903:                const char *result,
 2904: 	       const char *err,
 2905: 	       int options,
 2906: 	       xmlSchemaPtr schemas) {
 2907:     xmlDocPtr doc;
 2908:     xmlSchemaValidCtxtPtr ctxt;
 2909:     int ret = 0;
 2910:     int validResult = 0;
 2911:     char *temp;
 2912:     FILE *schemasOutput;
 2913: 
 2914:     doc = xmlReadFile(filename, NULL, options);
 2915:     if (doc == NULL) {
 2916:         fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
 2917: 	return(-1);
 2918:     }
 2919: 
 2920:     temp = resultFilename(result, "", ".res");
 2921:     if (temp == NULL) {
 2922:         fprintf(stderr, "Out of memory\n");
 2923:         fatalError();
 2924:     }
 2925:     schemasOutput = fopen(temp, "wb");
 2926:     if (schemasOutput == NULL) {
 2927: 	fprintf(stderr, "failed to open output file %s\n", temp);
 2928: 	xmlFreeDoc(doc);
 2929:         free(temp);
 2930: 	return(-1);
 2931:     }
 2932: 
 2933:     ctxt = xmlSchemaNewValidCtxt(schemas);
 2934:     xmlSchemaSetValidErrors(ctxt,
 2935:          (xmlSchemaValidityErrorFunc) testErrorHandler,
 2936:          (xmlSchemaValidityWarningFunc) testErrorHandler,
 2937: 	 ctxt);
 2938:     validResult = xmlSchemaValidateDoc(ctxt, doc);
 2939:     if (validResult == 0) {
 2940: 	fprintf(schemasOutput, "%s validates\n", filename);
 2941:     } else if (validResult > 0) {
 2942: 	fprintf(schemasOutput, "%s fails to validate\n", filename);
 2943:     } else {
 2944: 	fprintf(schemasOutput, "%s validation generated an internal error\n",
 2945: 	       filename);
 2946:     }
 2947:     fclose(schemasOutput);
 2948:     if (result) {
 2949: 	if (compareFiles(temp, result)) {
 2950: 	    fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
 2951: 	    ret = 1;
 2952: 	}
 2953:     }
 2954:     if (temp != NULL) {
 2955:         unlink(temp);
 2956:         free(temp);
 2957:     }
 2958: 
 2959:     if ((validResult != 0) && (err != NULL)) {
 2960: 	if (compareFileMem(err, testErrors, testErrorsSize)) {
 2961: 	    fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
 2962: 	    ret = 1;
 2963: 	}
 2964:     }
 2965: 
 2966:     xmlSchemaFreeValidCtxt(ctxt);
 2967:     xmlFreeDoc(doc);
 2968:     return(ret);
 2969: }
 2970: /**
 2971:  * schemasTest:
 2972:  * @filename: the schemas file
 2973:  * @result: the file with expected result
 2974:  * @err: the file with error messages
 2975:  *
 2976:  * Parse a file containing URI, compose them against a fixed base and
 2977:  * check for errors
 2978:  *
 2979:  * Returns 0 in case of success, an error code otherwise
 2980:  */
 2981: static int
 2982: schemasTest(const char *filename,
 2983:             const char *resul ATTRIBUTE_UNUSED,
 2984:             const char *errr ATTRIBUTE_UNUSED,
 2985:             int options) {
 2986:     const char *base = baseFilename(filename);
 2987:     const char *base2;
 2988:     const char *instance;
 2989:     xmlSchemaParserCtxtPtr ctxt;
 2990:     xmlSchemaPtr schemas;
 2991:     int res = 0, len, ret;
 2992:     char pattern[500];
 2993:     char prefix[500];
 2994:     char result[500];
 2995:     char err[500];
 2996:     glob_t globbuf;
 2997:     size_t i;
 2998:     char count = 0;
 2999: 
 3000:     /* first compile the schemas if possible */
 3001:     ctxt = xmlSchemaNewParserCtxt(filename);
 3002:     xmlSchemaSetParserErrors(ctxt,
 3003:          (xmlSchemaValidityErrorFunc) testErrorHandler,
 3004:          (xmlSchemaValidityWarningFunc) testErrorHandler,
 3005: 	 ctxt);
 3006:     schemas = xmlSchemaParse(ctxt);
 3007:     xmlSchemaFreeParserCtxt(ctxt);
 3008: 
 3009:     /*
 3010:      * most of the mess is about the output filenames generated by the Makefile
 3011:      */
 3012:     len = strlen(base);
 3013:     if ((len > 499) || (len < 5)) {
 3014:         xmlSchemaFree(schemas);
 3015: 	return(-1);
 3016:     }
 3017:     len -= 4; /* remove trailing .xsd */
 3018:     if (base[len - 2] == '_') {
 3019:         len -= 2; /* remove subtest number */
 3020:     }
 3021:     if (base[len - 2] == '_') {
 3022:         len -= 2; /* remove subtest number */
 3023:     }
 3024:     memcpy(prefix, base, len);
 3025:     prefix[len] = 0;
 3026: 
 3027:     snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
 3028:     pattern[499] = 0;
 3029: 
 3030:     if (base[len] == '_') {
 3031:         len += 2;
 3032: 	memcpy(prefix, base, len);
 3033: 	prefix[len] = 0;
 3034:     }
 3035: 
 3036:     globbuf.gl_offs = 0;
 3037:     glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
 3038:     for (i = 0;i < globbuf.gl_pathc;i++) {
 3039:         testErrorsSize = 0;
 3040: 	testErrors[0] = 0;
 3041:         instance = globbuf.gl_pathv[i];
 3042: 	base2 = baseFilename(instance);
 3043: 	len = strlen(base2);
 3044: 	if ((len > 6) && (base2[len - 6] == '_')) {
 3045: 	    count = base2[len - 5];
 3046: 	    snprintf(result, 499, "result/schemas/%s_%c",
 3047: 		     prefix, count);
 3048: 	    result[499] = 0;
 3049: 	    snprintf(err, 499, "result/schemas/%s_%c.err",
 3050: 		     prefix, count);
 3051: 	    err[499] = 0;
 3052: 	} else {
 3053: 	    fprintf(stderr, "don't know how to process %s\n", instance);
 3054: 	    continue;
 3055: 	}
 3056: 	if (schemas == NULL) {
 3057: 	} else {
 3058: 	    nb_tests++;
 3059: 	    ret = schemasOneTest(filename, instance, result, err,
 3060: 	                         options, schemas);
 3061: 	    if (ret != 0)
 3062: 		res = ret;
 3063: 	}
 3064:     }
 3065:     globfree(&globbuf);
 3066:     xmlSchemaFree(schemas);
 3067: 
 3068:     return(res);
 3069: }
 3070: 
 3071: /************************************************************************
 3072:  *									*
 3073:  *			Schemas tests					*
 3074:  *									*
 3075:  ************************************************************************/
 3076: static int
 3077: rngOneTest(const char *sch,
 3078:                const char *filename,
 3079:                const char *result,
 3080: 	       const char *err,
 3081: 	       int options,
 3082: 	       xmlRelaxNGPtr schemas) {
 3083:     xmlDocPtr doc;
 3084:     xmlRelaxNGValidCtxtPtr ctxt;
 3085:     int ret = 0;
 3086:     char *temp;
 3087:     FILE *schemasOutput;
 3088: 
 3089:     doc = xmlReadFile(filename, NULL, options);
 3090:     if (doc == NULL) {
 3091:         fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
 3092: 	return(-1);
 3093:     }
 3094: 
 3095:     temp = resultFilename(result, "", ".res");
 3096:     if (temp == NULL) {
 3097:         fprintf(stderr, "Out of memory\n");
 3098:         fatalError();
 3099:     }
 3100:     schemasOutput = fopen(temp, "wb");
 3101:     if (schemasOutput == NULL) {
 3102: 	fprintf(stderr, "failed to open output file %s\n", temp);
 3103: 	xmlFreeDoc(doc);
 3104:         free(temp);
 3105: 	return(-1);
 3106:     }
 3107: 
 3108:     ctxt = xmlRelaxNGNewValidCtxt(schemas);
 3109:     xmlRelaxNGSetValidErrors(ctxt,
 3110:          (xmlRelaxNGValidityErrorFunc) testErrorHandler,
 3111:          (xmlRelaxNGValidityWarningFunc) testErrorHandler,
 3112: 	 ctxt);
 3113:     ret = xmlRelaxNGValidateDoc(ctxt, doc);
 3114:     if (ret == 0) {
 3115: 	testErrorHandler(NULL, "%s validates\n", filename);
 3116:     } else if (ret > 0) {
 3117: 	testErrorHandler(NULL, "%s fails to validate\n", filename);
 3118:     } else {
 3119: 	testErrorHandler(NULL, "%s validation generated an internal error\n",
 3120: 	       filename);
 3121:     }
 3122:     fclose(schemasOutput);
 3123:     ret = 0;
 3124:     if (result) {
 3125: 	if (compareFiles(temp, result)) {
 3126: 	    fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
 3127: 	    ret = 1;
 3128: 	}
 3129:     }
 3130:     if (temp != NULL) {
 3131:         unlink(temp);
 3132:         free(temp);
 3133:     }
 3134: 
 3135:     if (err != NULL) {
 3136: 	if (compareFileMem(err, testErrors, testErrorsSize)) {
 3137: 	    fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
 3138: 	    ret = 1;
 3139: 	    printf("%s", testErrors);
 3140: 	}
 3141:     }
 3142: 
 3143: 
 3144:     xmlRelaxNGFreeValidCtxt(ctxt);
 3145:     xmlFreeDoc(doc);
 3146:     return(ret);
 3147: }
 3148: /**
 3149:  * rngTest:
 3150:  * @filename: the schemas file
 3151:  * @result: the file with expected result
 3152:  * @err: the file with error messages
 3153:  *
 3154:  * Parse an RNG schemas and then apply it to the related .xml
 3155:  *
 3156:  * Returns 0 in case of success, an error code otherwise
 3157:  */
 3158: static int
 3159: rngTest(const char *filename,
 3160:             const char *resul ATTRIBUTE_UNUSED,
 3161:             const char *errr ATTRIBUTE_UNUSED,
 3162:             int options) {
 3163:     const char *base = baseFilename(filename);
 3164:     const char *base2;
 3165:     const char *instance;
 3166:     xmlRelaxNGParserCtxtPtr ctxt;
 3167:     xmlRelaxNGPtr schemas;
 3168:     int res = 0, len, ret = 0;
 3169:     char pattern[500];
 3170:     char prefix[500];
 3171:     char result[500];
 3172:     char err[500];
 3173:     glob_t globbuf;
 3174:     size_t i;
 3175:     char count = 0;
 3176: 
 3177:     /* first compile the schemas if possible */
 3178:     ctxt = xmlRelaxNGNewParserCtxt(filename);
 3179:     xmlRelaxNGSetParserErrors(ctxt,
 3180:          (xmlRelaxNGValidityErrorFunc) testErrorHandler,
 3181:          (xmlRelaxNGValidityWarningFunc) testErrorHandler,
 3182: 	 ctxt);
 3183:     schemas = xmlRelaxNGParse(ctxt);
 3184:     xmlRelaxNGFreeParserCtxt(ctxt);
 3185: 
 3186:     /*
 3187:      * most of the mess is about the output filenames generated by the Makefile
 3188:      */
 3189:     len = strlen(base);
 3190:     if ((len > 499) || (len < 5)) {
 3191:         xmlRelaxNGFree(schemas);
 3192: 	return(-1);
 3193:     }
 3194:     len -= 4; /* remove trailing .rng */
 3195:     memcpy(prefix, base, len);
 3196:     prefix[len] = 0;
 3197: 
 3198:     snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
 3199:     pattern[499] = 0;
 3200: 
 3201:     globbuf.gl_offs = 0;
 3202:     glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
 3203:     for (i = 0;i < globbuf.gl_pathc;i++) {
 3204:         testErrorsSize = 0;
 3205: 	testErrors[0] = 0;
 3206:         instance = globbuf.gl_pathv[i];
 3207: 	base2 = baseFilename(instance);
 3208: 	len = strlen(base2);
 3209: 	if ((len > 6) && (base2[len - 6] == '_')) {
 3210: 	    count = base2[len - 5];
 3211: 	    snprintf(result, 499, "result/relaxng/%s_%c",
 3212: 		     prefix, count);
 3213: 	    result[499] = 0;
 3214: 	    snprintf(err, 499, "result/relaxng/%s_%c.err",
 3215: 		     prefix, count);
 3216: 	    err[499] = 0;
 3217: 	} else {
 3218: 	    fprintf(stderr, "don't know how to process %s\n", instance);
 3219: 	    continue;
 3220: 	}
 3221: 	if (schemas == NULL) {
 3222: 	} else {
 3223: 	    nb_tests++;
 3224: 	    ret = rngOneTest(filename, instance, result, err,
 3225: 	                         options, schemas);
 3226: 	    if (res != 0)
 3227: 		ret = res;
 3228: 	}
 3229:     }
 3230:     globfree(&globbuf);
 3231:     xmlRelaxNGFree(schemas);
 3232: 
 3233:     return(ret);
 3234: }
 3235: 
 3236: #ifdef LIBXML_READER_ENABLED
 3237: /**
 3238:  * rngStreamTest:
 3239:  * @filename: the schemas file
 3240:  * @result: the file with expected result
 3241:  * @err: the file with error messages
 3242:  *
 3243:  * Parse a set of files with streaming, applying an RNG schemas
 3244:  *
 3245:  * Returns 0 in case of success, an error code otherwise
 3246:  */
 3247: static int
 3248: rngStreamTest(const char *filename,
 3249:             const char *resul ATTRIBUTE_UNUSED,
 3250:             const char *errr ATTRIBUTE_UNUSED,
 3251:             int options) {
 3252:     const char *base = baseFilename(filename);
 3253:     const char *base2;
 3254:     const char *instance;
 3255:     int res = 0, len, ret;
 3256:     char pattern[500];
 3257:     char prefix[500];
 3258:     char result[500];
 3259:     char err[500];
 3260:     glob_t globbuf;
 3261:     size_t i;
 3262:     char count = 0;
 3263:     xmlTextReaderPtr reader;
 3264:     int disable_err = 0;
 3265: 
 3266:     /*
 3267:      * most of the mess is about the output filenames generated by the Makefile
 3268:      */
 3269:     len = strlen(base);
 3270:     if ((len > 499) || (len < 5)) {
 3271: 	fprintf(stderr, "len(base) == %d !\n", len);
 3272: 	return(-1);
 3273:     }
 3274:     len -= 4; /* remove trailing .rng */
 3275:     memcpy(prefix, base, len);
 3276:     prefix[len] = 0;
 3277: 
 3278:     /*
 3279:      * strictly unifying the error messages is nearly impossible this
 3280:      * hack is also done in the Makefile
 3281:      */
 3282:     if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
 3283:         (!strcmp(prefix, "tutor3_2")) || (!strcmp(prefix, "307377")) ||
 3284:         (!strcmp(prefix, "tutor8_2")))
 3285: 	disable_err = 1;
 3286: 
 3287:     snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
 3288:     pattern[499] = 0;
 3289: 
 3290:     globbuf.gl_offs = 0;
 3291:     glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
 3292:     for (i = 0;i < globbuf.gl_pathc;i++) {
 3293:         testErrorsSize = 0;
 3294: 	testErrors[0] = 0;
 3295:         instance = globbuf.gl_pathv[i];
 3296: 	base2 = baseFilename(instance);
 3297: 	len = strlen(base2);
 3298: 	if ((len > 6) && (base2[len - 6] == '_')) {
 3299: 	    count = base2[len - 5];
 3300: 	    snprintf(result, 499, "result/relaxng/%s_%c",
 3301: 		     prefix, count);
 3302: 	    result[499] = 0;
 3303: 	    snprintf(err, 499, "result/relaxng/%s_%c.err",
 3304: 		     prefix, count);
 3305: 	    err[499] = 0;
 3306: 	} else {
 3307: 	    fprintf(stderr, "don't know how to process %s\n", instance);
 3308: 	    continue;
 3309: 	}
 3310: 	reader = xmlReaderForFile(instance, NULL, options);
 3311: 	if (reader == NULL) {
 3312: 	    fprintf(stderr, "Failed to build reder for %s\n", instance);
 3313: 	}
 3314: 	if (disable_err == 1)
 3315: 	    ret = streamProcessTest(instance, result, NULL, reader, filename);
 3316: 	else
 3317: 	    ret = streamProcessTest(instance, result, err, reader, filename);
 3318: 	xmlFreeTextReader(reader);
 3319: 	if (ret != 0) {
 3320: 	    fprintf(stderr, "instance %s failed\n", instance);
 3321: 	    res = ret;
 3322: 	}
 3323:     }
 3324:     globfree(&globbuf);
 3325: 
 3326:     return(res);
 3327: }
 3328: #endif /* READER */
 3329: 
 3330: #endif
 3331: 
 3332: #ifdef LIBXML_PATTERN_ENABLED
 3333: #ifdef LIBXML_READER_ENABLED
 3334: /************************************************************************
 3335:  *									*
 3336:  *			Patterns tests					*
 3337:  *									*
 3338:  ************************************************************************/
 3339: static void patternNode(FILE *out, xmlTextReaderPtr reader,
 3340:                         const char *pattern, xmlPatternPtr patternc,
 3341: 			xmlStreamCtxtPtr patstream) {
 3342:     xmlChar *path = NULL;
 3343:     int match = -1;
 3344:     int type, empty;
 3345: 
 3346:     type = xmlTextReaderNodeType(reader);
 3347:     empty = xmlTextReaderIsEmptyElement(reader);
 3348: 
 3349:     if (type == XML_READER_TYPE_ELEMENT) {
 3350: 	/* do the check only on element start */
 3351: 	match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
 3352: 
 3353: 	if (match) {
 3354: 	    path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
 3355: 	    fprintf(out, "Node %s matches pattern %s\n", path, pattern);
 3356: 	}
 3357:     }
 3358:     if (patstream != NULL) {
 3359: 	int ret;
 3360: 
 3361: 	if (type == XML_READER_TYPE_ELEMENT) {
 3362: 	    ret = xmlStreamPush(patstream,
 3363: 				xmlTextReaderConstLocalName(reader),
 3364: 				xmlTextReaderConstNamespaceUri(reader));
 3365: 	    if (ret < 0) {
 3366: 		fprintf(out, "xmlStreamPush() failure\n");
 3367: 		xmlFreeStreamCtxt(patstream);
 3368: 		patstream = NULL;
 3369: 	    } else if (ret != match) {
 3370: 		if (path == NULL) {
 3371: 		    path = xmlGetNodePath(
 3372: 				   xmlTextReaderCurrentNode(reader));
 3373: 		}
 3374: 		fprintf(out,
 3375: 			"xmlPatternMatch and xmlStreamPush disagree\n");
 3376: 		fprintf(out,
 3377: 			"  pattern %s node %s\n",
 3378: 			pattern, path);
 3379: 	    }
 3380: 
 3381: 
 3382: 	}
 3383: 	if ((type == XML_READER_TYPE_END_ELEMENT) ||
 3384: 	    ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
 3385: 	    ret = xmlStreamPop(patstream);
 3386: 	    if (ret < 0) {
 3387: 		fprintf(out, "xmlStreamPop() failure\n");
 3388: 		xmlFreeStreamCtxt(patstream);
 3389: 		patstream = NULL;
 3390: 	    }
 3391: 	}
 3392:     }
 3393:     if (path != NULL)
 3394: 	xmlFree(path);
 3395: }
 3396: 
 3397: /**
 3398:  * patternTest:
 3399:  * @filename: the schemas file
 3400:  * @result: the file with expected result
 3401:  * @err: the file with error messages
 3402:  *
 3403:  * Parse a set of files with streaming, applying an RNG schemas
 3404:  *
 3405:  * Returns 0 in case of success, an error code otherwise
 3406:  */
 3407: static int
 3408: patternTest(const char *filename,
 3409:             const char *resul ATTRIBUTE_UNUSED,
 3410:             const char *err ATTRIBUTE_UNUSED,
 3411:             int options) {
 3412:     xmlPatternPtr patternc = NULL;
 3413:     xmlStreamCtxtPtr patstream = NULL;
 3414:     FILE *o, *f;
 3415:     char str[1024];
 3416:     char xml[500];
 3417:     char result[500];
 3418:     int len, i;
 3419:     int ret = 0, res;
 3420:     char *temp;
 3421:     xmlTextReaderPtr reader;
 3422:     xmlDocPtr doc;
 3423: 
 3424:     len = strlen(filename);
 3425:     len -= 4;
 3426:     memcpy(xml, filename, len);
 3427:     xml[len] = 0;
 3428:     snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
 3429:     result[499] = 0;
 3430:     memcpy(xml + len, ".xml", 5);
 3431: 
 3432:     if (!checkTestFile(xml)) {
 3433: 	fprintf(stderr, "Missing xml file %s\n", xml);
 3434: 	return(-1);
 3435:     }
 3436:     if (!checkTestFile(result)) {
 3437: 	fprintf(stderr, "Missing result file %s\n", result);
 3438: 	return(-1);
 3439:     }
 3440:     f = fopen(filename, "rb");
 3441:     if (f == NULL) {
 3442:         fprintf(stderr, "Failed to open %s\n", filename);
 3443: 	return(-1);
 3444:     }
 3445:     temp = resultFilename(filename, "", ".res");
 3446:     if (temp == NULL) {
 3447:         fprintf(stderr, "Out of memory\n");
 3448:         fatalError();
 3449:     }
 3450:     o = fopen(temp, "wb");
 3451:     if (o == NULL) {
 3452: 	fprintf(stderr, "failed to open output file %s\n", temp);
 3453: 	fclose(f);
 3454:         free(temp);
 3455: 	return(-1);
 3456:     }
 3457:     while (1) {
 3458: 	/*
 3459: 	 * read one line in string buffer.
 3460: 	 */
 3461: 	if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
 3462: 	   break;
 3463: 
 3464: 	/*
 3465: 	 * remove the ending spaces
 3466: 	 */
 3467: 	i = strlen(str);
 3468: 	while ((i > 0) &&
 3469: 	       ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
 3470: 		(str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
 3471: 	    i--;
 3472: 	    str[i] = 0;
 3473: 	}
 3474: 	doc = xmlReadFile(xml, NULL, options);
 3475: 	if (doc == NULL) {
 3476: 	    fprintf(stderr, "Failed to parse %s\n", xml);
 3477: 	    ret = 1;
 3478: 	} else {
 3479: 	    xmlNodePtr root;
 3480: 	    const xmlChar *namespaces[22];
 3481: 	    int j;
 3482: 	    xmlNsPtr ns;
 3483: 
 3484: 	    root = xmlDocGetRootElement(doc);
 3485: 	    for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
 3486: 		namespaces[j++] = ns->href;
 3487: 		namespaces[j++] = ns->prefix;
 3488: 	    }
 3489: 	    namespaces[j++] = NULL;
 3490: 	    namespaces[j] = NULL;
 3491: 
 3492: 	    patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
 3493: 					 0, &namespaces[0]);
 3494: 	    if (patternc == NULL) {
 3495: 		testErrorHandler(NULL,
 3496: 			"Pattern %s failed to compile\n", str);
 3497: 		xmlFreeDoc(doc);
 3498: 		ret = 1;
 3499: 		continue;
 3500: 	    }
 3501: 	    patstream = xmlPatternGetStreamCtxt(patternc);
 3502: 	    if (patstream != NULL) {
 3503: 		ret = xmlStreamPush(patstream, NULL, NULL);
 3504: 		if (ret < 0) {
 3505: 		    fprintf(stderr, "xmlStreamPush() failure\n");
 3506: 		    xmlFreeStreamCtxt(patstream);
 3507: 		    patstream = NULL;
 3508: 		}
 3509: 	    }
 3510: 	    nb_tests++;
 3511: 
 3512: 	    reader = xmlReaderWalker(doc);
 3513: 	    res = xmlTextReaderRead(reader);
 3514: 	    while (res == 1) {
 3515: 		patternNode(o, reader, str, patternc, patstream);
 3516: 		res = xmlTextReaderRead(reader);
 3517: 	    }
 3518: 	    if (res != 0) {
 3519: 		fprintf(o, "%s : failed to parse\n", filename);
 3520: 	    }
 3521: 	    xmlFreeTextReader(reader);
 3522: 	    xmlFreeDoc(doc);
 3523: 	    xmlFreeStreamCtxt(patstream);
 3524: 	    patstream = NULL;
 3525: 	    xmlFreePattern(patternc);
 3526: 
 3527: 	}
 3528:     }
 3529: 
 3530:     fclose(f);
 3531:     fclose(o);
 3532: 
 3533:     ret = compareFiles(temp, result);
 3534:     if (ret) {
 3535: 	fprintf(stderr, "Result for %s failed\n", filename);
 3536: 	ret = 1;
 3537:     }
 3538:     if (temp != NULL) {
 3539:         unlink(temp);
 3540:         free(temp);
 3541:     }
 3542:     return(ret);
 3543: }
 3544: #endif /* READER */
 3545: #endif /* PATTERN */
 3546: #ifdef LIBXML_C14N_ENABLED
 3547: /************************************************************************
 3548:  *									*
 3549:  *			Canonicalization tests				*
 3550:  *									*
 3551:  ************************************************************************/
 3552: static xmlXPathObjectPtr
 3553: load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
 3554:     xmlXPathObjectPtr xpath;
 3555:     xmlDocPtr doc;
 3556:     xmlChar *expr;
 3557:     xmlXPathContextPtr ctx;
 3558:     xmlNodePtr node;
 3559:     xmlNsPtr ns;
 3560: 
 3561:     /*
 3562:      * load XPath expr as a file
 3563:      */
 3564:     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
 3565:     xmlSubstituteEntitiesDefault(1);
 3566: 
 3567:     doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
 3568:     if (doc == NULL) {
 3569: 	fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
 3570: 	return(NULL);
 3571:     }
 3572: 
 3573:     /*
 3574:      * Check the document is of the right kind
 3575:      */
 3576:     if(xmlDocGetRootElement(doc) == NULL) {
 3577:         fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
 3578: 	xmlFreeDoc(doc);
 3579: 	return(NULL);
 3580:     }
 3581: 
 3582:     node = doc->children;
 3583:     while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
 3584: 	node = node->next;
 3585:     }
 3586: 
 3587:     if(node == NULL) {
 3588:         fprintf(stderr,"Error: XPath element expected in the file  \"%s\"\n", filename);
 3589: 	xmlFreeDoc(doc);
 3590: 	return(NULL);
 3591:     }
 3592: 
 3593:     expr = xmlNodeGetContent(node);
 3594:     if(expr == NULL) {
 3595:         fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
 3596: 	xmlFreeDoc(doc);
 3597: 	return(NULL);
 3598:     }
 3599: 
 3600:     ctx = xmlXPathNewContext(parent_doc);
 3601:     if(ctx == NULL) {
 3602:         fprintf(stderr,"Error: unable to create new context\n");
 3603:         xmlFree(expr);
 3604:         xmlFreeDoc(doc);
 3605:         return(NULL);
 3606:     }
 3607: 
 3608:     /*
 3609:      * Register namespaces
 3610:      */
 3611:     ns = node->nsDef;
 3612:     while(ns != NULL) {
 3613: 	if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
 3614: 	    fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
 3615:     xmlFree(expr);
 3616: 	    xmlXPathFreeContext(ctx);
 3617: 	    xmlFreeDoc(doc);
 3618: 	    return(NULL);
 3619: 	}
 3620: 	ns = ns->next;
 3621:     }
 3622: 
 3623:     /*
 3624:      * Evaluate xpath
 3625:      */
 3626:     xpath = xmlXPathEvalExpression(expr, ctx);
 3627:     if(xpath == NULL) {
 3628:         fprintf(stderr,"Error: unable to evaluate xpath expression\n");
 3629: xmlFree(expr);
 3630:         xmlXPathFreeContext(ctx);
 3631:         xmlFreeDoc(doc);
 3632:         return(NULL);
 3633:     }
 3634: 
 3635:     /* print_xpath_nodes(xpath->nodesetval); */
 3636: 
 3637:     xmlFree(expr);
 3638:     xmlXPathFreeContext(ctx);
 3639:     xmlFreeDoc(doc);
 3640:     return(xpath);
 3641: }
 3642: 
 3643: /*
 3644:  * Macro used to grow the current buffer.
 3645:  */
 3646: #define xxx_growBufferReentrant() {						\
 3647:     buffer_size *= 2;							\
 3648:     buffer = (xmlChar **)						\
 3649: 	xmlRealloc(buffer, buffer_size * sizeof(xmlChar*));	\
 3650:     if (buffer == NULL) {						\
 3651: 	perror("realloc failed");					\
 3652: 	return(NULL);							\
 3653:     }									\
 3654: }
 3655: 
 3656: static xmlChar **
 3657: parse_list(xmlChar *str) {
 3658:     xmlChar **buffer;
 3659:     xmlChar **out = NULL;
 3660:     int buffer_size = 0;
 3661:     int len;
 3662: 
 3663:     if(str == NULL) {
 3664: 	return(NULL);
 3665:     }
 3666: 
 3667:     len = xmlStrlen(str);
 3668:     if((str[0] == '\'') && (str[len - 1] == '\'')) {
 3669: 	str[len - 1] = '\0';
 3670: 	str++;
 3671:     }
 3672:     /*
 3673:      * allocate an translation buffer.
 3674:      */
 3675:     buffer_size = 1000;
 3676:     buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
 3677:     if (buffer == NULL) {
 3678: 	perror("malloc failed");
 3679: 	return(NULL);
 3680:     }
 3681:     out = buffer;
 3682: 
 3683:     while(*str != '\0') {
 3684: 	if (out - buffer > buffer_size - 10) {
 3685: 	    int indx = out - buffer;
 3686: 
 3687: 	    xxx_growBufferReentrant();
 3688: 	    out = &buffer[indx];
 3689: 	}
 3690: 	(*out++) = str;
 3691: 	while(*str != ',' && *str != '\0') ++str;
 3692: 	if(*str == ',') *(str++) = '\0';
 3693:     }
 3694:     (*out) = NULL;
 3695:     return buffer;
 3696: }
 3697: 
 3698: static int
 3699: c14nRunTest(const char* xml_filename, int with_comments, int mode,
 3700: 	    const char* xpath_filename, const char *ns_filename,
 3701: 	    const char* result_file) {
 3702:     xmlDocPtr doc;
 3703:     xmlXPathObjectPtr xpath = NULL;
 3704:     xmlChar *result = NULL;
 3705:     int ret;
 3706:     xmlChar **inclusive_namespaces = NULL;
 3707:     const char *nslist = NULL;
 3708:     int nssize;
 3709: 
 3710: 
 3711:     /*
 3712:      * build an XML tree from a the file; we need to add default
 3713:      * attributes and resolve all character and entities references
 3714:      */
 3715:     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
 3716:     xmlSubstituteEntitiesDefault(1);
 3717: 
 3718:     doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
 3719:     if (doc == NULL) {
 3720: 	fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
 3721: 	return(-1);
 3722:     }
 3723: 
 3724:     /*
 3725:      * Check the document is of the right kind
 3726:      */
 3727:     if(xmlDocGetRootElement(doc) == NULL) {
 3728:         fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
 3729: 	xmlFreeDoc(doc);
 3730: 	return(-1);
 3731:     }
 3732: 
 3733:     /*
 3734:      * load xpath file if specified
 3735:      */
 3736:     if(xpath_filename) {
 3737: 	xpath = load_xpath_expr(doc, xpath_filename);
 3738: 	if(xpath == NULL) {
 3739: 	    fprintf(stderr,"Error: unable to evaluate xpath expression\n");
 3740: 	    xmlFreeDoc(doc);
 3741: 	    return(-1);
 3742: 	}
 3743:     }
 3744: 
 3745:     if (ns_filename != NULL) {
 3746:         if (loadMem(ns_filename, &nslist, &nssize)) {
 3747: 	    fprintf(stderr,"Error: unable to evaluate xpath expression\n");
 3748: 	    if(xpath != NULL) xmlXPathFreeObject(xpath);
 3749: 	    xmlFreeDoc(doc);
 3750: 	    return(-1);
 3751: 	}
 3752:         inclusive_namespaces = parse_list((xmlChar *) nslist);
 3753:     }
 3754: 
 3755:     /*
 3756:      * Canonical form
 3757:      */
 3758:     /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
 3759:     ret = xmlC14NDocDumpMemory(doc,
 3760: 	    (xpath) ? xpath->nodesetval : NULL,
 3761: 	    mode, inclusive_namespaces,
 3762: 	    with_comments, &result);
 3763:     if (ret >= 0) {
 3764: 	if(result != NULL) {
 3765: 	    if (compareFileMem(result_file, (const char *) result, ret)) {
 3766: 		fprintf(stderr, "Result mismatch for %s\n", xml_filename);
 3767: 		fprintf(stderr, "RESULT:\n%s\n", (const char*)result);
 3768: 	        ret = -1;
 3769: 	    }
 3770: 	}
 3771:     } else {
 3772: 	fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
 3773: 	ret = -1;
 3774:     }
 3775: 
 3776:     /*
 3777:      * Cleanup
 3778:      */
 3779:     if (result != NULL) xmlFree(result);
 3780:     if(xpath != NULL) xmlXPathFreeObject(xpath);
 3781:     if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
 3782:     if (nslist != NULL) free((char *) nslist);
 3783:     xmlFreeDoc(doc);
 3784: 
 3785:     return(ret);
 3786: }
 3787: 
 3788: static int
 3789: c14nCommonTest(const char *filename, int with_comments, int mode,
 3790:                const char *subdir) {
 3791:     char buf[500];
 3792:     char prefix[500];
 3793:     const char *base;
 3794:     int len;
 3795:     char *result = NULL;
 3796:     char *xpath = NULL;
 3797:     char *ns = NULL;
 3798:     int ret = 0;
 3799: 
 3800:     base = baseFilename(filename);
 3801:     len = strlen(base);
 3802:     len -= 4;
 3803:     memcpy(prefix, base, len);
 3804:     prefix[len] = 0;
 3805: 
 3806:     snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
 3807:     if (!checkTestFile(buf)) {
 3808:         fprintf(stderr, "Missing result file %s", buf);
 3809: 	return(-1);
 3810:     }
 3811:     result = strdup(buf);
 3812:     snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
 3813:     if (checkTestFile(buf)) {
 3814: 	xpath = strdup(buf);
 3815:     }
 3816:     snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
 3817:     if (checkTestFile(buf)) {
 3818: 	ns = strdup(buf);
 3819:     }
 3820: 
 3821:     nb_tests++;
 3822:     if (c14nRunTest(filename, with_comments, mode,
 3823:                     xpath, ns, result) < 0)
 3824:         ret = 1;
 3825: 
 3826:     if (result != NULL) free(result);
 3827:     if (xpath != NULL) free(xpath);
 3828:     if (ns != NULL) free(ns);
 3829:     return(ret);
 3830: }
 3831: 
 3832: static int
 3833: c14nWithCommentTest(const char *filename,
 3834:                     const char *resul ATTRIBUTE_UNUSED,
 3835: 		    const char *err ATTRIBUTE_UNUSED,
 3836: 		    int options ATTRIBUTE_UNUSED) {
 3837:     return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments"));
 3838: }
 3839: static int
 3840: c14nWithoutCommentTest(const char *filename,
 3841:                     const char *resul ATTRIBUTE_UNUSED,
 3842: 		    const char *err ATTRIBUTE_UNUSED,
 3843: 		    int options ATTRIBUTE_UNUSED) {
 3844:     return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments"));
 3845: }
 3846: static int
 3847: c14nExcWithoutCommentTest(const char *filename,
 3848:                     const char *resul ATTRIBUTE_UNUSED,
 3849: 		    const char *err ATTRIBUTE_UNUSED,
 3850: 		    int options ATTRIBUTE_UNUSED) {
 3851:     return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments"));
 3852: }
 3853: static int
 3854: c14n11WithoutCommentTest(const char *filename,
 3855:                     const char *resul ATTRIBUTE_UNUSED,
 3856: 		    const char *err ATTRIBUTE_UNUSED,
 3857: 		    int options ATTRIBUTE_UNUSED) {
 3858:     return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments"));
 3859: }
 3860: #endif
 3861: #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined (LIBXML_SAX1_ENABLED)
 3862: /************************************************************************
 3863:  *									*
 3864:  *			Catalog and threads test			*
 3865:  *									*
 3866:  ************************************************************************/
 3867: 
 3868: /*
 3869:  * mostly a cut and paste from testThreads.c
 3870:  */
 3871: #define	MAX_ARGC	20
 3872: 
 3873: static const char *catalog = "test/threads/complex.xml";
 3874: static const char *testfiles[] = {
 3875:     "test/threads/abc.xml",
 3876:     "test/threads/acb.xml",
 3877:     "test/threads/bac.xml",
 3878:     "test/threads/bca.xml",
 3879:     "test/threads/cab.xml",
 3880:     "test/threads/cba.xml",
 3881:     "test/threads/invalid.xml",
 3882: };
 3883: 
 3884: static const char *Okay = "OK";
 3885: static const char *Failed = "Failed";
 3886: 
 3887: #ifndef xmlDoValidityCheckingDefaultValue
 3888: #error xmlDoValidityCheckingDefaultValue is not a macro
 3889: #endif
 3890: #ifndef xmlGenericErrorContext
 3891: #error xmlGenericErrorContext is not a macro
 3892: #endif
 3893: 
 3894: static void *
 3895: thread_specific_data(void *private_data)
 3896: {
 3897:     xmlDocPtr myDoc;
 3898:     const char *filename = (const char *) private_data;
 3899:     int okay = 1;
 3900: 
 3901:     if (!strcmp(filename, "test/threads/invalid.xml")) {
 3902:         xmlDoValidityCheckingDefaultValue = 0;
 3903:         xmlGenericErrorContext = stdout;
 3904:     } else {
 3905:         xmlDoValidityCheckingDefaultValue = 1;
 3906:         xmlGenericErrorContext = stderr;
 3907:     }
 3908:     myDoc = xmlParseFile(filename);
 3909:     if (myDoc) {
 3910:         xmlFreeDoc(myDoc);
 3911:     } else {
 3912:         printf("parse failed\n");
 3913:         okay = 0;
 3914:     }
 3915:     if (!strcmp(filename, "test/threads/invalid.xml")) {
 3916:         if (xmlDoValidityCheckingDefaultValue != 0) {
 3917:             printf("ValidityCheckingDefaultValue override failed\n");
 3918:             okay = 0;
 3919:         }
 3920:         if (xmlGenericErrorContext != stdout) {
 3921:             printf("xmlGenericErrorContext override failed\n");
 3922:             okay = 0;
 3923:         }
 3924:     } else {
 3925:         if (xmlDoValidityCheckingDefaultValue != 1) {
 3926:             printf("ValidityCheckingDefaultValue override failed\n");
 3927:             okay = 0;
 3928:         }
 3929:         if (xmlGenericErrorContext != stderr) {
 3930:             printf("xmlGenericErrorContext override failed\n");
 3931:             okay = 0;
 3932:         }
 3933:     }
 3934:     if (okay == 0)
 3935:         return ((void *) Failed);
 3936:     return ((void *) Okay);
 3937: }
 3938: 
 3939: #if defined(linux) || defined(__sun) || defined(__APPLE_CC__)
 3940: 
 3941: #include <pthread.h>
 3942: 
 3943: static pthread_t tid[MAX_ARGC];
 3944: 
 3945: static int
 3946: testThread(void)
 3947: {
 3948:     unsigned int i, repeat;
 3949:     unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
 3950:     void *results[MAX_ARGC];
 3951:     int ret;
 3952:     int res = 0;
 3953: 
 3954:     xmlInitParser();
 3955: 
 3956:     for (repeat = 0; repeat < 500; repeat++) {
 3957:         xmlLoadCatalog(catalog);
 3958:         nb_tests++;
 3959: 
 3960:         for (i = 0; i < num_threads; i++) {
 3961:             results[i] = NULL;
 3962:             tid[i] = (pthread_t) - 1;
 3963:         }
 3964: 
 3965:         for (i = 0; i < num_threads; i++) {
 3966:             ret = pthread_create(&tid[i], 0, thread_specific_data,
 3967:                                  (void *) testfiles[i]);
 3968:             if (ret != 0) {
 3969:                 fprintf(stderr, "pthread_create failed\n");
 3970:                 return (1);
 3971:             }
 3972:         }
 3973:         for (i = 0; i < num_threads; i++) {
 3974:             ret = pthread_join(tid[i], &results[i]);
 3975:             if (ret != 0) {
 3976:                 fprintf(stderr, "pthread_join failed\n");
 3977:                 return (1);
 3978:             }
 3979:         }
 3980: 
 3981:         xmlCatalogCleanup();
 3982:         for (i = 0; i < num_threads; i++)
 3983:             if (results[i] != (void *) Okay) {
 3984:                 fprintf(stderr, "Thread %d handling %s failed\n",
 3985:                         i, testfiles[i]);
 3986:                 res = 1;
 3987:             }
 3988:     }
 3989:     return (res);
 3990: }
 3991: 
 3992: #elif defined WIN32
 3993: #include <windows.h>
 3994: #include <string.h>
 3995: 
 3996: #define TEST_REPEAT_COUNT 500
 3997: 
 3998: static HANDLE tid[MAX_ARGC];
 3999: 
 4000: static DWORD WINAPI
 4001: win32_thread_specific_data(void *private_data)
 4002: {
 4003:     return((DWORD) thread_specific_data(private_data));
 4004: }
 4005: 
 4006: static int
 4007: testThread(void)
 4008: {
 4009:     unsigned int i, repeat;
 4010:     unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
 4011:     DWORD results[MAX_ARGC];
 4012:     BOOL ret;
 4013:     int res = 0;
 4014: 
 4015:     xmlInitParser();
 4016:     for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
 4017:         xmlLoadCatalog(catalog);
 4018:         nb_tests++;
 4019: 
 4020:         for (i = 0; i < num_threads; i++) {
 4021:             results[i] = 0;
 4022:             tid[i] = (HANDLE) - 1;
 4023:         }
 4024: 
 4025:         for (i = 0; i < num_threads; i++) {
 4026:             DWORD useless;
 4027: 
 4028:             tid[i] = CreateThread(NULL, 0,
 4029:                                   win32_thread_specific_data,
 4030: 				  (void *) testfiles[i], 0,
 4031:                                   &useless);
 4032:             if (tid[i] == NULL) {
 4033:                 fprintf(stderr, "CreateThread failed\n");
 4034:                 return(1);
 4035:             }
 4036:         }
 4037: 
 4038:         if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
 4039:             WAIT_FAILED) {
 4040:             fprintf(stderr, "WaitForMultipleObjects failed\n");
 4041: 	    return(1);
 4042: 	}
 4043: 
 4044:         for (i = 0; i < num_threads; i++) {
 4045:             ret = GetExitCodeThread(tid[i], &results[i]);
 4046:             if (ret == 0) {
 4047:                 fprintf(stderr, "GetExitCodeThread failed\n");
 4048:                 return(1);
 4049:             }
 4050:             CloseHandle(tid[i]);
 4051:         }
 4052: 
 4053:         xmlCatalogCleanup();
 4054:         for (i = 0; i < num_threads; i++) {
 4055:             if (results[i] != (DWORD) Okay) {
 4056:                 fprintf(stderr, "Thread %d handling %s failed\n",
 4057: 		        i, testfiles[i]);
 4058: 	        res = 1;
 4059: 	    }
 4060:         }
 4061:     }
 4062: 
 4063:     return (res);
 4064: }
 4065: 
 4066: #elif defined __BEOS__
 4067: #include <OS.h>
 4068: 
 4069: static thread_id tid[MAX_ARGC];
 4070: 
 4071: static int
 4072: testThread(void)
 4073: {
 4074:     unsigned int i, repeat;
 4075:     unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
 4076:     void *results[MAX_ARGC];
 4077:     status_t ret;
 4078:     int res = 0;
 4079: 
 4080:     xmlInitParser();
 4081:     for (repeat = 0; repeat < 500; repeat++) {
 4082:         xmlLoadCatalog(catalog);
 4083:         for (i = 0; i < num_threads; i++) {
 4084:             results[i] = NULL;
 4085:             tid[i] = (thread_id) - 1;
 4086:         }
 4087:         for (i = 0; i < num_threads; i++) {
 4088:             tid[i] =
 4089:                 spawn_thread(thread_specific_data, "xmlTestThread",
 4090:                              B_NORMAL_PRIORITY, (void *) testfiles[i]);
 4091:             if (tid[i] < B_OK) {
 4092:                 fprintf(stderr, "beos_thread_create failed\n");
 4093:                 return (1);
 4094:             }
 4095:             printf("beos_thread_create %d -> %d\n", i, tid[i]);
 4096:         }
 4097:         for (i = 0; i < num_threads; i++) {
 4098:             ret = wait_for_thread(tid[i], &results[i]);
 4099:             printf("beos_thread_wait %d -> %d\n", i, ret);
 4100:             if (ret != B_OK) {
 4101:                 fprintf(stderr, "beos_thread_wait failed\n");
 4102:                 return (1);
 4103:             }
 4104:         }
 4105: 
 4106:         xmlCatalogCleanup();
 4107:         ret = B_OK;
 4108:         for (i = 0; i < num_threads; i++)
 4109:             if (results[i] != (void *) Okay) {
 4110:                 printf("Thread %d handling %s failed\n", i, testfiles[i]);
 4111:                 ret = B_ERROR;
 4112:             }
 4113:     }
 4114:     if (ret != B_OK)
 4115:         return(1);
 4116:     return (0);
 4117: }
 4118: #else
 4119: static int
 4120: testThread(void)
 4121: {
 4122:     fprintf(stderr,
 4123:             "Specific platform thread support not detected\n");
 4124:     return (-1);
 4125: }
 4126: #endif
 4127: static int
 4128: threadsTest(const char *filename ATTRIBUTE_UNUSED,
 4129: 	    const char *resul ATTRIBUTE_UNUSED,
 4130: 	    const char *err ATTRIBUTE_UNUSED,
 4131: 	    int options ATTRIBUTE_UNUSED) {
 4132:     return(testThread());
 4133: }
 4134: #endif
 4135: /************************************************************************
 4136:  *									*
 4137:  *			Tests Descriptions				*
 4138:  *									*
 4139:  ************************************************************************/
 4140: 
 4141: static
 4142: testDesc testDescriptions[] = {
 4143:     { "XML regression tests" ,
 4144:       oldParseTest, "./test/*", "result/", "", NULL,
 4145:       0 },
 4146:     { "XML regression tests on memory" ,
 4147:       memParseTest, "./test/*", "result/", "", NULL,
 4148:       0 },
 4149:     { "XML entity subst regression tests" ,
 4150:       noentParseTest, "./test/*", "result/noent/", "", NULL,
 4151:       XML_PARSE_NOENT },
 4152:     { "XML Namespaces regression tests",
 4153:       errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
 4154:       0 },
 4155:     { "Error cases regression tests",
 4156:       errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
 4157:       0 },
 4158: #ifdef LIBXML_READER_ENABLED
 4159:     { "Error cases stream regression tests",
 4160:       streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
 4161:       0 },
 4162:     { "Reader regression tests",
 4163:       streamParseTest, "./test/*", "result/", ".rdr", NULL,
 4164:       0 },
 4165:     { "Reader entities substitution regression tests",
 4166:       streamParseTest, "./test/*", "result/", ".rde", NULL,
 4167:       XML_PARSE_NOENT },
 4168:     { "Reader on memory regression tests",
 4169:       streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
 4170:       0 },
 4171:     { "Walker regression tests",
 4172:       walkerParseTest, "./test/*", "result/", ".rdr", NULL,
 4173:       0 },
 4174: #endif
 4175: #ifdef LIBXML_SAX1_ENABLED
 4176:     { "SAX1 callbacks regression tests" ,
 4177:       saxParseTest, "./test/*", "result/", ".sax", NULL,
 4178:       XML_PARSE_SAX1 },
 4179:     { "SAX2 callbacks regression tests" ,
 4180:       saxParseTest, "./test/*", "result/", ".sax2", NULL,
 4181:       0 },
 4182: #endif
 4183: #ifdef LIBXML_PUSH_ENABLED
 4184:     { "XML push regression tests" ,
 4185:       pushParseTest, "./test/*", "result/", "", NULL,
 4186:       0 },
 4187: #endif
 4188: #ifdef LIBXML_HTML_ENABLED
 4189:     { "HTML regression tests" ,
 4190:       errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
 4191:       XML_PARSE_HTML },
 4192: #ifdef LIBXML_PUSH_ENABLED
 4193:     { "Push HTML regression tests" ,
 4194:       pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
 4195:       XML_PARSE_HTML },
 4196: #endif
 4197: #ifdef LIBXML_SAX1_ENABLED
 4198:     { "HTML SAX regression tests" ,
 4199:       saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
 4200:       XML_PARSE_HTML },
 4201: #endif
 4202: #endif
 4203: #ifdef LIBXML_VALID_ENABLED
 4204:     { "Valid documents regression tests" ,
 4205:       errParseTest, "./test/VCM/*", NULL, NULL, NULL,
 4206:       XML_PARSE_DTDVALID },
 4207:     { "Validity checking regression tests" ,
 4208:       errParseTest, "./test/VC/*", "result/VC/", NULL, "",
 4209:       XML_PARSE_DTDVALID },
 4210:     { "General documents valid regression tests" ,
 4211:       errParseTest, "./test/valid/*", "result/valid/", "", ".err",
 4212:       XML_PARSE_DTDVALID },
 4213: #endif
 4214: #ifdef LIBXML_XINCLUDE_ENABLED
 4215:     { "XInclude regression tests" ,
 4216:       errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
 4217:       /* Ignore errors at this point ".err", */
 4218:       XML_PARSE_XINCLUDE },
 4219: #ifdef LIBXML_READER_ENABLED
 4220:     { "XInclude xmlReader regression tests",
 4221:       streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
 4222:       /* Ignore errors at this point ".err", */
 4223:       NULL, XML_PARSE_XINCLUDE },
 4224: #endif
 4225:     { "XInclude regression tests stripping include nodes" ,
 4226:       errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
 4227:       /* Ignore errors at this point ".err", */
 4228:       XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
 4229: #ifdef LIBXML_READER_ENABLED
 4230:     { "XInclude xmlReader regression tests stripping include nodes",
 4231:       streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
 4232:       /* Ignore errors at this point ".err", */
 4233:       NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
 4234: #endif
 4235: #endif
 4236: #ifdef LIBXML_XPATH_ENABLED
 4237: #ifdef LIBXML_DEBUG_ENABLED
 4238:     { "XPath expressions regression tests" ,
 4239:       xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
 4240:       0 },
 4241:     { "XPath document queries regression tests" ,
 4242:       xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
 4243:       0 },
 4244: #ifdef LIBXML_XPTR_ENABLED
 4245:     { "XPointer document queries regression tests" ,
 4246:       xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
 4247:       0 },
 4248: #endif
 4249:     { "xml:id regression tests" ,
 4250:       xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
 4251:       0 },
 4252: #endif
 4253: #endif
 4254:     { "URI parsing tests" ,
 4255:       uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
 4256:       0 },
 4257:     { "URI base composition tests" ,
 4258:       uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
 4259:       0 },
 4260:     { "Path URI conversion tests" ,
 4261:       uriPathTest, NULL, NULL, NULL, NULL,
 4262:       0 },
 4263: #ifdef LIBXML_SCHEMAS_ENABLED
 4264:     { "Schemas regression tests" ,
 4265:       schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
 4266:       0 },
 4267:     { "Relax-NG regression tests" ,
 4268:       rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
 4269:       XML_PARSE_DTDATTR | XML_PARSE_NOENT },
 4270: #ifdef LIBXML_READER_ENABLED
 4271:     { "Relax-NG streaming regression tests" ,
 4272:       rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
 4273:       XML_PARSE_DTDATTR | XML_PARSE_NOENT },
 4274: #endif
 4275: #endif
 4276: #ifdef LIBXML_PATTERN_ENABLED
 4277: #ifdef LIBXML_READER_ENABLED
 4278:     { "Pattern regression tests" ,
 4279:       patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
 4280:       0 },
 4281: #endif
 4282: #endif
 4283: #ifdef LIBXML_C14N_ENABLED
 4284:     { "C14N with comments regression tests" ,
 4285:       c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
 4286:       0 },
 4287:     { "C14N without comments regression tests" ,
 4288:       c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
 4289:       0 },
 4290:     { "C14N exclusive without comments regression tests" ,
 4291:       c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
 4292:       0 },
 4293:     { "C14N 1.1 without comments regression tests" ,
 4294:       c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL,
 4295:       0 },
 4296: #endif
 4297: #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_SAX1_ENABLED)
 4298:     { "Catalog and Threads regression tests" ,
 4299:       threadsTest, NULL, NULL, NULL, NULL,
 4300:       0 },
 4301: #endif
 4302:     {NULL, NULL, NULL, NULL, NULL, NULL, 0}
 4303: };
 4304: 
 4305: /************************************************************************
 4306:  *									*
 4307:  *		The main code driving the tests				*
 4308:  *									*
 4309:  ************************************************************************/
 4310: 
 4311: static int
 4312: launchTests(testDescPtr tst) {
 4313:     int res = 0, err = 0;
 4314:     size_t i;
 4315:     char *result;
 4316:     char *error;
 4317:     int mem;
 4318: 
 4319:     if (tst == NULL) return(-1);
 4320:     if (tst->in != NULL) {
 4321: 	glob_t globbuf;
 4322: 
 4323: 	globbuf.gl_offs = 0;
 4324: 	glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
 4325: 	for (i = 0;i < globbuf.gl_pathc;i++) {
 4326: 	    if (!checkTestFile(globbuf.gl_pathv[i]))
 4327: 	        continue;
 4328: 	    if (tst->suffix != NULL) {
 4329: 		result = resultFilename(globbuf.gl_pathv[i], tst->out,
 4330: 					tst->suffix);
 4331: 		if (result == NULL) {
 4332: 		    fprintf(stderr, "Out of memory !\n");
 4333: 		    fatalError();
 4334: 		}
 4335: 	    } else {
 4336: 	        result = NULL;
 4337: 	    }
 4338: 	    if (tst->err != NULL) {
 4339: 		error = resultFilename(globbuf.gl_pathv[i], tst->out,
 4340: 		                        tst->err);
 4341: 		if (error == NULL) {
 4342: 		    fprintf(stderr, "Out of memory !\n");
 4343: 		    fatalError();
 4344: 		}
 4345: 	    } else {
 4346: 	        error = NULL;
 4347: 	    }
 4348: 	    if ((result) &&(!checkTestFile(result))) {
 4349: 	        fprintf(stderr, "Missing result file %s\n", result);
 4350: 	    } else if ((error) &&(!checkTestFile(error))) {
 4351: 	        fprintf(stderr, "Missing error file %s\n", error);
 4352: 	    } else {
 4353: 		mem = xmlMemUsed();
 4354: 		extraMemoryFromResolver = 0;
 4355: 		testErrorsSize = 0;
 4356: 		testErrors[0] = 0;
 4357: 		res = tst->func(globbuf.gl_pathv[i], result, error,
 4358: 		                tst->options | XML_PARSE_COMPACT);
 4359: 		xmlResetLastError();
 4360: 		if (res != 0) {
 4361: 		    fprintf(stderr, "File %s generated an error\n",
 4362: 		            globbuf.gl_pathv[i]);
 4363: 		    nb_errors++;
 4364: 		    err++;
 4365: 		}
 4366: 		else if (xmlMemUsed() != mem) {
 4367: 		    if ((xmlMemUsed() != mem) &&
 4368: 		        (extraMemoryFromResolver == 0)) {
 4369: 			fprintf(stderr, "File %s leaked %d bytes\n",
 4370: 				globbuf.gl_pathv[i], xmlMemUsed() - mem);
 4371: 			nb_leaks++;
 4372: 			err++;
 4373: 		    }
 4374: 		}
 4375: 		testErrorsSize = 0;
 4376: 	    }
 4377: 	    if (result)
 4378: 		free(result);
 4379: 	    if (error)
 4380: 		free(error);
 4381: 	}
 4382: 	globfree(&globbuf);
 4383:     } else {
 4384:         testErrorsSize = 0;
 4385: 	testErrors[0] = 0;
 4386: 	extraMemoryFromResolver = 0;
 4387:         res = tst->func(NULL, NULL, NULL, tst->options);
 4388: 	if (res != 0) {
 4389: 	    nb_errors++;
 4390: 	    err++;
 4391: 	}
 4392:     }
 4393:     return(err);
 4394: }
 4395: 
 4396: static int verbose = 0;
 4397: static int tests_quiet = 0;
 4398: 
 4399: static int
 4400: runtest(int i) {
 4401:     int ret = 0, res;
 4402:     int old_errors, old_tests, old_leaks;
 4403: 
 4404:     old_errors = nb_errors;
 4405:     old_tests = nb_tests;
 4406:     old_leaks = nb_leaks;
 4407:     if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
 4408: 	printf("## %s\n", testDescriptions[i].desc);
 4409:     res = launchTests(&testDescriptions[i]);
 4410:     if (res != 0)
 4411: 	ret++;
 4412:     if (verbose) {
 4413: 	if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
 4414: 	    printf("Ran %d tests, no errors\n", nb_tests - old_tests);
 4415: 	else
 4416: 	    printf("Ran %d tests, %d errors, %d leaks\n",
 4417: 		   nb_tests - old_tests,
 4418: 		   nb_errors - old_errors,
 4419: 		   nb_leaks - old_leaks);
 4420:     }
 4421:     return(ret);
 4422: }
 4423: 
 4424: int
 4425: main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
 4426:     int i, a, ret = 0;
 4427:     int subset = 0;
 4428: 
 4429:     initializeLibxml2();
 4430: 
 4431:     for (a = 1; a < argc;a++) {
 4432:         if (!strcmp(argv[a], "-v"))
 4433: 	    verbose = 1;
 4434:         else if (!strcmp(argv[a], "-quiet"))
 4435: 	    tests_quiet = 1;
 4436: 	else {
 4437: 	    for (i = 0; testDescriptions[i].func != NULL; i++) {
 4438: 	        if (strstr(testDescriptions[i].desc, argv[a])) {
 4439: 		    ret += runtest(i);
 4440: 		    subset++;
 4441: 		}
 4442: 	    }
 4443: 	}
 4444:     }
 4445:     if (subset == 0) {
 4446: 	for (i = 0; testDescriptions[i].func != NULL; i++) {
 4447: 	    ret += runtest(i);
 4448: 	}
 4449:     }
 4450:     if ((nb_errors == 0) && (nb_leaks == 0)) {
 4451:         ret = 0;
 4452: 	printf("Total %d tests, no errors\n",
 4453: 	       nb_tests);
 4454:     } else {
 4455:         ret = 1;
 4456: 	printf("Total %d tests, %d errors, %d leaks\n",
 4457: 	       nb_tests, nb_errors, nb_leaks);
 4458:     }
 4459:     xmlCleanupParser();
 4460:     xmlMemoryDump();
 4461: 
 4462:     return(ret);
 4463: }
 4464: 
 4465: #else /* ! LIBXML_OUTPUT_ENABLED */
 4466: int
 4467: main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
 4468:     fprintf(stderr, "runtest requires output to be enabled in libxml2\n");
 4469:     return(1);
 4470: }
 4471: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>