Annotation of embedaddon/libxml2/runsuite.c, revision 1.1
1.1 ! misho 1: /*
! 2: * runsuite.c: C program to run libxml2 againts published testsuites
! 3: *
! 4: * See Copyright for the status of this software.
! 5: *
! 6: * daniel@veillard.com
! 7: */
! 8:
! 9: #ifdef HAVE_CONFIG_H
! 10: #include "libxml.h"
! 11: #else
! 12: #include <stdio.h>
! 13: #endif
! 14:
! 15: #if !defined(_WIN32) || defined(__CYGWIN__)
! 16: #include <unistd.h>
! 17: #endif
! 18: #include <string.h>
! 19: #include <sys/types.h>
! 20: #include <sys/stat.h>
! 21: #include <fcntl.h>
! 22:
! 23: #include <libxml/parser.h>
! 24: #include <libxml/parserInternals.h>
! 25: #include <libxml/tree.h>
! 26: #include <libxml/uri.h>
! 27: #if defined(LIBXML_SCHEMAS_ENABLED) && defined(LIBXML_XPATH_ENABLED)
! 28: #include <libxml/xmlreader.h>
! 29:
! 30: #include <libxml/xpath.h>
! 31: #include <libxml/xpathInternals.h>
! 32:
! 33: #include <libxml/relaxng.h>
! 34: #include <libxml/xmlschemas.h>
! 35: #include <libxml/xmlschemastypes.h>
! 36:
! 37: #define LOGFILE "runsuite.log"
! 38: static FILE *logfile = NULL;
! 39: static int verbose = 0;
! 40:
! 41:
! 42:
! 43: #if defined(_WIN32) && !defined(__CYGWIN__)
! 44:
! 45: #define vsnprintf _vsnprintf
! 46:
! 47: #define snprintf _snprintf
! 48:
! 49: #endif
! 50:
! 51: /************************************************************************
! 52: * *
! 53: * File name and path utilities *
! 54: * *
! 55: ************************************************************************/
! 56:
! 57: static int checkTestFile(const char *filename) {
! 58: struct stat buf;
! 59:
! 60: if (stat(filename, &buf) == -1)
! 61: return(0);
! 62:
! 63: #if defined(_WIN32) && !defined(__CYGWIN__)
! 64: if (!(buf.st_mode & _S_IFREG))
! 65: return(0);
! 66: #else
! 67: if (!S_ISREG(buf.st_mode))
! 68: return(0);
! 69: #endif
! 70:
! 71: return(1);
! 72: }
! 73:
! 74: static xmlChar *composeDir(const xmlChar *dir, const xmlChar *path) {
! 75: char buf[500];
! 76:
! 77: if (dir == NULL) return(xmlStrdup(path));
! 78: if (path == NULL) return(NULL);
! 79:
! 80: snprintf(buf, 500, "%s/%s", (const char *) dir, (const char *) path);
! 81: return(xmlStrdup((const xmlChar *) buf));
! 82: }
! 83:
! 84: /************************************************************************
! 85: * *
! 86: * Libxml2 specific routines *
! 87: * *
! 88: ************************************************************************/
! 89:
! 90: static int nb_tests = 0;
! 91: static int nb_errors = 0;
! 92: static int nb_internals = 0;
! 93: static int nb_schematas = 0;
! 94: static int nb_unimplemented = 0;
! 95: static int nb_leaks = 0;
! 96: static int extraMemoryFromResolver = 0;
! 97:
! 98: static int
! 99: fatalError(void) {
! 100: fprintf(stderr, "Exitting tests on fatal error\n");
! 101: exit(1);
! 102: }
! 103:
! 104: /*
! 105: * that's needed to implement <resource>
! 106: */
! 107: #define MAX_ENTITIES 20
! 108: static char *testEntitiesName[MAX_ENTITIES];
! 109: static char *testEntitiesValue[MAX_ENTITIES];
! 110: static int nb_entities = 0;
! 111: static void resetEntities(void) {
! 112: int i;
! 113:
! 114: for (i = 0;i < nb_entities;i++) {
! 115: if (testEntitiesName[i] != NULL)
! 116: xmlFree(testEntitiesName[i]);
! 117: if (testEntitiesValue[i] != NULL)
! 118: xmlFree(testEntitiesValue[i]);
! 119: }
! 120: nb_entities = 0;
! 121: }
! 122: static int addEntity(char *name, char *content) {
! 123: if (nb_entities >= MAX_ENTITIES) {
! 124: fprintf(stderr, "Too many entities defined\n");
! 125: return(-1);
! 126: }
! 127: testEntitiesName[nb_entities] = name;
! 128: testEntitiesValue[nb_entities] = content;
! 129: nb_entities++;
! 130: return(0);
! 131: }
! 132:
! 133: /*
! 134: * We need to trap calls to the resolver to not account memory for the catalog
! 135: * which is shared to the current running test. We also don't want to have
! 136: * network downloads modifying tests.
! 137: */
! 138: static xmlParserInputPtr
! 139: testExternalEntityLoader(const char *URL, const char *ID,
! 140: xmlParserCtxtPtr ctxt) {
! 141: xmlParserInputPtr ret;
! 142: int i;
! 143:
! 144: for (i = 0;i < nb_entities;i++) {
! 145: if (!strcmp(testEntitiesName[i], URL)) {
! 146: ret = xmlNewStringInputStream(ctxt,
! 147: (const xmlChar *) testEntitiesValue[i]);
! 148: if (ret != NULL) {
! 149: ret->filename = (const char *)
! 150: xmlStrdup((xmlChar *)testEntitiesName[i]);
! 151: }
! 152: return(ret);
! 153: }
! 154: }
! 155: if (checkTestFile(URL)) {
! 156: ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
! 157: } else {
! 158: int memused = xmlMemUsed();
! 159: ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
! 160: extraMemoryFromResolver += xmlMemUsed() - memused;
! 161: }
! 162: #if 0
! 163: if (ret == NULL) {
! 164: fprintf(stderr, "Failed to find resource %s\n", URL);
! 165: }
! 166: #endif
! 167:
! 168: return(ret);
! 169: }
! 170:
! 171: /*
! 172: * Trapping the error messages at the generic level to grab the equivalent of
! 173: * stderr messages on CLI tools.
! 174: */
! 175: static char testErrors[32769];
! 176: static int testErrorsSize = 0;
! 177:
! 178: static void test_log(const char *msg, ...) {
! 179: va_list args;
! 180: if (logfile != NULL) {
! 181: fprintf(logfile, "\n------------\n");
! 182: va_start(args, msg);
! 183: vfprintf(logfile, msg, args);
! 184: va_end(args);
! 185: fprintf(logfile, "%s", testErrors);
! 186: testErrorsSize = 0; testErrors[0] = 0;
! 187: }
! 188: if (verbose) {
! 189: va_start(args, msg);
! 190: vfprintf(stderr, msg, args);
! 191: va_end(args);
! 192: }
! 193: }
! 194:
! 195: static void
! 196: testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
! 197: va_list args;
! 198: int res;
! 199:
! 200: if (testErrorsSize >= 32768)
! 201: return;
! 202: va_start(args, msg);
! 203: res = vsnprintf(&testErrors[testErrorsSize],
! 204: 32768 - testErrorsSize,
! 205: msg, args);
! 206: va_end(args);
! 207: if (testErrorsSize + res >= 32768) {
! 208: /* buffer is full */
! 209: testErrorsSize = 32768;
! 210: testErrors[testErrorsSize] = 0;
! 211: } else {
! 212: testErrorsSize += res;
! 213: }
! 214: testErrors[testErrorsSize] = 0;
! 215: }
! 216:
! 217: static xmlXPathContextPtr ctxtXPath;
! 218:
! 219: static void
! 220: initializeLibxml2(void) {
! 221: xmlGetWarningsDefaultValue = 0;
! 222: xmlPedanticParserDefault(0);
! 223:
! 224: xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
! 225: xmlInitParser();
! 226: xmlSetExternalEntityLoader(testExternalEntityLoader);
! 227: ctxtXPath = xmlXPathNewContext(NULL);
! 228: /*
! 229: * Deactivate the cache if created; otherwise we have to create/free it
! 230: * for every test, since it will confuse the memory leak detection.
! 231: * Note that normally this need not be done, since the cache is not
! 232: * created until set explicitely with xmlXPathContextSetCache();
! 233: * but for test purposes it is sometimes usefull to activate the
! 234: * cache by default for the whole library.
! 235: */
! 236: if (ctxtXPath->cache != NULL)
! 237: xmlXPathContextSetCache(ctxtXPath, 0, -1, 0);
! 238: /* used as default nanemspace in xstc tests */
! 239: xmlXPathRegisterNs(ctxtXPath, BAD_CAST "ts", BAD_CAST "TestSuite");
! 240: xmlXPathRegisterNs(ctxtXPath, BAD_CAST "xlink",
! 241: BAD_CAST "http://www.w3.org/1999/xlink");
! 242: xmlSetGenericErrorFunc(NULL, testErrorHandler);
! 243: #ifdef LIBXML_SCHEMAS_ENABLED
! 244: xmlSchemaInitTypes();
! 245: xmlRelaxNGInitTypes();
! 246: #endif
! 247: }
! 248:
! 249: static xmlNodePtr
! 250: getNext(xmlNodePtr cur, const char *xpath) {
! 251: xmlNodePtr ret = NULL;
! 252: xmlXPathObjectPtr res;
! 253: xmlXPathCompExprPtr comp;
! 254:
! 255: if ((cur == NULL) || (cur->doc == NULL) || (xpath == NULL))
! 256: return(NULL);
! 257: ctxtXPath->doc = cur->doc;
! 258: ctxtXPath->node = cur;
! 259: comp = xmlXPathCompile(BAD_CAST xpath);
! 260: if (comp == NULL) {
! 261: fprintf(stderr, "Failed to compile %s\n", xpath);
! 262: return(NULL);
! 263: }
! 264: res = xmlXPathCompiledEval(comp, ctxtXPath);
! 265: xmlXPathFreeCompExpr(comp);
! 266: if (res == NULL)
! 267: return(NULL);
! 268: if ((res->type == XPATH_NODESET) &&
! 269: (res->nodesetval != NULL) &&
! 270: (res->nodesetval->nodeNr > 0) &&
! 271: (res->nodesetval->nodeTab != NULL))
! 272: ret = res->nodesetval->nodeTab[0];
! 273: xmlXPathFreeObject(res);
! 274: return(ret);
! 275: }
! 276:
! 277: static xmlChar *
! 278: getString(xmlNodePtr cur, const char *xpath) {
! 279: xmlChar *ret = NULL;
! 280: xmlXPathObjectPtr res;
! 281: xmlXPathCompExprPtr comp;
! 282:
! 283: if ((cur == NULL) || (cur->doc == NULL) || (xpath == NULL))
! 284: return(NULL);
! 285: ctxtXPath->doc = cur->doc;
! 286: ctxtXPath->node = cur;
! 287: comp = xmlXPathCompile(BAD_CAST xpath);
! 288: if (comp == NULL) {
! 289: fprintf(stderr, "Failed to compile %s\n", xpath);
! 290: return(NULL);
! 291: }
! 292: res = xmlXPathCompiledEval(comp, ctxtXPath);
! 293: xmlXPathFreeCompExpr(comp);
! 294: if (res == NULL)
! 295: return(NULL);
! 296: if (res->type == XPATH_STRING) {
! 297: ret = res->stringval;
! 298: res->stringval = NULL;
! 299: }
! 300: xmlXPathFreeObject(res);
! 301: return(ret);
! 302: }
! 303:
! 304: /************************************************************************
! 305: * *
! 306: * Test test/xsdtest/xsdtestsuite.xml *
! 307: * *
! 308: ************************************************************************/
! 309:
! 310: static int
! 311: xsdIncorectTestCase(xmlNodePtr cur) {
! 312: xmlNodePtr test;
! 313: xmlBufferPtr buf;
! 314: xmlRelaxNGParserCtxtPtr pctxt;
! 315: xmlRelaxNGPtr rng = NULL;
! 316: int ret = 0, memt;
! 317:
! 318: cur = getNext(cur, "./incorrect[1]");
! 319: if (cur == NULL) {
! 320: return(0);
! 321: }
! 322:
! 323: test = getNext(cur, "./*");
! 324: if (test == NULL) {
! 325: test_log("Failed to find test in correct line %ld\n",
! 326: xmlGetLineNo(cur));
! 327: return(1);
! 328: }
! 329:
! 330: memt = xmlMemUsed();
! 331: extraMemoryFromResolver = 0;
! 332: /*
! 333: * dump the schemas to a buffer, then reparse it and compile the schemas
! 334: */
! 335: buf = xmlBufferCreate();
! 336: if (buf == NULL) {
! 337: fprintf(stderr, "out of memory !\n");
! 338: fatalError();
! 339: }
! 340: xmlNodeDump(buf, test->doc, test, 0, 0);
! 341: pctxt = xmlRelaxNGNewMemParserCtxt((const char *)buf->content, buf->use);
! 342: xmlRelaxNGSetParserErrors(pctxt,
! 343: (xmlRelaxNGValidityErrorFunc) testErrorHandler,
! 344: (xmlRelaxNGValidityWarningFunc) testErrorHandler,
! 345: pctxt);
! 346: rng = xmlRelaxNGParse(pctxt);
! 347: xmlRelaxNGFreeParserCtxt(pctxt);
! 348: if (rng != NULL) {
! 349: test_log("Failed to detect incorect RNG line %ld\n",
! 350: xmlGetLineNo(test));
! 351: ret = 1;
! 352: goto done;
! 353: }
! 354:
! 355: done:
! 356: if (buf != NULL)
! 357: xmlBufferFree(buf);
! 358: if (rng != NULL)
! 359: xmlRelaxNGFree(rng);
! 360: xmlResetLastError();
! 361: if ((memt < xmlMemUsed()) && (extraMemoryFromResolver == 0)) {
! 362: test_log("Validation of tests starting line %ld leaked %d\n",
! 363: xmlGetLineNo(cur), xmlMemUsed() - memt);
! 364: nb_leaks++;
! 365: }
! 366: return(ret);
! 367: }
! 368:
! 369: static void
! 370: installResources(xmlNodePtr tst, const xmlChar *base) {
! 371: xmlNodePtr test;
! 372: xmlBufferPtr buf;
! 373: xmlChar *name, *content, *res;
! 374:
! 375: buf = xmlBufferCreate();
! 376: if (buf == NULL) {
! 377: fprintf(stderr, "out of memory !\n");
! 378: fatalError();
! 379: }
! 380: xmlNodeDump(buf, tst->doc, tst, 0, 0);
! 381:
! 382: while (tst != NULL) {
! 383: test = getNext(tst, "./*");
! 384: if (test != NULL) {
! 385: xmlBufferEmpty(buf);
! 386: xmlNodeDump(buf, test->doc, test, 0, 0);
! 387: name = getString(tst, "string(@name)");
! 388: content = xmlStrdup(buf->content);
! 389: if ((name != NULL) && (content != NULL)) {
! 390: res = composeDir(base, name);
! 391: xmlFree(name);
! 392: addEntity((char *) res, (char *) content);
! 393: } else {
! 394: if (name != NULL) xmlFree(name);
! 395: if (content != NULL) xmlFree(content);
! 396: }
! 397: }
! 398: tst = getNext(tst, "following-sibling::resource[1]");
! 399: }
! 400: if (buf != NULL)
! 401: xmlBufferFree(buf);
! 402: }
! 403:
! 404: static void
! 405: installDirs(xmlNodePtr tst, const xmlChar *base) {
! 406: xmlNodePtr test;
! 407: xmlChar *name, *res;
! 408:
! 409: name = getString(tst, "string(@name)");
! 410: if (name == NULL)
! 411: return;
! 412: res = composeDir(base, name);
! 413: xmlFree(name);
! 414: if (res == NULL) {
! 415: return;
! 416: }
! 417: /* Now process resources and subdir recursively */
! 418: test = getNext(tst, "./resource[1]");
! 419: if (test != NULL) {
! 420: installResources(test, res);
! 421: }
! 422: test = getNext(tst, "./dir[1]");
! 423: while (test != NULL) {
! 424: installDirs(test, res);
! 425: test = getNext(test, "following-sibling::dir[1]");
! 426: }
! 427: xmlFree(res);
! 428: }
! 429:
! 430: static int
! 431: xsdTestCase(xmlNodePtr tst) {
! 432: xmlNodePtr test, tmp, cur;
! 433: xmlBufferPtr buf;
! 434: xmlDocPtr doc = NULL;
! 435: xmlRelaxNGParserCtxtPtr pctxt;
! 436: xmlRelaxNGValidCtxtPtr ctxt;
! 437: xmlRelaxNGPtr rng = NULL;
! 438: int ret = 0, mem, memt;
! 439: xmlChar *dtd;
! 440:
! 441: resetEntities();
! 442: testErrorsSize = 0; testErrors[0] = 0;
! 443:
! 444: tmp = getNext(tst, "./dir[1]");
! 445: if (tmp != NULL) {
! 446: installDirs(tmp, NULL);
! 447: }
! 448: tmp = getNext(tst, "./resource[1]");
! 449: if (tmp != NULL) {
! 450: installResources(tmp, NULL);
! 451: }
! 452:
! 453: cur = getNext(tst, "./correct[1]");
! 454: if (cur == NULL) {
! 455: return(xsdIncorectTestCase(tst));
! 456: }
! 457:
! 458: test = getNext(cur, "./*");
! 459: if (test == NULL) {
! 460: fprintf(stderr, "Failed to find test in correct line %ld\n",
! 461: xmlGetLineNo(cur));
! 462: return(1);
! 463: }
! 464:
! 465: memt = xmlMemUsed();
! 466: extraMemoryFromResolver = 0;
! 467: /*
! 468: * dump the schemas to a buffer, then reparse it and compile the schemas
! 469: */
! 470: buf = xmlBufferCreate();
! 471: if (buf == NULL) {
! 472: fprintf(stderr, "out of memory !\n");
! 473: fatalError();
! 474: }
! 475: xmlNodeDump(buf, test->doc, test, 0, 0);
! 476: pctxt = xmlRelaxNGNewMemParserCtxt((const char *)buf->content, buf->use);
! 477: xmlRelaxNGSetParserErrors(pctxt,
! 478: (xmlRelaxNGValidityErrorFunc) testErrorHandler,
! 479: (xmlRelaxNGValidityWarningFunc) testErrorHandler,
! 480: pctxt);
! 481: rng = xmlRelaxNGParse(pctxt);
! 482: xmlRelaxNGFreeParserCtxt(pctxt);
! 483: if (extraMemoryFromResolver)
! 484: memt = 0;
! 485:
! 486: if (rng == NULL) {
! 487: test_log("Failed to parse RNGtest line %ld\n",
! 488: xmlGetLineNo(test));
! 489: nb_errors++;
! 490: ret = 1;
! 491: goto done;
! 492: }
! 493: /*
! 494: * now scan all the siblings of correct to process the <valid> tests
! 495: */
! 496: tmp = getNext(cur, "following-sibling::valid[1]");
! 497: while (tmp != NULL) {
! 498: dtd = xmlGetProp(tmp, BAD_CAST "dtd");
! 499: test = getNext(tmp, "./*");
! 500: if (test == NULL) {
! 501: fprintf(stderr, "Failed to find test in <valid> line %ld\n",
! 502: xmlGetLineNo(tmp));
! 503:
! 504: } else {
! 505: xmlBufferEmpty(buf);
! 506: if (dtd != NULL)
! 507: xmlBufferAdd(buf, dtd, -1);
! 508: xmlNodeDump(buf, test->doc, test, 0, 0);
! 509:
! 510: /*
! 511: * We are ready to run the test
! 512: */
! 513: mem = xmlMemUsed();
! 514: extraMemoryFromResolver = 0;
! 515: doc = xmlReadMemory((const char *)buf->content, buf->use,
! 516: "test", NULL, 0);
! 517: if (doc == NULL) {
! 518: test_log("Failed to parse valid instance line %ld\n",
! 519: xmlGetLineNo(tmp));
! 520: nb_errors++;
! 521: } else {
! 522: nb_tests++;
! 523: ctxt = xmlRelaxNGNewValidCtxt(rng);
! 524: xmlRelaxNGSetValidErrors(ctxt,
! 525: (xmlRelaxNGValidityErrorFunc) testErrorHandler,
! 526: (xmlRelaxNGValidityWarningFunc) testErrorHandler,
! 527: ctxt);
! 528: ret = xmlRelaxNGValidateDoc(ctxt, doc);
! 529: xmlRelaxNGFreeValidCtxt(ctxt);
! 530: if (ret > 0) {
! 531: test_log("Failed to validate valid instance line %ld\n",
! 532: xmlGetLineNo(tmp));
! 533: nb_errors++;
! 534: } else if (ret < 0) {
! 535: test_log("Internal error validating instance line %ld\n",
! 536: xmlGetLineNo(tmp));
! 537: nb_errors++;
! 538: }
! 539: xmlFreeDoc(doc);
! 540: }
! 541: xmlResetLastError();
! 542: if ((mem != xmlMemUsed()) && (extraMemoryFromResolver == 0)) {
! 543: test_log("Validation of instance line %ld leaked %d\n",
! 544: xmlGetLineNo(tmp), xmlMemUsed() - mem);
! 545: xmlMemoryDump();
! 546: nb_leaks++;
! 547: }
! 548: }
! 549: if (dtd != NULL)
! 550: xmlFree(dtd);
! 551: tmp = getNext(tmp, "following-sibling::valid[1]");
! 552: }
! 553: /*
! 554: * now scan all the siblings of correct to process the <invalid> tests
! 555: */
! 556: tmp = getNext(cur, "following-sibling::invalid[1]");
! 557: while (tmp != NULL) {
! 558: test = getNext(tmp, "./*");
! 559: if (test == NULL) {
! 560: fprintf(stderr, "Failed to find test in <invalid> line %ld\n",
! 561: xmlGetLineNo(tmp));
! 562:
! 563: } else {
! 564: xmlBufferEmpty(buf);
! 565: xmlNodeDump(buf, test->doc, test, 0, 0);
! 566:
! 567: /*
! 568: * We are ready to run the test
! 569: */
! 570: mem = xmlMemUsed();
! 571: extraMemoryFromResolver = 0;
! 572: doc = xmlReadMemory((const char *)buf->content, buf->use,
! 573: "test", NULL, 0);
! 574: if (doc == NULL) {
! 575: test_log("Failed to parse valid instance line %ld\n",
! 576: xmlGetLineNo(tmp));
! 577: nb_errors++;
! 578: } else {
! 579: nb_tests++;
! 580: ctxt = xmlRelaxNGNewValidCtxt(rng);
! 581: xmlRelaxNGSetValidErrors(ctxt,
! 582: (xmlRelaxNGValidityErrorFunc) testErrorHandler,
! 583: (xmlRelaxNGValidityWarningFunc) testErrorHandler,
! 584: ctxt);
! 585: ret = xmlRelaxNGValidateDoc(ctxt, doc);
! 586: xmlRelaxNGFreeValidCtxt(ctxt);
! 587: if (ret == 0) {
! 588: test_log("Failed to detect invalid instance line %ld\n",
! 589: xmlGetLineNo(tmp));
! 590: nb_errors++;
! 591: } else if (ret < 0) {
! 592: test_log("Internal error validating instance line %ld\n",
! 593: xmlGetLineNo(tmp));
! 594: nb_errors++;
! 595: }
! 596: xmlFreeDoc(doc);
! 597: }
! 598: xmlResetLastError();
! 599: if ((mem != xmlMemUsed()) && (extraMemoryFromResolver == 0)) {
! 600: test_log("Validation of instance line %ld leaked %d\n",
! 601: xmlGetLineNo(tmp), xmlMemUsed() - mem);
! 602: xmlMemoryDump();
! 603: nb_leaks++;
! 604: }
! 605: }
! 606: tmp = getNext(tmp, "following-sibling::invalid[1]");
! 607: }
! 608:
! 609: done:
! 610: if (buf != NULL)
! 611: xmlBufferFree(buf);
! 612: if (rng != NULL)
! 613: xmlRelaxNGFree(rng);
! 614: xmlResetLastError();
! 615: if ((memt != xmlMemUsed()) && (memt != 0)) {
! 616: test_log("Validation of tests starting line %ld leaked %d\n",
! 617: xmlGetLineNo(cur), xmlMemUsed() - memt);
! 618: nb_leaks++;
! 619: }
! 620: return(ret);
! 621: }
! 622:
! 623: static int
! 624: xsdTestSuite(xmlNodePtr cur) {
! 625: if (verbose) {
! 626: xmlChar *doc = getString(cur, "string(documentation)");
! 627:
! 628: if (doc != NULL) {
! 629: printf("Suite %s\n", doc);
! 630: xmlFree(doc);
! 631: }
! 632: }
! 633: cur = getNext(cur, "./testCase[1]");
! 634: while (cur != NULL) {
! 635: xsdTestCase(cur);
! 636: cur = getNext(cur, "following-sibling::testCase[1]");
! 637: }
! 638:
! 639: return(0);
! 640: }
! 641:
! 642: static int
! 643: xsdTest(void) {
! 644: xmlDocPtr doc;
! 645: xmlNodePtr cur;
! 646: const char *filename = "test/xsdtest/xsdtestsuite.xml";
! 647: int ret = 0;
! 648:
! 649: doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT);
! 650: if (doc == NULL) {
! 651: fprintf(stderr, "Failed to parse %s\n", filename);
! 652: return(-1);
! 653: }
! 654: printf("## XML Schemas datatypes test suite from James Clark\n");
! 655:
! 656: cur = xmlDocGetRootElement(doc);
! 657: if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
! 658: fprintf(stderr, "Unexpected format %s\n", filename);
! 659: ret = -1;
! 660: goto done;
! 661: }
! 662:
! 663: cur = getNext(cur, "./testSuite[1]");
! 664: if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
! 665: fprintf(stderr, "Unexpected format %s\n", filename);
! 666: ret = -1;
! 667: goto done;
! 668: }
! 669: while (cur != NULL) {
! 670: xsdTestSuite(cur);
! 671: cur = getNext(cur, "following-sibling::testSuite[1]");
! 672: }
! 673:
! 674: done:
! 675: if (doc != NULL)
! 676: xmlFreeDoc(doc);
! 677: return(ret);
! 678: }
! 679:
! 680: static int
! 681: rngTestSuite(xmlNodePtr cur) {
! 682: if (verbose) {
! 683: xmlChar *doc = getString(cur, "string(documentation)");
! 684:
! 685: if (doc != NULL) {
! 686: printf("Suite %s\n", doc);
! 687: xmlFree(doc);
! 688: } else {
! 689: doc = getString(cur, "string(section)");
! 690: if (doc != NULL) {
! 691: printf("Section %s\n", doc);
! 692: xmlFree(doc);
! 693: }
! 694: }
! 695: }
! 696: cur = getNext(cur, "./testSuite[1]");
! 697: while (cur != NULL) {
! 698: xsdTestSuite(cur);
! 699: cur = getNext(cur, "following-sibling::testSuite[1]");
! 700: }
! 701:
! 702: return(0);
! 703: }
! 704:
! 705: static int
! 706: rngTest1(void) {
! 707: xmlDocPtr doc;
! 708: xmlNodePtr cur;
! 709: const char *filename = "test/relaxng/OASIS/spectest.xml";
! 710: int ret = 0;
! 711:
! 712: doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT);
! 713: if (doc == NULL) {
! 714: fprintf(stderr, "Failed to parse %s\n", filename);
! 715: return(-1);
! 716: }
! 717: printf("## Relax NG test suite from James Clark\n");
! 718:
! 719: cur = xmlDocGetRootElement(doc);
! 720: if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
! 721: fprintf(stderr, "Unexpected format %s\n", filename);
! 722: ret = -1;
! 723: goto done;
! 724: }
! 725:
! 726: cur = getNext(cur, "./testSuite[1]");
! 727: if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
! 728: fprintf(stderr, "Unexpected format %s\n", filename);
! 729: ret = -1;
! 730: goto done;
! 731: }
! 732: while (cur != NULL) {
! 733: rngTestSuite(cur);
! 734: cur = getNext(cur, "following-sibling::testSuite[1]");
! 735: }
! 736:
! 737: done:
! 738: if (doc != NULL)
! 739: xmlFreeDoc(doc);
! 740: return(ret);
! 741: }
! 742:
! 743: static int
! 744: rngTest2(void) {
! 745: xmlDocPtr doc;
! 746: xmlNodePtr cur;
! 747: const char *filename = "test/relaxng/testsuite.xml";
! 748: int ret = 0;
! 749:
! 750: doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT);
! 751: if (doc == NULL) {
! 752: fprintf(stderr, "Failed to parse %s\n", filename);
! 753: return(-1);
! 754: }
! 755: printf("## Relax NG test suite for libxml2\n");
! 756:
! 757: cur = xmlDocGetRootElement(doc);
! 758: if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
! 759: fprintf(stderr, "Unexpected format %s\n", filename);
! 760: ret = -1;
! 761: goto done;
! 762: }
! 763:
! 764: cur = getNext(cur, "./testSuite[1]");
! 765: if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) {
! 766: fprintf(stderr, "Unexpected format %s\n", filename);
! 767: ret = -1;
! 768: goto done;
! 769: }
! 770: while (cur != NULL) {
! 771: xsdTestSuite(cur);
! 772: cur = getNext(cur, "following-sibling::testSuite[1]");
! 773: }
! 774:
! 775: done:
! 776: if (doc != NULL)
! 777: xmlFreeDoc(doc);
! 778: return(ret);
! 779: }
! 780:
! 781: /************************************************************************
! 782: * *
! 783: * Schemas test suites from W3C/NIST/MS/Sun *
! 784: * *
! 785: ************************************************************************/
! 786:
! 787: static int
! 788: xstcTestInstance(xmlNodePtr cur, xmlSchemaPtr schemas,
! 789: const xmlChar *spath, const char *base) {
! 790: xmlChar *href = NULL;
! 791: xmlChar *path = NULL;
! 792: xmlChar *validity = NULL;
! 793: xmlSchemaValidCtxtPtr ctxt = NULL;
! 794: xmlDocPtr doc = NULL;
! 795: int ret = 0, mem;
! 796:
! 797: xmlResetLastError();
! 798: testErrorsSize = 0; testErrors[0] = 0;
! 799: mem = xmlMemUsed();
! 800: href = getString(cur,
! 801: "string(ts:instanceDocument/@xlink:href)");
! 802: if ((href == NULL) || (href[0] == 0)) {
! 803: test_log("testGroup line %ld misses href for schemaDocument\n",
! 804: xmlGetLineNo(cur));
! 805: ret = -1;
! 806: goto done;
! 807: }
! 808: path = xmlBuildURI(href, BAD_CAST base);
! 809: if (path == NULL) {
! 810: fprintf(stderr,
! 811: "Failed to build path to schemas testGroup line %ld : %s\n",
! 812: xmlGetLineNo(cur), href);
! 813: ret = -1;
! 814: goto done;
! 815: }
! 816: if (checkTestFile((const char *) path) <= 0) {
! 817: test_log("schemas for testGroup line %ld is missing: %s\n",
! 818: xmlGetLineNo(cur), path);
! 819: ret = -1;
! 820: goto done;
! 821: }
! 822: validity = getString(cur,
! 823: "string(ts:expected/@validity)");
! 824: if (validity == NULL) {
! 825: fprintf(stderr, "instanceDocument line %ld misses expected validity\n",
! 826: xmlGetLineNo(cur));
! 827: ret = -1;
! 828: goto done;
! 829: }
! 830: nb_tests++;
! 831: doc = xmlReadFile((const char *) path, NULL, XML_PARSE_NOENT);
! 832: if (doc == NULL) {
! 833: fprintf(stderr, "instance %s fails to parse\n", path);
! 834: ret = -1;
! 835: nb_errors++;
! 836: goto done;
! 837: }
! 838:
! 839: ctxt = xmlSchemaNewValidCtxt(schemas);
! 840: xmlSchemaSetValidErrors(ctxt,
! 841: (xmlSchemaValidityErrorFunc) testErrorHandler,
! 842: (xmlSchemaValidityWarningFunc) testErrorHandler,
! 843: ctxt);
! 844: ret = xmlSchemaValidateDoc(ctxt, doc);
! 845:
! 846: if (xmlStrEqual(validity, BAD_CAST "valid")) {
! 847: if (ret > 0) {
! 848: test_log("valid instance %s failed to validate against %s\n",
! 849: path, spath);
! 850: nb_errors++;
! 851: } else if (ret < 0) {
! 852: test_log("valid instance %s got internal error validating %s\n",
! 853: path, spath);
! 854: nb_internals++;
! 855: nb_errors++;
! 856: }
! 857: } else if (xmlStrEqual(validity, BAD_CAST "invalid")) {
! 858: if (ret == 0) {
! 859: test_log("Failed to detect invalid instance %s against %s\n",
! 860: path, spath);
! 861: nb_errors++;
! 862: }
! 863: } else {
! 864: test_log("instanceDocument line %ld has unexpected validity value%s\n",
! 865: xmlGetLineNo(cur), validity);
! 866: ret = -1;
! 867: goto done;
! 868: }
! 869:
! 870: done:
! 871: if (href != NULL) xmlFree(href);
! 872: if (path != NULL) xmlFree(path);
! 873: if (validity != NULL) xmlFree(validity);
! 874: if (ctxt != NULL) xmlSchemaFreeValidCtxt(ctxt);
! 875: if (doc != NULL) xmlFreeDoc(doc);
! 876: xmlResetLastError();
! 877: if (mem != xmlMemUsed()) {
! 878: test_log("Validation of tests starting line %ld leaked %d\n",
! 879: xmlGetLineNo(cur), xmlMemUsed() - mem);
! 880: nb_leaks++;
! 881: }
! 882: return(ret);
! 883: }
! 884:
! 885: static int
! 886: xstcTestGroup(xmlNodePtr cur, const char *base) {
! 887: xmlChar *href = NULL;
! 888: xmlChar *path = NULL;
! 889: xmlChar *validity = NULL;
! 890: xmlSchemaPtr schemas = NULL;
! 891: xmlSchemaParserCtxtPtr ctxt;
! 892: xmlNodePtr instance;
! 893: int ret = 0, mem;
! 894:
! 895: xmlResetLastError();
! 896: testErrorsSize = 0; testErrors[0] = 0;
! 897: mem = xmlMemUsed();
! 898: href = getString(cur,
! 899: "string(ts:schemaTest/ts:schemaDocument/@xlink:href)");
! 900: if ((href == NULL) || (href[0] == 0)) {
! 901: test_log("testGroup line %ld misses href for schemaDocument\n",
! 902: xmlGetLineNo(cur));
! 903: ret = -1;
! 904: goto done;
! 905: }
! 906: path = xmlBuildURI(href, BAD_CAST base);
! 907: if (path == NULL) {
! 908: test_log("Failed to build path to schemas testGroup line %ld : %s\n",
! 909: xmlGetLineNo(cur), href);
! 910: ret = -1;
! 911: goto done;
! 912: }
! 913: if (checkTestFile((const char *) path) <= 0) {
! 914: test_log("schemas for testGroup line %ld is missing: %s\n",
! 915: xmlGetLineNo(cur), path);
! 916: ret = -1;
! 917: goto done;
! 918: }
! 919: validity = getString(cur,
! 920: "string(ts:schemaTest/ts:expected/@validity)");
! 921: if (validity == NULL) {
! 922: test_log("testGroup line %ld misses expected validity\n",
! 923: xmlGetLineNo(cur));
! 924: ret = -1;
! 925: goto done;
! 926: }
! 927: nb_tests++;
! 928: if (xmlStrEqual(validity, BAD_CAST "valid")) {
! 929: nb_schematas++;
! 930: ctxt = xmlSchemaNewParserCtxt((const char *) path);
! 931: xmlSchemaSetParserErrors(ctxt,
! 932: (xmlSchemaValidityErrorFunc) testErrorHandler,
! 933: (xmlSchemaValidityWarningFunc) testErrorHandler,
! 934: ctxt);
! 935: schemas = xmlSchemaParse(ctxt);
! 936: xmlSchemaFreeParserCtxt(ctxt);
! 937: if (schemas == NULL) {
! 938: test_log("valid schemas %s failed to parse\n",
! 939: path);
! 940: ret = 1;
! 941: nb_errors++;
! 942: }
! 943: if ((ret == 0) && (strstr(testErrors, "nimplemented") != NULL)) {
! 944: test_log("valid schemas %s hit an unimplemented block\n",
! 945: path);
! 946: ret = 1;
! 947: nb_unimplemented++;
! 948: nb_errors++;
! 949: }
! 950: instance = getNext(cur, "./ts:instanceTest[1]");
! 951: while (instance != NULL) {
! 952: if (schemas != NULL) {
! 953: xstcTestInstance(instance, schemas, path, base);
! 954: } else {
! 955: /*
! 956: * We'll automatically mark the instances as failed
! 957: * if the schema was broken.
! 958: */
! 959: nb_errors++;
! 960: }
! 961: instance = getNext(instance,
! 962: "following-sibling::ts:instanceTest[1]");
! 963: }
! 964: } else if (xmlStrEqual(validity, BAD_CAST "invalid")) {
! 965: nb_schematas++;
! 966: ctxt = xmlSchemaNewParserCtxt((const char *) path);
! 967: xmlSchemaSetParserErrors(ctxt,
! 968: (xmlSchemaValidityErrorFunc) testErrorHandler,
! 969: (xmlSchemaValidityWarningFunc) testErrorHandler,
! 970: ctxt);
! 971: schemas = xmlSchemaParse(ctxt);
! 972: xmlSchemaFreeParserCtxt(ctxt);
! 973: if (schemas != NULL) {
! 974: test_log("Failed to detect error in schemas %s\n",
! 975: path);
! 976: nb_errors++;
! 977: ret = 1;
! 978: }
! 979: if ((ret == 0) && (strstr(testErrors, "nimplemented") != NULL)) {
! 980: nb_unimplemented++;
! 981: test_log("invalid schemas %s hit an unimplemented block\n",
! 982: path);
! 983: ret = 1;
! 984: nb_errors++;
! 985: }
! 986: } else {
! 987: test_log("testGroup line %ld misses unexpected validity value%s\n",
! 988: xmlGetLineNo(cur), validity);
! 989: ret = -1;
! 990: goto done;
! 991: }
! 992:
! 993: done:
! 994: if (href != NULL) xmlFree(href);
! 995: if (path != NULL) xmlFree(path);
! 996: if (validity != NULL) xmlFree(validity);
! 997: if (schemas != NULL) xmlSchemaFree(schemas);
! 998: xmlResetLastError();
! 999: if ((mem != xmlMemUsed()) && (extraMemoryFromResolver == 0)) {
! 1000: test_log("Processing test line %ld %s leaked %d\n",
! 1001: xmlGetLineNo(cur), path, xmlMemUsed() - mem);
! 1002: nb_leaks++;
! 1003: }
! 1004: return(ret);
! 1005: }
! 1006:
! 1007: static int
! 1008: xstcMetadata(const char *metadata, const char *base) {
! 1009: xmlDocPtr doc;
! 1010: xmlNodePtr cur;
! 1011: xmlChar *contributor;
! 1012: xmlChar *name;
! 1013: int ret = 0;
! 1014:
! 1015: doc = xmlReadFile(metadata, NULL, XML_PARSE_NOENT);
! 1016: if (doc == NULL) {
! 1017: fprintf(stderr, "Failed to parse %s\n", metadata);
! 1018: return(-1);
! 1019: }
! 1020:
! 1021: cur = xmlDocGetRootElement(doc);
! 1022: if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSet"))) {
! 1023: fprintf(stderr, "Unexpected format %s\n", metadata);
! 1024: return(-1);
! 1025: }
! 1026: contributor = xmlGetProp(cur, BAD_CAST "contributor");
! 1027: if (contributor == NULL) {
! 1028: contributor = xmlStrdup(BAD_CAST "Unknown");
! 1029: }
! 1030: name = xmlGetProp(cur, BAD_CAST "name");
! 1031: if (name == NULL) {
! 1032: name = xmlStrdup(BAD_CAST "Unknown");
! 1033: }
! 1034: printf("## %s test suite for Schemas version %s\n", contributor, name);
! 1035: xmlFree(contributor);
! 1036: xmlFree(name);
! 1037:
! 1038: cur = getNext(cur, "./ts:testGroup[1]");
! 1039: if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testGroup"))) {
! 1040: fprintf(stderr, "Unexpected format %s\n", metadata);
! 1041: ret = -1;
! 1042: goto done;
! 1043: }
! 1044: while (cur != NULL) {
! 1045: xstcTestGroup(cur, base);
! 1046: cur = getNext(cur, "following-sibling::ts:testGroup[1]");
! 1047: }
! 1048:
! 1049: done:
! 1050: xmlFreeDoc(doc);
! 1051: return(ret);
! 1052: }
! 1053:
! 1054: /************************************************************************
! 1055: * *
! 1056: * The driver for the tests *
! 1057: * *
! 1058: ************************************************************************/
! 1059:
! 1060: int
! 1061: main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
! 1062: int ret = 0;
! 1063: int old_errors, old_tests, old_leaks;
! 1064:
! 1065: logfile = fopen(LOGFILE, "w");
! 1066: if (logfile == NULL) {
! 1067: fprintf(stderr,
! 1068: "Could not open the log file, running in verbose mode\n");
! 1069: verbose = 1;
! 1070: }
! 1071: initializeLibxml2();
! 1072:
! 1073: if ((argc >= 2) && (!strcmp(argv[1], "-v")))
! 1074: verbose = 1;
! 1075:
! 1076:
! 1077: old_errors = nb_errors;
! 1078: old_tests = nb_tests;
! 1079: old_leaks = nb_leaks;
! 1080: xsdTest();
! 1081: if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
! 1082: printf("Ran %d tests, no errors\n", nb_tests - old_tests);
! 1083: else
! 1084: printf("Ran %d tests, %d errors, %d leaks\n",
! 1085: nb_tests - old_tests,
! 1086: nb_errors - old_errors,
! 1087: nb_leaks - old_leaks);
! 1088: old_errors = nb_errors;
! 1089: old_tests = nb_tests;
! 1090: old_leaks = nb_leaks;
! 1091: rngTest1();
! 1092: if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
! 1093: printf("Ran %d tests, no errors\n", nb_tests - old_tests);
! 1094: else
! 1095: printf("Ran %d tests, %d errors, %d leaks\n",
! 1096: nb_tests - old_tests,
! 1097: nb_errors - old_errors,
! 1098: nb_leaks - old_leaks);
! 1099: old_errors = nb_errors;
! 1100: old_tests = nb_tests;
! 1101: old_leaks = nb_leaks;
! 1102: rngTest2();
! 1103: if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
! 1104: printf("Ran %d tests, no errors\n", nb_tests - old_tests);
! 1105: else
! 1106: printf("Ran %d tests, %d errors, %d leaks\n",
! 1107: nb_tests - old_tests,
! 1108: nb_errors - old_errors,
! 1109: nb_leaks - old_leaks);
! 1110: old_errors = nb_errors;
! 1111: old_tests = nb_tests;
! 1112: old_leaks = nb_leaks;
! 1113: nb_internals = 0;
! 1114: nb_schematas = 0;
! 1115: xstcMetadata("xstc/Tests/Metadata/NISTXMLSchemaDatatypes.testSet",
! 1116: "xstc/Tests/Metadata/");
! 1117: if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
! 1118: printf("Ran %d tests (%d schemata), no errors\n",
! 1119: nb_tests - old_tests, nb_schematas);
! 1120: else
! 1121: printf("Ran %d tests (%d schemata), %d errors (%d internals), %d leaks\n",
! 1122: nb_tests - old_tests,
! 1123: nb_schematas,
! 1124: nb_errors - old_errors,
! 1125: nb_internals,
! 1126: nb_leaks - old_leaks);
! 1127: old_errors = nb_errors;
! 1128: old_tests = nb_tests;
! 1129: old_leaks = nb_leaks;
! 1130: nb_internals = 0;
! 1131: nb_schematas = 0;
! 1132: xstcMetadata("xstc/Tests/Metadata/SunXMLSchema1-0-20020116.testSet",
! 1133: "xstc/Tests/");
! 1134: if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
! 1135: printf("Ran %d tests (%d schemata), no errors\n",
! 1136: nb_tests - old_tests, nb_schematas);
! 1137: else
! 1138: printf("Ran %d tests (%d schemata), %d errors (%d internals), %d leaks\n",
! 1139: nb_tests - old_tests,
! 1140: nb_schematas,
! 1141: nb_errors - old_errors,
! 1142: nb_internals,
! 1143: nb_leaks - old_leaks);
! 1144: old_errors = nb_errors;
! 1145: old_tests = nb_tests;
! 1146: old_leaks = nb_leaks;
! 1147: nb_internals = 0;
! 1148: nb_schematas = 0;
! 1149: xstcMetadata("xstc/Tests/Metadata/MSXMLSchema1-0-20020116.testSet",
! 1150: "xstc/Tests/");
! 1151: if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
! 1152: printf("Ran %d tests (%d schemata), no errors\n",
! 1153: nb_tests - old_tests, nb_schematas);
! 1154: else
! 1155: printf("Ran %d tests (%d schemata), %d errors (%d internals), %d leaks\n",
! 1156: nb_tests - old_tests,
! 1157: nb_schematas,
! 1158: nb_errors - old_errors,
! 1159: nb_internals,
! 1160: nb_leaks - old_leaks);
! 1161:
! 1162: if ((nb_errors == 0) && (nb_leaks == 0)) {
! 1163: ret = 0;
! 1164: printf("Total %d tests, no errors\n",
! 1165: nb_tests);
! 1166: } else {
! 1167: ret = 1;
! 1168: printf("Total %d tests, %d errors, %d leaks\n",
! 1169: nb_tests, nb_errors, nb_leaks);
! 1170: }
! 1171: xmlXPathFreeContext(ctxtXPath);
! 1172: xmlCleanupParser();
! 1173: xmlMemoryDump();
! 1174:
! 1175: if (logfile != NULL)
! 1176: fclose(logfile);
! 1177: return(ret);
! 1178: }
! 1179: #else /* !SCHEMAS */
! 1180: int
! 1181: main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
! 1182: fprintf(stderr, "runsuite requires support for schemas and xpath in libxml2\n");
! 1183: }
! 1184: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>