File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / runtest.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 19:53:30 2014 UTC (10 years ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_9_1p0, v2_9_1, HEAD
libxml2 2.9.1

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

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