Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrunsuite.c
Go to the documentation of this file.
00001 /* 00002 * runsuite.c: C program to run libxml2 againts published testsuites 00003 * 00004 * See Copyright for the status of this software. 00005 * 00006 * daniel@veillard.com 00007 */ 00008 00009 #ifdef HAVE_CONFIG_H 00010 #include "libxml.h" 00011 #else 00012 #include <stdio.h> 00013 #endif 00014 00015 #if !defined(_WIN32) || defined(__CYGWIN__) 00016 #include <unistd.h> 00017 #endif 00018 #include <string.h> 00019 #include <sys/types.h> 00020 #include <sys/stat.h> 00021 #include <fcntl.h> 00022 00023 #include <libxml/parser.h> 00024 #include <libxml/parserInternals.h> 00025 #include <libxml/tree.h> 00026 #include <libxml/uri.h> 00027 #if defined(LIBXML_SCHEMAS_ENABLED) && defined(LIBXML_XPATH_ENABLED) 00028 #include <libxml/xmlreader.h> 00029 00030 #include <libxml/xpath.h> 00031 #include <libxml/xpathInternals.h> 00032 00033 #include <libxml/relaxng.h> 00034 #include <libxml/xmlschemas.h> 00035 #include <libxml/xmlschemastypes.h> 00036 00037 #define LOGFILE "runsuite.log" 00038 static FILE *logfile = NULL; 00039 static int verbose = 0; 00040 00041 00042 00043 #if defined(_WIN32) && !defined(__CYGWIN__) 00044 00045 #define vsnprintf _vsnprintf 00046 00047 #define snprintf _snprintf 00048 00049 #endif 00050 00051 /************************************************************************ 00052 * * 00053 * File name and path utilities * 00054 * * 00055 ************************************************************************/ 00056 00057 static int checkTestFile(const char *filename) { 00058 struct stat buf; 00059 00060 if (stat(filename, &buf) == -1) 00061 return(0); 00062 00063 #if defined(_WIN32) && !defined(__CYGWIN__) 00064 if (!(buf.st_mode & _S_IFREG)) 00065 return(0); 00066 #else 00067 if (!S_ISREG(buf.st_mode)) 00068 return(0); 00069 #endif 00070 00071 return(1); 00072 } 00073 00074 static xmlChar *composeDir(const xmlChar *dir, const xmlChar *path) { 00075 char buf[500]; 00076 00077 if (dir == NULL) return(xmlStrdup(path)); 00078 if (path == NULL) return(NULL); 00079 00080 snprintf(buf, 500, "%s/%s", (const char *) dir, (const char *) path); 00081 return(xmlStrdup((const xmlChar *) buf)); 00082 } 00083 00084 /************************************************************************ 00085 * * 00086 * Libxml2 specific routines * 00087 * * 00088 ************************************************************************/ 00089 00090 static int nb_tests = 0; 00091 static int nb_errors = 0; 00092 static int nb_internals = 0; 00093 static int nb_schematas = 0; 00094 static int nb_unimplemented = 0; 00095 static int nb_leaks = 0; 00096 static int extraMemoryFromResolver = 0; 00097 00098 static int 00099 fatalError(void) { 00100 fprintf(stderr, "Exitting tests on fatal error\n"); 00101 exit(1); 00102 } 00103 00104 /* 00105 * that's needed to implement <resource> 00106 */ 00107 #define MAX_ENTITIES 20 00108 static char *testEntitiesName[MAX_ENTITIES]; 00109 static char *testEntitiesValue[MAX_ENTITIES]; 00110 static int nb_entities = 0; 00111 static void resetEntities(void) { 00112 int i; 00113 00114 for (i = 0;i < nb_entities;i++) { 00115 if (testEntitiesName[i] != NULL) 00116 xmlFree(testEntitiesName[i]); 00117 if (testEntitiesValue[i] != NULL) 00118 xmlFree(testEntitiesValue[i]); 00119 } 00120 nb_entities = 0; 00121 } 00122 static int addEntity(char *name, char *content) { 00123 if (nb_entities >= MAX_ENTITIES) { 00124 fprintf(stderr, "Too many entities defined\n"); 00125 return(-1); 00126 } 00127 testEntitiesName[nb_entities] = name; 00128 testEntitiesValue[nb_entities] = content; 00129 nb_entities++; 00130 return(0); 00131 } 00132 00133 /* 00134 * We need to trap calls to the resolver to not account memory for the catalog 00135 * which is shared to the current running test. We also don't want to have 00136 * network downloads modifying tests. 00137 */ 00138 static xmlParserInputPtr 00139 testExternalEntityLoader(const char *URL, const char *ID, 00140 xmlParserCtxtPtr ctxt) { 00141 xmlParserInputPtr ret; 00142 int i; 00143 00144 for (i = 0;i < nb_entities;i++) { 00145 if (!strcmp(testEntitiesName[i], URL)) { 00146 ret = xmlNewStringInputStream(ctxt, 00147 (const xmlChar *) testEntitiesValue[i]); 00148 if (ret != NULL) { 00149 ret->filename = (const char *) 00150 xmlStrdup((xmlChar *)testEntitiesName[i]); 00151 } 00152 return(ret); 00153 } 00154 } 00155 if (checkTestFile(URL)) { 00156 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt); 00157 } else { 00158 int memused = xmlMemUsed(); 00159 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt); 00160 extraMemoryFromResolver += xmlMemUsed() - memused; 00161 } 00162 #if 0 00163 if (ret == NULL) { 00164 fprintf(stderr, "Failed to find resource %s\n", URL); 00165 } 00166 #endif 00167 00168 return(ret); 00169 } 00170 00171 /* 00172 * Trapping the error messages at the generic level to grab the equivalent of 00173 * stderr messages on CLI tools. 00174 */ 00175 static char testErrors[32769]; 00176 static int testErrorsSize = 0; 00177 00178 static void test_log(const char *msg, ...) { 00179 va_list args; 00180 if (logfile != NULL) { 00181 fprintf(logfile, "\n------------\n"); 00182 va_start(args, msg); 00183 vfprintf(logfile, msg, args); 00184 va_end(args); 00185 fprintf(logfile, "%s", testErrors); 00186 testErrorsSize = 0; testErrors[0] = 0; 00187 } 00188 if (verbose) { 00189 va_start(args, msg); 00190 vfprintf(stderr, msg, args); 00191 va_end(args); 00192 } 00193 } 00194 00195 static void 00196 testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) { 00197 va_list args; 00198 int res; 00199 00200 if (testErrorsSize >= 32768) 00201 return; 00202 va_start(args, msg); 00203 res = vsnprintf(&testErrors[testErrorsSize], 00204 32768 - testErrorsSize, 00205 msg, args); 00206 va_end(args); 00207 if (testErrorsSize + res >= 32768) { 00208 /* buffer is full */ 00209 testErrorsSize = 32768; 00210 testErrors[testErrorsSize] = 0; 00211 } else { 00212 testErrorsSize += res; 00213 } 00214 testErrors[testErrorsSize] = 0; 00215 } 00216 00217 static xmlXPathContextPtr ctxtXPath; 00218 00219 static void 00220 initializeLibxml2(void) { 00221 xmlGetWarningsDefaultValue = 0; 00222 xmlPedanticParserDefault(0); 00223 00224 xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup); 00225 xmlInitParser(); 00226 xmlSetExternalEntityLoader(testExternalEntityLoader); 00227 ctxtXPath = xmlXPathNewContext(NULL); 00228 /* 00229 * Deactivate the cache if created; otherwise we have to create/free it 00230 * for every test, since it will confuse the memory leak detection. 00231 * Note that normally this need not be done, since the cache is not 00232 * created until set explicitely with xmlXPathContextSetCache(); 00233 * but for test purposes it is sometimes usefull to activate the 00234 * cache by default for the whole library. 00235 */ 00236 if (ctxtXPath->cache != NULL) 00237 xmlXPathContextSetCache(ctxtXPath, 0, -1, 0); 00238 /* used as default nanemspace in xstc tests */ 00239 xmlXPathRegisterNs(ctxtXPath, BAD_CAST "ts", BAD_CAST "TestSuite"); 00240 xmlXPathRegisterNs(ctxtXPath, BAD_CAST "xlink", 00241 BAD_CAST "http://www.w3.org/1999/xlink"); 00242 xmlSetGenericErrorFunc(NULL, testErrorHandler); 00243 #ifdef LIBXML_SCHEMAS_ENABLED 00244 xmlSchemaInitTypes(); 00245 xmlRelaxNGInitTypes(); 00246 #endif 00247 } 00248 00249 static xmlNodePtr 00250 getNext(xmlNodePtr cur, const char *xpath) { 00251 xmlNodePtr ret = NULL; 00252 xmlXPathObjectPtr res; 00253 xmlXPathCompExprPtr comp; 00254 00255 if ((cur == NULL) || (cur->doc == NULL) || (xpath == NULL)) 00256 return(NULL); 00257 ctxtXPath->doc = cur->doc; 00258 ctxtXPath->node = cur; 00259 comp = xmlXPathCompile(BAD_CAST xpath); 00260 if (comp == NULL) { 00261 fprintf(stderr, "Failed to compile %s\n", xpath); 00262 return(NULL); 00263 } 00264 res = xmlXPathCompiledEval(comp, ctxtXPath); 00265 xmlXPathFreeCompExpr(comp); 00266 if (res == NULL) 00267 return(NULL); 00268 if ((res->type == XPATH_NODESET) && 00269 (res->nodesetval != NULL) && 00270 (res->nodesetval->nodeNr > 0) && 00271 (res->nodesetval->nodeTab != NULL)) 00272 ret = res->nodesetval->nodeTab[0]; 00273 xmlXPathFreeObject(res); 00274 return(ret); 00275 } 00276 00277 static xmlChar * 00278 getString(xmlNodePtr cur, const char *xpath) { 00279 xmlChar *ret = NULL; 00280 xmlXPathObjectPtr res; 00281 xmlXPathCompExprPtr comp; 00282 00283 if ((cur == NULL) || (cur->doc == NULL) || (xpath == NULL)) 00284 return(NULL); 00285 ctxtXPath->doc = cur->doc; 00286 ctxtXPath->node = cur; 00287 comp = xmlXPathCompile(BAD_CAST xpath); 00288 if (comp == NULL) { 00289 fprintf(stderr, "Failed to compile %s\n", xpath); 00290 return(NULL); 00291 } 00292 res = xmlXPathCompiledEval(comp, ctxtXPath); 00293 xmlXPathFreeCompExpr(comp); 00294 if (res == NULL) 00295 return(NULL); 00296 if (res->type == XPATH_STRING) { 00297 ret = res->stringval; 00298 res->stringval = NULL; 00299 } 00300 xmlXPathFreeObject(res); 00301 return(ret); 00302 } 00303 00304 /************************************************************************ 00305 * * 00306 * Test test/xsdtest/xsdtestsuite.xml * 00307 * * 00308 ************************************************************************/ 00309 00310 static int 00311 xsdIncorectTestCase(xmlNodePtr cur) { 00312 xmlNodePtr test; 00313 xmlBufferPtr buf; 00314 xmlRelaxNGParserCtxtPtr pctxt; 00315 xmlRelaxNGPtr rng = NULL; 00316 int ret = 0, memt; 00317 00318 cur = getNext(cur, "./incorrect[1]"); 00319 if (cur == NULL) { 00320 return(0); 00321 } 00322 00323 test = getNext(cur, "./*"); 00324 if (test == NULL) { 00325 test_log("Failed to find test in correct line %ld\n", 00326 xmlGetLineNo(cur)); 00327 return(1); 00328 } 00329 00330 memt = xmlMemUsed(); 00331 extraMemoryFromResolver = 0; 00332 /* 00333 * dump the schemas to a buffer, then reparse it and compile the schemas 00334 */ 00335 buf = xmlBufferCreate(); 00336 if (buf == NULL) { 00337 fprintf(stderr, "out of memory !\n"); 00338 fatalError(); 00339 } 00340 xmlNodeDump(buf, test->doc, test, 0, 0); 00341 pctxt = xmlRelaxNGNewMemParserCtxt((const char *)buf->content, buf->use); 00342 xmlRelaxNGSetParserErrors(pctxt, 00343 (xmlRelaxNGValidityErrorFunc) testErrorHandler, 00344 (xmlRelaxNGValidityWarningFunc) testErrorHandler, 00345 pctxt); 00346 rng = xmlRelaxNGParse(pctxt); 00347 xmlRelaxNGFreeParserCtxt(pctxt); 00348 if (rng != NULL) { 00349 test_log("Failed to detect incorect RNG line %ld\n", 00350 xmlGetLineNo(test)); 00351 ret = 1; 00352 goto done; 00353 } 00354 00355 done: 00356 if (buf != NULL) 00357 xmlBufferFree(buf); 00358 if (rng != NULL) 00359 xmlRelaxNGFree(rng); 00360 xmlResetLastError(); 00361 if ((memt < xmlMemUsed()) && (extraMemoryFromResolver == 0)) { 00362 test_log("Validation of tests starting line %ld leaked %d\n", 00363 xmlGetLineNo(cur), xmlMemUsed() - memt); 00364 nb_leaks++; 00365 } 00366 return(ret); 00367 } 00368 00369 static void 00370 installResources(xmlNodePtr tst, const xmlChar *base) { 00371 xmlNodePtr test; 00372 xmlBufferPtr buf; 00373 xmlChar *name, *content, *res; 00374 00375 buf = xmlBufferCreate(); 00376 if (buf == NULL) { 00377 fprintf(stderr, "out of memory !\n"); 00378 fatalError(); 00379 } 00380 xmlNodeDump(buf, tst->doc, tst, 0, 0); 00381 00382 while (tst != NULL) { 00383 test = getNext(tst, "./*"); 00384 if (test != NULL) { 00385 xmlBufferEmpty(buf); 00386 xmlNodeDump(buf, test->doc, test, 0, 0); 00387 name = getString(tst, "string(@name)"); 00388 content = xmlStrdup(buf->content); 00389 if ((name != NULL) && (content != NULL)) { 00390 res = composeDir(base, name); 00391 xmlFree(name); 00392 addEntity((char *) res, (char *) content); 00393 } else { 00394 if (name != NULL) xmlFree(name); 00395 if (content != NULL) xmlFree(content); 00396 } 00397 } 00398 tst = getNext(tst, "following-sibling::resource[1]"); 00399 } 00400 if (buf != NULL) 00401 xmlBufferFree(buf); 00402 } 00403 00404 static void 00405 installDirs(xmlNodePtr tst, const xmlChar *base) { 00406 xmlNodePtr test; 00407 xmlChar *name, *res; 00408 00409 name = getString(tst, "string(@name)"); 00410 if (name == NULL) 00411 return; 00412 res = composeDir(base, name); 00413 xmlFree(name); 00414 if (res == NULL) { 00415 return; 00416 } 00417 /* Now process resources and subdir recursively */ 00418 test = getNext(tst, "./resource[1]"); 00419 if (test != NULL) { 00420 installResources(test, res); 00421 } 00422 test = getNext(tst, "./dir[1]"); 00423 while (test != NULL) { 00424 installDirs(test, res); 00425 test = getNext(test, "following-sibling::dir[1]"); 00426 } 00427 xmlFree(res); 00428 } 00429 00430 static int 00431 xsdTestCase(xmlNodePtr tst) { 00432 xmlNodePtr test, tmp, cur; 00433 xmlBufferPtr buf; 00434 xmlDocPtr doc = NULL; 00435 xmlRelaxNGParserCtxtPtr pctxt; 00436 xmlRelaxNGValidCtxtPtr ctxt; 00437 xmlRelaxNGPtr rng = NULL; 00438 int ret = 0, mem, memt; 00439 xmlChar *dtd; 00440 00441 resetEntities(); 00442 testErrorsSize = 0; testErrors[0] = 0; 00443 00444 tmp = getNext(tst, "./dir[1]"); 00445 if (tmp != NULL) { 00446 installDirs(tmp, NULL); 00447 } 00448 tmp = getNext(tst, "./resource[1]"); 00449 if (tmp != NULL) { 00450 installResources(tmp, NULL); 00451 } 00452 00453 cur = getNext(tst, "./correct[1]"); 00454 if (cur == NULL) { 00455 return(xsdIncorectTestCase(tst)); 00456 } 00457 00458 test = getNext(cur, "./*"); 00459 if (test == NULL) { 00460 fprintf(stderr, "Failed to find test in correct line %ld\n", 00461 xmlGetLineNo(cur)); 00462 return(1); 00463 } 00464 00465 memt = xmlMemUsed(); 00466 extraMemoryFromResolver = 0; 00467 /* 00468 * dump the schemas to a buffer, then reparse it and compile the schemas 00469 */ 00470 buf = xmlBufferCreate(); 00471 if (buf == NULL) { 00472 fprintf(stderr, "out of memory !\n"); 00473 fatalError(); 00474 } 00475 xmlNodeDump(buf, test->doc, test, 0, 0); 00476 pctxt = xmlRelaxNGNewMemParserCtxt((const char *)buf->content, buf->use); 00477 xmlRelaxNGSetParserErrors(pctxt, 00478 (xmlRelaxNGValidityErrorFunc) testErrorHandler, 00479 (xmlRelaxNGValidityWarningFunc) testErrorHandler, 00480 pctxt); 00481 rng = xmlRelaxNGParse(pctxt); 00482 xmlRelaxNGFreeParserCtxt(pctxt); 00483 if (extraMemoryFromResolver) 00484 memt = 0; 00485 00486 if (rng == NULL) { 00487 test_log("Failed to parse RNGtest line %ld\n", 00488 xmlGetLineNo(test)); 00489 nb_errors++; 00490 ret = 1; 00491 goto done; 00492 } 00493 /* 00494 * now scan all the siblings of correct to process the <valid> tests 00495 */ 00496 tmp = getNext(cur, "following-sibling::valid[1]"); 00497 while (tmp != NULL) { 00498 dtd = xmlGetProp(tmp, BAD_CAST "dtd"); 00499 test = getNext(tmp, "./*"); 00500 if (test == NULL) { 00501 fprintf(stderr, "Failed to find test in <valid> line %ld\n", 00502 xmlGetLineNo(tmp)); 00503 00504 } else { 00505 xmlBufferEmpty(buf); 00506 if (dtd != NULL) 00507 xmlBufferAdd(buf, dtd, -1); 00508 xmlNodeDump(buf, test->doc, test, 0, 0); 00509 00510 /* 00511 * We are ready to run the test 00512 */ 00513 mem = xmlMemUsed(); 00514 extraMemoryFromResolver = 0; 00515 doc = xmlReadMemory((const char *)buf->content, buf->use, 00516 "test", NULL, 0); 00517 if (doc == NULL) { 00518 test_log("Failed to parse valid instance line %ld\n", 00519 xmlGetLineNo(tmp)); 00520 nb_errors++; 00521 } else { 00522 nb_tests++; 00523 ctxt = xmlRelaxNGNewValidCtxt(rng); 00524 xmlRelaxNGSetValidErrors(ctxt, 00525 (xmlRelaxNGValidityErrorFunc) testErrorHandler, 00526 (xmlRelaxNGValidityWarningFunc) testErrorHandler, 00527 ctxt); 00528 ret = xmlRelaxNGValidateDoc(ctxt, doc); 00529 xmlRelaxNGFreeValidCtxt(ctxt); 00530 if (ret > 0) { 00531 test_log("Failed to validate valid instance line %ld\n", 00532 xmlGetLineNo(tmp)); 00533 nb_errors++; 00534 } else if (ret < 0) { 00535 test_log("Internal error validating instance line %ld\n", 00536 xmlGetLineNo(tmp)); 00537 nb_errors++; 00538 } 00539 xmlFreeDoc(doc); 00540 } 00541 xmlResetLastError(); 00542 if ((mem != xmlMemUsed()) && (extraMemoryFromResolver == 0)) { 00543 test_log("Validation of instance line %ld leaked %d\n", 00544 xmlGetLineNo(tmp), xmlMemUsed() - mem); 00545 xmlMemoryDump(); 00546 nb_leaks++; 00547 } 00548 } 00549 if (dtd != NULL) 00550 xmlFree(dtd); 00551 tmp = getNext(tmp, "following-sibling::valid[1]"); 00552 } 00553 /* 00554 * now scan all the siblings of correct to process the <invalid> tests 00555 */ 00556 tmp = getNext(cur, "following-sibling::invalid[1]"); 00557 while (tmp != NULL) { 00558 test = getNext(tmp, "./*"); 00559 if (test == NULL) { 00560 fprintf(stderr, "Failed to find test in <invalid> line %ld\n", 00561 xmlGetLineNo(tmp)); 00562 00563 } else { 00564 xmlBufferEmpty(buf); 00565 xmlNodeDump(buf, test->doc, test, 0, 0); 00566 00567 /* 00568 * We are ready to run the test 00569 */ 00570 mem = xmlMemUsed(); 00571 extraMemoryFromResolver = 0; 00572 doc = xmlReadMemory((const char *)buf->content, buf->use, 00573 "test", NULL, 0); 00574 if (doc == NULL) { 00575 test_log("Failed to parse valid instance line %ld\n", 00576 xmlGetLineNo(tmp)); 00577 nb_errors++; 00578 } else { 00579 nb_tests++; 00580 ctxt = xmlRelaxNGNewValidCtxt(rng); 00581 xmlRelaxNGSetValidErrors(ctxt, 00582 (xmlRelaxNGValidityErrorFunc) testErrorHandler, 00583 (xmlRelaxNGValidityWarningFunc) testErrorHandler, 00584 ctxt); 00585 ret = xmlRelaxNGValidateDoc(ctxt, doc); 00586 xmlRelaxNGFreeValidCtxt(ctxt); 00587 if (ret == 0) { 00588 test_log("Failed to detect invalid instance line %ld\n", 00589 xmlGetLineNo(tmp)); 00590 nb_errors++; 00591 } else if (ret < 0) { 00592 test_log("Internal error validating instance line %ld\n", 00593 xmlGetLineNo(tmp)); 00594 nb_errors++; 00595 } 00596 xmlFreeDoc(doc); 00597 } 00598 xmlResetLastError(); 00599 if ((mem != xmlMemUsed()) && (extraMemoryFromResolver == 0)) { 00600 test_log("Validation of instance line %ld leaked %d\n", 00601 xmlGetLineNo(tmp), xmlMemUsed() - mem); 00602 xmlMemoryDump(); 00603 nb_leaks++; 00604 } 00605 } 00606 tmp = getNext(tmp, "following-sibling::invalid[1]"); 00607 } 00608 00609 done: 00610 if (buf != NULL) 00611 xmlBufferFree(buf); 00612 if (rng != NULL) 00613 xmlRelaxNGFree(rng); 00614 xmlResetLastError(); 00615 if ((memt != xmlMemUsed()) && (memt != 0)) { 00616 test_log("Validation of tests starting line %ld leaked %d\n", 00617 xmlGetLineNo(cur), xmlMemUsed() - memt); 00618 nb_leaks++; 00619 } 00620 return(ret); 00621 } 00622 00623 static int 00624 xsdTestSuite(xmlNodePtr cur) { 00625 if (verbose) { 00626 xmlChar *doc = getString(cur, "string(documentation)"); 00627 00628 if (doc != NULL) { 00629 printf("Suite %s\n", doc); 00630 xmlFree(doc); 00631 } 00632 } 00633 cur = getNext(cur, "./testCase[1]"); 00634 while (cur != NULL) { 00635 xsdTestCase(cur); 00636 cur = getNext(cur, "following-sibling::testCase[1]"); 00637 } 00638 00639 return(0); 00640 } 00641 00642 static int 00643 xsdTest(void) { 00644 xmlDocPtr doc; 00645 xmlNodePtr cur; 00646 const char *filename = "test/xsdtest/xsdtestsuite.xml"; 00647 int ret = 0; 00648 00649 doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT); 00650 if (doc == NULL) { 00651 fprintf(stderr, "Failed to parse %s\n", filename); 00652 return(-1); 00653 } 00654 printf("## XML Schemas datatypes test suite from James Clark\n"); 00655 00656 cur = xmlDocGetRootElement(doc); 00657 if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) { 00658 fprintf(stderr, "Unexpected format %s\n", filename); 00659 ret = -1; 00660 goto done; 00661 } 00662 00663 cur = getNext(cur, "./testSuite[1]"); 00664 if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) { 00665 fprintf(stderr, "Unexpected format %s\n", filename); 00666 ret = -1; 00667 goto done; 00668 } 00669 while (cur != NULL) { 00670 xsdTestSuite(cur); 00671 cur = getNext(cur, "following-sibling::testSuite[1]"); 00672 } 00673 00674 done: 00675 if (doc != NULL) 00676 xmlFreeDoc(doc); 00677 return(ret); 00678 } 00679 00680 static int 00681 rngTestSuite(xmlNodePtr cur) { 00682 if (verbose) { 00683 xmlChar *doc = getString(cur, "string(documentation)"); 00684 00685 if (doc != NULL) { 00686 printf("Suite %s\n", doc); 00687 xmlFree(doc); 00688 } else { 00689 doc = getString(cur, "string(section)"); 00690 if (doc != NULL) { 00691 printf("Section %s\n", doc); 00692 xmlFree(doc); 00693 } 00694 } 00695 } 00696 cur = getNext(cur, "./testSuite[1]"); 00697 while (cur != NULL) { 00698 xsdTestSuite(cur); 00699 cur = getNext(cur, "following-sibling::testSuite[1]"); 00700 } 00701 00702 return(0); 00703 } 00704 00705 static int 00706 rngTest1(void) { 00707 xmlDocPtr doc; 00708 xmlNodePtr cur; 00709 const char *filename = "test/relaxng/OASIS/spectest.xml"; 00710 int ret = 0; 00711 00712 doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT); 00713 if (doc == NULL) { 00714 fprintf(stderr, "Failed to parse %s\n", filename); 00715 return(-1); 00716 } 00717 printf("## Relax NG test suite from James Clark\n"); 00718 00719 cur = xmlDocGetRootElement(doc); 00720 if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) { 00721 fprintf(stderr, "Unexpected format %s\n", filename); 00722 ret = -1; 00723 goto done; 00724 } 00725 00726 cur = getNext(cur, "./testSuite[1]"); 00727 if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) { 00728 fprintf(stderr, "Unexpected format %s\n", filename); 00729 ret = -1; 00730 goto done; 00731 } 00732 while (cur != NULL) { 00733 rngTestSuite(cur); 00734 cur = getNext(cur, "following-sibling::testSuite[1]"); 00735 } 00736 00737 done: 00738 if (doc != NULL) 00739 xmlFreeDoc(doc); 00740 return(ret); 00741 } 00742 00743 static int 00744 rngTest2(void) { 00745 xmlDocPtr doc; 00746 xmlNodePtr cur; 00747 const char *filename = "test/relaxng/testsuite.xml"; 00748 int ret = 0; 00749 00750 doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT); 00751 if (doc == NULL) { 00752 fprintf(stderr, "Failed to parse %s\n", filename); 00753 return(-1); 00754 } 00755 printf("## Relax NG test suite for libxml2\n"); 00756 00757 cur = xmlDocGetRootElement(doc); 00758 if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) { 00759 fprintf(stderr, "Unexpected format %s\n", filename); 00760 ret = -1; 00761 goto done; 00762 } 00763 00764 cur = getNext(cur, "./testSuite[1]"); 00765 if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSuite"))) { 00766 fprintf(stderr, "Unexpected format %s\n", filename); 00767 ret = -1; 00768 goto done; 00769 } 00770 while (cur != NULL) { 00771 xsdTestSuite(cur); 00772 cur = getNext(cur, "following-sibling::testSuite[1]"); 00773 } 00774 00775 done: 00776 if (doc != NULL) 00777 xmlFreeDoc(doc); 00778 return(ret); 00779 } 00780 00781 /************************************************************************ 00782 * * 00783 * Schemas test suites from W3C/NIST/MS/Sun * 00784 * * 00785 ************************************************************************/ 00786 00787 static int 00788 xstcTestInstance(xmlNodePtr cur, xmlSchemaPtr schemas, 00789 const xmlChar *spath, const char *base) { 00790 xmlChar *href = NULL; 00791 xmlChar *path = NULL; 00792 xmlChar *validity = NULL; 00793 xmlSchemaValidCtxtPtr ctxt = NULL; 00794 xmlDocPtr doc = NULL; 00795 int ret = 0, mem; 00796 00797 xmlResetLastError(); 00798 testErrorsSize = 0; testErrors[0] = 0; 00799 mem = xmlMemUsed(); 00800 href = getString(cur, 00801 "string(ts:instanceDocument/@xlink:href)"); 00802 if ((href == NULL) || (href[0] == 0)) { 00803 test_log("testGroup line %ld misses href for schemaDocument\n", 00804 xmlGetLineNo(cur)); 00805 ret = -1; 00806 goto done; 00807 } 00808 path = xmlBuildURI(href, BAD_CAST base); 00809 if (path == NULL) { 00810 fprintf(stderr, 00811 "Failed to build path to schemas testGroup line %ld : %s\n", 00812 xmlGetLineNo(cur), href); 00813 ret = -1; 00814 goto done; 00815 } 00816 if (checkTestFile((const char *) path) <= 0) { 00817 test_log("schemas for testGroup line %ld is missing: %s\n", 00818 xmlGetLineNo(cur), path); 00819 ret = -1; 00820 goto done; 00821 } 00822 validity = getString(cur, 00823 "string(ts:expected/@validity)"); 00824 if (validity == NULL) { 00825 fprintf(stderr, "instanceDocument line %ld misses expected validity\n", 00826 xmlGetLineNo(cur)); 00827 ret = -1; 00828 goto done; 00829 } 00830 nb_tests++; 00831 doc = xmlReadFile((const char *) path, NULL, XML_PARSE_NOENT); 00832 if (doc == NULL) { 00833 fprintf(stderr, "instance %s fails to parse\n", path); 00834 ret = -1; 00835 nb_errors++; 00836 goto done; 00837 } 00838 00839 ctxt = xmlSchemaNewValidCtxt(schemas); 00840 xmlSchemaSetValidErrors(ctxt, 00841 (xmlSchemaValidityErrorFunc) testErrorHandler, 00842 (xmlSchemaValidityWarningFunc) testErrorHandler, 00843 ctxt); 00844 ret = xmlSchemaValidateDoc(ctxt, doc); 00845 00846 if (xmlStrEqual(validity, BAD_CAST "valid")) { 00847 if (ret > 0) { 00848 test_log("valid instance %s failed to validate against %s\n", 00849 path, spath); 00850 nb_errors++; 00851 } else if (ret < 0) { 00852 test_log("valid instance %s got internal error validating %s\n", 00853 path, spath); 00854 nb_internals++; 00855 nb_errors++; 00856 } 00857 } else if (xmlStrEqual(validity, BAD_CAST "invalid")) { 00858 if (ret == 0) { 00859 test_log("Failed to detect invalid instance %s against %s\n", 00860 path, spath); 00861 nb_errors++; 00862 } 00863 } else { 00864 test_log("instanceDocument line %ld has unexpected validity value%s\n", 00865 xmlGetLineNo(cur), validity); 00866 ret = -1; 00867 goto done; 00868 } 00869 00870 done: 00871 if (href != NULL) xmlFree(href); 00872 if (path != NULL) xmlFree(path); 00873 if (validity != NULL) xmlFree(validity); 00874 if (ctxt != NULL) xmlSchemaFreeValidCtxt(ctxt); 00875 if (doc != NULL) xmlFreeDoc(doc); 00876 xmlResetLastError(); 00877 if (mem != xmlMemUsed()) { 00878 test_log("Validation of tests starting line %ld leaked %d\n", 00879 xmlGetLineNo(cur), xmlMemUsed() - mem); 00880 nb_leaks++; 00881 } 00882 return(ret); 00883 } 00884 00885 static int 00886 xstcTestGroup(xmlNodePtr cur, const char *base) { 00887 xmlChar *href = NULL; 00888 xmlChar *path = NULL; 00889 xmlChar *validity = NULL; 00890 xmlSchemaPtr schemas = NULL; 00891 xmlSchemaParserCtxtPtr ctxt; 00892 xmlNodePtr instance; 00893 int ret = 0, mem; 00894 00895 xmlResetLastError(); 00896 testErrorsSize = 0; testErrors[0] = 0; 00897 mem = xmlMemUsed(); 00898 href = getString(cur, 00899 "string(ts:schemaTest/ts:schemaDocument/@xlink:href)"); 00900 if ((href == NULL) || (href[0] == 0)) { 00901 test_log("testGroup line %ld misses href for schemaDocument\n", 00902 xmlGetLineNo(cur)); 00903 ret = -1; 00904 goto done; 00905 } 00906 path = xmlBuildURI(href, BAD_CAST base); 00907 if (path == NULL) { 00908 test_log("Failed to build path to schemas testGroup line %ld : %s\n", 00909 xmlGetLineNo(cur), href); 00910 ret = -1; 00911 goto done; 00912 } 00913 if (checkTestFile((const char *) path) <= 0) { 00914 test_log("schemas for testGroup line %ld is missing: %s\n", 00915 xmlGetLineNo(cur), path); 00916 ret = -1; 00917 goto done; 00918 } 00919 validity = getString(cur, 00920 "string(ts:schemaTest/ts:expected/@validity)"); 00921 if (validity == NULL) { 00922 test_log("testGroup line %ld misses expected validity\n", 00923 xmlGetLineNo(cur)); 00924 ret = -1; 00925 goto done; 00926 } 00927 nb_tests++; 00928 if (xmlStrEqual(validity, BAD_CAST "valid")) { 00929 nb_schematas++; 00930 ctxt = xmlSchemaNewParserCtxt((const char *) path); 00931 xmlSchemaSetParserErrors(ctxt, 00932 (xmlSchemaValidityErrorFunc) testErrorHandler, 00933 (xmlSchemaValidityWarningFunc) testErrorHandler, 00934 ctxt); 00935 schemas = xmlSchemaParse(ctxt); 00936 xmlSchemaFreeParserCtxt(ctxt); 00937 if (schemas == NULL) { 00938 test_log("valid schemas %s failed to parse\n", 00939 path); 00940 ret = 1; 00941 nb_errors++; 00942 } 00943 if ((ret == 0) && (strstr(testErrors, "nimplemented") != NULL)) { 00944 test_log("valid schemas %s hit an unimplemented block\n", 00945 path); 00946 ret = 1; 00947 nb_unimplemented++; 00948 nb_errors++; 00949 } 00950 instance = getNext(cur, "./ts:instanceTest[1]"); 00951 while (instance != NULL) { 00952 if (schemas != NULL) { 00953 xstcTestInstance(instance, schemas, path, base); 00954 } else { 00955 /* 00956 * We'll automatically mark the instances as failed 00957 * if the schema was broken. 00958 */ 00959 nb_errors++; 00960 } 00961 instance = getNext(instance, 00962 "following-sibling::ts:instanceTest[1]"); 00963 } 00964 } else if (xmlStrEqual(validity, BAD_CAST "invalid")) { 00965 nb_schematas++; 00966 ctxt = xmlSchemaNewParserCtxt((const char *) path); 00967 xmlSchemaSetParserErrors(ctxt, 00968 (xmlSchemaValidityErrorFunc) testErrorHandler, 00969 (xmlSchemaValidityWarningFunc) testErrorHandler, 00970 ctxt); 00971 schemas = xmlSchemaParse(ctxt); 00972 xmlSchemaFreeParserCtxt(ctxt); 00973 if (schemas != NULL) { 00974 test_log("Failed to detect error in schemas %s\n", 00975 path); 00976 nb_errors++; 00977 ret = 1; 00978 } 00979 if ((ret == 0) && (strstr(testErrors, "nimplemented") != NULL)) { 00980 nb_unimplemented++; 00981 test_log("invalid schemas %s hit an unimplemented block\n", 00982 path); 00983 ret = 1; 00984 nb_errors++; 00985 } 00986 } else { 00987 test_log("testGroup line %ld misses unexpected validity value%s\n", 00988 xmlGetLineNo(cur), validity); 00989 ret = -1; 00990 goto done; 00991 } 00992 00993 done: 00994 if (href != NULL) xmlFree(href); 00995 if (path != NULL) xmlFree(path); 00996 if (validity != NULL) xmlFree(validity); 00997 if (schemas != NULL) xmlSchemaFree(schemas); 00998 xmlResetLastError(); 00999 if ((mem != xmlMemUsed()) && (extraMemoryFromResolver == 0)) { 01000 test_log("Processing test line %ld %s leaked %d\n", 01001 xmlGetLineNo(cur), path, xmlMemUsed() - mem); 01002 nb_leaks++; 01003 } 01004 return(ret); 01005 } 01006 01007 static int 01008 xstcMetadata(const char *metadata, const char *base) { 01009 xmlDocPtr doc; 01010 xmlNodePtr cur; 01011 xmlChar *contributor; 01012 xmlChar *name; 01013 int ret = 0; 01014 01015 doc = xmlReadFile(metadata, NULL, XML_PARSE_NOENT); 01016 if (doc == NULL) { 01017 fprintf(stderr, "Failed to parse %s\n", metadata); 01018 return(-1); 01019 } 01020 01021 cur = xmlDocGetRootElement(doc); 01022 if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testSet"))) { 01023 fprintf(stderr, "Unexpected format %s\n", metadata); 01024 return(-1); 01025 } 01026 contributor = xmlGetProp(cur, BAD_CAST "contributor"); 01027 if (contributor == NULL) { 01028 contributor = xmlStrdup(BAD_CAST "Unknown"); 01029 } 01030 name = xmlGetProp(cur, BAD_CAST "name"); 01031 if (name == NULL) { 01032 name = xmlStrdup(BAD_CAST "Unknown"); 01033 } 01034 printf("## %s test suite for Schemas version %s\n", contributor, name); 01035 xmlFree(contributor); 01036 xmlFree(name); 01037 01038 cur = getNext(cur, "./ts:testGroup[1]"); 01039 if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "testGroup"))) { 01040 fprintf(stderr, "Unexpected format %s\n", metadata); 01041 ret = -1; 01042 goto done; 01043 } 01044 while (cur != NULL) { 01045 xstcTestGroup(cur, base); 01046 cur = getNext(cur, "following-sibling::ts:testGroup[1]"); 01047 } 01048 01049 done: 01050 xmlFreeDoc(doc); 01051 return(ret); 01052 } 01053 01054 /************************************************************************ 01055 * * 01056 * The driver for the tests * 01057 * * 01058 ************************************************************************/ 01059 01060 int 01061 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { 01062 int ret = 0; 01063 int old_errors, old_tests, old_leaks; 01064 01065 logfile = fopen(LOGFILE, "w"); 01066 if (logfile == NULL) { 01067 fprintf(stderr, 01068 "Could not open the log file, running in verbose mode\n"); 01069 verbose = 1; 01070 } 01071 initializeLibxml2(); 01072 01073 if ((argc >= 2) && (!strcmp(argv[1], "-v"))) 01074 verbose = 1; 01075 01076 01077 old_errors = nb_errors; 01078 old_tests = nb_tests; 01079 old_leaks = nb_leaks; 01080 xsdTest(); 01081 if ((nb_errors == old_errors) && (nb_leaks == old_leaks)) 01082 printf("Ran %d tests, no errors\n", nb_tests - old_tests); 01083 else 01084 printf("Ran %d tests, %d errors, %d leaks\n", 01085 nb_tests - old_tests, 01086 nb_errors - old_errors, 01087 nb_leaks - old_leaks); 01088 old_errors = nb_errors; 01089 old_tests = nb_tests; 01090 old_leaks = nb_leaks; 01091 rngTest1(); 01092 if ((nb_errors == old_errors) && (nb_leaks == old_leaks)) 01093 printf("Ran %d tests, no errors\n", nb_tests - old_tests); 01094 else 01095 printf("Ran %d tests, %d errors, %d leaks\n", 01096 nb_tests - old_tests, 01097 nb_errors - old_errors, 01098 nb_leaks - old_leaks); 01099 old_errors = nb_errors; 01100 old_tests = nb_tests; 01101 old_leaks = nb_leaks; 01102 rngTest2(); 01103 if ((nb_errors == old_errors) && (nb_leaks == old_leaks)) 01104 printf("Ran %d tests, no errors\n", nb_tests - old_tests); 01105 else 01106 printf("Ran %d tests, %d errors, %d leaks\n", 01107 nb_tests - old_tests, 01108 nb_errors - old_errors, 01109 nb_leaks - old_leaks); 01110 old_errors = nb_errors; 01111 old_tests = nb_tests; 01112 old_leaks = nb_leaks; 01113 nb_internals = 0; 01114 nb_schematas = 0; 01115 xstcMetadata("xstc/Tests/Metadata/NISTXMLSchemaDatatypes.testSet", 01116 "xstc/Tests/Metadata/"); 01117 if ((nb_errors == old_errors) && (nb_leaks == old_leaks)) 01118 printf("Ran %d tests (%d schemata), no errors\n", 01119 nb_tests - old_tests, nb_schematas); 01120 else 01121 printf("Ran %d tests (%d schemata), %d errors (%d internals), %d leaks\n", 01122 nb_tests - old_tests, 01123 nb_schematas, 01124 nb_errors - old_errors, 01125 nb_internals, 01126 nb_leaks - old_leaks); 01127 old_errors = nb_errors; 01128 old_tests = nb_tests; 01129 old_leaks = nb_leaks; 01130 nb_internals = 0; 01131 nb_schematas = 0; 01132 xstcMetadata("xstc/Tests/Metadata/SunXMLSchema1-0-20020116.testSet", 01133 "xstc/Tests/"); 01134 if ((nb_errors == old_errors) && (nb_leaks == old_leaks)) 01135 printf("Ran %d tests (%d schemata), no errors\n", 01136 nb_tests - old_tests, nb_schematas); 01137 else 01138 printf("Ran %d tests (%d schemata), %d errors (%d internals), %d leaks\n", 01139 nb_tests - old_tests, 01140 nb_schematas, 01141 nb_errors - old_errors, 01142 nb_internals, 01143 nb_leaks - old_leaks); 01144 old_errors = nb_errors; 01145 old_tests = nb_tests; 01146 old_leaks = nb_leaks; 01147 nb_internals = 0; 01148 nb_schematas = 0; 01149 xstcMetadata("xstc/Tests/Metadata/MSXMLSchema1-0-20020116.testSet", 01150 "xstc/Tests/"); 01151 if ((nb_errors == old_errors) && (nb_leaks == old_leaks)) 01152 printf("Ran %d tests (%d schemata), no errors\n", 01153 nb_tests - old_tests, nb_schematas); 01154 else 01155 printf("Ran %d tests (%d schemata), %d errors (%d internals), %d leaks\n", 01156 nb_tests - old_tests, 01157 nb_schematas, 01158 nb_errors - old_errors, 01159 nb_internals, 01160 nb_leaks - old_leaks); 01161 01162 if ((nb_errors == 0) && (nb_leaks == 0)) { 01163 ret = 0; 01164 printf("Total %d tests, no errors\n", 01165 nb_tests); 01166 } else { 01167 ret = 1; 01168 printf("Total %d tests, %d errors, %d leaks\n", 01169 nb_tests, nb_errors, nb_leaks); 01170 } 01171 xmlXPathFreeContext(ctxtXPath); 01172 xmlCleanupParser(); 01173 xmlMemoryDump(); 01174 01175 if (logfile != NULL) 01176 fclose(logfile); 01177 return(ret); 01178 } 01179 #else /* !SCHEMAS */ 01180 int 01181 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { 01182 fprintf(stderr, "runsuite requires support for schemas and xpath in libxml2\n"); 01183 } 01184 #endif Generated on Sat May 26 2012 04:33:22 for ReactOS by
1.7.6.1
|