VirtualBox

source: vbox/trunk/src/libs/libxml2-2.12.6/runsuite.c

Last change on this file was 104106, checked in by vboxsync, 8 weeks ago

libxml2-2.9.14: Applied and adjusted our libxml2 changes to 2.9.14. bugref:10640

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

© 2023 Oracle
ContactPrivacy policyTerms of Use