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

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

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