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

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

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