VirtualBox

source: vbox/trunk/src/libs/libxml2-2.9.14/runsuite.c@ 102654

Last change on this file since 102654 was 95312, checked in by vboxsync, 2 years ago

libs/{curl,libxml2}: OSE export fixes, bugref:8515

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette