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