Annotation of embedaddon/libxml2/runtest.c, revision 1.1.1.3

1.1       misho       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: }
1.1.1.2   misho     194: 
1.1       misho     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,
1.1.1.3 ! misho    2096:                   xmlTextReaderPtr reader, const char *rng, int options) {
1.1       misho    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);
1.1.1.3 ! misho    2192:     ret = streamProcessTest(filename, result, err, reader, NULL, options);
1.1       misho    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);
1.1.1.3 ! misho    2220:     ret = streamProcessTest(filename, result, err, reader, NULL, options);
1.1       misho    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);
1.1.1.3 ! misho    2252:     ret = streamProcessTest(filename, result, err, reader, NULL, options);
1.1       misho    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",
1.1.1.3 ! misho    2727:     "urip://example.com/r" "\xe9" "sum" "\xe9" ".html",
1.1       misho    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)
1.1.1.3 ! misho    3311:            ret = streamProcessTest(instance, result, NULL, reader, filename,
        !          3312:                                    options);
1.1       misho    3313:        else
1.1.1.3 ! misho    3314:            ret = streamProcessTest(instance, result, err, reader, filename,
        !          3315:                                    options);
1.1       misho    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: 
1.1.1.3 ! misho    3937: #if defined WIN32
1.1       misho    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: }
1.1.1.3 ! misho    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: 
1.1       misho    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 },
1.1.1.3 ! misho    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
1.1       misho    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>