Annotation of embedaddon/libxml2/runtest.c, revision 1.1.1.2
1.1 misho 1: /*
2: * runtest.c: C program to run libxml2 regression tests without
3: * requiring make or Python, and reducing platform dependancies
4: * to a strict minimum.
5: *
6: * To compile on Unixes:
7: * cc -o runtest `xml2-config --cflags` runtest.c `xml2-config --libs` -lpthread
8: *
9: * See Copyright for the status of this software.
10: *
11: * daniel@veillard.com
12: */
13:
14: #ifdef HAVE_CONFIG_H
15: #include "libxml.h"
16: #else
17: #include <stdio.h>
18: #endif
19:
20: #if !defined(_WIN32) || defined(__CYGWIN__)
21: #include <unistd.h>
22: #endif
23: #include <string.h>
24: #include <sys/types.h>
25: #include <sys/stat.h>
26: #include <fcntl.h>
27:
28: #include <libxml/parser.h>
29: #include <libxml/tree.h>
30: #include <libxml/uri.h>
31:
32: #ifdef LIBXML_OUTPUT_ENABLED
33: #ifdef LIBXML_READER_ENABLED
34: #include <libxml/xmlreader.h>
35: #endif
36:
37: #ifdef LIBXML_XINCLUDE_ENABLED
38: #include <libxml/xinclude.h>
39: #endif
40:
41: #ifdef LIBXML_XPATH_ENABLED
42: #include <libxml/xpath.h>
43: #include <libxml/xpathInternals.h>
44: #ifdef LIBXML_XPTR_ENABLED
45: #include <libxml/xpointer.h>
46: #endif
47: #endif
48:
49: #ifdef LIBXML_SCHEMAS_ENABLED
50: #include <libxml/relaxng.h>
51: #include <libxml/xmlschemas.h>
52: #include <libxml/xmlschemastypes.h>
53: #endif
54:
55: #ifdef LIBXML_PATTERN_ENABLED
56: #include <libxml/pattern.h>
57: #endif
58:
59: #ifdef LIBXML_C14N_ENABLED
60: #include <libxml/c14n.h>
61: #endif
62:
63: #ifdef LIBXML_HTML_ENABLED
64: #include <libxml/HTMLparser.h>
65: #include <libxml/HTMLtree.h>
66:
67: /*
68: * pseudo flag for the unification of HTML and XML tests
69: */
70: #define XML_PARSE_HTML 1 << 24
71: #endif
72:
73: #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
74: #include <libxml/globals.h>
75: #include <libxml/threads.h>
76: #include <libxml/parser.h>
77: #include <libxml/catalog.h>
78: #include <string.h>
79: #endif
80:
81: /*
82: * O_BINARY is just for Windows compatibility - if it isn't defined
83: * on this system, avoid any compilation error
84: */
85: #ifdef O_BINARY
86: #define RD_FLAGS O_RDONLY | O_BINARY
87: #else
88: #define RD_FLAGS O_RDONLY
89: #endif
90:
91: typedef int (*functest) (const char *filename, const char *result,
92: const char *error, int options);
93:
94: typedef struct testDesc testDesc;
95: typedef testDesc *testDescPtr;
96: struct testDesc {
97: const char *desc; /* descripton of the test */
98: functest func; /* function implementing the test */
99: const char *in; /* glob to path for input files */
100: const char *out; /* output directory */
101: const char *suffix;/* suffix for output files */
102: const char *err; /* suffix for error output files */
103: int options; /* parser options for the test */
104: };
105:
106: static int checkTestFile(const char *filename);
107:
108: #if defined(_WIN32) && !defined(__CYGWIN__)
109:
110: #include <windows.h>
111: #include <io.h>
112:
113: typedef struct
114: {
115: size_t gl_pathc; /* Count of paths matched so far */
116: char **gl_pathv; /* List of matched pathnames. */
117: size_t gl_offs; /* Slots to reserve in 'gl_pathv'. */
118: } glob_t;
119:
120: #define GLOB_DOOFFS 0
121: static int glob(const char *pattern, int flags,
122: int errfunc(const char *epath, int eerrno),
123: glob_t *pglob) {
124: glob_t *ret;
125: WIN32_FIND_DATA FindFileData;
126: HANDLE hFind;
127: unsigned int nb_paths = 0;
128: char directory[500];
129: int len;
130:
131: if ((pattern == NULL) || (pglob == NULL)) return(-1);
132:
133: strncpy(directory, pattern, 499);
134: for (len = strlen(directory);len >= 0;len--) {
135: if (directory[len] == '/') {
136: len++;
137: directory[len] = 0;
138: break;
139: }
140: }
141: if (len <= 0)
142: len = 0;
143:
144:
145: ret = pglob;
146: memset(ret, 0, sizeof(glob_t));
147:
148: hFind = FindFirstFileA(pattern, &FindFileData);
149: if (hFind == INVALID_HANDLE_VALUE)
150: return(0);
151: nb_paths = 20;
152: ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
153: if (ret->gl_pathv == NULL) {
154: FindClose(hFind);
155: return(-1);
156: }
157: strncpy(directory + len, FindFileData.cFileName, 499 - len);
158: ret->gl_pathv[ret->gl_pathc] = strdup(directory);
159: if (ret->gl_pathv[ret->gl_pathc] == NULL)
160: goto done;
161: ret->gl_pathc++;
162: while(FindNextFileA(hFind, &FindFileData)) {
163: if (FindFileData.cFileName[0] == '.')
164: continue;
165: if (ret->gl_pathc + 2 > nb_paths) {
166: char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
167: if (tmp == NULL)
168: break;
169: ret->gl_pathv = tmp;
170: nb_paths *= 2;
171: }
172: strncpy(directory + len, FindFileData.cFileName, 499 - len);
173: ret->gl_pathv[ret->gl_pathc] = strdup(directory);
174: if (ret->gl_pathv[ret->gl_pathc] == NULL)
175: break;
176: ret->gl_pathc++;
177: }
178: ret->gl_pathv[ret->gl_pathc] = NULL;
179:
180: done:
181: FindClose(hFind);
182: return(0);
183: }
184:
185:
186:
187: static void globfree(glob_t *pglob) {
188: unsigned int i;
189: if (pglob == NULL)
190: return;
191:
192: for (i = 0;i < pglob->gl_pathc;i++) {
193: if (pglob->gl_pathv[i] != NULL)
194: free(pglob->gl_pathv[i]);
195: }
196: }
1.1.1.2 ! misho 197:
! 198: #if !defined(__MINGW32__)
1.1 misho 199: #define vsnprintf _vsnprintf
200: #define snprintf _snprintf
1.1.1.2 ! misho 201: #endif
1.1 misho 202: #else
203: #include <glob.h>
204: #endif
205:
206: /************************************************************************
207: * *
208: * Libxml2 specific routines *
209: * *
210: ************************************************************************/
211:
212: static int nb_tests = 0;
213: static int nb_errors = 0;
214: static int nb_leaks = 0;
215: static int extraMemoryFromResolver = 0;
216:
217: static int
218: fatalError(void) {
219: fprintf(stderr, "Exitting tests on fatal error\n");
220: exit(1);
221: }
222:
223: /*
224: * We need to trap calls to the resolver to not account memory for the catalog
225: * which is shared to the current running test. We also don't want to have
226: * network downloads modifying tests.
227: */
228: static xmlParserInputPtr
229: testExternalEntityLoader(const char *URL, const char *ID,
230: xmlParserCtxtPtr ctxt) {
231: xmlParserInputPtr ret;
232:
233: if (checkTestFile(URL)) {
234: ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
235: } else {
236: int memused = xmlMemUsed();
237: ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
238: extraMemoryFromResolver += xmlMemUsed() - memused;
239: }
240:
241: return(ret);
242: }
243:
244: /*
245: * Trapping the error messages at the generic level to grab the equivalent of
246: * stderr messages on CLI tools.
247: */
248: static char testErrors[32769];
249: static int testErrorsSize = 0;
250:
251: static void XMLCDECL
252: testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
253: va_list args;
254: int res;
255:
256: if (testErrorsSize >= 32768)
257: return;
258: va_start(args, msg);
259: res = vsnprintf(&testErrors[testErrorsSize],
260: 32768 - testErrorsSize,
261: msg, args);
262: va_end(args);
263: if (testErrorsSize + res >= 32768) {
264: /* buffer is full */
265: testErrorsSize = 32768;
266: testErrors[testErrorsSize] = 0;
267: } else {
268: testErrorsSize += res;
269: }
270: testErrors[testErrorsSize] = 0;
271: }
272:
273: static void XMLCDECL
274: channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
275: va_list args;
276: int res;
277:
278: if (testErrorsSize >= 32768)
279: return;
280: va_start(args, msg);
281: res = vsnprintf(&testErrors[testErrorsSize],
282: 32768 - testErrorsSize,
283: msg, args);
284: va_end(args);
285: if (testErrorsSize + res >= 32768) {
286: /* buffer is full */
287: testErrorsSize = 32768;
288: testErrors[testErrorsSize] = 0;
289: } else {
290: testErrorsSize += res;
291: }
292: testErrors[testErrorsSize] = 0;
293: }
294:
295: /**
296: * xmlParserPrintFileContext:
297: * @input: an xmlParserInputPtr input
298: *
299: * Displays current context within the input content for error tracking
300: */
301:
302: static void
303: xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
304: xmlGenericErrorFunc chanl, void *data ) {
305: const xmlChar *cur, *base;
306: unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
307: xmlChar content[81]; /* space for 80 chars + line terminator */
308: xmlChar *ctnt;
309:
310: if (input == NULL) return;
311: cur = input->cur;
312: base = input->base;
313: /* skip backwards over any end-of-lines */
314: while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
315: cur--;
316: }
317: n = 0;
318: /* search backwards for beginning-of-line (to max buff size) */
319: while ((n++ < (sizeof(content)-1)) && (cur > base) &&
320: (*(cur) != '\n') && (*(cur) != '\r'))
321: cur--;
322: if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
323: /* calculate the error position in terms of the current position */
324: col = input->cur - cur;
325: /* search forward for end-of-line (to max buff size) */
326: n = 0;
327: ctnt = content;
328: /* copy selected text to our buffer */
329: while ((*cur != 0) && (*(cur) != '\n') &&
330: (*(cur) != '\r') && (n < sizeof(content)-1)) {
331: *ctnt++ = *cur++;
332: n++;
333: }
334: *ctnt = 0;
335: /* print out the selected text */
336: chanl(data ,"%s\n", content);
337: /* create blank line with problem pointer */
338: n = 0;
339: ctnt = content;
340: /* (leave buffer space for pointer + line terminator) */
341: while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
342: if (*(ctnt) != '\t')
343: *(ctnt) = ' ';
344: ctnt++;
345: }
346: *ctnt++ = '^';
347: *ctnt = 0;
348: chanl(data ,"%s\n", content);
349: }
350:
351: static void
352: testStructuredErrorHandler(void *ctx ATTRIBUTE_UNUSED, xmlErrorPtr err) {
353: char *file = NULL;
354: int line = 0;
355: int code = -1;
356: int domain;
357: void *data = NULL;
358: const char *str;
359: const xmlChar *name = NULL;
360: xmlNodePtr node;
361: xmlErrorLevel level;
362: xmlParserInputPtr input = NULL;
363: xmlParserInputPtr cur = NULL;
364: xmlParserCtxtPtr ctxt = NULL;
365:
366: if (err == NULL)
367: return;
368:
369: file = err->file;
370: line = err->line;
371: code = err->code;
372: domain = err->domain;
373: level = err->level;
374: node = err->node;
375: if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
376: (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
377: (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
378: ctxt = err->ctxt;
379: }
380: str = err->message;
381:
382: if (code == XML_ERR_OK)
383: return;
384:
385: if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
386: name = node->name;
387:
388: /*
389: * Maintain the compatibility with the legacy error handling
390: */
391: if (ctxt != NULL) {
392: input = ctxt->input;
393: if ((input != NULL) && (input->filename == NULL) &&
394: (ctxt->inputNr > 1)) {
395: cur = input;
396: input = ctxt->inputTab[ctxt->inputNr - 2];
397: }
398: if (input != NULL) {
399: if (input->filename)
400: channel(data, "%s:%d: ", input->filename, input->line);
401: else if ((line != 0) && (domain == XML_FROM_PARSER))
402: channel(data, "Entity: line %d: ", input->line);
403: }
404: } else {
405: if (file != NULL)
406: channel(data, "%s:%d: ", file, line);
407: else if ((line != 0) && (domain == XML_FROM_PARSER))
408: channel(data, "Entity: line %d: ", line);
409: }
410: if (name != NULL) {
411: channel(data, "element %s: ", name);
412: }
413: if (code == XML_ERR_OK)
414: return;
415: switch (domain) {
416: case XML_FROM_PARSER:
417: channel(data, "parser ");
418: break;
419: case XML_FROM_NAMESPACE:
420: channel(data, "namespace ");
421: break;
422: case XML_FROM_DTD:
423: case XML_FROM_VALID:
424: channel(data, "validity ");
425: break;
426: case XML_FROM_HTML:
427: channel(data, "HTML parser ");
428: break;
429: case XML_FROM_MEMORY:
430: channel(data, "memory ");
431: break;
432: case XML_FROM_OUTPUT:
433: channel(data, "output ");
434: break;
435: case XML_FROM_IO:
436: channel(data, "I/O ");
437: break;
438: case XML_FROM_XINCLUDE:
439: channel(data, "XInclude ");
440: break;
441: case XML_FROM_XPATH:
442: channel(data, "XPath ");
443: break;
444: case XML_FROM_XPOINTER:
445: channel(data, "parser ");
446: break;
447: case XML_FROM_REGEXP:
448: channel(data, "regexp ");
449: break;
450: case XML_FROM_MODULE:
451: channel(data, "module ");
452: break;
453: case XML_FROM_SCHEMASV:
454: channel(data, "Schemas validity ");
455: break;
456: case XML_FROM_SCHEMASP:
457: channel(data, "Schemas parser ");
458: break;
459: case XML_FROM_RELAXNGP:
460: channel(data, "Relax-NG parser ");
461: break;
462: case XML_FROM_RELAXNGV:
463: channel(data, "Relax-NG validity ");
464: break;
465: case XML_FROM_CATALOG:
466: channel(data, "Catalog ");
467: break;
468: case XML_FROM_C14N:
469: channel(data, "C14N ");
470: break;
471: case XML_FROM_XSLT:
472: channel(data, "XSLT ");
473: break;
474: default:
475: break;
476: }
477: if (code == XML_ERR_OK)
478: return;
479: switch (level) {
480: case XML_ERR_NONE:
481: channel(data, ": ");
482: break;
483: case XML_ERR_WARNING:
484: channel(data, "warning : ");
485: break;
486: case XML_ERR_ERROR:
487: channel(data, "error : ");
488: break;
489: case XML_ERR_FATAL:
490: channel(data, "error : ");
491: break;
492: }
493: if (code == XML_ERR_OK)
494: return;
495: if (str != NULL) {
496: int len;
497: len = xmlStrlen((const xmlChar *)str);
498: if ((len > 0) && (str[len - 1] != '\n'))
499: channel(data, "%s\n", str);
500: else
501: channel(data, "%s", str);
502: } else {
503: channel(data, "%s\n", "out of memory error");
504: }
505: if (code == XML_ERR_OK)
506: return;
507:
508: if (ctxt != NULL) {
509: xmlParserPrintFileContextInternal(input, channel, data);
510: if (cur != NULL) {
511: if (cur->filename)
512: channel(data, "%s:%d: \n", cur->filename, cur->line);
513: else if ((line != 0) && (domain == XML_FROM_PARSER))
514: channel(data, "Entity: line %d: \n", cur->line);
515: xmlParserPrintFileContextInternal(cur, channel, data);
516: }
517: }
518: if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
519: (err->int1 < 100) &&
520: (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
521: xmlChar buf[150];
522: int i;
523:
524: channel(data, "%s\n", err->str1);
525: for (i=0;i < err->int1;i++)
526: buf[i] = ' ';
527: buf[i++] = '^';
528: buf[i] = 0;
529: channel(data, "%s\n", buf);
530: }
531: }
532:
533: static void
534: initializeLibxml2(void) {
535: xmlGetWarningsDefaultValue = 0;
536: xmlPedanticParserDefault(0);
537:
538: xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
539: xmlInitParser();
540: xmlSetExternalEntityLoader(testExternalEntityLoader);
541: xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
542: #ifdef LIBXML_SCHEMAS_ENABLED
543: xmlSchemaInitTypes();
544: xmlRelaxNGInitTypes();
545: #endif
546: }
547:
548:
549: /************************************************************************
550: * *
551: * File name and path utilities *
552: * *
553: ************************************************************************/
554:
555: static const char *baseFilename(const char *filename) {
556: const char *cur;
557: if (filename == NULL)
558: return(NULL);
559: cur = &filename[strlen(filename)];
560: while ((cur > filename) && (*cur != '/'))
561: cur--;
562: if (*cur == '/')
563: return(cur + 1);
564: return(cur);
565: }
566:
567: static char *resultFilename(const char *filename, const char *out,
568: const char *suffix) {
569: const char *base;
570: char res[500];
571: char suffixbuff[500];
572:
573: /*************
574: if ((filename[0] == 't') && (filename[1] == 'e') &&
575: (filename[2] == 's') && (filename[3] == 't') &&
576: (filename[4] == '/'))
577: filename = &filename[5];
578: *************/
579:
580: base = baseFilename(filename);
581: if (suffix == NULL)
582: suffix = ".tmp";
583: if (out == NULL)
584: out = "";
585:
586: strncpy(suffixbuff,suffix,499);
587: #ifdef VMS
588: if(strstr(base,".") && suffixbuff[0]=='.')
589: suffixbuff[0]='_';
590: #endif
591:
592: snprintf(res, 499, "%s%s%s", out, base, suffixbuff);
593: res[499] = 0;
594: return(strdup(res));
595: }
596:
597: static int checkTestFile(const char *filename) {
598: struct stat buf;
599:
600: if (stat(filename, &buf) == -1)
601: return(0);
602:
603: #if defined(_WIN32) && !defined(__CYGWIN__)
604: if (!(buf.st_mode & _S_IFREG))
605: return(0);
606: #else
607: if (!S_ISREG(buf.st_mode))
608: return(0);
609: #endif
610:
611: return(1);
612: }
613:
614: static int compareFiles(const char *r1, const char *r2) {
615: int res1, res2;
616: int fd1, fd2;
617: char bytes1[4096];
618: char bytes2[4096];
619:
620: fd1 = open(r1, RD_FLAGS);
621: if (fd1 < 0)
622: return(-1);
623: fd2 = open(r2, RD_FLAGS);
624: if (fd2 < 0) {
625: close(fd1);
626: return(-1);
627: }
628: while (1) {
629: res1 = read(fd1, bytes1, 4096);
630: res2 = read(fd2, bytes2, 4096);
631: if ((res1 != res2) || (res1 < 0)) {
632: close(fd1);
633: close(fd2);
634: return(1);
635: }
636: if (res1 == 0)
637: break;
638: if (memcmp(bytes1, bytes2, res1) != 0) {
639: close(fd1);
640: close(fd2);
641: return(1);
642: }
643: }
644: close(fd1);
645: close(fd2);
646: return(0);
647: }
648:
649: static int compareFileMem(const char *filename, const char *mem, int size) {
650: int res;
651: int fd;
652: char bytes[4096];
653: int idx = 0;
654: struct stat info;
655:
656: if (stat(filename, &info) < 0)
657: return(-1);
658: if (info.st_size != size)
659: return(-1);
660: fd = open(filename, RD_FLAGS);
661: if (fd < 0)
662: return(-1);
663: while (idx < size) {
664: res = read(fd, bytes, 4096);
665: if (res <= 0)
666: break;
667: if (res + idx > size)
668: break;
669: if (memcmp(bytes, &mem[idx], res) != 0) {
670: int ix;
671: for (ix=0; ix<res; ix++)
672: if (bytes[ix] != mem[idx+ix])
673: break;
674: fprintf(stderr,"Compare error at position %d\n", idx+ix);
675: close(fd);
676: return(1);
677: }
678: idx += res;
679: }
680: close(fd);
681: return(idx != size);
682: }
683:
684: static int loadMem(const char *filename, const char **mem, int *size) {
685: int fd, res;
686: struct stat info;
687: char *base;
688: int siz = 0;
689: if (stat(filename, &info) < 0)
690: return(-1);
691: base = malloc(info.st_size + 1);
692: if (base == NULL)
693: return(-1);
694: if ((fd = open(filename, RD_FLAGS)) < 0) {
695: free(base);
696: return(-1);
697: }
698: while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
699: siz += res;
700: }
701: close(fd);
702: #if !defined(_WIN32)
703: if (siz != info.st_size) {
704: free(base);
705: return(-1);
706: }
707: #endif
708: base[siz] = 0;
709: *mem = base;
710: *size = siz;
711: return(0);
712: }
713:
714: static int unloadMem(const char *mem) {
715: free((char *)mem);
716: return(0);
717: }
718:
719: /************************************************************************
720: * *
721: * Tests implementations *
722: * *
723: ************************************************************************/
724:
725: /************************************************************************
726: * *
727: * Parse to SAX based tests *
728: * *
729: ************************************************************************/
730:
731: static FILE *SAXdebug = NULL;
732:
733: /*
734: * empty SAX block
735: */
736: static xmlSAXHandler emptySAXHandlerStruct = {
737: NULL, /* internalSubset */
738: NULL, /* isStandalone */
739: NULL, /* hasInternalSubset */
740: NULL, /* hasExternalSubset */
741: NULL, /* resolveEntity */
742: NULL, /* getEntity */
743: NULL, /* entityDecl */
744: NULL, /* notationDecl */
745: NULL, /* attributeDecl */
746: NULL, /* elementDecl */
747: NULL, /* unparsedEntityDecl */
748: NULL, /* setDocumentLocator */
749: NULL, /* startDocument */
750: NULL, /* endDocument */
751: NULL, /* startElement */
752: NULL, /* endElement */
753: NULL, /* reference */
754: NULL, /* characters */
755: NULL, /* ignorableWhitespace */
756: NULL, /* processingInstruction */
757: NULL, /* comment */
758: NULL, /* xmlParserWarning */
759: NULL, /* xmlParserError */
760: NULL, /* xmlParserError */
761: NULL, /* getParameterEntity */
762: NULL, /* cdataBlock; */
763: NULL, /* externalSubset; */
764: 1,
765: NULL,
766: NULL, /* startElementNs */
767: NULL, /* endElementNs */
768: NULL /* xmlStructuredErrorFunc */
769: };
770:
771: static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
772: static int callbacks = 0;
773: static int quiet = 0;
774:
775: /**
776: * isStandaloneDebug:
777: * @ctxt: An XML parser context
778: *
779: * Is this document tagged standalone ?
780: *
781: * Returns 1 if true
782: */
783: static int
784: isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED)
785: {
786: callbacks++;
787: if (quiet)
788: return(0);
789: fprintf(SAXdebug, "SAX.isStandalone()\n");
790: return(0);
791: }
792:
793: /**
794: * hasInternalSubsetDebug:
795: * @ctxt: An XML parser context
796: *
797: * Does this document has an internal subset
798: *
799: * Returns 1 if true
800: */
801: static int
802: hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
803: {
804: callbacks++;
805: if (quiet)
806: return(0);
807: fprintf(SAXdebug, "SAX.hasInternalSubset()\n");
808: return(0);
809: }
810:
811: /**
812: * hasExternalSubsetDebug:
813: * @ctxt: An XML parser context
814: *
815: * Does this document has an external subset
816: *
817: * Returns 1 if true
818: */
819: static int
820: hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED)
821: {
822: callbacks++;
823: if (quiet)
824: return(0);
825: fprintf(SAXdebug, "SAX.hasExternalSubset()\n");
826: return(0);
827: }
828:
829: /**
830: * internalSubsetDebug:
831: * @ctxt: An XML parser context
832: *
833: * Does this document has an internal subset
834: */
835: static void
836: internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
837: const xmlChar *ExternalID, const xmlChar *SystemID)
838: {
839: callbacks++;
840: if (quiet)
841: return;
842: fprintf(SAXdebug, "SAX.internalSubset(%s,", name);
843: if (ExternalID == NULL)
844: fprintf(SAXdebug, " ,");
845: else
846: fprintf(SAXdebug, " %s,", ExternalID);
847: if (SystemID == NULL)
848: fprintf(SAXdebug, " )\n");
849: else
850: fprintf(SAXdebug, " %s)\n", SystemID);
851: }
852:
853: /**
854: * externalSubsetDebug:
855: * @ctxt: An XML parser context
856: *
857: * Does this document has an external subset
858: */
859: static void
860: externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
861: const xmlChar *ExternalID, const xmlChar *SystemID)
862: {
863: callbacks++;
864: if (quiet)
865: return;
866: fprintf(SAXdebug, "SAX.externalSubset(%s,", name);
867: if (ExternalID == NULL)
868: fprintf(SAXdebug, " ,");
869: else
870: fprintf(SAXdebug, " %s,", ExternalID);
871: if (SystemID == NULL)
872: fprintf(SAXdebug, " )\n");
873: else
874: fprintf(SAXdebug, " %s)\n", SystemID);
875: }
876:
877: /**
878: * resolveEntityDebug:
879: * @ctxt: An XML parser context
880: * @publicId: The public ID of the entity
881: * @systemId: The system ID of the entity
882: *
883: * Special entity resolver, better left to the parser, it has
884: * more context than the application layer.
885: * The default behaviour is to NOT resolve the entities, in that case
886: * the ENTITY_REF nodes are built in the structure (and the parameter
887: * values).
888: *
889: * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
890: */
891: static xmlParserInputPtr
892: resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId)
893: {
894: callbacks++;
895: if (quiet)
896: return(NULL);
897: /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
898:
899:
900: fprintf(SAXdebug, "SAX.resolveEntity(");
901: if (publicId != NULL)
902: fprintf(SAXdebug, "%s", (char *)publicId);
903: else
904: fprintf(SAXdebug, " ");
905: if (systemId != NULL)
906: fprintf(SAXdebug, ", %s)\n", (char *)systemId);
907: else
908: fprintf(SAXdebug, ", )\n");
909: /*********
910: if (systemId != NULL) {
911: return(xmlNewInputFromFile(ctxt, (char *) systemId));
912: }
913: *********/
914: return(NULL);
915: }
916:
917: /**
918: * getEntityDebug:
919: * @ctxt: An XML parser context
920: * @name: The entity name
921: *
922: * Get an entity by name
923: *
924: * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
925: */
926: static xmlEntityPtr
927: getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
928: {
929: callbacks++;
930: if (quiet)
931: return(NULL);
932: fprintf(SAXdebug, "SAX.getEntity(%s)\n", name);
933: return(NULL);
934: }
935:
936: /**
937: * getParameterEntityDebug:
938: * @ctxt: An XML parser context
939: * @name: The entity name
940: *
941: * Get a parameter entity by name
942: *
943: * Returns the xmlParserInputPtr
944: */
945: static xmlEntityPtr
946: getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
947: {
948: callbacks++;
949: if (quiet)
950: return(NULL);
951: fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name);
952: return(NULL);
953: }
954:
955:
956: /**
957: * entityDeclDebug:
958: * @ctxt: An XML parser context
959: * @name: the entity name
960: * @type: the entity type
961: * @publicId: The public ID of the entity
962: * @systemId: The system ID of the entity
963: * @content: the entity value (without processing).
964: *
965: * An entity definition has been parsed
966: */
967: static void
968: entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
969: const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
970: {
971: const xmlChar *nullstr = BAD_CAST "(null)";
972: /* not all libraries handle printing null pointers nicely */
973: if (publicId == NULL)
974: publicId = nullstr;
975: if (systemId == NULL)
976: systemId = nullstr;
977: if (content == NULL)
978: content = (xmlChar *)nullstr;
979: callbacks++;
980: if (quiet)
981: return;
982: fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
983: name, type, publicId, systemId, content);
984: }
985:
986: /**
987: * attributeDeclDebug:
988: * @ctxt: An XML parser context
989: * @name: the attribute name
990: * @type: the attribute type
991: *
992: * An attribute definition has been parsed
993: */
994: static void
995: attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
996: const xmlChar * name, int type, int def,
997: const xmlChar * defaultValue, xmlEnumerationPtr tree)
998: {
999: callbacks++;
1000: if (quiet)
1001: return;
1002: if (defaultValue == NULL)
1003: fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
1004: elem, name, type, def);
1005: else
1006: fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
1007: elem, name, type, def, defaultValue);
1008: xmlFreeEnumeration(tree);
1009: }
1010:
1011: /**
1012: * elementDeclDebug:
1013: * @ctxt: An XML parser context
1014: * @name: the element name
1015: * @type: the element type
1016: * @content: the element value (without processing).
1017: *
1018: * An element definition has been parsed
1019: */
1020: static void
1021: elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type,
1022: xmlElementContentPtr content ATTRIBUTE_UNUSED)
1023: {
1024: callbacks++;
1025: if (quiet)
1026: return;
1027: fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n",
1028: name, type);
1029: }
1030:
1031: /**
1032: * notationDeclDebug:
1033: * @ctxt: An XML parser context
1034: * @name: The name of the notation
1035: * @publicId: The public ID of the entity
1036: * @systemId: The system ID of the entity
1037: *
1038: * What to do when a notation declaration has been parsed.
1039: */
1040: static void
1041: notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1042: const xmlChar *publicId, const xmlChar *systemId)
1043: {
1044: callbacks++;
1045: if (quiet)
1046: return;
1047: fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n",
1048: (char *) name, (char *) publicId, (char *) systemId);
1049: }
1050:
1051: /**
1052: * unparsedEntityDeclDebug:
1053: * @ctxt: An XML parser context
1054: * @name: The name of the entity
1055: * @publicId: The public ID of the entity
1056: * @systemId: The system ID of the entity
1057: * @notationName: the name of the notation
1058: *
1059: * What to do when an unparsed entity declaration is parsed
1060: */
1061: static void
1062: unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name,
1063: const xmlChar *publicId, const xmlChar *systemId,
1064: const xmlChar *notationName)
1065: {
1066: const xmlChar *nullstr = BAD_CAST "(null)";
1067:
1068: if (publicId == NULL)
1069: publicId = nullstr;
1070: if (systemId == NULL)
1071: systemId = nullstr;
1072: if (notationName == NULL)
1073: notationName = nullstr;
1074: callbacks++;
1075: if (quiet)
1076: return;
1077: fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
1078: (char *) name, (char *) publicId, (char *) systemId,
1079: (char *) notationName);
1080: }
1081:
1082: /**
1083: * setDocumentLocatorDebug:
1084: * @ctxt: An XML parser context
1085: * @loc: A SAX Locator
1086: *
1087: * Receive the document locator at startup, actually xmlDefaultSAXLocator
1088: * Everything is available on the context, so this is useless in our case.
1089: */
1090: static void
1091: setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
1092: {
1093: callbacks++;
1094: if (quiet)
1095: return;
1096: fprintf(SAXdebug, "SAX.setDocumentLocator()\n");
1097: }
1098:
1099: /**
1100: * startDocumentDebug:
1101: * @ctxt: An XML parser context
1102: *
1103: * called when the document start being processed.
1104: */
1105: static void
1106: startDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1107: {
1108: callbacks++;
1109: if (quiet)
1110: return;
1111: fprintf(SAXdebug, "SAX.startDocument()\n");
1112: }
1113:
1114: /**
1115: * endDocumentDebug:
1116: * @ctxt: An XML parser context
1117: *
1118: * called when the document end has been detected.
1119: */
1120: static void
1121: endDocumentDebug(void *ctx ATTRIBUTE_UNUSED)
1122: {
1123: callbacks++;
1124: if (quiet)
1125: return;
1126: fprintf(SAXdebug, "SAX.endDocument()\n");
1127: }
1128:
1129: /**
1130: * startElementDebug:
1131: * @ctxt: An XML parser context
1132: * @name: The element name
1133: *
1134: * called when an opening tag has been processed.
1135: */
1136: static void
1137: startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1138: {
1139: int i;
1140:
1141: callbacks++;
1142: if (quiet)
1143: return;
1144: fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1145: if (atts != NULL) {
1146: for (i = 0;(atts[i] != NULL);i++) {
1147: fprintf(SAXdebug, ", %s='", atts[i++]);
1148: if (atts[i] != NULL)
1149: fprintf(SAXdebug, "%s'", atts[i]);
1150: }
1151: }
1152: fprintf(SAXdebug, ")\n");
1153: }
1154:
1155: /**
1156: * endElementDebug:
1157: * @ctxt: An XML parser context
1158: * @name: The element name
1159: *
1160: * called when the end of an element has been detected.
1161: */
1162: static void
1163: endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1164: {
1165: callbacks++;
1166: if (quiet)
1167: return;
1168: fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name);
1169: }
1170:
1171: /**
1172: * charactersDebug:
1173: * @ctxt: An XML parser context
1174: * @ch: a xmlChar string
1175: * @len: the number of xmlChar
1176: *
1177: * receiving some chars from the parser.
1178: * Question: how much at a time ???
1179: */
1180: static void
1181: charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1182: {
1183: char output[40];
1184: int i;
1185:
1186: callbacks++;
1187: if (quiet)
1188: return;
1189: for (i = 0;(i<len) && (i < 30);i++)
1190: output[i] = ch[i];
1191: output[i] = 0;
1192:
1193: fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1194: }
1195:
1196: /**
1197: * referenceDebug:
1198: * @ctxt: An XML parser context
1199: * @name: The entity name
1200: *
1201: * called when an entity reference is detected.
1202: */
1203: static void
1204: referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name)
1205: {
1206: callbacks++;
1207: if (quiet)
1208: return;
1209: fprintf(SAXdebug, "SAX.reference(%s)\n", name);
1210: }
1211:
1212: /**
1213: * ignorableWhitespaceDebug:
1214: * @ctxt: An XML parser context
1215: * @ch: a xmlChar string
1216: * @start: the first char in the string
1217: * @len: the number of xmlChar
1218: *
1219: * receiving some ignorable whitespaces from the parser.
1220: * Question: how much at a time ???
1221: */
1222: static void
1223: ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1224: {
1225: char output[40];
1226: int i;
1227:
1228: callbacks++;
1229: if (quiet)
1230: return;
1231: for (i = 0;(i<len) && (i < 30);i++)
1232: output[i] = ch[i];
1233: output[i] = 0;
1234: fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len);
1235: }
1236:
1237: /**
1238: * processingInstructionDebug:
1239: * @ctxt: An XML parser context
1240: * @target: the target name
1241: * @data: the PI data's
1242: * @len: the number of xmlChar
1243: *
1244: * A processing instruction has been parsed.
1245: */
1246: static void
1247: processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target,
1248: const xmlChar *data)
1249: {
1250: callbacks++;
1251: if (quiet)
1252: return;
1253: if (data != NULL)
1254: fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n",
1255: (char *) target, (char *) data);
1256: else
1257: fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n",
1258: (char *) target);
1259: }
1260:
1261: /**
1262: * cdataBlockDebug:
1263: * @ctx: the user data (XML parser context)
1264: * @value: The pcdata content
1265: * @len: the block length
1266: *
1267: * called when a pcdata block has been parsed
1268: */
1269: static void
1270: cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len)
1271: {
1272: callbacks++;
1273: if (quiet)
1274: return;
1275: fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n",
1276: (char *) value, len);
1277: }
1278:
1279: /**
1280: * commentDebug:
1281: * @ctxt: An XML parser context
1282: * @value: the comment content
1283: *
1284: * A comment has been parsed.
1285: */
1286: static void
1287: commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value)
1288: {
1289: callbacks++;
1290: if (quiet)
1291: return;
1292: fprintf(SAXdebug, "SAX.comment(%s)\n", value);
1293: }
1294:
1295: /**
1296: * warningDebug:
1297: * @ctxt: An XML parser context
1298: * @msg: the message to display/transmit
1299: * @...: extra parameters for the message display
1300: *
1301: * Display and format a warning messages, gives file, line, position and
1302: * extra parameters.
1303: */
1304: static void XMLCDECL
1305: warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1306: {
1307: va_list args;
1308:
1309: callbacks++;
1310: if (quiet)
1311: return;
1312: va_start(args, msg);
1313: fprintf(SAXdebug, "SAX.warning: ");
1314: vfprintf(SAXdebug, msg, args);
1315: va_end(args);
1316: }
1317:
1318: /**
1319: * errorDebug:
1320: * @ctxt: An XML parser context
1321: * @msg: the message to display/transmit
1322: * @...: extra parameters for the message display
1323: *
1324: * Display and format a error messages, gives file, line, position and
1325: * extra parameters.
1326: */
1327: static void XMLCDECL
1328: errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1329: {
1330: va_list args;
1331:
1332: callbacks++;
1333: if (quiet)
1334: return;
1335: va_start(args, msg);
1336: fprintf(SAXdebug, "SAX.error: ");
1337: vfprintf(SAXdebug, msg, args);
1338: va_end(args);
1339: }
1340:
1341: /**
1342: * fatalErrorDebug:
1343: * @ctxt: An XML parser context
1344: * @msg: the message to display/transmit
1345: * @...: extra parameters for the message display
1346: *
1347: * Display and format a fatalError messages, gives file, line, position and
1348: * extra parameters.
1349: */
1350: static void XMLCDECL
1351: fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...)
1352: {
1353: va_list args;
1354:
1355: callbacks++;
1356: if (quiet)
1357: return;
1358: va_start(args, msg);
1359: fprintf(SAXdebug, "SAX.fatalError: ");
1360: vfprintf(SAXdebug, msg, args);
1361: va_end(args);
1362: }
1363:
1364: static xmlSAXHandler debugSAXHandlerStruct = {
1365: internalSubsetDebug,
1366: isStandaloneDebug,
1367: hasInternalSubsetDebug,
1368: hasExternalSubsetDebug,
1369: resolveEntityDebug,
1370: getEntityDebug,
1371: entityDeclDebug,
1372: notationDeclDebug,
1373: attributeDeclDebug,
1374: elementDeclDebug,
1375: unparsedEntityDeclDebug,
1376: setDocumentLocatorDebug,
1377: startDocumentDebug,
1378: endDocumentDebug,
1379: startElementDebug,
1380: endElementDebug,
1381: referenceDebug,
1382: charactersDebug,
1383: ignorableWhitespaceDebug,
1384: processingInstructionDebug,
1385: commentDebug,
1386: warningDebug,
1387: errorDebug,
1388: fatalErrorDebug,
1389: getParameterEntityDebug,
1390: cdataBlockDebug,
1391: externalSubsetDebug,
1392: 1,
1393: NULL,
1394: NULL,
1395: NULL,
1396: NULL
1397: };
1398:
1399: static xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct;
1400:
1401: /*
1402: * SAX2 specific callbacks
1403: */
1404: /**
1405: * startElementNsDebug:
1406: * @ctxt: An XML parser context
1407: * @name: The element name
1408: *
1409: * called when an opening tag has been processed.
1410: */
1411: static void
1412: startElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1413: const xmlChar *localname,
1414: const xmlChar *prefix,
1415: const xmlChar *URI,
1416: int nb_namespaces,
1417: const xmlChar **namespaces,
1418: int nb_attributes,
1419: int nb_defaulted,
1420: const xmlChar **attributes)
1421: {
1422: int i;
1423:
1424: callbacks++;
1425: if (quiet)
1426: return;
1427: fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname);
1428: if (prefix == NULL)
1429: fprintf(SAXdebug, ", NULL");
1430: else
1431: fprintf(SAXdebug, ", %s", (char *) prefix);
1432: if (URI == NULL)
1433: fprintf(SAXdebug, ", NULL");
1434: else
1435: fprintf(SAXdebug, ", '%s'", (char *) URI);
1436: fprintf(SAXdebug, ", %d", nb_namespaces);
1437:
1438: if (namespaces != NULL) {
1439: for (i = 0;i < nb_namespaces * 2;i++) {
1440: fprintf(SAXdebug, ", xmlns");
1441: if (namespaces[i] != NULL)
1442: fprintf(SAXdebug, ":%s", namespaces[i]);
1443: i++;
1444: fprintf(SAXdebug, "='%s'", namespaces[i]);
1445: }
1446: }
1447: fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted);
1448: if (attributes != NULL) {
1449: for (i = 0;i < nb_attributes * 5;i += 5) {
1450: if (attributes[i + 1] != NULL)
1451: fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]);
1452: else
1453: fprintf(SAXdebug, ", %s='", attributes[i]);
1454: fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3],
1455: (int)(attributes[i + 4] - attributes[i + 3]));
1456: }
1457: }
1458: fprintf(SAXdebug, ")\n");
1459: }
1460:
1461: /**
1462: * endElementDebug:
1463: * @ctxt: An XML parser context
1464: * @name: The element name
1465: *
1466: * called when the end of an element has been detected.
1467: */
1468: static void
1469: endElementNsDebug(void *ctx ATTRIBUTE_UNUSED,
1470: const xmlChar *localname,
1471: const xmlChar *prefix,
1472: const xmlChar *URI)
1473: {
1474: callbacks++;
1475: if (quiet)
1476: return;
1477: fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname);
1478: if (prefix == NULL)
1479: fprintf(SAXdebug, ", NULL");
1480: else
1481: fprintf(SAXdebug, ", %s", (char *) prefix);
1482: if (URI == NULL)
1483: fprintf(SAXdebug, ", NULL)\n");
1484: else
1485: fprintf(SAXdebug, ", '%s')\n", (char *) URI);
1486: }
1487:
1488: static xmlSAXHandler debugSAX2HandlerStruct = {
1489: internalSubsetDebug,
1490: isStandaloneDebug,
1491: hasInternalSubsetDebug,
1492: hasExternalSubsetDebug,
1493: resolveEntityDebug,
1494: getEntityDebug,
1495: entityDeclDebug,
1496: notationDeclDebug,
1497: attributeDeclDebug,
1498: elementDeclDebug,
1499: unparsedEntityDeclDebug,
1500: setDocumentLocatorDebug,
1501: startDocumentDebug,
1502: endDocumentDebug,
1503: NULL,
1504: NULL,
1505: referenceDebug,
1506: charactersDebug,
1507: ignorableWhitespaceDebug,
1508: processingInstructionDebug,
1509: commentDebug,
1510: warningDebug,
1511: errorDebug,
1512: fatalErrorDebug,
1513: getParameterEntityDebug,
1514: cdataBlockDebug,
1515: externalSubsetDebug,
1516: XML_SAX2_MAGIC,
1517: NULL,
1518: startElementNsDebug,
1519: endElementNsDebug,
1520: NULL
1521: };
1522:
1523: static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
1524:
1525: #ifdef LIBXML_HTML_ENABLED
1526: /**
1527: * htmlstartElementDebug:
1528: * @ctxt: An XML parser context
1529: * @name: The element name
1530: *
1531: * called when an opening tag has been processed.
1532: */
1533: static void
1534: htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts)
1535: {
1536: int i;
1537:
1538: fprintf(SAXdebug, "SAX.startElement(%s", (char *) name);
1539: if (atts != NULL) {
1540: for (i = 0;(atts[i] != NULL);i++) {
1541: fprintf(SAXdebug, ", %s", atts[i++]);
1542: if (atts[i] != NULL) {
1543: unsigned char output[40];
1544: const unsigned char *att = atts[i];
1545: int outlen, attlen;
1546: fprintf(SAXdebug, "='");
1547: while ((attlen = strlen((char*)att)) > 0) {
1548: outlen = sizeof output - 1;
1549: htmlEncodeEntities(output, &outlen, att, &attlen, '\'');
1550: output[outlen] = 0;
1551: fprintf(SAXdebug, "%s", (char *) output);
1552: att += attlen;
1553: }
1554: fprintf(SAXdebug, "'");
1555: }
1556: }
1557: }
1558: fprintf(SAXdebug, ")\n");
1559: }
1560:
1561: /**
1562: * htmlcharactersDebug:
1563: * @ctxt: An XML parser context
1564: * @ch: a xmlChar string
1565: * @len: the number of xmlChar
1566: *
1567: * receiving some chars from the parser.
1568: * Question: how much at a time ???
1569: */
1570: static void
1571: htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1572: {
1573: unsigned char output[40];
1574: int inlen = len, outlen = 30;
1575:
1576: htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1577: output[outlen] = 0;
1578:
1579: fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len);
1580: }
1581:
1582: /**
1583: * htmlcdataDebug:
1584: * @ctxt: An XML parser context
1585: * @ch: a xmlChar string
1586: * @len: the number of xmlChar
1587: *
1588: * receiving some cdata chars from the parser.
1589: * Question: how much at a time ???
1590: */
1591: static void
1592: htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len)
1593: {
1594: unsigned char output[40];
1595: int inlen = len, outlen = 30;
1596:
1597: htmlEncodeEntities(output, &outlen, ch, &inlen, 0);
1598: output[outlen] = 0;
1599:
1600: fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len);
1601: }
1602:
1603: static xmlSAXHandler debugHTMLSAXHandlerStruct = {
1604: internalSubsetDebug,
1605: isStandaloneDebug,
1606: hasInternalSubsetDebug,
1607: hasExternalSubsetDebug,
1608: resolveEntityDebug,
1609: getEntityDebug,
1610: entityDeclDebug,
1611: notationDeclDebug,
1612: attributeDeclDebug,
1613: elementDeclDebug,
1614: unparsedEntityDeclDebug,
1615: setDocumentLocatorDebug,
1616: startDocumentDebug,
1617: endDocumentDebug,
1618: htmlstartElementDebug,
1619: endElementDebug,
1620: referenceDebug,
1621: htmlcharactersDebug,
1622: ignorableWhitespaceDebug,
1623: processingInstructionDebug,
1624: commentDebug,
1625: warningDebug,
1626: errorDebug,
1627: fatalErrorDebug,
1628: getParameterEntityDebug,
1629: htmlcdataDebug,
1630: externalSubsetDebug,
1631: 1,
1632: NULL,
1633: NULL,
1634: NULL,
1635: NULL
1636: };
1637:
1638: static xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct;
1639: #endif /* LIBXML_HTML_ENABLED */
1640:
1641: #ifdef LIBXML_SAX1_ENABLED
1642: /**
1643: * saxParseTest:
1644: * @filename: the file to parse
1645: * @result: the file with expected result
1646: * @err: the file with error messages
1647: *
1648: * Parse a file using the SAX API and check for errors.
1649: *
1650: * Returns 0 in case of success, an error code otherwise
1651: */
1652: static int
1653: saxParseTest(const char *filename, const char *result,
1654: const char *err ATTRIBUTE_UNUSED,
1655: int options) {
1656: int ret;
1657: char *temp;
1658:
1659: nb_tests++;
1660: temp = resultFilename(filename, "", ".res");
1661: if (temp == NULL) {
1662: fprintf(stderr, "out of memory\n");
1663: fatalError();
1664: }
1665: SAXdebug = fopen(temp, "wb");
1666: if (SAXdebug == NULL) {
1667: fprintf(stderr, "Failed to write to %s\n", temp);
1668: free(temp);
1669: return(-1);
1670: }
1671:
1672: /* for SAX we really want the callbacks though the context handlers */
1673: xmlSetStructuredErrorFunc(NULL, NULL);
1674: xmlSetGenericErrorFunc(NULL, testErrorHandler);
1675:
1676: #ifdef LIBXML_HTML_ENABLED
1677: if (options & XML_PARSE_HTML) {
1678: htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL);
1679: ret = 0;
1680: } else
1681: #endif
1682: ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename);
1683: if (ret == XML_WAR_UNDECLARED_ENTITY) {
1684: fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1685: ret = 0;
1686: }
1687: if (ret != 0) {
1688: fprintf(stderr, "Failed to parse %s\n", filename);
1689: return(1);
1690: }
1691: #ifdef LIBXML_HTML_ENABLED
1692: if (options & XML_PARSE_HTML) {
1693: htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL);
1694: ret = 0;
1695: } else
1696: #endif
1697: if (options & XML_PARSE_SAX1) {
1698: ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename);
1699: } else {
1700: ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename);
1701: }
1702: if (ret == XML_WAR_UNDECLARED_ENTITY) {
1703: fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret);
1704: ret = 0;
1705: }
1706: fclose(SAXdebug);
1707: if (compareFiles(temp, result)) {
1708: fprintf(stderr, "Got a difference for %s\n", filename);
1709: ret = 1;
1710: }
1711: if (temp != NULL) {
1712: unlink(temp);
1713: free(temp);
1714: }
1715:
1716: /* switch back to structured error handling */
1717: xmlSetGenericErrorFunc(NULL, NULL);
1718: xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
1719:
1720: return(ret);
1721: }
1722: #endif
1723:
1724: /************************************************************************
1725: * *
1726: * Parse to tree based tests *
1727: * *
1728: ************************************************************************/
1729: /**
1730: * oldParseTest:
1731: * @filename: the file to parse
1732: * @result: the file with expected result
1733: * @err: the file with error messages: unused
1734: *
1735: * Parse a file using the old xmlParseFile API, then serialize back
1736: * reparse the result and serialize again, then check for deviation
1737: * in serialization.
1738: *
1739: * Returns 0 in case of success, an error code otherwise
1740: */
1741: static int
1742: oldParseTest(const char *filename, const char *result,
1743: const char *err ATTRIBUTE_UNUSED,
1744: int options ATTRIBUTE_UNUSED) {
1745: xmlDocPtr doc;
1746: char *temp;
1747: int res = 0;
1748:
1749: nb_tests++;
1750: /*
1751: * base of the test, parse with the old API
1752: */
1753: #ifdef LIBXML_SAX1_ENABLED
1754: doc = xmlParseFile(filename);
1755: #else
1756: doc = xmlReadFile(filename, NULL, 0);
1757: #endif
1758: if (doc == NULL)
1759: return(1);
1760: temp = resultFilename(filename, "", ".res");
1761: if (temp == NULL) {
1762: fprintf(stderr, "out of memory\n");
1763: fatalError();
1764: }
1765: xmlSaveFile(temp, doc);
1766: if (compareFiles(temp, result)) {
1767: res = 1;
1768: }
1769: xmlFreeDoc(doc);
1770:
1771: /*
1772: * Parse the saved result to make sure the round trip is okay
1773: */
1774: #ifdef LIBXML_SAX1_ENABLED
1775: doc = xmlParseFile(temp);
1776: #else
1777: doc = xmlReadFile(temp, NULL, 0);
1778: #endif
1779: if (doc == NULL)
1780: return(1);
1781: xmlSaveFile(temp, doc);
1782: if (compareFiles(temp, result)) {
1783: res = 1;
1784: }
1785: xmlFreeDoc(doc);
1786:
1787: if (temp != NULL) {
1788: unlink(temp);
1789: free(temp);
1790: }
1791: return(res);
1792: }
1793:
1794: #ifdef LIBXML_PUSH_ENABLED
1795: /**
1796: * pushParseTest:
1797: * @filename: the file to parse
1798: * @result: the file with expected result
1799: * @err: the file with error messages: unused
1800: *
1801: * Parse a file using the Push API, then serialize back
1802: * to check for content.
1803: *
1804: * Returns 0 in case of success, an error code otherwise
1805: */
1806: static int
1807: pushParseTest(const char *filename, const char *result,
1808: const char *err ATTRIBUTE_UNUSED,
1809: int options) {
1810: xmlParserCtxtPtr ctxt;
1811: xmlDocPtr doc;
1812: const char *base;
1813: int size, res;
1814: int cur = 0;
1815:
1816: nb_tests++;
1817: /*
1818: * load the document in memory and work from there.
1819: */
1820: if (loadMem(filename, &base, &size) != 0) {
1821: fprintf(stderr, "Failed to load %s\n", filename);
1822: return(-1);
1823: }
1824:
1825: #ifdef LIBXML_HTML_ENABLED
1826: if (options & XML_PARSE_HTML)
1827: ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename,
1828: XML_CHAR_ENCODING_NONE);
1829: else
1830: #endif
1831: ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename);
1832: xmlCtxtUseOptions(ctxt, options);
1833: cur += 4;
1834: while (cur < size) {
1835: if (cur + 1024 >= size) {
1836: #ifdef LIBXML_HTML_ENABLED
1837: if (options & XML_PARSE_HTML)
1838: htmlParseChunk(ctxt, base + cur, size - cur, 1);
1839: else
1840: #endif
1841: xmlParseChunk(ctxt, base + cur, size - cur, 1);
1842: break;
1843: } else {
1844: #ifdef LIBXML_HTML_ENABLED
1845: if (options & XML_PARSE_HTML)
1846: htmlParseChunk(ctxt, base + cur, 1024, 0);
1847: else
1848: #endif
1849: xmlParseChunk(ctxt, base + cur, 1024, 0);
1850: cur += 1024;
1851: }
1852: }
1853: doc = ctxt->myDoc;
1854: #ifdef LIBXML_HTML_ENABLED
1855: if (options & XML_PARSE_HTML)
1856: res = 1;
1857: else
1858: #endif
1859: res = ctxt->wellFormed;
1860: xmlFreeParserCtxt(ctxt);
1861: free((char *)base);
1862: if (!res) {
1863: xmlFreeDoc(doc);
1864: fprintf(stderr, "Failed to parse %s\n", filename);
1865: return(-1);
1866: }
1867: #ifdef LIBXML_HTML_ENABLED
1868: if (options & XML_PARSE_HTML)
1869: htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1870: else
1871: #endif
1872: xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1873: xmlFreeDoc(doc);
1874: res = compareFileMem(result, base, size);
1875: if ((base == NULL) || (res != 0)) {
1876: if (base != NULL)
1877: xmlFree((char *)base);
1878: fprintf(stderr, "Result for %s failed\n", filename);
1879: return(-1);
1880: }
1881: xmlFree((char *)base);
1882: if (err != NULL) {
1883: res = compareFileMem(err, testErrors, testErrorsSize);
1884: if (res != 0) {
1885: fprintf(stderr, "Error for %s failed\n", filename);
1886: return(-1);
1887: }
1888: }
1889: return(0);
1890: }
1891: #endif
1892:
1893: /**
1894: * memParseTest:
1895: * @filename: the file to parse
1896: * @result: the file with expected result
1897: * @err: the file with error messages: unused
1898: *
1899: * Parse a file using the old xmlReadMemory API, then serialize back
1900: * reparse the result and serialize again, then check for deviation
1901: * in serialization.
1902: *
1903: * Returns 0 in case of success, an error code otherwise
1904: */
1905: static int
1906: memParseTest(const char *filename, const char *result,
1907: const char *err ATTRIBUTE_UNUSED,
1908: int options ATTRIBUTE_UNUSED) {
1909: xmlDocPtr doc;
1910: const char *base;
1911: int size, res;
1912:
1913: nb_tests++;
1914: /*
1915: * load and parse the memory
1916: */
1917: if (loadMem(filename, &base, &size) != 0) {
1918: fprintf(stderr, "Failed to load %s\n", filename);
1919: return(-1);
1920: }
1921:
1922: doc = xmlReadMemory(base, size, filename, NULL, 0);
1923: unloadMem(base);
1924: if (doc == NULL) {
1925: return(1);
1926: }
1927: xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
1928: xmlFreeDoc(doc);
1929: res = compareFileMem(result, base, size);
1930: if ((base == NULL) || (res != 0)) {
1931: if (base != NULL)
1932: xmlFree((char *)base);
1933: fprintf(stderr, "Result for %s failed\n", filename);
1934: return(-1);
1935: }
1936: xmlFree((char *)base);
1937: return(0);
1938: }
1939:
1940: /**
1941: * noentParseTest:
1942: * @filename: the file to parse
1943: * @result: the file with expected result
1944: * @err: the file with error messages: unused
1945: *
1946: * Parse a file with entity resolution, then serialize back
1947: * reparse the result and serialize again, then check for deviation
1948: * in serialization.
1949: *
1950: * Returns 0 in case of success, an error code otherwise
1951: */
1952: static int
1953: noentParseTest(const char *filename, const char *result,
1954: const char *err ATTRIBUTE_UNUSED,
1955: int options) {
1956: xmlDocPtr doc;
1957: char *temp;
1958: int res = 0;
1959:
1960: nb_tests++;
1961: /*
1962: * base of the test, parse with the old API
1963: */
1964: doc = xmlReadFile(filename, NULL, options);
1965: if (doc == NULL)
1966: return(1);
1967: temp = resultFilename(filename, "", ".res");
1968: if (temp == NULL) {
1969: fprintf(stderr, "Out of memory\n");
1970: fatalError();
1971: }
1972: xmlSaveFile(temp, doc);
1973: if (compareFiles(temp, result)) {
1974: res = 1;
1975: }
1976: xmlFreeDoc(doc);
1977:
1978: /*
1979: * Parse the saved result to make sure the round trip is okay
1980: */
1981: doc = xmlReadFile(filename, NULL, options);
1982: if (doc == NULL)
1983: return(1);
1984: xmlSaveFile(temp, doc);
1985: if (compareFiles(temp, result)) {
1986: res = 1;
1987: }
1988: xmlFreeDoc(doc);
1989:
1990: if (temp != NULL) {
1991: unlink(temp);
1992: free(temp);
1993: }
1994: return(res);
1995: }
1996:
1997: /**
1998: * errParseTest:
1999: * @filename: the file to parse
2000: * @result: the file with expected result
2001: * @err: the file with error messages
2002: *
2003: * Parse a file using the xmlReadFile API and check for errors.
2004: *
2005: * Returns 0 in case of success, an error code otherwise
2006: */
2007: static int
2008: errParseTest(const char *filename, const char *result, const char *err,
2009: int options) {
2010: xmlDocPtr doc;
2011: const char *base = NULL;
2012: int size, res = 0;
2013:
2014: nb_tests++;
2015: #ifdef LIBXML_HTML_ENABLED
2016: if (options & XML_PARSE_HTML) {
2017: doc = htmlReadFile(filename, NULL, options);
2018: } else
2019: #endif
2020: #ifdef LIBXML_XINCLUDE_ENABLED
2021: if (options & XML_PARSE_XINCLUDE) {
2022: doc = xmlReadFile(filename, NULL, options);
2023: xmlXIncludeProcessFlags(doc, options);
2024: } else
2025: #endif
2026: {
2027: xmlGetWarningsDefaultValue = 1;
2028: doc = xmlReadFile(filename, NULL, options);
2029: }
2030: xmlGetWarningsDefaultValue = 0;
2031: if (result) {
2032: if (doc == NULL) {
2033: base = "";
2034: size = 0;
2035: } else {
2036: #ifdef LIBXML_HTML_ENABLED
2037: if (options & XML_PARSE_HTML) {
2038: htmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2039: } else
2040: #endif
2041: xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
2042: }
2043: res = compareFileMem(result, base, size);
2044: }
2045: if (doc != NULL) {
2046: if (base != NULL)
2047: xmlFree((char *)base);
2048: xmlFreeDoc(doc);
2049: }
2050: if (res != 0) {
2051: fprintf(stderr, "Result for %s failed\n", filename);
2052: return(-1);
2053: }
2054: if (err != NULL) {
2055: res = compareFileMem(err, testErrors, testErrorsSize);
2056: if (res != 0) {
2057: fprintf(stderr, "Error for %s failed\n", filename);
2058: return(-1);
2059: }
2060: } else if (options & XML_PARSE_DTDVALID) {
2061: if (testErrorsSize != 0)
2062: fprintf(stderr, "Validation for %s failed\n", filename);
2063: }
2064:
2065: return(0);
2066: }
2067:
2068: #ifdef LIBXML_READER_ENABLED
2069: /************************************************************************
2070: * *
2071: * Reader based tests *
2072: * *
2073: ************************************************************************/
2074:
2075: static void processNode(FILE *out, xmlTextReaderPtr reader) {
2076: const xmlChar *name, *value;
2077: int type, empty;
2078:
2079: type = xmlTextReaderNodeType(reader);
2080: empty = xmlTextReaderIsEmptyElement(reader);
2081:
2082: name = xmlTextReaderConstName(reader);
2083: if (name == NULL)
2084: name = BAD_CAST "--";
2085:
2086: value = xmlTextReaderConstValue(reader);
2087:
2088:
2089: fprintf(out, "%d %d %s %d %d",
2090: xmlTextReaderDepth(reader),
2091: type,
2092: name,
2093: empty,
2094: xmlTextReaderHasValue(reader));
2095: if (value == NULL)
2096: fprintf(out, "\n");
2097: else {
2098: fprintf(out, " %s\n", value);
2099: }
2100: }
2101: static int
2102: streamProcessTest(const char *filename, const char *result, const char *err,
2103: xmlTextReaderPtr reader, const char *rng) {
2104: int ret;
2105: char *temp = NULL;
2106: FILE *t = NULL;
2107:
2108: if (reader == NULL)
2109: return(-1);
2110:
2111: nb_tests++;
2112: if (result != NULL) {
2113: temp = resultFilename(filename, "", ".res");
2114: if (temp == NULL) {
2115: fprintf(stderr, "Out of memory\n");
2116: fatalError();
2117: }
2118: t = fopen(temp, "wb");
2119: if (t == NULL) {
2120: fprintf(stderr, "Can't open temp file %s\n", temp);
2121: free(temp);
2122: return(-1);
2123: }
2124: }
2125: #ifdef LIBXML_SCHEMAS_ENABLED
2126: if (rng != NULL) {
2127: ret = xmlTextReaderRelaxNGValidate(reader, rng);
2128: if (ret < 0) {
2129: testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n",
2130: rng);
2131: fclose(t);
2132: if (temp != NULL) {
2133: unlink(temp);
2134: free(temp);
2135: }
2136: return(0);
2137: }
2138: }
2139: #endif
2140: xmlGetWarningsDefaultValue = 1;
2141: ret = xmlTextReaderRead(reader);
2142: while (ret == 1) {
2143: if ((t != NULL) && (rng == NULL))
2144: processNode(t, reader);
2145: ret = xmlTextReaderRead(reader);
2146: }
2147: if (ret != 0) {
2148: testErrorHandler(NULL, "%s : failed to parse\n", filename);
2149: }
2150: if (rng != NULL) {
2151: if (xmlTextReaderIsValid(reader) != 1) {
2152: testErrorHandler(NULL, "%s fails to validate\n", filename);
2153: } else {
2154: testErrorHandler(NULL, "%s validates\n", filename);
2155: }
2156: }
2157: xmlGetWarningsDefaultValue = 0;
2158: if (t != NULL) {
2159: fclose(t);
2160: ret = compareFiles(temp, result);
2161: if (temp != NULL) {
2162: unlink(temp);
2163: free(temp);
2164: }
2165: if (ret) {
2166: fprintf(stderr, "Result for %s failed\n", filename);
2167: return(-1);
2168: }
2169: }
2170: if (err != NULL) {
2171: ret = compareFileMem(err, testErrors, testErrorsSize);
2172: if (ret != 0) {
2173: fprintf(stderr, "Error for %s failed\n", filename);
2174: printf("%s", testErrors);
2175: return(-1);
2176: }
2177: }
2178:
2179: return(0);
2180: }
2181:
2182: /**
2183: * streamParseTest:
2184: * @filename: the file to parse
2185: * @result: the file with expected result
2186: * @err: the file with error messages
2187: *
2188: * Parse a file using the reader API and check for errors.
2189: *
2190: * Returns 0 in case of success, an error code otherwise
2191: */
2192: static int
2193: streamParseTest(const char *filename, const char *result, const char *err,
2194: int options) {
2195: xmlTextReaderPtr reader;
2196: int ret;
2197:
2198: reader = xmlReaderForFile(filename, NULL, options);
2199: ret = streamProcessTest(filename, result, err, reader, NULL);
2200: xmlFreeTextReader(reader);
2201: return(ret);
2202: }
2203:
2204: /**
2205: * walkerParseTest:
2206: * @filename: the file to parse
2207: * @result: the file with expected result
2208: * @err: the file with error messages
2209: *
2210: * Parse a file using the walker, i.e. a reader built from a atree.
2211: *
2212: * Returns 0 in case of success, an error code otherwise
2213: */
2214: static int
2215: walkerParseTest(const char *filename, const char *result, const char *err,
2216: int options) {
2217: xmlDocPtr doc;
2218: xmlTextReaderPtr reader;
2219: int ret;
2220:
2221: doc = xmlReadFile(filename, NULL, options);
2222: if (doc == NULL) {
2223: fprintf(stderr, "Failed to parse %s\n", filename);
2224: return(-1);
2225: }
2226: reader = xmlReaderWalker(doc);
2227: ret = streamProcessTest(filename, result, err, reader, NULL);
2228: xmlFreeTextReader(reader);
2229: xmlFreeDoc(doc);
2230: return(ret);
2231: }
2232:
2233: /**
2234: * streamMemParseTest:
2235: * @filename: the file to parse
2236: * @result: the file with expected result
2237: * @err: the file with error messages
2238: *
2239: * Parse a file using the reader API from memory and check for errors.
2240: *
2241: * Returns 0 in case of success, an error code otherwise
2242: */
2243: static int
2244: streamMemParseTest(const char *filename, const char *result, const char *err,
2245: int options) {
2246: xmlTextReaderPtr reader;
2247: int ret;
2248: const char *base;
2249: int size;
2250:
2251: /*
2252: * load and parse the memory
2253: */
2254: if (loadMem(filename, &base, &size) != 0) {
2255: fprintf(stderr, "Failed to load %s\n", filename);
2256: return(-1);
2257: }
2258: reader = xmlReaderForMemory(base, size, filename, NULL, options);
2259: ret = streamProcessTest(filename, result, err, reader, NULL);
2260: free((char *)base);
2261: xmlFreeTextReader(reader);
2262: return(ret);
2263: }
2264: #endif
2265:
2266: #ifdef LIBXML_XPATH_ENABLED
2267: #ifdef LIBXML_DEBUG_ENABLED
2268: /************************************************************************
2269: * *
2270: * XPath and XPointer based tests *
2271: * *
2272: ************************************************************************/
2273:
2274: static FILE *xpathOutput;
2275: static xmlDocPtr xpathDocument;
2276:
2277: static void
2278: testXPath(const char *str, int xptr, int expr) {
2279: xmlXPathObjectPtr res;
2280: xmlXPathContextPtr ctxt;
2281:
2282: nb_tests++;
2283: #if defined(LIBXML_XPTR_ENABLED)
2284: if (xptr) {
2285: ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL);
2286: res = xmlXPtrEval(BAD_CAST str, ctxt);
2287: } else {
2288: #endif
2289: ctxt = xmlXPathNewContext(xpathDocument);
2290: ctxt->node = xmlDocGetRootElement(xpathDocument);
2291: if (expr)
2292: res = xmlXPathEvalExpression(BAD_CAST str, ctxt);
2293: else {
2294: /* res = xmlXPathEval(BAD_CAST str, ctxt); */
2295: xmlXPathCompExprPtr comp;
2296:
2297: comp = xmlXPathCompile(BAD_CAST str);
2298: if (comp != NULL) {
2299: res = xmlXPathCompiledEval(comp, ctxt);
2300: xmlXPathFreeCompExpr(comp);
2301: } else
2302: res = NULL;
2303: }
2304: #if defined(LIBXML_XPTR_ENABLED)
2305: }
2306: #endif
2307: xmlXPathDebugDumpObject(xpathOutput, res, 0);
2308: xmlXPathFreeObject(res);
2309: xmlXPathFreeContext(ctxt);
2310: }
2311:
2312: /**
2313: * xpathExprTest:
2314: * @filename: the file to parse
2315: * @result: the file with expected result
2316: * @err: the file with error messages
2317: *
2318: * Parse a file containing XPath standalone expressions and evaluate them
2319: *
2320: * Returns 0 in case of success, an error code otherwise
2321: */
2322: static int
2323: xpathCommonTest(const char *filename, const char *result,
2324: int xptr, int expr) {
2325: FILE *input;
2326: char expression[5000];
2327: int len, ret = 0;
2328: char *temp;
2329:
2330: temp = resultFilename(filename, "", ".res");
2331: if (temp == NULL) {
2332: fprintf(stderr, "Out of memory\n");
2333: fatalError();
2334: }
2335: xpathOutput = fopen(temp, "wb");
2336: if (xpathOutput == NULL) {
2337: fprintf(stderr, "failed to open output file %s\n", temp);
2338: free(temp);
2339: return(-1);
2340: }
2341:
2342: input = fopen(filename, "rb");
2343: if (input == NULL) {
2344: xmlGenericError(xmlGenericErrorContext,
2345: "Cannot open %s for reading\n", filename);
2346: free(temp);
2347: return(-1);
2348: }
2349: while (fgets(expression, 4500, input) != NULL) {
2350: len = strlen(expression);
2351: len--;
2352: while ((len >= 0) &&
2353: ((expression[len] == '\n') || (expression[len] == '\t') ||
2354: (expression[len] == '\r') || (expression[len] == ' '))) len--;
2355: expression[len + 1] = 0;
2356: if (len >= 0) {
2357: fprintf(xpathOutput,
2358: "\n========================\nExpression: %s\n",
2359: expression) ;
2360: testXPath(expression, xptr, expr);
2361: }
2362: }
2363:
2364: fclose(input);
2365: fclose(xpathOutput);
2366: if (result != NULL) {
2367: ret = compareFiles(temp, result);
2368: if (ret) {
2369: fprintf(stderr, "Result for %s failed\n", filename);
2370: }
2371: }
2372:
2373: if (temp != NULL) {
2374: unlink(temp);
2375: free(temp);
2376: }
2377: return(ret);
2378: }
2379:
2380: /**
2381: * xpathExprTest:
2382: * @filename: the file to parse
2383: * @result: the file with expected result
2384: * @err: the file with error messages
2385: *
2386: * Parse a file containing XPath standalone expressions and evaluate them
2387: *
2388: * Returns 0 in case of success, an error code otherwise
2389: */
2390: static int
2391: xpathExprTest(const char *filename, const char *result,
2392: const char *err ATTRIBUTE_UNUSED,
2393: int options ATTRIBUTE_UNUSED) {
2394: return(xpathCommonTest(filename, result, 0, 1));
2395: }
2396:
2397: /**
2398: * xpathDocTest:
2399: * @filename: the file to parse
2400: * @result: the file with expected result
2401: * @err: the file with error messages
2402: *
2403: * Parse a file containing XPath expressions and evaluate them against
2404: * a set of corresponding documents.
2405: *
2406: * Returns 0 in case of success, an error code otherwise
2407: */
2408: static int
2409: xpathDocTest(const char *filename,
2410: const char *resul ATTRIBUTE_UNUSED,
2411: const char *err ATTRIBUTE_UNUSED,
2412: int options) {
2413:
2414: char pattern[500];
2415: char result[500];
2416: glob_t globbuf;
2417: size_t i;
2418: int ret = 0, res;
2419:
2420: xpathDocument = xmlReadFile(filename, NULL,
2421: options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2422: if (xpathDocument == NULL) {
2423: fprintf(stderr, "Failed to load %s\n", filename);
2424: return(-1);
2425: }
2426:
2427: snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename));
2428: pattern[499] = 0;
2429: globbuf.gl_offs = 0;
2430: glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2431: for (i = 0;i < globbuf.gl_pathc;i++) {
2432: snprintf(result, 499, "result/XPath/tests/%s",
2433: baseFilename(globbuf.gl_pathv[i]));
2434: res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0);
2435: if (res != 0)
2436: ret = res;
2437: }
2438: globfree(&globbuf);
2439:
2440: xmlFreeDoc(xpathDocument);
2441: return(ret);
2442: }
2443:
2444: #ifdef LIBXML_XPTR_ENABLED
2445: /**
2446: * xptrDocTest:
2447: * @filename: the file to parse
2448: * @result: the file with expected result
2449: * @err: the file with error messages
2450: *
2451: * Parse a file containing XPath expressions and evaluate them against
2452: * a set of corresponding documents.
2453: *
2454: * Returns 0 in case of success, an error code otherwise
2455: */
2456: static int
2457: xptrDocTest(const char *filename,
2458: const char *resul ATTRIBUTE_UNUSED,
2459: const char *err ATTRIBUTE_UNUSED,
2460: int options) {
2461:
2462: char pattern[500];
2463: char result[500];
2464: glob_t globbuf;
2465: size_t i;
2466: int ret = 0, res;
2467:
2468: xpathDocument = xmlReadFile(filename, NULL,
2469: options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2470: if (xpathDocument == NULL) {
2471: fprintf(stderr, "Failed to load %s\n", filename);
2472: return(-1);
2473: }
2474:
2475: snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename));
2476: pattern[499] = 0;
2477: globbuf.gl_offs = 0;
2478: glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
2479: for (i = 0;i < globbuf.gl_pathc;i++) {
2480: snprintf(result, 499, "result/XPath/xptr/%s",
2481: baseFilename(globbuf.gl_pathv[i]));
2482: res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0);
2483: if (res != 0)
2484: ret = res;
2485: }
2486: globfree(&globbuf);
2487:
2488: xmlFreeDoc(xpathDocument);
2489: return(ret);
2490: }
2491: #endif /* LIBXML_XPTR_ENABLED */
2492:
2493: /**
2494: * xmlidDocTest:
2495: * @filename: the file to parse
2496: * @result: the file with expected result
2497: * @err: the file with error messages
2498: *
2499: * Parse a file containing xml:id and check for errors and verify
2500: * that XPath queries will work on them as expected.
2501: *
2502: * Returns 0 in case of success, an error code otherwise
2503: */
2504: static int
2505: xmlidDocTest(const char *filename,
2506: const char *result,
2507: const char *err,
2508: int options) {
2509:
2510: int res = 0;
2511: int ret = 0;
2512: char *temp;
2513:
2514: xpathDocument = xmlReadFile(filename, NULL,
2515: options | XML_PARSE_DTDATTR | XML_PARSE_NOENT);
2516: if (xpathDocument == NULL) {
2517: fprintf(stderr, "Failed to load %s\n", filename);
2518: return(-1);
2519: }
2520:
2521: temp = resultFilename(filename, "", ".res");
2522: if (temp == NULL) {
2523: fprintf(stderr, "Out of memory\n");
2524: fatalError();
2525: }
2526: xpathOutput = fopen(temp, "wb");
2527: if (xpathOutput == NULL) {
2528: fprintf(stderr, "failed to open output file %s\n", temp);
2529: xmlFreeDoc(xpathDocument);
2530: free(temp);
2531: return(-1);
2532: }
2533:
2534: testXPath("id('bar')", 0, 0);
2535:
2536: fclose(xpathOutput);
2537: if (result != NULL) {
2538: ret = compareFiles(temp, result);
2539: if (ret) {
2540: fprintf(stderr, "Result for %s failed\n", filename);
2541: res = 1;
2542: }
2543: }
2544:
2545: if (temp != NULL) {
2546: unlink(temp);
2547: free(temp);
2548: }
2549: xmlFreeDoc(xpathDocument);
2550:
2551: if (err != NULL) {
2552: ret = compareFileMem(err, testErrors, testErrorsSize);
2553: if (ret != 0) {
2554: fprintf(stderr, "Error for %s failed\n", filename);
2555: res = 1;
2556: }
2557: }
2558: return(res);
2559: }
2560:
2561: #endif /* LIBXML_DEBUG_ENABLED */
2562: #endif /* XPATH */
2563: /************************************************************************
2564: * *
2565: * URI based tests *
2566: * *
2567: ************************************************************************/
2568:
2569: static void
2570: handleURI(const char *str, const char *base, FILE *o) {
2571: int ret;
2572: xmlURIPtr uri;
2573: xmlChar *res = NULL;
2574:
2575: uri = xmlCreateURI();
2576:
2577: if (base == NULL) {
2578: ret = xmlParseURIReference(uri, str);
2579: if (ret != 0)
2580: fprintf(o, "%s : error %d\n", str, ret);
2581: else {
2582: xmlNormalizeURIPath(uri->path);
2583: xmlPrintURI(o, uri);
2584: fprintf(o, "\n");
2585: }
2586: } else {
2587: res = xmlBuildURI((xmlChar *)str, (xmlChar *) base);
2588: if (res != NULL) {
2589: fprintf(o, "%s\n", (char *) res);
2590: }
2591: else
2592: fprintf(o, "::ERROR::\n");
2593: }
2594: if (res != NULL)
2595: xmlFree(res);
2596: xmlFreeURI(uri);
2597: }
2598:
2599: /**
2600: * uriCommonTest:
2601: * @filename: the file to parse
2602: * @result: the file with expected result
2603: * @err: the file with error messages
2604: *
2605: * Parse a file containing URI and check for errors
2606: *
2607: * Returns 0 in case of success, an error code otherwise
2608: */
2609: static int
2610: uriCommonTest(const char *filename,
2611: const char *result,
2612: const char *err,
2613: const char *base) {
2614: char *temp;
2615: FILE *o, *f;
2616: char str[1024];
2617: int res = 0, i, ret;
2618:
2619: temp = resultFilename(filename, "", ".res");
2620: if (temp == NULL) {
2621: fprintf(stderr, "Out of memory\n");
2622: fatalError();
2623: }
2624: o = fopen(temp, "wb");
2625: if (o == NULL) {
2626: fprintf(stderr, "failed to open output file %s\n", temp);
2627: free(temp);
2628: return(-1);
2629: }
2630: f = fopen(filename, "rb");
2631: if (f == NULL) {
2632: fprintf(stderr, "failed to open input file %s\n", filename);
2633: fclose(o);
2634: if (temp != NULL) {
2635: unlink(temp);
2636: free(temp);
2637: }
2638: return(-1);
2639: }
2640:
2641: while (1) {
2642: /*
2643: * read one line in string buffer.
2644: */
2645: if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
2646: break;
2647:
2648: /*
2649: * remove the ending spaces
2650: */
2651: i = strlen(str);
2652: while ((i > 0) &&
2653: ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
2654: (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
2655: i--;
2656: str[i] = 0;
2657: }
2658: nb_tests++;
2659: handleURI(str, base, o);
2660: }
2661:
2662: fclose(f);
2663: fclose(o);
2664:
2665: if (result != NULL) {
2666: ret = compareFiles(temp, result);
2667: if (ret) {
2668: fprintf(stderr, "Result for %s failed\n", filename);
2669: res = 1;
2670: }
2671: }
2672: if (err != NULL) {
2673: ret = compareFileMem(err, testErrors, testErrorsSize);
2674: if (ret != 0) {
2675: fprintf(stderr, "Error for %s failed\n", filename);
2676: res = 1;
2677: }
2678: }
2679:
2680: if (temp != NULL) {
2681: unlink(temp);
2682: free(temp);
2683: }
2684: return(res);
2685: }
2686:
2687: /**
2688: * uriParseTest:
2689: * @filename: the file to parse
2690: * @result: the file with expected result
2691: * @err: the file with error messages
2692: *
2693: * Parse a file containing URI and check for errors
2694: *
2695: * Returns 0 in case of success, an error code otherwise
2696: */
2697: static int
2698: uriParseTest(const char *filename,
2699: const char *result,
2700: const char *err,
2701: int options ATTRIBUTE_UNUSED) {
2702: return(uriCommonTest(filename, result, err, NULL));
2703: }
2704:
2705: /**
2706: * uriBaseTest:
2707: * @filename: the file to parse
2708: * @result: the file with expected result
2709: * @err: the file with error messages
2710: *
2711: * Parse a file containing URI, compose them against a fixed base and
2712: * check for errors
2713: *
2714: * Returns 0 in case of success, an error code otherwise
2715: */
2716: static int
2717: uriBaseTest(const char *filename,
2718: const char *result,
2719: const char *err,
2720: int options ATTRIBUTE_UNUSED) {
2721: return(uriCommonTest(filename, result, err,
2722: "http://foo.com/path/to/index.html?orig#help"));
2723: }
2724:
2725: static int urip_success = 1;
2726: static int urip_current = 0;
2727: static const char *urip_testURLs[] = {
2728: "urip://example.com/a b.html",
2729: "urip://example.com/a%20b.html",
2730: "file:///path/to/a b.html",
2731: "file:///path/to/a%20b.html",
2732: "/path/to/a b.html",
2733: "/path/to/a%20b.html",
2734: "urip://example.com/résumé.html",
2735: "urip://example.com/test?a=1&b=2%263&c=4#foo",
2736: NULL
2737: };
2738: static const char *urip_rcvsURLs[] = {
2739: /* it is an URI the strings must be escaped */
2740: "urip://example.com/a%20b.html",
2741: /* check that % escaping is not broken */
2742: "urip://example.com/a%20b.html",
2743: /* it's an URI path the strings must be escaped */
2744: "file:///path/to/a%20b.html",
2745: /* check that % escaping is not broken */
2746: "file:///path/to/a%20b.html",
2747: /* this is not an URI, this is a path, so this should not be escaped */
2748: "/path/to/a b.html",
2749: /* check that paths with % are not broken */
2750: "/path/to/a%20b.html",
2751: /* out of context the encoding can't be guessed byte by byte conversion */
2752: "urip://example.com/r%E9sum%E9.html",
2753: /* verify we don't destroy URIs especially the query part */
2754: "urip://example.com/test?a=1&b=2%263&c=4#foo",
2755: NULL
2756: };
2757: static const char *urip_res = "<list/>";
2758: static const char *urip_cur = NULL;
2759: static int urip_rlen;
2760:
2761: /**
2762: * uripMatch:
2763: * @URI: an URI to test
2764: *
2765: * Check for an urip: query
2766: *
2767: * Returns 1 if yes and 0 if another Input module should be used
2768: */
2769: static int
2770: uripMatch(const char * URI) {
2771: if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2772: return(0);
2773: /* Verify we received the escaped URL */
2774: if (strcmp(urip_rcvsURLs[urip_current], URI))
2775: urip_success = 0;
2776: return(1);
2777: }
2778:
2779: /**
2780: * uripOpen:
2781: * @URI: an URI to test
2782: *
2783: * Return a pointer to the urip: query handler, in this example simply
2784: * the urip_current pointer...
2785: *
2786: * Returns an Input context or NULL in case or error
2787: */
2788: static void *
2789: uripOpen(const char * URI) {
2790: if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog")))
2791: return(NULL);
2792: /* Verify we received the escaped URL */
2793: if (strcmp(urip_rcvsURLs[urip_current], URI))
2794: urip_success = 0;
2795: urip_cur = urip_res;
2796: urip_rlen = strlen(urip_res);
2797: return((void *) urip_cur);
2798: }
2799:
2800: /**
2801: * uripClose:
2802: * @context: the read context
2803: *
2804: * Close the urip: query handler
2805: *
2806: * Returns 0 or -1 in case of error
2807: */
2808: static int
2809: uripClose(void * context) {
2810: if (context == NULL) return(-1);
2811: urip_cur = NULL;
2812: urip_rlen = 0;
2813: return(0);
2814: }
2815:
2816: /**
2817: * uripRead:
2818: * @context: the read context
2819: * @buffer: where to store data
2820: * @len: number of bytes to read
2821: *
2822: * Implement an urip: query read.
2823: *
2824: * Returns the number of bytes read or -1 in case of error
2825: */
2826: static int
2827: uripRead(void * context, char * buffer, int len) {
2828: const char *ptr = (const char *) context;
2829:
2830: if ((context == NULL) || (buffer == NULL) || (len < 0))
2831: return(-1);
2832:
2833: if (len > urip_rlen) len = urip_rlen;
2834: memcpy(buffer, ptr, len);
2835: urip_rlen -= len;
2836: return(len);
2837: }
2838:
2839: static int
2840: urip_checkURL(const char *URL) {
2841: xmlDocPtr doc;
2842:
2843: doc = xmlReadFile(URL, NULL, 0);
2844: if (doc == NULL)
2845: return(-1);
2846: xmlFreeDoc(doc);
2847: return(1);
2848: }
2849:
2850: /**
2851: * uriPathTest:
2852: * @filename: ignored
2853: * @result: ignored
2854: * @err: ignored
2855: *
2856: * Run a set of tests to check how Path and URI are handled before
2857: * being passed to the I/O layer
2858: *
2859: * Returns 0 in case of success, an error code otherwise
2860: */
2861: static int
2862: uriPathTest(const char *filename ATTRIBUTE_UNUSED,
2863: const char *result ATTRIBUTE_UNUSED,
2864: const char *err ATTRIBUTE_UNUSED,
2865: int options ATTRIBUTE_UNUSED) {
2866: int parsed;
2867: int failures = 0;
2868:
2869: /*
2870: * register the new I/O handlers
2871: */
2872: if (xmlRegisterInputCallbacks(uripMatch, uripOpen, uripRead, uripClose) < 0)
2873: {
2874: fprintf(stderr, "failed to register HTTP handler\n");
2875: return(-1);
2876: }
2877:
2878: for (urip_current = 0;urip_testURLs[urip_current] != NULL;urip_current++) {
2879: urip_success = 1;
2880: parsed = urip_checkURL(urip_testURLs[urip_current]);
2881: if (urip_success != 1) {
2882: fprintf(stderr, "failed the URL passing test for %s",
2883: urip_testURLs[urip_current]);
2884: failures++;
2885: } else if (parsed != 1) {
2886: fprintf(stderr, "failed the parsing test for %s",
2887: urip_testURLs[urip_current]);
2888: failures++;
2889: }
2890: nb_tests++;
2891: }
2892:
2893: xmlPopInputCallbacks();
2894: return(failures);
2895: }
2896:
2897: #ifdef LIBXML_SCHEMAS_ENABLED
2898: /************************************************************************
2899: * *
2900: * Schemas tests *
2901: * *
2902: ************************************************************************/
2903: static int
2904: schemasOneTest(const char *sch,
2905: const char *filename,
2906: const char *result,
2907: const char *err,
2908: int options,
2909: xmlSchemaPtr schemas) {
2910: xmlDocPtr doc;
2911: xmlSchemaValidCtxtPtr ctxt;
2912: int ret = 0;
2913: int validResult = 0;
2914: char *temp;
2915: FILE *schemasOutput;
2916:
2917: doc = xmlReadFile(filename, NULL, options);
2918: if (doc == NULL) {
2919: fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
2920: return(-1);
2921: }
2922:
2923: temp = resultFilename(result, "", ".res");
2924: if (temp == NULL) {
2925: fprintf(stderr, "Out of memory\n");
2926: fatalError();
2927: }
2928: schemasOutput = fopen(temp, "wb");
2929: if (schemasOutput == NULL) {
2930: fprintf(stderr, "failed to open output file %s\n", temp);
2931: xmlFreeDoc(doc);
2932: free(temp);
2933: return(-1);
2934: }
2935:
2936: ctxt = xmlSchemaNewValidCtxt(schemas);
2937: xmlSchemaSetValidErrors(ctxt,
2938: (xmlSchemaValidityErrorFunc) testErrorHandler,
2939: (xmlSchemaValidityWarningFunc) testErrorHandler,
2940: ctxt);
2941: validResult = xmlSchemaValidateDoc(ctxt, doc);
2942: if (validResult == 0) {
2943: fprintf(schemasOutput, "%s validates\n", filename);
2944: } else if (validResult > 0) {
2945: fprintf(schemasOutput, "%s fails to validate\n", filename);
2946: } else {
2947: fprintf(schemasOutput, "%s validation generated an internal error\n",
2948: filename);
2949: }
2950: fclose(schemasOutput);
2951: if (result) {
2952: if (compareFiles(temp, result)) {
2953: fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
2954: ret = 1;
2955: }
2956: }
2957: if (temp != NULL) {
2958: unlink(temp);
2959: free(temp);
2960: }
2961:
2962: if ((validResult != 0) && (err != NULL)) {
2963: if (compareFileMem(err, testErrors, testErrorsSize)) {
2964: fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
2965: ret = 1;
2966: }
2967: }
2968:
2969: xmlSchemaFreeValidCtxt(ctxt);
2970: xmlFreeDoc(doc);
2971: return(ret);
2972: }
2973: /**
2974: * schemasTest:
2975: * @filename: the schemas file
2976: * @result: the file with expected result
2977: * @err: the file with error messages
2978: *
2979: * Parse a file containing URI, compose them against a fixed base and
2980: * check for errors
2981: *
2982: * Returns 0 in case of success, an error code otherwise
2983: */
2984: static int
2985: schemasTest(const char *filename,
2986: const char *resul ATTRIBUTE_UNUSED,
2987: const char *errr ATTRIBUTE_UNUSED,
2988: int options) {
2989: const char *base = baseFilename(filename);
2990: const char *base2;
2991: const char *instance;
2992: xmlSchemaParserCtxtPtr ctxt;
2993: xmlSchemaPtr schemas;
2994: int res = 0, len, ret;
2995: char pattern[500];
2996: char prefix[500];
2997: char result[500];
2998: char err[500];
2999: glob_t globbuf;
3000: size_t i;
3001: char count = 0;
3002:
3003: /* first compile the schemas if possible */
3004: ctxt = xmlSchemaNewParserCtxt(filename);
3005: xmlSchemaSetParserErrors(ctxt,
3006: (xmlSchemaValidityErrorFunc) testErrorHandler,
3007: (xmlSchemaValidityWarningFunc) testErrorHandler,
3008: ctxt);
3009: schemas = xmlSchemaParse(ctxt);
3010: xmlSchemaFreeParserCtxt(ctxt);
3011:
3012: /*
3013: * most of the mess is about the output filenames generated by the Makefile
3014: */
3015: len = strlen(base);
3016: if ((len > 499) || (len < 5)) {
3017: xmlSchemaFree(schemas);
3018: return(-1);
3019: }
3020: len -= 4; /* remove trailing .xsd */
3021: if (base[len - 2] == '_') {
3022: len -= 2; /* remove subtest number */
3023: }
3024: if (base[len - 2] == '_') {
3025: len -= 2; /* remove subtest number */
3026: }
3027: memcpy(prefix, base, len);
3028: prefix[len] = 0;
3029:
3030: snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix);
3031: pattern[499] = 0;
3032:
3033: if (base[len] == '_') {
3034: len += 2;
3035: memcpy(prefix, base, len);
3036: prefix[len] = 0;
3037: }
3038:
3039: globbuf.gl_offs = 0;
3040: glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3041: for (i = 0;i < globbuf.gl_pathc;i++) {
3042: testErrorsSize = 0;
3043: testErrors[0] = 0;
3044: instance = globbuf.gl_pathv[i];
3045: base2 = baseFilename(instance);
3046: len = strlen(base2);
3047: if ((len > 6) && (base2[len - 6] == '_')) {
3048: count = base2[len - 5];
3049: snprintf(result, 499, "result/schemas/%s_%c",
3050: prefix, count);
3051: result[499] = 0;
3052: snprintf(err, 499, "result/schemas/%s_%c.err",
3053: prefix, count);
3054: err[499] = 0;
3055: } else {
3056: fprintf(stderr, "don't know how to process %s\n", instance);
3057: continue;
3058: }
3059: if (schemas == NULL) {
3060: } else {
3061: nb_tests++;
3062: ret = schemasOneTest(filename, instance, result, err,
3063: options, schemas);
3064: if (ret != 0)
3065: res = ret;
3066: }
3067: }
3068: globfree(&globbuf);
3069: xmlSchemaFree(schemas);
3070:
3071: return(res);
3072: }
3073:
3074: /************************************************************************
3075: * *
3076: * Schemas tests *
3077: * *
3078: ************************************************************************/
3079: static int
3080: rngOneTest(const char *sch,
3081: const char *filename,
3082: const char *result,
3083: const char *err,
3084: int options,
3085: xmlRelaxNGPtr schemas) {
3086: xmlDocPtr doc;
3087: xmlRelaxNGValidCtxtPtr ctxt;
3088: int ret = 0;
3089: char *temp;
3090: FILE *schemasOutput;
3091:
3092: doc = xmlReadFile(filename, NULL, options);
3093: if (doc == NULL) {
3094: fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
3095: return(-1);
3096: }
3097:
3098: temp = resultFilename(result, "", ".res");
3099: if (temp == NULL) {
3100: fprintf(stderr, "Out of memory\n");
3101: fatalError();
3102: }
3103: schemasOutput = fopen(temp, "wb");
3104: if (schemasOutput == NULL) {
3105: fprintf(stderr, "failed to open output file %s\n", temp);
3106: xmlFreeDoc(doc);
3107: free(temp);
3108: return(-1);
3109: }
3110:
3111: ctxt = xmlRelaxNGNewValidCtxt(schemas);
3112: xmlRelaxNGSetValidErrors(ctxt,
3113: (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3114: (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3115: ctxt);
3116: ret = xmlRelaxNGValidateDoc(ctxt, doc);
3117: if (ret == 0) {
3118: testErrorHandler(NULL, "%s validates\n", filename);
3119: } else if (ret > 0) {
3120: testErrorHandler(NULL, "%s fails to validate\n", filename);
3121: } else {
3122: testErrorHandler(NULL, "%s validation generated an internal error\n",
3123: filename);
3124: }
3125: fclose(schemasOutput);
3126: ret = 0;
3127: if (result) {
3128: if (compareFiles(temp, result)) {
3129: fprintf(stderr, "Result for %s on %s failed\n", filename, sch);
3130: ret = 1;
3131: }
3132: }
3133: if (temp != NULL) {
3134: unlink(temp);
3135: free(temp);
3136: }
3137:
3138: if (err != NULL) {
3139: if (compareFileMem(err, testErrors, testErrorsSize)) {
3140: fprintf(stderr, "Error for %s on %s failed\n", filename, sch);
3141: ret = 1;
3142: printf("%s", testErrors);
3143: }
3144: }
3145:
3146:
3147: xmlRelaxNGFreeValidCtxt(ctxt);
3148: xmlFreeDoc(doc);
3149: return(ret);
3150: }
3151: /**
3152: * rngTest:
3153: * @filename: the schemas file
3154: * @result: the file with expected result
3155: * @err: the file with error messages
3156: *
3157: * Parse an RNG schemas and then apply it to the related .xml
3158: *
3159: * Returns 0 in case of success, an error code otherwise
3160: */
3161: static int
3162: rngTest(const char *filename,
3163: const char *resul ATTRIBUTE_UNUSED,
3164: const char *errr ATTRIBUTE_UNUSED,
3165: int options) {
3166: const char *base = baseFilename(filename);
3167: const char *base2;
3168: const char *instance;
3169: xmlRelaxNGParserCtxtPtr ctxt;
3170: xmlRelaxNGPtr schemas;
3171: int res = 0, len, ret = 0;
3172: char pattern[500];
3173: char prefix[500];
3174: char result[500];
3175: char err[500];
3176: glob_t globbuf;
3177: size_t i;
3178: char count = 0;
3179:
3180: /* first compile the schemas if possible */
3181: ctxt = xmlRelaxNGNewParserCtxt(filename);
3182: xmlRelaxNGSetParserErrors(ctxt,
3183: (xmlRelaxNGValidityErrorFunc) testErrorHandler,
3184: (xmlRelaxNGValidityWarningFunc) testErrorHandler,
3185: ctxt);
3186: schemas = xmlRelaxNGParse(ctxt);
3187: xmlRelaxNGFreeParserCtxt(ctxt);
3188:
3189: /*
3190: * most of the mess is about the output filenames generated by the Makefile
3191: */
3192: len = strlen(base);
3193: if ((len > 499) || (len < 5)) {
3194: xmlRelaxNGFree(schemas);
3195: return(-1);
3196: }
3197: len -= 4; /* remove trailing .rng */
3198: memcpy(prefix, base, len);
3199: prefix[len] = 0;
3200:
3201: snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3202: pattern[499] = 0;
3203:
3204: globbuf.gl_offs = 0;
3205: glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3206: for (i = 0;i < globbuf.gl_pathc;i++) {
3207: testErrorsSize = 0;
3208: testErrors[0] = 0;
3209: instance = globbuf.gl_pathv[i];
3210: base2 = baseFilename(instance);
3211: len = strlen(base2);
3212: if ((len > 6) && (base2[len - 6] == '_')) {
3213: count = base2[len - 5];
3214: snprintf(result, 499, "result/relaxng/%s_%c",
3215: prefix, count);
3216: result[499] = 0;
3217: snprintf(err, 499, "result/relaxng/%s_%c.err",
3218: prefix, count);
3219: err[499] = 0;
3220: } else {
3221: fprintf(stderr, "don't know how to process %s\n", instance);
3222: continue;
3223: }
3224: if (schemas == NULL) {
3225: } else {
3226: nb_tests++;
3227: ret = rngOneTest(filename, instance, result, err,
3228: options, schemas);
3229: if (res != 0)
3230: ret = res;
3231: }
3232: }
3233: globfree(&globbuf);
3234: xmlRelaxNGFree(schemas);
3235:
3236: return(ret);
3237: }
3238:
3239: #ifdef LIBXML_READER_ENABLED
3240: /**
3241: * rngStreamTest:
3242: * @filename: the schemas file
3243: * @result: the file with expected result
3244: * @err: the file with error messages
3245: *
3246: * Parse a set of files with streaming, applying an RNG schemas
3247: *
3248: * Returns 0 in case of success, an error code otherwise
3249: */
3250: static int
3251: rngStreamTest(const char *filename,
3252: const char *resul ATTRIBUTE_UNUSED,
3253: const char *errr ATTRIBUTE_UNUSED,
3254: int options) {
3255: const char *base = baseFilename(filename);
3256: const char *base2;
3257: const char *instance;
3258: int res = 0, len, ret;
3259: char pattern[500];
3260: char prefix[500];
3261: char result[500];
3262: char err[500];
3263: glob_t globbuf;
3264: size_t i;
3265: char count = 0;
3266: xmlTextReaderPtr reader;
3267: int disable_err = 0;
3268:
3269: /*
3270: * most of the mess is about the output filenames generated by the Makefile
3271: */
3272: len = strlen(base);
3273: if ((len > 499) || (len < 5)) {
3274: fprintf(stderr, "len(base) == %d !\n", len);
3275: return(-1);
3276: }
3277: len -= 4; /* remove trailing .rng */
3278: memcpy(prefix, base, len);
3279: prefix[len] = 0;
3280:
3281: /*
3282: * strictly unifying the error messages is nearly impossible this
3283: * hack is also done in the Makefile
3284: */
3285: if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) ||
3286: (!strcmp(prefix, "tutor3_2")) || (!strcmp(prefix, "307377")) ||
3287: (!strcmp(prefix, "tutor8_2")))
3288: disable_err = 1;
3289:
3290: snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix);
3291: pattern[499] = 0;
3292:
3293: globbuf.gl_offs = 0;
3294: glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
3295: for (i = 0;i < globbuf.gl_pathc;i++) {
3296: testErrorsSize = 0;
3297: testErrors[0] = 0;
3298: instance = globbuf.gl_pathv[i];
3299: base2 = baseFilename(instance);
3300: len = strlen(base2);
3301: if ((len > 6) && (base2[len - 6] == '_')) {
3302: count = base2[len - 5];
3303: snprintf(result, 499, "result/relaxng/%s_%c",
3304: prefix, count);
3305: result[499] = 0;
3306: snprintf(err, 499, "result/relaxng/%s_%c.err",
3307: prefix, count);
3308: err[499] = 0;
3309: } else {
3310: fprintf(stderr, "don't know how to process %s\n", instance);
3311: continue;
3312: }
3313: reader = xmlReaderForFile(instance, NULL, options);
3314: if (reader == NULL) {
3315: fprintf(stderr, "Failed to build reder for %s\n", instance);
3316: }
3317: if (disable_err == 1)
3318: ret = streamProcessTest(instance, result, NULL, reader, filename);
3319: else
3320: ret = streamProcessTest(instance, result, err, reader, filename);
3321: xmlFreeTextReader(reader);
3322: if (ret != 0) {
3323: fprintf(stderr, "instance %s failed\n", instance);
3324: res = ret;
3325: }
3326: }
3327: globfree(&globbuf);
3328:
3329: return(res);
3330: }
3331: #endif /* READER */
3332:
3333: #endif
3334:
3335: #ifdef LIBXML_PATTERN_ENABLED
3336: #ifdef LIBXML_READER_ENABLED
3337: /************************************************************************
3338: * *
3339: * Patterns tests *
3340: * *
3341: ************************************************************************/
3342: static void patternNode(FILE *out, xmlTextReaderPtr reader,
3343: const char *pattern, xmlPatternPtr patternc,
3344: xmlStreamCtxtPtr patstream) {
3345: xmlChar *path = NULL;
3346: int match = -1;
3347: int type, empty;
3348:
3349: type = xmlTextReaderNodeType(reader);
3350: empty = xmlTextReaderIsEmptyElement(reader);
3351:
3352: if (type == XML_READER_TYPE_ELEMENT) {
3353: /* do the check only on element start */
3354: match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader));
3355:
3356: if (match) {
3357: path = xmlGetNodePath(xmlTextReaderCurrentNode(reader));
3358: fprintf(out, "Node %s matches pattern %s\n", path, pattern);
3359: }
3360: }
3361: if (patstream != NULL) {
3362: int ret;
3363:
3364: if (type == XML_READER_TYPE_ELEMENT) {
3365: ret = xmlStreamPush(patstream,
3366: xmlTextReaderConstLocalName(reader),
3367: xmlTextReaderConstNamespaceUri(reader));
3368: if (ret < 0) {
3369: fprintf(out, "xmlStreamPush() failure\n");
3370: xmlFreeStreamCtxt(patstream);
3371: patstream = NULL;
3372: } else if (ret != match) {
3373: if (path == NULL) {
3374: path = xmlGetNodePath(
3375: xmlTextReaderCurrentNode(reader));
3376: }
3377: fprintf(out,
3378: "xmlPatternMatch and xmlStreamPush disagree\n");
3379: fprintf(out,
3380: " pattern %s node %s\n",
3381: pattern, path);
3382: }
3383:
3384:
3385: }
3386: if ((type == XML_READER_TYPE_END_ELEMENT) ||
3387: ((type == XML_READER_TYPE_ELEMENT) && (empty))) {
3388: ret = xmlStreamPop(patstream);
3389: if (ret < 0) {
3390: fprintf(out, "xmlStreamPop() failure\n");
3391: xmlFreeStreamCtxt(patstream);
3392: patstream = NULL;
3393: }
3394: }
3395: }
3396: if (path != NULL)
3397: xmlFree(path);
3398: }
3399:
3400: /**
3401: * patternTest:
3402: * @filename: the schemas file
3403: * @result: the file with expected result
3404: * @err: the file with error messages
3405: *
3406: * Parse a set of files with streaming, applying an RNG schemas
3407: *
3408: * Returns 0 in case of success, an error code otherwise
3409: */
3410: static int
3411: patternTest(const char *filename,
3412: const char *resul ATTRIBUTE_UNUSED,
3413: const char *err ATTRIBUTE_UNUSED,
3414: int options) {
3415: xmlPatternPtr patternc = NULL;
3416: xmlStreamCtxtPtr patstream = NULL;
3417: FILE *o, *f;
3418: char str[1024];
3419: char xml[500];
3420: char result[500];
3421: int len, i;
3422: int ret = 0, res;
3423: char *temp;
3424: xmlTextReaderPtr reader;
3425: xmlDocPtr doc;
3426:
3427: len = strlen(filename);
3428: len -= 4;
3429: memcpy(xml, filename, len);
3430: xml[len] = 0;
3431: snprintf(result, 499, "result/pattern/%s", baseFilename(xml));
3432: result[499] = 0;
3433: memcpy(xml + len, ".xml", 5);
3434:
3435: if (!checkTestFile(xml)) {
3436: fprintf(stderr, "Missing xml file %s\n", xml);
3437: return(-1);
3438: }
3439: if (!checkTestFile(result)) {
3440: fprintf(stderr, "Missing result file %s\n", result);
3441: return(-1);
3442: }
3443: f = fopen(filename, "rb");
3444: if (f == NULL) {
3445: fprintf(stderr, "Failed to open %s\n", filename);
3446: return(-1);
3447: }
3448: temp = resultFilename(filename, "", ".res");
3449: if (temp == NULL) {
3450: fprintf(stderr, "Out of memory\n");
3451: fatalError();
3452: }
3453: o = fopen(temp, "wb");
3454: if (o == NULL) {
3455: fprintf(stderr, "failed to open output file %s\n", temp);
3456: fclose(f);
3457: free(temp);
3458: return(-1);
3459: }
3460: while (1) {
3461: /*
3462: * read one line in string buffer.
3463: */
3464: if (fgets (&str[0], sizeof (str) - 1, f) == NULL)
3465: break;
3466:
3467: /*
3468: * remove the ending spaces
3469: */
3470: i = strlen(str);
3471: while ((i > 0) &&
3472: ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
3473: (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
3474: i--;
3475: str[i] = 0;
3476: }
3477: doc = xmlReadFile(xml, NULL, options);
3478: if (doc == NULL) {
3479: fprintf(stderr, "Failed to parse %s\n", xml);
3480: ret = 1;
3481: } else {
3482: xmlNodePtr root;
3483: const xmlChar *namespaces[22];
3484: int j;
3485: xmlNsPtr ns;
3486:
3487: root = xmlDocGetRootElement(doc);
3488: for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) {
3489: namespaces[j++] = ns->href;
3490: namespaces[j++] = ns->prefix;
3491: }
3492: namespaces[j++] = NULL;
3493: namespaces[j] = NULL;
3494:
3495: patternc = xmlPatterncompile((const xmlChar *) str, doc->dict,
3496: 0, &namespaces[0]);
3497: if (patternc == NULL) {
3498: testErrorHandler(NULL,
3499: "Pattern %s failed to compile\n", str);
3500: xmlFreeDoc(doc);
3501: ret = 1;
3502: continue;
3503: }
3504: patstream = xmlPatternGetStreamCtxt(patternc);
3505: if (patstream != NULL) {
3506: ret = xmlStreamPush(patstream, NULL, NULL);
3507: if (ret < 0) {
3508: fprintf(stderr, "xmlStreamPush() failure\n");
3509: xmlFreeStreamCtxt(patstream);
3510: patstream = NULL;
3511: }
3512: }
3513: nb_tests++;
3514:
3515: reader = xmlReaderWalker(doc);
3516: res = xmlTextReaderRead(reader);
3517: while (res == 1) {
3518: patternNode(o, reader, str, patternc, patstream);
3519: res = xmlTextReaderRead(reader);
3520: }
3521: if (res != 0) {
3522: fprintf(o, "%s : failed to parse\n", filename);
3523: }
3524: xmlFreeTextReader(reader);
3525: xmlFreeDoc(doc);
3526: xmlFreeStreamCtxt(patstream);
3527: patstream = NULL;
3528: xmlFreePattern(patternc);
3529:
3530: }
3531: }
3532:
3533: fclose(f);
3534: fclose(o);
3535:
3536: ret = compareFiles(temp, result);
3537: if (ret) {
3538: fprintf(stderr, "Result for %s failed\n", filename);
3539: ret = 1;
3540: }
3541: if (temp != NULL) {
3542: unlink(temp);
3543: free(temp);
3544: }
3545: return(ret);
3546: }
3547: #endif /* READER */
3548: #endif /* PATTERN */
3549: #ifdef LIBXML_C14N_ENABLED
3550: /************************************************************************
3551: * *
3552: * Canonicalization tests *
3553: * *
3554: ************************************************************************/
3555: static xmlXPathObjectPtr
3556: load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
3557: xmlXPathObjectPtr xpath;
3558: xmlDocPtr doc;
3559: xmlChar *expr;
3560: xmlXPathContextPtr ctx;
3561: xmlNodePtr node;
3562: xmlNsPtr ns;
3563:
3564: /*
3565: * load XPath expr as a file
3566: */
3567: xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3568: xmlSubstituteEntitiesDefault(1);
3569:
3570: doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3571: if (doc == NULL) {
3572: fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
3573: return(NULL);
3574: }
3575:
3576: /*
3577: * Check the document is of the right kind
3578: */
3579: if(xmlDocGetRootElement(doc) == NULL) {
3580: fprintf(stderr,"Error: empty document for file \"%s\"\n", filename);
3581: xmlFreeDoc(doc);
3582: return(NULL);
3583: }
3584:
3585: node = doc->children;
3586: while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) {
3587: node = node->next;
3588: }
3589:
3590: if(node == NULL) {
3591: fprintf(stderr,"Error: XPath element expected in the file \"%s\"\n", filename);
3592: xmlFreeDoc(doc);
3593: return(NULL);
3594: }
3595:
3596: expr = xmlNodeGetContent(node);
3597: if(expr == NULL) {
3598: fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename);
3599: xmlFreeDoc(doc);
3600: return(NULL);
3601: }
3602:
3603: ctx = xmlXPathNewContext(parent_doc);
3604: if(ctx == NULL) {
3605: fprintf(stderr,"Error: unable to create new context\n");
3606: xmlFree(expr);
3607: xmlFreeDoc(doc);
3608: return(NULL);
3609: }
3610:
3611: /*
3612: * Register namespaces
3613: */
3614: ns = node->nsDef;
3615: while(ns != NULL) {
3616: if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) {
3617: fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href);
3618: xmlFree(expr);
3619: xmlXPathFreeContext(ctx);
3620: xmlFreeDoc(doc);
3621: return(NULL);
3622: }
3623: ns = ns->next;
3624: }
3625:
3626: /*
3627: * Evaluate xpath
3628: */
3629: xpath = xmlXPathEvalExpression(expr, ctx);
3630: if(xpath == NULL) {
3631: fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3632: xmlFree(expr);
3633: xmlXPathFreeContext(ctx);
3634: xmlFreeDoc(doc);
3635: return(NULL);
3636: }
3637:
3638: /* print_xpath_nodes(xpath->nodesetval); */
3639:
3640: xmlFree(expr);
3641: xmlXPathFreeContext(ctx);
3642: xmlFreeDoc(doc);
3643: return(xpath);
3644: }
3645:
3646: /*
3647: * Macro used to grow the current buffer.
3648: */
3649: #define xxx_growBufferReentrant() { \
3650: buffer_size *= 2; \
3651: buffer = (xmlChar **) \
3652: xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \
3653: if (buffer == NULL) { \
3654: perror("realloc failed"); \
3655: return(NULL); \
3656: } \
3657: }
3658:
3659: static xmlChar **
3660: parse_list(xmlChar *str) {
3661: xmlChar **buffer;
3662: xmlChar **out = NULL;
3663: int buffer_size = 0;
3664: int len;
3665:
3666: if(str == NULL) {
3667: return(NULL);
3668: }
3669:
3670: len = xmlStrlen(str);
3671: if((str[0] == '\'') && (str[len - 1] == '\'')) {
3672: str[len - 1] = '\0';
3673: str++;
3674: }
3675: /*
3676: * allocate an translation buffer.
3677: */
3678: buffer_size = 1000;
3679: buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*));
3680: if (buffer == NULL) {
3681: perror("malloc failed");
3682: return(NULL);
3683: }
3684: out = buffer;
3685:
3686: while(*str != '\0') {
3687: if (out - buffer > buffer_size - 10) {
3688: int indx = out - buffer;
3689:
3690: xxx_growBufferReentrant();
3691: out = &buffer[indx];
3692: }
3693: (*out++) = str;
3694: while(*str != ',' && *str != '\0') ++str;
3695: if(*str == ',') *(str++) = '\0';
3696: }
3697: (*out) = NULL;
3698: return buffer;
3699: }
3700:
3701: static int
3702: c14nRunTest(const char* xml_filename, int with_comments, int mode,
3703: const char* xpath_filename, const char *ns_filename,
3704: const char* result_file) {
3705: xmlDocPtr doc;
3706: xmlXPathObjectPtr xpath = NULL;
3707: xmlChar *result = NULL;
3708: int ret;
3709: xmlChar **inclusive_namespaces = NULL;
3710: const char *nslist = NULL;
3711: int nssize;
3712:
3713:
3714: /*
3715: * build an XML tree from a the file; we need to add default
3716: * attributes and resolve all character and entities references
3717: */
3718: xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
3719: xmlSubstituteEntitiesDefault(1);
3720:
3721: doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT);
3722: if (doc == NULL) {
3723: fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename);
3724: return(-1);
3725: }
3726:
3727: /*
3728: * Check the document is of the right kind
3729: */
3730: if(xmlDocGetRootElement(doc) == NULL) {
3731: fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename);
3732: xmlFreeDoc(doc);
3733: return(-1);
3734: }
3735:
3736: /*
3737: * load xpath file if specified
3738: */
3739: if(xpath_filename) {
3740: xpath = load_xpath_expr(doc, xpath_filename);
3741: if(xpath == NULL) {
3742: fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3743: xmlFreeDoc(doc);
3744: return(-1);
3745: }
3746: }
3747:
3748: if (ns_filename != NULL) {
3749: if (loadMem(ns_filename, &nslist, &nssize)) {
3750: fprintf(stderr,"Error: unable to evaluate xpath expression\n");
3751: if(xpath != NULL) xmlXPathFreeObject(xpath);
3752: xmlFreeDoc(doc);
3753: return(-1);
3754: }
3755: inclusive_namespaces = parse_list((xmlChar *) nslist);
3756: }
3757:
3758: /*
3759: * Canonical form
3760: */
3761: /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
3762: ret = xmlC14NDocDumpMemory(doc,
3763: (xpath) ? xpath->nodesetval : NULL,
3764: mode, inclusive_namespaces,
3765: with_comments, &result);
3766: if (ret >= 0) {
3767: if(result != NULL) {
3768: if (compareFileMem(result_file, (const char *) result, ret)) {
3769: fprintf(stderr, "Result mismatch for %s\n", xml_filename);
3770: fprintf(stderr, "RESULT:\n%s\n", (const char*)result);
3771: ret = -1;
3772: }
3773: }
3774: } else {
3775: fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret);
3776: ret = -1;
3777: }
3778:
3779: /*
3780: * Cleanup
3781: */
3782: if (result != NULL) xmlFree(result);
3783: if(xpath != NULL) xmlXPathFreeObject(xpath);
3784: if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces);
3785: if (nslist != NULL) free((char *) nslist);
3786: xmlFreeDoc(doc);
3787:
3788: return(ret);
3789: }
3790:
3791: static int
3792: c14nCommonTest(const char *filename, int with_comments, int mode,
3793: const char *subdir) {
3794: char buf[500];
3795: char prefix[500];
3796: const char *base;
3797: int len;
3798: char *result = NULL;
3799: char *xpath = NULL;
3800: char *ns = NULL;
3801: int ret = 0;
3802:
3803: base = baseFilename(filename);
3804: len = strlen(base);
3805: len -= 4;
3806: memcpy(prefix, base, len);
3807: prefix[len] = 0;
3808:
3809: snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix);
3810: if (!checkTestFile(buf)) {
3811: fprintf(stderr, "Missing result file %s", buf);
3812: return(-1);
3813: }
3814: result = strdup(buf);
3815: snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix);
3816: if (checkTestFile(buf)) {
3817: xpath = strdup(buf);
3818: }
3819: snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix);
3820: if (checkTestFile(buf)) {
3821: ns = strdup(buf);
3822: }
3823:
3824: nb_tests++;
3825: if (c14nRunTest(filename, with_comments, mode,
3826: xpath, ns, result) < 0)
3827: ret = 1;
3828:
3829: if (result != NULL) free(result);
3830: if (xpath != NULL) free(xpath);
3831: if (ns != NULL) free(ns);
3832: return(ret);
3833: }
3834:
3835: static int
3836: c14nWithCommentTest(const char *filename,
3837: const char *resul ATTRIBUTE_UNUSED,
3838: const char *err ATTRIBUTE_UNUSED,
3839: int options ATTRIBUTE_UNUSED) {
3840: return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments"));
3841: }
3842: static int
3843: c14nWithoutCommentTest(const char *filename,
3844: const char *resul ATTRIBUTE_UNUSED,
3845: const char *err ATTRIBUTE_UNUSED,
3846: int options ATTRIBUTE_UNUSED) {
3847: return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments"));
3848: }
3849: static int
3850: c14nExcWithoutCommentTest(const char *filename,
3851: const char *resul ATTRIBUTE_UNUSED,
3852: const char *err ATTRIBUTE_UNUSED,
3853: int options ATTRIBUTE_UNUSED) {
3854: return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments"));
3855: }
3856: static int
3857: c14n11WithoutCommentTest(const char *filename,
3858: const char *resul ATTRIBUTE_UNUSED,
3859: const char *err ATTRIBUTE_UNUSED,
3860: int options ATTRIBUTE_UNUSED) {
3861: return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments"));
3862: }
3863: #endif
3864: #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined (LIBXML_SAX1_ENABLED)
3865: /************************************************************************
3866: * *
3867: * Catalog and threads test *
3868: * *
3869: ************************************************************************/
3870:
3871: /*
3872: * mostly a cut and paste from testThreads.c
3873: */
3874: #define MAX_ARGC 20
3875:
3876: static const char *catalog = "test/threads/complex.xml";
3877: static const char *testfiles[] = {
3878: "test/threads/abc.xml",
3879: "test/threads/acb.xml",
3880: "test/threads/bac.xml",
3881: "test/threads/bca.xml",
3882: "test/threads/cab.xml",
3883: "test/threads/cba.xml",
3884: "test/threads/invalid.xml",
3885: };
3886:
3887: static const char *Okay = "OK";
3888: static const char *Failed = "Failed";
3889:
3890: #ifndef xmlDoValidityCheckingDefaultValue
3891: #error xmlDoValidityCheckingDefaultValue is not a macro
3892: #endif
3893: #ifndef xmlGenericErrorContext
3894: #error xmlGenericErrorContext is not a macro
3895: #endif
3896:
3897: static void *
3898: thread_specific_data(void *private_data)
3899: {
3900: xmlDocPtr myDoc;
3901: const char *filename = (const char *) private_data;
3902: int okay = 1;
3903:
3904: if (!strcmp(filename, "test/threads/invalid.xml")) {
3905: xmlDoValidityCheckingDefaultValue = 0;
3906: xmlGenericErrorContext = stdout;
3907: } else {
3908: xmlDoValidityCheckingDefaultValue = 1;
3909: xmlGenericErrorContext = stderr;
3910: }
3911: myDoc = xmlParseFile(filename);
3912: if (myDoc) {
3913: xmlFreeDoc(myDoc);
3914: } else {
3915: printf("parse failed\n");
3916: okay = 0;
3917: }
3918: if (!strcmp(filename, "test/threads/invalid.xml")) {
3919: if (xmlDoValidityCheckingDefaultValue != 0) {
3920: printf("ValidityCheckingDefaultValue override failed\n");
3921: okay = 0;
3922: }
3923: if (xmlGenericErrorContext != stdout) {
3924: printf("xmlGenericErrorContext override failed\n");
3925: okay = 0;
3926: }
3927: } else {
3928: if (xmlDoValidityCheckingDefaultValue != 1) {
3929: printf("ValidityCheckingDefaultValue override failed\n");
3930: okay = 0;
3931: }
3932: if (xmlGenericErrorContext != stderr) {
3933: printf("xmlGenericErrorContext override failed\n");
3934: okay = 0;
3935: }
3936: }
3937: if (okay == 0)
3938: return ((void *) Failed);
3939: return ((void *) Okay);
3940: }
3941:
3942: #if defined(linux) || defined(__sun) || defined(__APPLE_CC__)
3943:
3944: #include <pthread.h>
3945:
3946: static pthread_t tid[MAX_ARGC];
3947:
3948: static int
3949: testThread(void)
3950: {
3951: unsigned int i, repeat;
3952: unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
3953: void *results[MAX_ARGC];
3954: int ret;
3955: int res = 0;
3956:
3957: xmlInitParser();
3958:
3959: for (repeat = 0; repeat < 500; repeat++) {
3960: xmlLoadCatalog(catalog);
3961: nb_tests++;
3962:
3963: for (i = 0; i < num_threads; i++) {
3964: results[i] = NULL;
3965: tid[i] = (pthread_t) - 1;
3966: }
3967:
3968: for (i = 0; i < num_threads; i++) {
3969: ret = pthread_create(&tid[i], 0, thread_specific_data,
3970: (void *) testfiles[i]);
3971: if (ret != 0) {
3972: fprintf(stderr, "pthread_create failed\n");
3973: return (1);
3974: }
3975: }
3976: for (i = 0; i < num_threads; i++) {
3977: ret = pthread_join(tid[i], &results[i]);
3978: if (ret != 0) {
3979: fprintf(stderr, "pthread_join failed\n");
3980: return (1);
3981: }
3982: }
3983:
3984: xmlCatalogCleanup();
3985: for (i = 0; i < num_threads; i++)
3986: if (results[i] != (void *) Okay) {
3987: fprintf(stderr, "Thread %d handling %s failed\n",
3988: i, testfiles[i]);
3989: res = 1;
3990: }
3991: }
3992: return (res);
3993: }
3994:
3995: #elif defined WIN32
3996: #include <windows.h>
3997: #include <string.h>
3998:
3999: #define TEST_REPEAT_COUNT 500
4000:
4001: static HANDLE tid[MAX_ARGC];
4002:
4003: static DWORD WINAPI
4004: win32_thread_specific_data(void *private_data)
4005: {
4006: return((DWORD) thread_specific_data(private_data));
4007: }
4008:
4009: static int
4010: testThread(void)
4011: {
4012: unsigned int i, repeat;
4013: unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4014: DWORD results[MAX_ARGC];
4015: BOOL ret;
4016: int res = 0;
4017:
4018: xmlInitParser();
4019: for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) {
4020: xmlLoadCatalog(catalog);
4021: nb_tests++;
4022:
4023: for (i = 0; i < num_threads; i++) {
4024: results[i] = 0;
4025: tid[i] = (HANDLE) - 1;
4026: }
4027:
4028: for (i = 0; i < num_threads; i++) {
4029: DWORD useless;
4030:
4031: tid[i] = CreateThread(NULL, 0,
4032: win32_thread_specific_data,
4033: (void *) testfiles[i], 0,
4034: &useless);
4035: if (tid[i] == NULL) {
4036: fprintf(stderr, "CreateThread failed\n");
4037: return(1);
4038: }
4039: }
4040:
4041: if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) ==
4042: WAIT_FAILED) {
4043: fprintf(stderr, "WaitForMultipleObjects failed\n");
4044: return(1);
4045: }
4046:
4047: for (i = 0; i < num_threads; i++) {
4048: ret = GetExitCodeThread(tid[i], &results[i]);
4049: if (ret == 0) {
4050: fprintf(stderr, "GetExitCodeThread failed\n");
4051: return(1);
4052: }
4053: CloseHandle(tid[i]);
4054: }
4055:
4056: xmlCatalogCleanup();
4057: for (i = 0; i < num_threads; i++) {
4058: if (results[i] != (DWORD) Okay) {
4059: fprintf(stderr, "Thread %d handling %s failed\n",
4060: i, testfiles[i]);
4061: res = 1;
4062: }
4063: }
4064: }
4065:
4066: return (res);
4067: }
4068:
4069: #elif defined __BEOS__
4070: #include <OS.h>
4071:
4072: static thread_id tid[MAX_ARGC];
4073:
4074: static int
4075: testThread(void)
4076: {
4077: unsigned int i, repeat;
4078: unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]);
4079: void *results[MAX_ARGC];
4080: status_t ret;
4081: int res = 0;
4082:
4083: xmlInitParser();
4084: for (repeat = 0; repeat < 500; repeat++) {
4085: xmlLoadCatalog(catalog);
4086: for (i = 0; i < num_threads; i++) {
4087: results[i] = NULL;
4088: tid[i] = (thread_id) - 1;
4089: }
4090: for (i = 0; i < num_threads; i++) {
4091: tid[i] =
4092: spawn_thread(thread_specific_data, "xmlTestThread",
4093: B_NORMAL_PRIORITY, (void *) testfiles[i]);
4094: if (tid[i] < B_OK) {
4095: fprintf(stderr, "beos_thread_create failed\n");
4096: return (1);
4097: }
4098: printf("beos_thread_create %d -> %d\n", i, tid[i]);
4099: }
4100: for (i = 0; i < num_threads; i++) {
4101: ret = wait_for_thread(tid[i], &results[i]);
4102: printf("beos_thread_wait %d -> %d\n", i, ret);
4103: if (ret != B_OK) {
4104: fprintf(stderr, "beos_thread_wait failed\n");
4105: return (1);
4106: }
4107: }
4108:
4109: xmlCatalogCleanup();
4110: ret = B_OK;
4111: for (i = 0; i < num_threads; i++)
4112: if (results[i] != (void *) Okay) {
4113: printf("Thread %d handling %s failed\n", i, testfiles[i]);
4114: ret = B_ERROR;
4115: }
4116: }
4117: if (ret != B_OK)
4118: return(1);
4119: return (0);
4120: }
4121: #else
4122: static int
4123: testThread(void)
4124: {
4125: fprintf(stderr,
4126: "Specific platform thread support not detected\n");
4127: return (-1);
4128: }
4129: #endif
4130: static int
4131: threadsTest(const char *filename ATTRIBUTE_UNUSED,
4132: const char *resul ATTRIBUTE_UNUSED,
4133: const char *err ATTRIBUTE_UNUSED,
4134: int options ATTRIBUTE_UNUSED) {
4135: return(testThread());
4136: }
4137: #endif
4138: /************************************************************************
4139: * *
4140: * Tests Descriptions *
4141: * *
4142: ************************************************************************/
4143:
4144: static
4145: testDesc testDescriptions[] = {
4146: { "XML regression tests" ,
4147: oldParseTest, "./test/*", "result/", "", NULL,
4148: 0 },
4149: { "XML regression tests on memory" ,
4150: memParseTest, "./test/*", "result/", "", NULL,
4151: 0 },
4152: { "XML entity subst regression tests" ,
4153: noentParseTest, "./test/*", "result/noent/", "", NULL,
4154: XML_PARSE_NOENT },
4155: { "XML Namespaces regression tests",
4156: errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err",
4157: 0 },
4158: { "Error cases regression tests",
4159: errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err",
4160: 0 },
4161: #ifdef LIBXML_READER_ENABLED
4162: { "Error cases stream regression tests",
4163: streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str",
4164: 0 },
4165: { "Reader regression tests",
4166: streamParseTest, "./test/*", "result/", ".rdr", NULL,
4167: 0 },
4168: { "Reader entities substitution regression tests",
4169: streamParseTest, "./test/*", "result/", ".rde", NULL,
4170: XML_PARSE_NOENT },
4171: { "Reader on memory regression tests",
4172: streamMemParseTest, "./test/*", "result/", ".rdr", NULL,
4173: 0 },
4174: { "Walker regression tests",
4175: walkerParseTest, "./test/*", "result/", ".rdr", NULL,
4176: 0 },
4177: #endif
4178: #ifdef LIBXML_SAX1_ENABLED
4179: { "SAX1 callbacks regression tests" ,
4180: saxParseTest, "./test/*", "result/", ".sax", NULL,
4181: XML_PARSE_SAX1 },
4182: { "SAX2 callbacks regression tests" ,
4183: saxParseTest, "./test/*", "result/", ".sax2", NULL,
4184: 0 },
4185: #endif
4186: #ifdef LIBXML_PUSH_ENABLED
4187: { "XML push regression tests" ,
4188: pushParseTest, "./test/*", "result/", "", NULL,
4189: 0 },
4190: #endif
4191: #ifdef LIBXML_HTML_ENABLED
4192: { "HTML regression tests" ,
4193: errParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4194: XML_PARSE_HTML },
4195: #ifdef LIBXML_PUSH_ENABLED
4196: { "Push HTML regression tests" ,
4197: pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err",
4198: XML_PARSE_HTML },
4199: #endif
4200: #ifdef LIBXML_SAX1_ENABLED
4201: { "HTML SAX regression tests" ,
4202: saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL,
4203: XML_PARSE_HTML },
4204: #endif
4205: #endif
4206: #ifdef LIBXML_VALID_ENABLED
4207: { "Valid documents regression tests" ,
4208: errParseTest, "./test/VCM/*", NULL, NULL, NULL,
4209: XML_PARSE_DTDVALID },
4210: { "Validity checking regression tests" ,
4211: errParseTest, "./test/VC/*", "result/VC/", NULL, "",
4212: XML_PARSE_DTDVALID },
4213: { "General documents valid regression tests" ,
4214: errParseTest, "./test/valid/*", "result/valid/", "", ".err",
4215: XML_PARSE_DTDVALID },
4216: #endif
4217: #ifdef LIBXML_XINCLUDE_ENABLED
4218: { "XInclude regression tests" ,
4219: errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4220: /* Ignore errors at this point ".err", */
4221: XML_PARSE_XINCLUDE },
4222: #ifdef LIBXML_READER_ENABLED
4223: { "XInclude xmlReader regression tests",
4224: streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4225: /* Ignore errors at this point ".err", */
4226: NULL, XML_PARSE_XINCLUDE },
4227: #endif
4228: { "XInclude regression tests stripping include nodes" ,
4229: errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL,
4230: /* Ignore errors at this point ".err", */
4231: XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4232: #ifdef LIBXML_READER_ENABLED
4233: { "XInclude xmlReader regression tests stripping include nodes",
4234: streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr",
4235: /* Ignore errors at this point ".err", */
4236: NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE },
4237: #endif
4238: #endif
4239: #ifdef LIBXML_XPATH_ENABLED
4240: #ifdef LIBXML_DEBUG_ENABLED
4241: { "XPath expressions regression tests" ,
4242: xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL,
4243: 0 },
4244: { "XPath document queries regression tests" ,
4245: xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4246: 0 },
4247: #ifdef LIBXML_XPTR_ENABLED
4248: { "XPointer document queries regression tests" ,
4249: xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL,
4250: 0 },
4251: #endif
4252: { "xml:id regression tests" ,
4253: xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err",
4254: 0 },
4255: #endif
4256: #endif
4257: { "URI parsing tests" ,
4258: uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL,
4259: 0 },
4260: { "URI base composition tests" ,
4261: uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL,
4262: 0 },
4263: { "Path URI conversion tests" ,
4264: uriPathTest, NULL, NULL, NULL, NULL,
4265: 0 },
4266: #ifdef LIBXML_SCHEMAS_ENABLED
4267: { "Schemas regression tests" ,
4268: schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL,
4269: 0 },
4270: { "Relax-NG regression tests" ,
4271: rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4272: XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4273: #ifdef LIBXML_READER_ENABLED
4274: { "Relax-NG streaming regression tests" ,
4275: rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
4276: XML_PARSE_DTDATTR | XML_PARSE_NOENT },
4277: #endif
4278: #endif
4279: #ifdef LIBXML_PATTERN_ENABLED
4280: #ifdef LIBXML_READER_ENABLED
4281: { "Pattern regression tests" ,
4282: patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL,
4283: 0 },
4284: #endif
4285: #endif
4286: #ifdef LIBXML_C14N_ENABLED
4287: { "C14N with comments regression tests" ,
4288: c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL,
4289: 0 },
4290: { "C14N without comments regression tests" ,
4291: c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL,
4292: 0 },
4293: { "C14N exclusive without comments regression tests" ,
4294: c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
4295: 0 },
4296: { "C14N 1.1 without comments regression tests" ,
4297: c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL,
4298: 0 },
4299: #endif
4300: #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_SAX1_ENABLED)
4301: { "Catalog and Threads regression tests" ,
4302: threadsTest, NULL, NULL, NULL, NULL,
4303: 0 },
4304: #endif
4305: {NULL, NULL, NULL, NULL, NULL, NULL, 0}
4306: };
4307:
4308: /************************************************************************
4309: * *
4310: * The main code driving the tests *
4311: * *
4312: ************************************************************************/
4313:
4314: static int
4315: launchTests(testDescPtr tst) {
4316: int res = 0, err = 0;
4317: size_t i;
4318: char *result;
4319: char *error;
4320: int mem;
4321:
4322: if (tst == NULL) return(-1);
4323: if (tst->in != NULL) {
4324: glob_t globbuf;
4325:
4326: globbuf.gl_offs = 0;
4327: glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
4328: for (i = 0;i < globbuf.gl_pathc;i++) {
4329: if (!checkTestFile(globbuf.gl_pathv[i]))
4330: continue;
4331: if (tst->suffix != NULL) {
4332: result = resultFilename(globbuf.gl_pathv[i], tst->out,
4333: tst->suffix);
4334: if (result == NULL) {
4335: fprintf(stderr, "Out of memory !\n");
4336: fatalError();
4337: }
4338: } else {
4339: result = NULL;
4340: }
4341: if (tst->err != NULL) {
4342: error = resultFilename(globbuf.gl_pathv[i], tst->out,
4343: tst->err);
4344: if (error == NULL) {
4345: fprintf(stderr, "Out of memory !\n");
4346: fatalError();
4347: }
4348: } else {
4349: error = NULL;
4350: }
4351: if ((result) &&(!checkTestFile(result))) {
4352: fprintf(stderr, "Missing result file %s\n", result);
4353: } else if ((error) &&(!checkTestFile(error))) {
4354: fprintf(stderr, "Missing error file %s\n", error);
4355: } else {
4356: mem = xmlMemUsed();
4357: extraMemoryFromResolver = 0;
4358: testErrorsSize = 0;
4359: testErrors[0] = 0;
4360: res = tst->func(globbuf.gl_pathv[i], result, error,
4361: tst->options | XML_PARSE_COMPACT);
4362: xmlResetLastError();
4363: if (res != 0) {
4364: fprintf(stderr, "File %s generated an error\n",
4365: globbuf.gl_pathv[i]);
4366: nb_errors++;
4367: err++;
4368: }
4369: else if (xmlMemUsed() != mem) {
4370: if ((xmlMemUsed() != mem) &&
4371: (extraMemoryFromResolver == 0)) {
4372: fprintf(stderr, "File %s leaked %d bytes\n",
4373: globbuf.gl_pathv[i], xmlMemUsed() - mem);
4374: nb_leaks++;
4375: err++;
4376: }
4377: }
4378: testErrorsSize = 0;
4379: }
4380: if (result)
4381: free(result);
4382: if (error)
4383: free(error);
4384: }
4385: globfree(&globbuf);
4386: } else {
4387: testErrorsSize = 0;
4388: testErrors[0] = 0;
4389: extraMemoryFromResolver = 0;
4390: res = tst->func(NULL, NULL, NULL, tst->options);
4391: if (res != 0) {
4392: nb_errors++;
4393: err++;
4394: }
4395: }
4396: return(err);
4397: }
4398:
4399: static int verbose = 0;
4400: static int tests_quiet = 0;
4401:
4402: static int
4403: runtest(int i) {
4404: int ret = 0, res;
4405: int old_errors, old_tests, old_leaks;
4406:
4407: old_errors = nb_errors;
4408: old_tests = nb_tests;
4409: old_leaks = nb_leaks;
4410: if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
4411: printf("## %s\n", testDescriptions[i].desc);
4412: res = launchTests(&testDescriptions[i]);
4413: if (res != 0)
4414: ret++;
4415: if (verbose) {
4416: if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
4417: printf("Ran %d tests, no errors\n", nb_tests - old_tests);
4418: else
4419: printf("Ran %d tests, %d errors, %d leaks\n",
4420: nb_tests - old_tests,
4421: nb_errors - old_errors,
4422: nb_leaks - old_leaks);
4423: }
4424: return(ret);
4425: }
4426:
4427: int
4428: main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4429: int i, a, ret = 0;
4430: int subset = 0;
4431:
4432: initializeLibxml2();
4433:
4434: for (a = 1; a < argc;a++) {
4435: if (!strcmp(argv[a], "-v"))
4436: verbose = 1;
4437: else if (!strcmp(argv[a], "-quiet"))
4438: tests_quiet = 1;
4439: else {
4440: for (i = 0; testDescriptions[i].func != NULL; i++) {
4441: if (strstr(testDescriptions[i].desc, argv[a])) {
4442: ret += runtest(i);
4443: subset++;
4444: }
4445: }
4446: }
4447: }
4448: if (subset == 0) {
4449: for (i = 0; testDescriptions[i].func != NULL; i++) {
4450: ret += runtest(i);
4451: }
4452: }
4453: if ((nb_errors == 0) && (nb_leaks == 0)) {
4454: ret = 0;
4455: printf("Total %d tests, no errors\n",
4456: nb_tests);
4457: } else {
4458: ret = 1;
4459: printf("Total %d tests, %d errors, %d leaks\n",
4460: nb_tests, nb_errors, nb_leaks);
4461: }
4462: xmlCleanupParser();
4463: xmlMemoryDump();
4464:
4465: return(ret);
4466: }
4467:
4468: #else /* ! LIBXML_OUTPUT_ENABLED */
4469: int
4470: main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
4471: fprintf(stderr, "runtest requires output to be enabled in libxml2\n");
4472: return(1);
4473: }
4474: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>