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