Annotation of embedaddon/libxml2/runsuite.c, revision 1.1.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>