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