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