Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenruntest.c
Go to the documentation of this file.
00001 /* 00002 * runtest.c: C program to run libxml2 regression tests without 00003 * requiring make or Python, and reducing platform dependancies 00004 * to a strict minimum. 00005 * 00006 * To compile on Unixes: 00007 * cc -o runtest `xml2-config --cflags` runtest.c `xml2-config --libs` -lpthread 00008 * 00009 * See Copyright for the status of this software. 00010 * 00011 * daniel@veillard.com 00012 */ 00013 00014 #ifdef HAVE_CONFIG_H 00015 #include "libxml.h" 00016 #else 00017 #include <stdio.h> 00018 #endif 00019 00020 #if !defined(_WIN32) || defined(__CYGWIN__) 00021 #include <unistd.h> 00022 #endif 00023 #include <string.h> 00024 #include <sys/types.h> 00025 #include <sys/stat.h> 00026 #include <fcntl.h> 00027 00028 #include <libxml/parser.h> 00029 #include <libxml/tree.h> 00030 #include <libxml/uri.h> 00031 00032 #ifdef LIBXML_OUTPUT_ENABLED 00033 #ifdef LIBXML_READER_ENABLED 00034 #include <libxml/xmlreader.h> 00035 #endif 00036 00037 #ifdef LIBXML_XINCLUDE_ENABLED 00038 #include <libxml/xinclude.h> 00039 #endif 00040 00041 #ifdef LIBXML_XPATH_ENABLED 00042 #include <libxml/xpath.h> 00043 #include <libxml/xpathInternals.h> 00044 #ifdef LIBXML_XPTR_ENABLED 00045 #include <libxml/xpointer.h> 00046 #endif 00047 #endif 00048 00049 #ifdef LIBXML_SCHEMAS_ENABLED 00050 #include <libxml/relaxng.h> 00051 #include <libxml/xmlschemas.h> 00052 #include <libxml/xmlschemastypes.h> 00053 #endif 00054 00055 #ifdef LIBXML_PATTERN_ENABLED 00056 #include <libxml/pattern.h> 00057 #endif 00058 00059 #ifdef LIBXML_C14N_ENABLED 00060 #include <libxml/c14n.h> 00061 #endif 00062 00063 #ifdef LIBXML_HTML_ENABLED 00064 #include <libxml/HTMLparser.h> 00065 #include <libxml/HTMLtree.h> 00066 00067 /* 00068 * pseudo flag for the unification of HTML and XML tests 00069 */ 00070 #define XML_PARSE_HTML 1 << 24 00071 #endif 00072 00073 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) 00074 #include <libxml/globals.h> 00075 #include <libxml/threads.h> 00076 #include <libxml/parser.h> 00077 #include <libxml/catalog.h> 00078 #include <string.h> 00079 #endif 00080 00081 /* 00082 * O_BINARY is just for Windows compatibility - if it isn't defined 00083 * on this system, avoid any compilation error 00084 */ 00085 #ifdef O_BINARY 00086 #define RD_FLAGS O_RDONLY | O_BINARY 00087 #else 00088 #define RD_FLAGS O_RDONLY 00089 #endif 00090 00091 typedef int (*functest) (const char *filename, const char *result, 00092 const char *error, int options); 00093 00094 typedef struct testDesc testDesc; 00095 typedef testDesc *testDescPtr; 00096 struct testDesc { 00097 const char *desc; /* descripton of the test */ 00098 functest func; /* function implementing the test */ 00099 const char *in; /* glob to path for input files */ 00100 const char *out; /* output directory */ 00101 const char *suffix;/* suffix for output files */ 00102 const char *err; /* suffix for error output files */ 00103 int options; /* parser options for the test */ 00104 }; 00105 00106 static int checkTestFile(const char *filename); 00107 00108 #if defined(_WIN32) && !defined(__CYGWIN__) 00109 00110 #include <windows.h> 00111 #include <io.h> 00112 00113 typedef struct 00114 { 00115 size_t gl_pathc; /* Count of paths matched so far */ 00116 char **gl_pathv; /* List of matched pathnames. */ 00117 size_t gl_offs; /* Slots to reserve in 'gl_pathv'. */ 00118 } glob_t; 00119 00120 #define GLOB_DOOFFS 0 00121 static int glob(const char *pattern, int flags, 00122 int errfunc(const char *epath, int eerrno), 00123 glob_t *pglob) { 00124 glob_t *ret; 00125 WIN32_FIND_DATA FindFileData; 00126 HANDLE hFind; 00127 unsigned int nb_paths = 0; 00128 char directory[500]; 00129 int len; 00130 00131 if ((pattern == NULL) || (pglob == NULL)) return(-1); 00132 00133 strncpy(directory, pattern, 499); 00134 for (len = strlen(directory);len >= 0;len--) { 00135 if (directory[len] == '/') { 00136 len++; 00137 directory[len] = 0; 00138 break; 00139 } 00140 } 00141 if (len <= 0) 00142 len = 0; 00143 00144 00145 ret = pglob; 00146 memset(ret, 0, sizeof(glob_t)); 00147 00148 hFind = FindFirstFileA(pattern, &FindFileData); 00149 if (hFind == INVALID_HANDLE_VALUE) 00150 return(0); 00151 nb_paths = 20; 00152 ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *)); 00153 if (ret->gl_pathv == NULL) { 00154 FindClose(hFind); 00155 return(-1); 00156 } 00157 strncpy(directory + len, FindFileData.cFileName, 499 - len); 00158 ret->gl_pathv[ret->gl_pathc] = strdup(directory); 00159 if (ret->gl_pathv[ret->gl_pathc] == NULL) 00160 goto done; 00161 ret->gl_pathc++; 00162 while(FindNextFileA(hFind, &FindFileData)) { 00163 if (FindFileData.cFileName[0] == '.') 00164 continue; 00165 if (ret->gl_pathc + 2 > nb_paths) { 00166 char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *)); 00167 if (tmp == NULL) 00168 break; 00169 ret->gl_pathv = tmp; 00170 nb_paths *= 2; 00171 } 00172 strncpy(directory + len, FindFileData.cFileName, 499 - len); 00173 ret->gl_pathv[ret->gl_pathc] = strdup(directory); 00174 if (ret->gl_pathv[ret->gl_pathc] == NULL) 00175 break; 00176 ret->gl_pathc++; 00177 } 00178 ret->gl_pathv[ret->gl_pathc] = NULL; 00179 00180 done: 00181 FindClose(hFind); 00182 return(0); 00183 } 00184 00185 00186 00187 static void globfree(glob_t *pglob) { 00188 unsigned int i; 00189 if (pglob == NULL) 00190 return; 00191 00192 for (i = 0;i < pglob->gl_pathc;i++) { 00193 if (pglob->gl_pathv[i] != NULL) 00194 free(pglob->gl_pathv[i]); 00195 } 00196 } 00197 #define vsnprintf _vsnprintf 00198 #define snprintf _snprintf 00199 #else 00200 #include <glob.h> 00201 #endif 00202 00203 /************************************************************************ 00204 * * 00205 * Libxml2 specific routines * 00206 * * 00207 ************************************************************************/ 00208 00209 static int nb_tests = 0; 00210 static int nb_errors = 0; 00211 static int nb_leaks = 0; 00212 static int extraMemoryFromResolver = 0; 00213 00214 static int 00215 fatalError(void) { 00216 fprintf(stderr, "Exitting tests on fatal error\n"); 00217 exit(1); 00218 } 00219 00220 /* 00221 * We need to trap calls to the resolver to not account memory for the catalog 00222 * which is shared to the current running test. We also don't want to have 00223 * network downloads modifying tests. 00224 */ 00225 static xmlParserInputPtr 00226 testExternalEntityLoader(const char *URL, const char *ID, 00227 xmlParserCtxtPtr ctxt) { 00228 xmlParserInputPtr ret; 00229 00230 if (checkTestFile(URL)) { 00231 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt); 00232 } else { 00233 int memused = xmlMemUsed(); 00234 ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt); 00235 extraMemoryFromResolver += xmlMemUsed() - memused; 00236 } 00237 00238 return(ret); 00239 } 00240 00241 /* 00242 * Trapping the error messages at the generic level to grab the equivalent of 00243 * stderr messages on CLI tools. 00244 */ 00245 static char testErrors[32769]; 00246 static int testErrorsSize = 0; 00247 00248 static void XMLCDECL 00249 testErrorHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) { 00250 va_list args; 00251 int res; 00252 00253 if (testErrorsSize >= 32768) 00254 return; 00255 va_start(args, msg); 00256 res = vsnprintf(&testErrors[testErrorsSize], 00257 32768 - testErrorsSize, 00258 msg, args); 00259 va_end(args); 00260 if (testErrorsSize + res >= 32768) { 00261 /* buffer is full */ 00262 testErrorsSize = 32768; 00263 testErrors[testErrorsSize] = 0; 00264 } else { 00265 testErrorsSize += res; 00266 } 00267 testErrors[testErrorsSize] = 0; 00268 } 00269 00270 static void XMLCDECL 00271 channel(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) { 00272 va_list args; 00273 int res; 00274 00275 if (testErrorsSize >= 32768) 00276 return; 00277 va_start(args, msg); 00278 res = vsnprintf(&testErrors[testErrorsSize], 00279 32768 - testErrorsSize, 00280 msg, args); 00281 va_end(args); 00282 if (testErrorsSize + res >= 32768) { 00283 /* buffer is full */ 00284 testErrorsSize = 32768; 00285 testErrors[testErrorsSize] = 0; 00286 } else { 00287 testErrorsSize += res; 00288 } 00289 testErrors[testErrorsSize] = 0; 00290 } 00291 00299 static void 00300 xmlParserPrintFileContextInternal(xmlParserInputPtr input , 00301 xmlGenericErrorFunc chanl, void *data ) { 00302 const xmlChar *cur, *base; 00303 unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */ 00304 xmlChar content[81]; /* space for 80 chars + line terminator */ 00305 xmlChar *ctnt; 00306 00307 if (input == NULL) return; 00308 cur = input->cur; 00309 base = input->base; 00310 /* skip backwards over any end-of-lines */ 00311 while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) { 00312 cur--; 00313 } 00314 n = 0; 00315 /* search backwards for beginning-of-line (to max buff size) */ 00316 while ((n++ < (sizeof(content)-1)) && (cur > base) && 00317 (*(cur) != '\n') && (*(cur) != '\r')) 00318 cur--; 00319 if ((*(cur) == '\n') || (*(cur) == '\r')) cur++; 00320 /* calculate the error position in terms of the current position */ 00321 col = input->cur - cur; 00322 /* search forward for end-of-line (to max buff size) */ 00323 n = 0; 00324 ctnt = content; 00325 /* copy selected text to our buffer */ 00326 while ((*cur != 0) && (*(cur) != '\n') && 00327 (*(cur) != '\r') && (n < sizeof(content)-1)) { 00328 *ctnt++ = *cur++; 00329 n++; 00330 } 00331 *ctnt = 0; 00332 /* print out the selected text */ 00333 chanl(data ,"%s\n", content); 00334 /* create blank line with problem pointer */ 00335 n = 0; 00336 ctnt = content; 00337 /* (leave buffer space for pointer + line terminator) */ 00338 while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) { 00339 if (*(ctnt) != '\t') 00340 *(ctnt) = ' '; 00341 ctnt++; 00342 } 00343 *ctnt++ = '^'; 00344 *ctnt = 0; 00345 chanl(data ,"%s\n", content); 00346 } 00347 00348 static void 00349 testStructuredErrorHandler(void *ctx ATTRIBUTE_UNUSED, xmlErrorPtr err) { 00350 char *file = NULL; 00351 int line = 0; 00352 int code = -1; 00353 int domain; 00354 void *data = NULL; 00355 const char *str; 00356 const xmlChar *name = NULL; 00357 xmlNodePtr node; 00358 xmlErrorLevel level; 00359 xmlParserInputPtr input = NULL; 00360 xmlParserInputPtr cur = NULL; 00361 xmlParserCtxtPtr ctxt = NULL; 00362 00363 if (err == NULL) 00364 return; 00365 00366 file = err->file; 00367 line = err->line; 00368 code = err->code; 00369 domain = err->domain; 00370 level = err->level; 00371 node = err->node; 00372 if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) || 00373 (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || 00374 (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { 00375 ctxt = err->ctxt; 00376 } 00377 str = err->message; 00378 00379 if (code == XML_ERR_OK) 00380 return; 00381 00382 if ((node != NULL) && (node->type == XML_ELEMENT_NODE)) 00383 name = node->name; 00384 00385 /* 00386 * Maintain the compatibility with the legacy error handling 00387 */ 00388 if (ctxt != NULL) { 00389 input = ctxt->input; 00390 if ((input != NULL) && (input->filename == NULL) && 00391 (ctxt->inputNr > 1)) { 00392 cur = input; 00393 input = ctxt->inputTab[ctxt->inputNr - 2]; 00394 } 00395 if (input != NULL) { 00396 if (input->filename) 00397 channel(data, "%s:%d: ", input->filename, input->line); 00398 else if ((line != 0) && (domain == XML_FROM_PARSER)) 00399 channel(data, "Entity: line %d: ", input->line); 00400 } 00401 } else { 00402 if (file != NULL) 00403 channel(data, "%s:%d: ", file, line); 00404 else if ((line != 0) && (domain == XML_FROM_PARSER)) 00405 channel(data, "Entity: line %d: ", line); 00406 } 00407 if (name != NULL) { 00408 channel(data, "element %s: ", name); 00409 } 00410 if (code == XML_ERR_OK) 00411 return; 00412 switch (domain) { 00413 case XML_FROM_PARSER: 00414 channel(data, "parser "); 00415 break; 00416 case XML_FROM_NAMESPACE: 00417 channel(data, "namespace "); 00418 break; 00419 case XML_FROM_DTD: 00420 case XML_FROM_VALID: 00421 channel(data, "validity "); 00422 break; 00423 case XML_FROM_HTML: 00424 channel(data, "HTML parser "); 00425 break; 00426 case XML_FROM_MEMORY: 00427 channel(data, "memory "); 00428 break; 00429 case XML_FROM_OUTPUT: 00430 channel(data, "output "); 00431 break; 00432 case XML_FROM_IO: 00433 channel(data, "I/O "); 00434 break; 00435 case XML_FROM_XINCLUDE: 00436 channel(data, "XInclude "); 00437 break; 00438 case XML_FROM_XPATH: 00439 channel(data, "XPath "); 00440 break; 00441 case XML_FROM_XPOINTER: 00442 channel(data, "parser "); 00443 break; 00444 case XML_FROM_REGEXP: 00445 channel(data, "regexp "); 00446 break; 00447 case XML_FROM_MODULE: 00448 channel(data, "module "); 00449 break; 00450 case XML_FROM_SCHEMASV: 00451 channel(data, "Schemas validity "); 00452 break; 00453 case XML_FROM_SCHEMASP: 00454 channel(data, "Schemas parser "); 00455 break; 00456 case XML_FROM_RELAXNGP: 00457 channel(data, "Relax-NG parser "); 00458 break; 00459 case XML_FROM_RELAXNGV: 00460 channel(data, "Relax-NG validity "); 00461 break; 00462 case XML_FROM_CATALOG: 00463 channel(data, "Catalog "); 00464 break; 00465 case XML_FROM_C14N: 00466 channel(data, "C14N "); 00467 break; 00468 case XML_FROM_XSLT: 00469 channel(data, "XSLT "); 00470 break; 00471 default: 00472 break; 00473 } 00474 if (code == XML_ERR_OK) 00475 return; 00476 switch (level) { 00477 case XML_ERR_NONE: 00478 channel(data, ": "); 00479 break; 00480 case XML_ERR_WARNING: 00481 channel(data, "warning : "); 00482 break; 00483 case XML_ERR_ERROR: 00484 channel(data, "error : "); 00485 break; 00486 case XML_ERR_FATAL: 00487 channel(data, "error : "); 00488 break; 00489 } 00490 if (code == XML_ERR_OK) 00491 return; 00492 if (str != NULL) { 00493 int len; 00494 len = xmlStrlen((const xmlChar *)str); 00495 if ((len > 0) && (str[len - 1] != '\n')) 00496 channel(data, "%s\n", str); 00497 else 00498 channel(data, "%s", str); 00499 } else { 00500 channel(data, "%s\n", "out of memory error"); 00501 } 00502 if (code == XML_ERR_OK) 00503 return; 00504 00505 if (ctxt != NULL) { 00506 xmlParserPrintFileContextInternal(input, channel, data); 00507 if (cur != NULL) { 00508 if (cur->filename) 00509 channel(data, "%s:%d: \n", cur->filename, cur->line); 00510 else if ((line != 0) && (domain == XML_FROM_PARSER)) 00511 channel(data, "Entity: line %d: \n", cur->line); 00512 xmlParserPrintFileContextInternal(cur, channel, data); 00513 } 00514 } 00515 if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) && 00516 (err->int1 < 100) && 00517 (err->int1 < xmlStrlen((const xmlChar *)err->str1))) { 00518 xmlChar buf[150]; 00519 int i; 00520 00521 channel(data, "%s\n", err->str1); 00522 for (i=0;i < err->int1;i++) 00523 buf[i] = ' '; 00524 buf[i++] = '^'; 00525 buf[i] = 0; 00526 channel(data, "%s\n", buf); 00527 } 00528 } 00529 00530 static void 00531 initializeLibxml2(void) { 00532 xmlGetWarningsDefaultValue = 0; 00533 xmlPedanticParserDefault(0); 00534 00535 xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup); 00536 xmlInitParser(); 00537 xmlSetExternalEntityLoader(testExternalEntityLoader); 00538 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler); 00539 #ifdef LIBXML_SCHEMAS_ENABLED 00540 xmlSchemaInitTypes(); 00541 xmlRelaxNGInitTypes(); 00542 #endif 00543 } 00544 00545 00546 /************************************************************************ 00547 * * 00548 * File name and path utilities * 00549 * * 00550 ************************************************************************/ 00551 00552 static const char *baseFilename(const char *filename) { 00553 const char *cur; 00554 if (filename == NULL) 00555 return(NULL); 00556 cur = &filename[strlen(filename)]; 00557 while ((cur > filename) && (*cur != '/')) 00558 cur--; 00559 if (*cur == '/') 00560 return(cur + 1); 00561 return(cur); 00562 } 00563 00564 static char *resultFilename(const char *filename, const char *out, 00565 const char *suffix) { 00566 const char *base; 00567 char res[500]; 00568 char suffixbuff[500]; 00569 00570 /************* 00571 if ((filename[0] == 't') && (filename[1] == 'e') && 00572 (filename[2] == 's') && (filename[3] == 't') && 00573 (filename[4] == '/')) 00574 filename = &filename[5]; 00575 *************/ 00576 00577 base = baseFilename(filename); 00578 if (suffix == NULL) 00579 suffix = ".tmp"; 00580 if (out == NULL) 00581 out = ""; 00582 00583 strncpy(suffixbuff,suffix,499); 00584 #ifdef VMS 00585 if(strstr(base,".") && suffixbuff[0]=='.') 00586 suffixbuff[0]='_'; 00587 #endif 00588 00589 snprintf(res, 499, "%s%s%s", out, base, suffixbuff); 00590 res[499] = 0; 00591 return(strdup(res)); 00592 } 00593 00594 static int checkTestFile(const char *filename) { 00595 struct stat buf; 00596 00597 if (stat(filename, &buf) == -1) 00598 return(0); 00599 00600 #if defined(_WIN32) && !defined(__CYGWIN__) 00601 if (!(buf.st_mode & _S_IFREG)) 00602 return(0); 00603 #else 00604 if (!S_ISREG(buf.st_mode)) 00605 return(0); 00606 #endif 00607 00608 return(1); 00609 } 00610 00611 static int compareFiles(const char *r1, const char *r2) { 00612 int res1, res2; 00613 int fd1, fd2; 00614 char bytes1[4096]; 00615 char bytes2[4096]; 00616 00617 fd1 = open(r1, RD_FLAGS); 00618 if (fd1 < 0) 00619 return(-1); 00620 fd2 = open(r2, RD_FLAGS); 00621 if (fd2 < 0) { 00622 close(fd1); 00623 return(-1); 00624 } 00625 while (1) { 00626 res1 = read(fd1, bytes1, 4096); 00627 res2 = read(fd2, bytes2, 4096); 00628 if ((res1 != res2) || (res1 < 0)) { 00629 close(fd1); 00630 close(fd2); 00631 return(1); 00632 } 00633 if (res1 == 0) 00634 break; 00635 if (memcmp(bytes1, bytes2, res1) != 0) { 00636 close(fd1); 00637 close(fd2); 00638 return(1); 00639 } 00640 } 00641 close(fd1); 00642 close(fd2); 00643 return(0); 00644 } 00645 00646 static int compareFileMem(const char *filename, const char *mem, int size) { 00647 int res; 00648 int fd; 00649 char bytes[4096]; 00650 int idx = 0; 00651 struct stat info; 00652 00653 if (stat(filename, &info) < 0) 00654 return(-1); 00655 if (info.st_size != size) 00656 return(-1); 00657 fd = open(filename, RD_FLAGS); 00658 if (fd < 0) 00659 return(-1); 00660 while (idx < size) { 00661 res = read(fd, bytes, 4096); 00662 if (res <= 0) 00663 break; 00664 if (res + idx > size) 00665 break; 00666 if (memcmp(bytes, &mem[idx], res) != 0) { 00667 int ix; 00668 for (ix=0; ix<res; ix++) 00669 if (bytes[ix] != mem[idx+ix]) 00670 break; 00671 fprintf(stderr,"Compare error at position %d\n", idx+ix); 00672 close(fd); 00673 return(1); 00674 } 00675 idx += res; 00676 } 00677 close(fd); 00678 return(idx != size); 00679 } 00680 00681 static int loadMem(const char *filename, const char **mem, int *size) { 00682 int fd, res; 00683 struct stat info; 00684 char *base; 00685 int siz = 0; 00686 if (stat(filename, &info) < 0) 00687 return(-1); 00688 base = malloc(info.st_size + 1); 00689 if (base == NULL) 00690 return(-1); 00691 if ((fd = open(filename, RD_FLAGS)) < 0) { 00692 free(base); 00693 return(-1); 00694 } 00695 while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) { 00696 siz += res; 00697 } 00698 close(fd); 00699 #if !defined(_WIN32) 00700 if (siz != info.st_size) { 00701 free(base); 00702 return(-1); 00703 } 00704 #endif 00705 base[siz] = 0; 00706 *mem = base; 00707 *size = siz; 00708 return(0); 00709 } 00710 00711 static int unloadMem(const char *mem) { 00712 free((char *)mem); 00713 return(0); 00714 } 00715 00716 /************************************************************************ 00717 * * 00718 * Tests implementations * 00719 * * 00720 ************************************************************************/ 00721 00722 /************************************************************************ 00723 * * 00724 * Parse to SAX based tests * 00725 * * 00726 ************************************************************************/ 00727 00728 static FILE *SAXdebug = NULL; 00729 00730 /* 00731 * empty SAX block 00732 */ 00733 static xmlSAXHandler emptySAXHandlerStruct = { 00734 NULL, /* internalSubset */ 00735 NULL, /* isStandalone */ 00736 NULL, /* hasInternalSubset */ 00737 NULL, /* hasExternalSubset */ 00738 NULL, /* resolveEntity */ 00739 NULL, /* getEntity */ 00740 NULL, /* entityDecl */ 00741 NULL, /* notationDecl */ 00742 NULL, /* attributeDecl */ 00743 NULL, /* elementDecl */ 00744 NULL, /* unparsedEntityDecl */ 00745 NULL, /* setDocumentLocator */ 00746 NULL, /* startDocument */ 00747 NULL, /* endDocument */ 00748 NULL, /* startElement */ 00749 NULL, /* endElement */ 00750 NULL, /* reference */ 00751 NULL, /* characters */ 00752 NULL, /* ignorableWhitespace */ 00753 NULL, /* processingInstruction */ 00754 NULL, /* comment */ 00755 NULL, /* xmlParserWarning */ 00756 NULL, /* xmlParserError */ 00757 NULL, /* xmlParserError */ 00758 NULL, /* getParameterEntity */ 00759 NULL, /* cdataBlock; */ 00760 NULL, /* externalSubset; */ 00761 1, 00762 NULL, 00763 NULL, /* startElementNs */ 00764 NULL, /* endElementNs */ 00765 NULL /* xmlStructuredErrorFunc */ 00766 }; 00767 00768 static xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct; 00769 static int callbacks = 0; 00770 static int quiet = 0; 00771 00780 static int 00781 isStandaloneDebug(void *ctx ATTRIBUTE_UNUSED) 00782 { 00783 callbacks++; 00784 if (quiet) 00785 return(0); 00786 fprintf(SAXdebug, "SAX.isStandalone()\n"); 00787 return(0); 00788 } 00789 00798 static int 00799 hasInternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED) 00800 { 00801 callbacks++; 00802 if (quiet) 00803 return(0); 00804 fprintf(SAXdebug, "SAX.hasInternalSubset()\n"); 00805 return(0); 00806 } 00807 00816 static int 00817 hasExternalSubsetDebug(void *ctx ATTRIBUTE_UNUSED) 00818 { 00819 callbacks++; 00820 if (quiet) 00821 return(0); 00822 fprintf(SAXdebug, "SAX.hasExternalSubset()\n"); 00823 return(0); 00824 } 00825 00832 static void 00833 internalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, 00834 const xmlChar *ExternalID, const xmlChar *SystemID) 00835 { 00836 callbacks++; 00837 if (quiet) 00838 return; 00839 fprintf(SAXdebug, "SAX.internalSubset(%s,", name); 00840 if (ExternalID == NULL) 00841 fprintf(SAXdebug, " ,"); 00842 else 00843 fprintf(SAXdebug, " %s,", ExternalID); 00844 if (SystemID == NULL) 00845 fprintf(SAXdebug, " )\n"); 00846 else 00847 fprintf(SAXdebug, " %s)\n", SystemID); 00848 } 00849 00856 static void 00857 externalSubsetDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, 00858 const xmlChar *ExternalID, const xmlChar *SystemID) 00859 { 00860 callbacks++; 00861 if (quiet) 00862 return; 00863 fprintf(SAXdebug, "SAX.externalSubset(%s,", name); 00864 if (ExternalID == NULL) 00865 fprintf(SAXdebug, " ,"); 00866 else 00867 fprintf(SAXdebug, " %s,", ExternalID); 00868 if (SystemID == NULL) 00869 fprintf(SAXdebug, " )\n"); 00870 else 00871 fprintf(SAXdebug, " %s)\n", SystemID); 00872 } 00873 00888 static xmlParserInputPtr 00889 resolveEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *publicId, const xmlChar *systemId) 00890 { 00891 callbacks++; 00892 if (quiet) 00893 return(NULL); 00894 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ 00895 00896 00897 fprintf(SAXdebug, "SAX.resolveEntity("); 00898 if (publicId != NULL) 00899 fprintf(SAXdebug, "%s", (char *)publicId); 00900 else 00901 fprintf(SAXdebug, " "); 00902 if (systemId != NULL) 00903 fprintf(SAXdebug, ", %s)\n", (char *)systemId); 00904 else 00905 fprintf(SAXdebug, ", )\n"); 00906 /********* 00907 if (systemId != NULL) { 00908 return(xmlNewInputFromFile(ctxt, (char *) systemId)); 00909 } 00910 *********/ 00911 return(NULL); 00912 } 00913 00923 static xmlEntityPtr 00924 getEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name) 00925 { 00926 callbacks++; 00927 if (quiet) 00928 return(NULL); 00929 fprintf(SAXdebug, "SAX.getEntity(%s)\n", name); 00930 return(NULL); 00931 } 00932 00942 static xmlEntityPtr 00943 getParameterEntityDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name) 00944 { 00945 callbacks++; 00946 if (quiet) 00947 return(NULL); 00948 fprintf(SAXdebug, "SAX.getParameterEntity(%s)\n", name); 00949 return(NULL); 00950 } 00951 00952 00964 static void 00965 entityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type, 00966 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) 00967 { 00968 const xmlChar *nullstr = BAD_CAST "(null)"; 00969 /* not all libraries handle printing null pointers nicely */ 00970 if (publicId == NULL) 00971 publicId = nullstr; 00972 if (systemId == NULL) 00973 systemId = nullstr; 00974 if (content == NULL) 00975 content = (xmlChar *)nullstr; 00976 callbacks++; 00977 if (quiet) 00978 return; 00979 fprintf(SAXdebug, "SAX.entityDecl(%s, %d, %s, %s, %s)\n", 00980 name, type, publicId, systemId, content); 00981 } 00982 00991 static void 00992 attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem, 00993 const xmlChar * name, int type, int def, 00994 const xmlChar * defaultValue, xmlEnumerationPtr tree) 00995 { 00996 callbacks++; 00997 if (quiet) 00998 return; 00999 if (defaultValue == NULL) 01000 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n", 01001 elem, name, type, def); 01002 else 01003 fprintf(SAXdebug, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n", 01004 elem, name, type, def, defaultValue); 01005 xmlFreeEnumeration(tree); 01006 } 01007 01017 static void 01018 elementDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, int type, 01019 xmlElementContentPtr content ATTRIBUTE_UNUSED) 01020 { 01021 callbacks++; 01022 if (quiet) 01023 return; 01024 fprintf(SAXdebug, "SAX.elementDecl(%s, %d, ...)\n", 01025 name, type); 01026 } 01027 01037 static void 01038 notationDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, 01039 const xmlChar *publicId, const xmlChar *systemId) 01040 { 01041 callbacks++; 01042 if (quiet) 01043 return; 01044 fprintf(SAXdebug, "SAX.notationDecl(%s, %s, %s)\n", 01045 (char *) name, (char *) publicId, (char *) systemId); 01046 } 01047 01058 static void 01059 unparsedEntityDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, 01060 const xmlChar *publicId, const xmlChar *systemId, 01061 const xmlChar *notationName) 01062 { 01063 const xmlChar *nullstr = BAD_CAST "(null)"; 01064 01065 if (publicId == NULL) 01066 publicId = nullstr; 01067 if (systemId == NULL) 01068 systemId = nullstr; 01069 if (notationName == NULL) 01070 notationName = nullstr; 01071 callbacks++; 01072 if (quiet) 01073 return; 01074 fprintf(SAXdebug, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n", 01075 (char *) name, (char *) publicId, (char *) systemId, 01076 (char *) notationName); 01077 } 01078 01087 static void 01088 setDocumentLocatorDebug(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED) 01089 { 01090 callbacks++; 01091 if (quiet) 01092 return; 01093 fprintf(SAXdebug, "SAX.setDocumentLocator()\n"); 01094 } 01095 01102 static void 01103 startDocumentDebug(void *ctx ATTRIBUTE_UNUSED) 01104 { 01105 callbacks++; 01106 if (quiet) 01107 return; 01108 fprintf(SAXdebug, "SAX.startDocument()\n"); 01109 } 01110 01117 static void 01118 endDocumentDebug(void *ctx ATTRIBUTE_UNUSED) 01119 { 01120 callbacks++; 01121 if (quiet) 01122 return; 01123 fprintf(SAXdebug, "SAX.endDocument()\n"); 01124 } 01125 01133 static void 01134 startElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts) 01135 { 01136 int i; 01137 01138 callbacks++; 01139 if (quiet) 01140 return; 01141 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name); 01142 if (atts != NULL) { 01143 for (i = 0;(atts[i] != NULL);i++) { 01144 fprintf(SAXdebug, ", %s='", atts[i++]); 01145 if (atts[i] != NULL) 01146 fprintf(SAXdebug, "%s'", atts[i]); 01147 } 01148 } 01149 fprintf(SAXdebug, ")\n"); 01150 } 01151 01159 static void 01160 endElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name) 01161 { 01162 callbacks++; 01163 if (quiet) 01164 return; 01165 fprintf(SAXdebug, "SAX.endElement(%s)\n", (char *) name); 01166 } 01167 01177 static void 01178 charactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len) 01179 { 01180 char output[40]; 01181 int i; 01182 01183 callbacks++; 01184 if (quiet) 01185 return; 01186 for (i = 0;(i<len) && (i < 30);i++) 01187 output[i] = ch[i]; 01188 output[i] = 0; 01189 01190 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len); 01191 } 01192 01200 static void 01201 referenceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name) 01202 { 01203 callbacks++; 01204 if (quiet) 01205 return; 01206 fprintf(SAXdebug, "SAX.reference(%s)\n", name); 01207 } 01208 01219 static void 01220 ignorableWhitespaceDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len) 01221 { 01222 char output[40]; 01223 int i; 01224 01225 callbacks++; 01226 if (quiet) 01227 return; 01228 for (i = 0;(i<len) && (i < 30);i++) 01229 output[i] = ch[i]; 01230 output[i] = 0; 01231 fprintf(SAXdebug, "SAX.ignorableWhitespace(%s, %d)\n", output, len); 01232 } 01233 01243 static void 01244 processingInstructionDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *target, 01245 const xmlChar *data) 01246 { 01247 callbacks++; 01248 if (quiet) 01249 return; 01250 if (data != NULL) 01251 fprintf(SAXdebug, "SAX.processingInstruction(%s, %s)\n", 01252 (char *) target, (char *) data); 01253 else 01254 fprintf(SAXdebug, "SAX.processingInstruction(%s, NULL)\n", 01255 (char *) target); 01256 } 01257 01266 static void 01267 cdataBlockDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value, int len) 01268 { 01269 callbacks++; 01270 if (quiet) 01271 return; 01272 fprintf(SAXdebug, "SAX.pcdata(%.20s, %d)\n", 01273 (char *) value, len); 01274 } 01275 01283 static void 01284 commentDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *value) 01285 { 01286 callbacks++; 01287 if (quiet) 01288 return; 01289 fprintf(SAXdebug, "SAX.comment(%s)\n", value); 01290 } 01291 01301 static void XMLCDECL 01302 warningDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) 01303 { 01304 va_list args; 01305 01306 callbacks++; 01307 if (quiet) 01308 return; 01309 va_start(args, msg); 01310 fprintf(SAXdebug, "SAX.warning: "); 01311 vfprintf(SAXdebug, msg, args); 01312 va_end(args); 01313 } 01314 01324 static void XMLCDECL 01325 errorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) 01326 { 01327 va_list args; 01328 01329 callbacks++; 01330 if (quiet) 01331 return; 01332 va_start(args, msg); 01333 fprintf(SAXdebug, "SAX.error: "); 01334 vfprintf(SAXdebug, msg, args); 01335 va_end(args); 01336 } 01337 01347 static void XMLCDECL 01348 fatalErrorDebug(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) 01349 { 01350 va_list args; 01351 01352 callbacks++; 01353 if (quiet) 01354 return; 01355 va_start(args, msg); 01356 fprintf(SAXdebug, "SAX.fatalError: "); 01357 vfprintf(SAXdebug, msg, args); 01358 va_end(args); 01359 } 01360 01361 static xmlSAXHandler debugSAXHandlerStruct = { 01362 internalSubsetDebug, 01363 isStandaloneDebug, 01364 hasInternalSubsetDebug, 01365 hasExternalSubsetDebug, 01366 resolveEntityDebug, 01367 getEntityDebug, 01368 entityDeclDebug, 01369 notationDeclDebug, 01370 attributeDeclDebug, 01371 elementDeclDebug, 01372 unparsedEntityDeclDebug, 01373 setDocumentLocatorDebug, 01374 startDocumentDebug, 01375 endDocumentDebug, 01376 startElementDebug, 01377 endElementDebug, 01378 referenceDebug, 01379 charactersDebug, 01380 ignorableWhitespaceDebug, 01381 processingInstructionDebug, 01382 commentDebug, 01383 warningDebug, 01384 errorDebug, 01385 fatalErrorDebug, 01386 getParameterEntityDebug, 01387 cdataBlockDebug, 01388 externalSubsetDebug, 01389 1, 01390 NULL, 01391 NULL, 01392 NULL, 01393 NULL 01394 }; 01395 01396 static xmlSAXHandlerPtr debugSAXHandler = &debugSAXHandlerStruct; 01397 01398 /* 01399 * SAX2 specific callbacks 01400 */ 01408 static void 01409 startElementNsDebug(void *ctx ATTRIBUTE_UNUSED, 01410 const xmlChar *localname, 01411 const xmlChar *prefix, 01412 const xmlChar *URI, 01413 int nb_namespaces, 01414 const xmlChar **namespaces, 01415 int nb_attributes, 01416 int nb_defaulted, 01417 const xmlChar **attributes) 01418 { 01419 int i; 01420 01421 callbacks++; 01422 if (quiet) 01423 return; 01424 fprintf(SAXdebug, "SAX.startElementNs(%s", (char *) localname); 01425 if (prefix == NULL) 01426 fprintf(SAXdebug, ", NULL"); 01427 else 01428 fprintf(SAXdebug, ", %s", (char *) prefix); 01429 if (URI == NULL) 01430 fprintf(SAXdebug, ", NULL"); 01431 else 01432 fprintf(SAXdebug, ", '%s'", (char *) URI); 01433 fprintf(SAXdebug, ", %d", nb_namespaces); 01434 01435 if (namespaces != NULL) { 01436 for (i = 0;i < nb_namespaces * 2;i++) { 01437 fprintf(SAXdebug, ", xmlns"); 01438 if (namespaces[i] != NULL) 01439 fprintf(SAXdebug, ":%s", namespaces[i]); 01440 i++; 01441 fprintf(SAXdebug, "='%s'", namespaces[i]); 01442 } 01443 } 01444 fprintf(SAXdebug, ", %d, %d", nb_attributes, nb_defaulted); 01445 if (attributes != NULL) { 01446 for (i = 0;i < nb_attributes * 5;i += 5) { 01447 if (attributes[i + 1] != NULL) 01448 fprintf(SAXdebug, ", %s:%s='", attributes[i + 1], attributes[i]); 01449 else 01450 fprintf(SAXdebug, ", %s='", attributes[i]); 01451 fprintf(SAXdebug, "%.4s...', %d", attributes[i + 3], 01452 (int)(attributes[i + 4] - attributes[i + 3])); 01453 } 01454 } 01455 fprintf(SAXdebug, ")\n"); 01456 } 01457 01465 static void 01466 endElementNsDebug(void *ctx ATTRIBUTE_UNUSED, 01467 const xmlChar *localname, 01468 const xmlChar *prefix, 01469 const xmlChar *URI) 01470 { 01471 callbacks++; 01472 if (quiet) 01473 return; 01474 fprintf(SAXdebug, "SAX.endElementNs(%s", (char *) localname); 01475 if (prefix == NULL) 01476 fprintf(SAXdebug, ", NULL"); 01477 else 01478 fprintf(SAXdebug, ", %s", (char *) prefix); 01479 if (URI == NULL) 01480 fprintf(SAXdebug, ", NULL)\n"); 01481 else 01482 fprintf(SAXdebug, ", '%s')\n", (char *) URI); 01483 } 01484 01485 static xmlSAXHandler debugSAX2HandlerStruct = { 01486 internalSubsetDebug, 01487 isStandaloneDebug, 01488 hasInternalSubsetDebug, 01489 hasExternalSubsetDebug, 01490 resolveEntityDebug, 01491 getEntityDebug, 01492 entityDeclDebug, 01493 notationDeclDebug, 01494 attributeDeclDebug, 01495 elementDeclDebug, 01496 unparsedEntityDeclDebug, 01497 setDocumentLocatorDebug, 01498 startDocumentDebug, 01499 endDocumentDebug, 01500 NULL, 01501 NULL, 01502 referenceDebug, 01503 charactersDebug, 01504 ignorableWhitespaceDebug, 01505 processingInstructionDebug, 01506 commentDebug, 01507 warningDebug, 01508 errorDebug, 01509 fatalErrorDebug, 01510 getParameterEntityDebug, 01511 cdataBlockDebug, 01512 externalSubsetDebug, 01513 XML_SAX2_MAGIC, 01514 NULL, 01515 startElementNsDebug, 01516 endElementNsDebug, 01517 NULL 01518 }; 01519 01520 static xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct; 01521 01522 #ifdef LIBXML_HTML_ENABLED 01523 01530 static void 01531 htmlstartElementDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts) 01532 { 01533 int i; 01534 01535 fprintf(SAXdebug, "SAX.startElement(%s", (char *) name); 01536 if (atts != NULL) { 01537 for (i = 0;(atts[i] != NULL);i++) { 01538 fprintf(SAXdebug, ", %s", atts[i++]); 01539 if (atts[i] != NULL) { 01540 unsigned char output[40]; 01541 const unsigned char *att = atts[i]; 01542 int outlen, attlen; 01543 fprintf(SAXdebug, "='"); 01544 while ((attlen = strlen((char*)att)) > 0) { 01545 outlen = sizeof output - 1; 01546 htmlEncodeEntities(output, &outlen, att, &attlen, '\''); 01547 output[outlen] = 0; 01548 fprintf(SAXdebug, "%s", (char *) output); 01549 att += attlen; 01550 } 01551 fprintf(SAXdebug, "'"); 01552 } 01553 } 01554 } 01555 fprintf(SAXdebug, ")\n"); 01556 } 01557 01567 static void 01568 htmlcharactersDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len) 01569 { 01570 unsigned char output[40]; 01571 int inlen = len, outlen = 30; 01572 01573 htmlEncodeEntities(output, &outlen, ch, &inlen, 0); 01574 output[outlen] = 0; 01575 01576 fprintf(SAXdebug, "SAX.characters(%s, %d)\n", output, len); 01577 } 01578 01588 static void 01589 htmlcdataDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len) 01590 { 01591 unsigned char output[40]; 01592 int inlen = len, outlen = 30; 01593 01594 htmlEncodeEntities(output, &outlen, ch, &inlen, 0); 01595 output[outlen] = 0; 01596 01597 fprintf(SAXdebug, "SAX.cdata(%s, %d)\n", output, len); 01598 } 01599 01600 static xmlSAXHandler debugHTMLSAXHandlerStruct = { 01601 internalSubsetDebug, 01602 isStandaloneDebug, 01603 hasInternalSubsetDebug, 01604 hasExternalSubsetDebug, 01605 resolveEntityDebug, 01606 getEntityDebug, 01607 entityDeclDebug, 01608 notationDeclDebug, 01609 attributeDeclDebug, 01610 elementDeclDebug, 01611 unparsedEntityDeclDebug, 01612 setDocumentLocatorDebug, 01613 startDocumentDebug, 01614 endDocumentDebug, 01615 htmlstartElementDebug, 01616 endElementDebug, 01617 referenceDebug, 01618 htmlcharactersDebug, 01619 ignorableWhitespaceDebug, 01620 processingInstructionDebug, 01621 commentDebug, 01622 warningDebug, 01623 errorDebug, 01624 fatalErrorDebug, 01625 getParameterEntityDebug, 01626 htmlcdataDebug, 01627 externalSubsetDebug, 01628 1, 01629 NULL, 01630 NULL, 01631 NULL, 01632 NULL 01633 }; 01634 01635 static xmlSAXHandlerPtr debugHTMLSAXHandler = &debugHTMLSAXHandlerStruct; 01636 #endif /* LIBXML_HTML_ENABLED */ 01637 01638 #ifdef LIBXML_SAX1_ENABLED 01639 01649 static int 01650 saxParseTest(const char *filename, const char *result, 01651 const char *err ATTRIBUTE_UNUSED, 01652 int options) { 01653 int ret; 01654 char *temp; 01655 01656 nb_tests++; 01657 temp = resultFilename(filename, "", ".res"); 01658 if (temp == NULL) { 01659 fprintf(stderr, "out of memory\n"); 01660 fatalError(); 01661 } 01662 SAXdebug = fopen(temp, "wb"); 01663 if (SAXdebug == NULL) { 01664 fprintf(stderr, "Failed to write to %s\n", temp); 01665 free(temp); 01666 return(-1); 01667 } 01668 01669 /* for SAX we really want the callbacks though the context handlers */ 01670 xmlSetStructuredErrorFunc(NULL, NULL); 01671 xmlSetGenericErrorFunc(NULL, testErrorHandler); 01672 01673 #ifdef LIBXML_HTML_ENABLED 01674 if (options & XML_PARSE_HTML) { 01675 htmlSAXParseFile(filename, NULL, emptySAXHandler, NULL); 01676 ret = 0; 01677 } else 01678 #endif 01679 ret = xmlSAXUserParseFile(emptySAXHandler, NULL, filename); 01680 if (ret == XML_WAR_UNDECLARED_ENTITY) { 01681 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret); 01682 ret = 0; 01683 } 01684 if (ret != 0) { 01685 fprintf(stderr, "Failed to parse %s\n", filename); 01686 return(1); 01687 } 01688 #ifdef LIBXML_HTML_ENABLED 01689 if (options & XML_PARSE_HTML) { 01690 htmlSAXParseFile(filename, NULL, debugHTMLSAXHandler, NULL); 01691 ret = 0; 01692 } else 01693 #endif 01694 if (options & XML_PARSE_SAX1) { 01695 ret = xmlSAXUserParseFile(debugSAXHandler, NULL, filename); 01696 } else { 01697 ret = xmlSAXUserParseFile(debugSAX2Handler, NULL, filename); 01698 } 01699 if (ret == XML_WAR_UNDECLARED_ENTITY) { 01700 fprintf(SAXdebug, "xmlSAXUserParseFile returned error %d\n", ret); 01701 ret = 0; 01702 } 01703 fclose(SAXdebug); 01704 if (compareFiles(temp, result)) { 01705 fprintf(stderr, "Got a difference for %s\n", filename); 01706 ret = 1; 01707 } 01708 if (temp != NULL) { 01709 unlink(temp); 01710 free(temp); 01711 } 01712 01713 /* switch back to structured error handling */ 01714 xmlSetGenericErrorFunc(NULL, NULL); 01715 xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler); 01716 01717 return(ret); 01718 } 01719 #endif 01720 01721 /************************************************************************ 01722 * * 01723 * Parse to tree based tests * 01724 * * 01725 ************************************************************************/ 01738 static int 01739 oldParseTest(const char *filename, const char *result, 01740 const char *err ATTRIBUTE_UNUSED, 01741 int options ATTRIBUTE_UNUSED) { 01742 xmlDocPtr doc; 01743 char *temp; 01744 int res = 0; 01745 01746 nb_tests++; 01747 /* 01748 * base of the test, parse with the old API 01749 */ 01750 #ifdef LIBXML_SAX1_ENABLED 01751 doc = xmlParseFile(filename); 01752 #else 01753 doc = xmlReadFile(filename, NULL, 0); 01754 #endif 01755 if (doc == NULL) 01756 return(1); 01757 temp = resultFilename(filename, "", ".res"); 01758 if (temp == NULL) { 01759 fprintf(stderr, "out of memory\n"); 01760 fatalError(); 01761 } 01762 xmlSaveFile(temp, doc); 01763 if (compareFiles(temp, result)) { 01764 res = 1; 01765 } 01766 xmlFreeDoc(doc); 01767 01768 /* 01769 * Parse the saved result to make sure the round trip is okay 01770 */ 01771 #ifdef LIBXML_SAX1_ENABLED 01772 doc = xmlParseFile(temp); 01773 #else 01774 doc = xmlReadFile(temp, NULL, 0); 01775 #endif 01776 if (doc == NULL) 01777 return(1); 01778 xmlSaveFile(temp, doc); 01779 if (compareFiles(temp, result)) { 01780 res = 1; 01781 } 01782 xmlFreeDoc(doc); 01783 01784 if (temp != NULL) { 01785 unlink(temp); 01786 free(temp); 01787 } 01788 return(res); 01789 } 01790 01791 #ifdef LIBXML_PUSH_ENABLED 01792 01803 static int 01804 pushParseTest(const char *filename, const char *result, 01805 const char *err ATTRIBUTE_UNUSED, 01806 int options) { 01807 xmlParserCtxtPtr ctxt; 01808 xmlDocPtr doc; 01809 const char *base; 01810 int size, res; 01811 int cur = 0; 01812 01813 nb_tests++; 01814 /* 01815 * load the document in memory and work from there. 01816 */ 01817 if (loadMem(filename, &base, &size) != 0) { 01818 fprintf(stderr, "Failed to load %s\n", filename); 01819 return(-1); 01820 } 01821 01822 #ifdef LIBXML_HTML_ENABLED 01823 if (options & XML_PARSE_HTML) 01824 ctxt = htmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename, 01825 XML_CHAR_ENCODING_NONE); 01826 else 01827 #endif 01828 ctxt = xmlCreatePushParserCtxt(NULL, NULL, base + cur, 4, filename); 01829 xmlCtxtUseOptions(ctxt, options); 01830 cur += 4; 01831 while (cur < size) { 01832 if (cur + 1024 >= size) { 01833 #ifdef LIBXML_HTML_ENABLED 01834 if (options & XML_PARSE_HTML) 01835 htmlParseChunk(ctxt, base + cur, size - cur, 1); 01836 else 01837 #endif 01838 xmlParseChunk(ctxt, base + cur, size - cur, 1); 01839 break; 01840 } else { 01841 #ifdef LIBXML_HTML_ENABLED 01842 if (options & XML_PARSE_HTML) 01843 htmlParseChunk(ctxt, base + cur, 1024, 0); 01844 else 01845 #endif 01846 xmlParseChunk(ctxt, base + cur, 1024, 0); 01847 cur += 1024; 01848 } 01849 } 01850 doc = ctxt->myDoc; 01851 #ifdef LIBXML_HTML_ENABLED 01852 if (options & XML_PARSE_HTML) 01853 res = 1; 01854 else 01855 #endif 01856 res = ctxt->wellFormed; 01857 xmlFreeParserCtxt(ctxt); 01858 free((char *)base); 01859 if (!res) { 01860 xmlFreeDoc(doc); 01861 fprintf(stderr, "Failed to parse %s\n", filename); 01862 return(-1); 01863 } 01864 #ifdef LIBXML_HTML_ENABLED 01865 if (options & XML_PARSE_HTML) 01866 htmlDocDumpMemory(doc, (xmlChar **) &base, &size); 01867 else 01868 #endif 01869 xmlDocDumpMemory(doc, (xmlChar **) &base, &size); 01870 xmlFreeDoc(doc); 01871 res = compareFileMem(result, base, size); 01872 if ((base == NULL) || (res != 0)) { 01873 if (base != NULL) 01874 xmlFree((char *)base); 01875 fprintf(stderr, "Result for %s failed\n", filename); 01876 return(-1); 01877 } 01878 xmlFree((char *)base); 01879 if (err != NULL) { 01880 res = compareFileMem(err, testErrors, testErrorsSize); 01881 if (res != 0) { 01882 fprintf(stderr, "Error for %s failed\n", filename); 01883 return(-1); 01884 } 01885 } 01886 return(0); 01887 } 01888 #endif 01889 01902 static int 01903 memParseTest(const char *filename, const char *result, 01904 const char *err ATTRIBUTE_UNUSED, 01905 int options ATTRIBUTE_UNUSED) { 01906 xmlDocPtr doc; 01907 const char *base; 01908 int size, res; 01909 01910 nb_tests++; 01911 /* 01912 * load and parse the memory 01913 */ 01914 if (loadMem(filename, &base, &size) != 0) { 01915 fprintf(stderr, "Failed to load %s\n", filename); 01916 return(-1); 01917 } 01918 01919 doc = xmlReadMemory(base, size, filename, NULL, 0); 01920 unloadMem(base); 01921 if (doc == NULL) { 01922 return(1); 01923 } 01924 xmlDocDumpMemory(doc, (xmlChar **) &base, &size); 01925 xmlFreeDoc(doc); 01926 res = compareFileMem(result, base, size); 01927 if ((base == NULL) || (res != 0)) { 01928 if (base != NULL) 01929 xmlFree((char *)base); 01930 fprintf(stderr, "Result for %s failed\n", filename); 01931 return(-1); 01932 } 01933 xmlFree((char *)base); 01934 return(0); 01935 } 01936 01949 static int 01950 noentParseTest(const char *filename, const char *result, 01951 const char *err ATTRIBUTE_UNUSED, 01952 int options) { 01953 xmlDocPtr doc; 01954 char *temp; 01955 int res = 0; 01956 01957 nb_tests++; 01958 /* 01959 * base of the test, parse with the old API 01960 */ 01961 doc = xmlReadFile(filename, NULL, options); 01962 if (doc == NULL) 01963 return(1); 01964 temp = resultFilename(filename, "", ".res"); 01965 if (temp == NULL) { 01966 fprintf(stderr, "Out of memory\n"); 01967 fatalError(); 01968 } 01969 xmlSaveFile(temp, doc); 01970 if (compareFiles(temp, result)) { 01971 res = 1; 01972 } 01973 xmlFreeDoc(doc); 01974 01975 /* 01976 * Parse the saved result to make sure the round trip is okay 01977 */ 01978 doc = xmlReadFile(filename, NULL, options); 01979 if (doc == NULL) 01980 return(1); 01981 xmlSaveFile(temp, doc); 01982 if (compareFiles(temp, result)) { 01983 res = 1; 01984 } 01985 xmlFreeDoc(doc); 01986 01987 if (temp != NULL) { 01988 unlink(temp); 01989 free(temp); 01990 } 01991 return(res); 01992 } 01993 02004 static int 02005 errParseTest(const char *filename, const char *result, const char *err, 02006 int options) { 02007 xmlDocPtr doc; 02008 const char *base = NULL; 02009 int size, res = 0; 02010 02011 nb_tests++; 02012 #ifdef LIBXML_HTML_ENABLED 02013 if (options & XML_PARSE_HTML) { 02014 doc = htmlReadFile(filename, NULL, options); 02015 } else 02016 #endif 02017 #ifdef LIBXML_XINCLUDE_ENABLED 02018 if (options & XML_PARSE_XINCLUDE) { 02019 doc = xmlReadFile(filename, NULL, options); 02020 xmlXIncludeProcessFlags(doc, options); 02021 } else 02022 #endif 02023 { 02024 xmlGetWarningsDefaultValue = 1; 02025 doc = xmlReadFile(filename, NULL, options); 02026 } 02027 xmlGetWarningsDefaultValue = 0; 02028 if (result) { 02029 if (doc == NULL) { 02030 base = ""; 02031 size = 0; 02032 } else { 02033 #ifdef LIBXML_HTML_ENABLED 02034 if (options & XML_PARSE_HTML) { 02035 htmlDocDumpMemory(doc, (xmlChar **) &base, &size); 02036 } else 02037 #endif 02038 xmlDocDumpMemory(doc, (xmlChar **) &base, &size); 02039 } 02040 res = compareFileMem(result, base, size); 02041 } 02042 if (doc != NULL) { 02043 if (base != NULL) 02044 xmlFree((char *)base); 02045 xmlFreeDoc(doc); 02046 } 02047 if (res != 0) { 02048 fprintf(stderr, "Result for %s failed\n", filename); 02049 return(-1); 02050 } 02051 if (err != NULL) { 02052 res = compareFileMem(err, testErrors, testErrorsSize); 02053 if (res != 0) { 02054 fprintf(stderr, "Error for %s failed\n", filename); 02055 return(-1); 02056 } 02057 } else if (options & XML_PARSE_DTDVALID) { 02058 if (testErrorsSize != 0) 02059 fprintf(stderr, "Validation for %s failed\n", filename); 02060 } 02061 02062 return(0); 02063 } 02064 02065 #ifdef LIBXML_READER_ENABLED 02066 /************************************************************************ 02067 * * 02068 * Reader based tests * 02069 * * 02070 ************************************************************************/ 02071 02072 static void processNode(FILE *out, xmlTextReaderPtr reader) { 02073 const xmlChar *name, *value; 02074 int type, empty; 02075 02076 type = xmlTextReaderNodeType(reader); 02077 empty = xmlTextReaderIsEmptyElement(reader); 02078 02079 name = xmlTextReaderConstName(reader); 02080 if (name == NULL) 02081 name = BAD_CAST "--"; 02082 02083 value = xmlTextReaderConstValue(reader); 02084 02085 02086 fprintf(out, "%d %d %s %d %d", 02087 xmlTextReaderDepth(reader), 02088 type, 02089 name, 02090 empty, 02091 xmlTextReaderHasValue(reader)); 02092 if (value == NULL) 02093 fprintf(out, "\n"); 02094 else { 02095 fprintf(out, " %s\n", value); 02096 } 02097 } 02098 static int 02099 streamProcessTest(const char *filename, const char *result, const char *err, 02100 xmlTextReaderPtr reader, const char *rng) { 02101 int ret; 02102 char *temp = NULL; 02103 FILE *t = NULL; 02104 02105 if (reader == NULL) 02106 return(-1); 02107 02108 nb_tests++; 02109 if (result != NULL) { 02110 temp = resultFilename(filename, "", ".res"); 02111 if (temp == NULL) { 02112 fprintf(stderr, "Out of memory\n"); 02113 fatalError(); 02114 } 02115 t = fopen(temp, "wb"); 02116 if (t == NULL) { 02117 fprintf(stderr, "Can't open temp file %s\n", temp); 02118 free(temp); 02119 return(-1); 02120 } 02121 } 02122 #ifdef LIBXML_SCHEMAS_ENABLED 02123 if (rng != NULL) { 02124 ret = xmlTextReaderRelaxNGValidate(reader, rng); 02125 if (ret < 0) { 02126 testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n", 02127 rng); 02128 fclose(t); 02129 if (temp != NULL) { 02130 unlink(temp); 02131 free(temp); 02132 } 02133 return(0); 02134 } 02135 } 02136 #endif 02137 xmlGetWarningsDefaultValue = 1; 02138 ret = xmlTextReaderRead(reader); 02139 while (ret == 1) { 02140 if ((t != NULL) && (rng == NULL)) 02141 processNode(t, reader); 02142 ret = xmlTextReaderRead(reader); 02143 } 02144 if (ret != 0) { 02145 testErrorHandler(NULL, "%s : failed to parse\n", filename); 02146 } 02147 if (rng != NULL) { 02148 if (xmlTextReaderIsValid(reader) != 1) { 02149 testErrorHandler(NULL, "%s fails to validate\n", filename); 02150 } else { 02151 testErrorHandler(NULL, "%s validates\n", filename); 02152 } 02153 } 02154 xmlGetWarningsDefaultValue = 0; 02155 if (t != NULL) { 02156 fclose(t); 02157 ret = compareFiles(temp, result); 02158 if (temp != NULL) { 02159 unlink(temp); 02160 free(temp); 02161 } 02162 if (ret) { 02163 fprintf(stderr, "Result for %s failed\n", filename); 02164 return(-1); 02165 } 02166 } 02167 if (err != NULL) { 02168 ret = compareFileMem(err, testErrors, testErrorsSize); 02169 if (ret != 0) { 02170 fprintf(stderr, "Error for %s failed\n", filename); 02171 printf("%s", testErrors); 02172 return(-1); 02173 } 02174 } 02175 02176 return(0); 02177 } 02178 02189 static int 02190 streamParseTest(const char *filename, const char *result, const char *err, 02191 int options) { 02192 xmlTextReaderPtr reader; 02193 int ret; 02194 02195 reader = xmlReaderForFile(filename, NULL, options); 02196 ret = streamProcessTest(filename, result, err, reader, NULL); 02197 xmlFreeTextReader(reader); 02198 return(ret); 02199 } 02200 02211 static int 02212 walkerParseTest(const char *filename, const char *result, const char *err, 02213 int options) { 02214 xmlDocPtr doc; 02215 xmlTextReaderPtr reader; 02216 int ret; 02217 02218 doc = xmlReadFile(filename, NULL, options); 02219 if (doc == NULL) { 02220 fprintf(stderr, "Failed to parse %s\n", filename); 02221 return(-1); 02222 } 02223 reader = xmlReaderWalker(doc); 02224 ret = streamProcessTest(filename, result, err, reader, NULL); 02225 xmlFreeTextReader(reader); 02226 xmlFreeDoc(doc); 02227 return(ret); 02228 } 02229 02240 static int 02241 streamMemParseTest(const char *filename, const char *result, const char *err, 02242 int options) { 02243 xmlTextReaderPtr reader; 02244 int ret; 02245 const char *base; 02246 int size; 02247 02248 /* 02249 * load and parse the memory 02250 */ 02251 if (loadMem(filename, &base, &size) != 0) { 02252 fprintf(stderr, "Failed to load %s\n", filename); 02253 return(-1); 02254 } 02255 reader = xmlReaderForMemory(base, size, filename, NULL, options); 02256 ret = streamProcessTest(filename, result, err, reader, NULL); 02257 free((char *)base); 02258 xmlFreeTextReader(reader); 02259 return(ret); 02260 } 02261 #endif 02262 02263 #ifdef LIBXML_XPATH_ENABLED 02264 #ifdef LIBXML_DEBUG_ENABLED 02265 /************************************************************************ 02266 * * 02267 * XPath and XPointer based tests * 02268 * * 02269 ************************************************************************/ 02270 02271 static FILE *xpathOutput; 02272 static xmlDocPtr xpathDocument; 02273 02274 static void 02275 testXPath(const char *str, int xptr, int expr) { 02276 xmlXPathObjectPtr res; 02277 xmlXPathContextPtr ctxt; 02278 02279 nb_tests++; 02280 #if defined(LIBXML_XPTR_ENABLED) 02281 if (xptr) { 02282 ctxt = xmlXPtrNewContext(xpathDocument, NULL, NULL); 02283 res = xmlXPtrEval(BAD_CAST str, ctxt); 02284 } else { 02285 #endif 02286 ctxt = xmlXPathNewContext(xpathDocument); 02287 ctxt->node = xmlDocGetRootElement(xpathDocument); 02288 if (expr) 02289 res = xmlXPathEvalExpression(BAD_CAST str, ctxt); 02290 else { 02291 /* res = xmlXPathEval(BAD_CAST str, ctxt); */ 02292 xmlXPathCompExprPtr comp; 02293 02294 comp = xmlXPathCompile(BAD_CAST str); 02295 if (comp != NULL) { 02296 res = xmlXPathCompiledEval(comp, ctxt); 02297 xmlXPathFreeCompExpr(comp); 02298 } else 02299 res = NULL; 02300 } 02301 #if defined(LIBXML_XPTR_ENABLED) 02302 } 02303 #endif 02304 xmlXPathDebugDumpObject(xpathOutput, res, 0); 02305 xmlXPathFreeObject(res); 02306 xmlXPathFreeContext(ctxt); 02307 } 02308 02319 static int 02320 xpathCommonTest(const char *filename, const char *result, 02321 int xptr, int expr) { 02322 FILE *input; 02323 char expression[5000]; 02324 int len, ret = 0; 02325 char *temp; 02326 02327 temp = resultFilename(filename, "", ".res"); 02328 if (temp == NULL) { 02329 fprintf(stderr, "Out of memory\n"); 02330 fatalError(); 02331 } 02332 xpathOutput = fopen(temp, "wb"); 02333 if (xpathOutput == NULL) { 02334 fprintf(stderr, "failed to open output file %s\n", temp); 02335 free(temp); 02336 return(-1); 02337 } 02338 02339 input = fopen(filename, "rb"); 02340 if (input == NULL) { 02341 xmlGenericError(xmlGenericErrorContext, 02342 "Cannot open %s for reading\n", filename); 02343 free(temp); 02344 return(-1); 02345 } 02346 while (fgets(expression, 4500, input) != NULL) { 02347 len = strlen(expression); 02348 len--; 02349 while ((len >= 0) && 02350 ((expression[len] == '\n') || (expression[len] == '\t') || 02351 (expression[len] == '\r') || (expression[len] == ' '))) len--; 02352 expression[len + 1] = 0; 02353 if (len >= 0) { 02354 fprintf(xpathOutput, 02355 "\n========================\nExpression: %s\n", 02356 expression) ; 02357 testXPath(expression, xptr, expr); 02358 } 02359 } 02360 02361 fclose(input); 02362 fclose(xpathOutput); 02363 if (result != NULL) { 02364 ret = compareFiles(temp, result); 02365 if (ret) { 02366 fprintf(stderr, "Result for %s failed\n", filename); 02367 } 02368 } 02369 02370 if (temp != NULL) { 02371 unlink(temp); 02372 free(temp); 02373 } 02374 return(ret); 02375 } 02376 02387 static int 02388 xpathExprTest(const char *filename, const char *result, 02389 const char *err ATTRIBUTE_UNUSED, 02390 int options ATTRIBUTE_UNUSED) { 02391 return(xpathCommonTest(filename, result, 0, 1)); 02392 } 02393 02405 static int 02406 xpathDocTest(const char *filename, 02407 const char *resul ATTRIBUTE_UNUSED, 02408 const char *err ATTRIBUTE_UNUSED, 02409 int options) { 02410 02411 char pattern[500]; 02412 char result[500]; 02413 glob_t globbuf; 02414 size_t i; 02415 int ret = 0, res; 02416 02417 xpathDocument = xmlReadFile(filename, NULL, 02418 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT); 02419 if (xpathDocument == NULL) { 02420 fprintf(stderr, "Failed to load %s\n", filename); 02421 return(-1); 02422 } 02423 02424 snprintf(pattern, 499, "./test/XPath/tests/%s*", baseFilename(filename)); 02425 pattern[499] = 0; 02426 globbuf.gl_offs = 0; 02427 glob(pattern, GLOB_DOOFFS, NULL, &globbuf); 02428 for (i = 0;i < globbuf.gl_pathc;i++) { 02429 snprintf(result, 499, "result/XPath/tests/%s", 02430 baseFilename(globbuf.gl_pathv[i])); 02431 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 0, 0); 02432 if (res != 0) 02433 ret = res; 02434 } 02435 globfree(&globbuf); 02436 02437 xmlFreeDoc(xpathDocument); 02438 return(ret); 02439 } 02440 02441 #ifdef LIBXML_XPTR_ENABLED 02442 02453 static int 02454 xptrDocTest(const char *filename, 02455 const char *resul ATTRIBUTE_UNUSED, 02456 const char *err ATTRIBUTE_UNUSED, 02457 int options) { 02458 02459 char pattern[500]; 02460 char result[500]; 02461 glob_t globbuf; 02462 size_t i; 02463 int ret = 0, res; 02464 02465 xpathDocument = xmlReadFile(filename, NULL, 02466 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT); 02467 if (xpathDocument == NULL) { 02468 fprintf(stderr, "Failed to load %s\n", filename); 02469 return(-1); 02470 } 02471 02472 snprintf(pattern, 499, "./test/XPath/xptr/%s*", baseFilename(filename)); 02473 pattern[499] = 0; 02474 globbuf.gl_offs = 0; 02475 glob(pattern, GLOB_DOOFFS, NULL, &globbuf); 02476 for (i = 0;i < globbuf.gl_pathc;i++) { 02477 snprintf(result, 499, "result/XPath/xptr/%s", 02478 baseFilename(globbuf.gl_pathv[i])); 02479 res = xpathCommonTest(globbuf.gl_pathv[i], &result[0], 1, 0); 02480 if (res != 0) 02481 ret = res; 02482 } 02483 globfree(&globbuf); 02484 02485 xmlFreeDoc(xpathDocument); 02486 return(ret); 02487 } 02488 #endif /* LIBXML_XPTR_ENABLED */ 02489 02501 static int 02502 xmlidDocTest(const char *filename, 02503 const char *result, 02504 const char *err, 02505 int options) { 02506 02507 int res = 0; 02508 int ret = 0; 02509 char *temp; 02510 02511 xpathDocument = xmlReadFile(filename, NULL, 02512 options | XML_PARSE_DTDATTR | XML_PARSE_NOENT); 02513 if (xpathDocument == NULL) { 02514 fprintf(stderr, "Failed to load %s\n", filename); 02515 return(-1); 02516 } 02517 02518 temp = resultFilename(filename, "", ".res"); 02519 if (temp == NULL) { 02520 fprintf(stderr, "Out of memory\n"); 02521 fatalError(); 02522 } 02523 xpathOutput = fopen(temp, "wb"); 02524 if (xpathOutput == NULL) { 02525 fprintf(stderr, "failed to open output file %s\n", temp); 02526 xmlFreeDoc(xpathDocument); 02527 free(temp); 02528 return(-1); 02529 } 02530 02531 testXPath("id('bar')", 0, 0); 02532 02533 fclose(xpathOutput); 02534 if (result != NULL) { 02535 ret = compareFiles(temp, result); 02536 if (ret) { 02537 fprintf(stderr, "Result for %s failed\n", filename); 02538 res = 1; 02539 } 02540 } 02541 02542 if (temp != NULL) { 02543 unlink(temp); 02544 free(temp); 02545 } 02546 xmlFreeDoc(xpathDocument); 02547 02548 if (err != NULL) { 02549 ret = compareFileMem(err, testErrors, testErrorsSize); 02550 if (ret != 0) { 02551 fprintf(stderr, "Error for %s failed\n", filename); 02552 res = 1; 02553 } 02554 } 02555 return(res); 02556 } 02557 02558 #endif /* LIBXML_DEBUG_ENABLED */ 02559 #endif /* XPATH */ 02560 /************************************************************************ 02561 * * 02562 * URI based tests * 02563 * * 02564 ************************************************************************/ 02565 02566 static void 02567 handleURI(const char *str, const char *base, FILE *o) { 02568 int ret; 02569 xmlURIPtr uri; 02570 xmlChar *res = NULL; 02571 02572 uri = xmlCreateURI(); 02573 02574 if (base == NULL) { 02575 ret = xmlParseURIReference(uri, str); 02576 if (ret != 0) 02577 fprintf(o, "%s : error %d\n", str, ret); 02578 else { 02579 xmlNormalizeURIPath(uri->path); 02580 xmlPrintURI(o, uri); 02581 fprintf(o, "\n"); 02582 } 02583 } else { 02584 res = xmlBuildURI((xmlChar *)str, (xmlChar *) base); 02585 if (res != NULL) { 02586 fprintf(o, "%s\n", (char *) res); 02587 } 02588 else 02589 fprintf(o, "::ERROR::\n"); 02590 } 02591 if (res != NULL) 02592 xmlFree(res); 02593 xmlFreeURI(uri); 02594 } 02595 02606 static int 02607 uriCommonTest(const char *filename, 02608 const char *result, 02609 const char *err, 02610 const char *base) { 02611 char *temp; 02612 FILE *o, *f; 02613 char str[1024]; 02614 int res = 0, i, ret; 02615 02616 temp = resultFilename(filename, "", ".res"); 02617 if (temp == NULL) { 02618 fprintf(stderr, "Out of memory\n"); 02619 fatalError(); 02620 } 02621 o = fopen(temp, "wb"); 02622 if (o == NULL) { 02623 fprintf(stderr, "failed to open output file %s\n", temp); 02624 free(temp); 02625 return(-1); 02626 } 02627 f = fopen(filename, "rb"); 02628 if (f == NULL) { 02629 fprintf(stderr, "failed to open input file %s\n", filename); 02630 fclose(o); 02631 if (temp != NULL) { 02632 unlink(temp); 02633 free(temp); 02634 } 02635 return(-1); 02636 } 02637 02638 while (1) { 02639 /* 02640 * read one line in string buffer. 02641 */ 02642 if (fgets (&str[0], sizeof (str) - 1, f) == NULL) 02643 break; 02644 02645 /* 02646 * remove the ending spaces 02647 */ 02648 i = strlen(str); 02649 while ((i > 0) && 02650 ((str[i - 1] == '\n') || (str[i - 1] == '\r') || 02651 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) { 02652 i--; 02653 str[i] = 0; 02654 } 02655 nb_tests++; 02656 handleURI(str, base, o); 02657 } 02658 02659 fclose(f); 02660 fclose(o); 02661 02662 if (result != NULL) { 02663 ret = compareFiles(temp, result); 02664 if (ret) { 02665 fprintf(stderr, "Result for %s failed\n", filename); 02666 res = 1; 02667 } 02668 } 02669 if (err != NULL) { 02670 ret = compareFileMem(err, testErrors, testErrorsSize); 02671 if (ret != 0) { 02672 fprintf(stderr, "Error for %s failed\n", filename); 02673 res = 1; 02674 } 02675 } 02676 02677 if (temp != NULL) { 02678 unlink(temp); 02679 free(temp); 02680 } 02681 return(res); 02682 } 02683 02694 static int 02695 uriParseTest(const char *filename, 02696 const char *result, 02697 const char *err, 02698 int options ATTRIBUTE_UNUSED) { 02699 return(uriCommonTest(filename, result, err, NULL)); 02700 } 02701 02713 static int 02714 uriBaseTest(const char *filename, 02715 const char *result, 02716 const char *err, 02717 int options ATTRIBUTE_UNUSED) { 02718 return(uriCommonTest(filename, result, err, 02719 "http://foo.com/path/to/index.html?orig#help")); 02720 } 02721 02722 static int urip_success = 1; 02723 static int urip_current = 0; 02724 static const char *urip_testURLs[] = { 02725 "urip://example.com/a b.html", 02726 "urip://example.com/a%20b.html", 02727 "file:///path/to/a b.html", 02728 "file:///path/to/a%20b.html", 02729 "/path/to/a b.html", 02730 "/path/to/a%20b.html", 02731 "urip://example.com/résumé.html", 02732 "urip://example.com/test?a=1&b=2%263&c=4#foo", 02733 NULL 02734 }; 02735 static const char *urip_rcvsURLs[] = { 02736 /* it is an URI the strings must be escaped */ 02737 "urip://example.com/a%20b.html", 02738 /* check that % escaping is not broken */ 02739 "urip://example.com/a%20b.html", 02740 /* it's an URI path the strings must be escaped */ 02741 "file:///path/to/a%20b.html", 02742 /* check that % escaping is not broken */ 02743 "file:///path/to/a%20b.html", 02744 /* this is not an URI, this is a path, so this should not be escaped */ 02745 "/path/to/a b.html", 02746 /* check that paths with % are not broken */ 02747 "/path/to/a%20b.html", 02748 /* out of context the encoding can't be guessed byte by byte conversion */ 02749 "urip://example.com/r%E9sum%E9.html", 02750 /* verify we don't destroy URIs especially the query part */ 02751 "urip://example.com/test?a=1&b=2%263&c=4#foo", 02752 NULL 02753 }; 02754 static const char *urip_res = "<list/>"; 02755 static const char *urip_cur = NULL; 02756 static int urip_rlen; 02757 02766 static int 02767 uripMatch(const char * URI) { 02768 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog"))) 02769 return(0); 02770 /* Verify we received the escaped URL */ 02771 if (strcmp(urip_rcvsURLs[urip_current], URI)) 02772 urip_success = 0; 02773 return(1); 02774 } 02775 02785 static void * 02786 uripOpen(const char * URI) { 02787 if ((URI == NULL) || (!strcmp(URI, "file:///etc/xml/catalog"))) 02788 return(NULL); 02789 /* Verify we received the escaped URL */ 02790 if (strcmp(urip_rcvsURLs[urip_current], URI)) 02791 urip_success = 0; 02792 urip_cur = urip_res; 02793 urip_rlen = strlen(urip_res); 02794 return((void *) urip_cur); 02795 } 02796 02805 static int 02806 uripClose(void * context) { 02807 if (context == NULL) return(-1); 02808 urip_cur = NULL; 02809 urip_rlen = 0; 02810 return(0); 02811 } 02812 02823 static int 02824 uripRead(void * context, char * buffer, int len) { 02825 const char *ptr = (const char *) context; 02826 02827 if ((context == NULL) || (buffer == NULL) || (len < 0)) 02828 return(-1); 02829 02830 if (len > urip_rlen) len = urip_rlen; 02831 memcpy(buffer, ptr, len); 02832 urip_rlen -= len; 02833 return(len); 02834 } 02835 02836 static int 02837 urip_checkURL(const char *URL) { 02838 xmlDocPtr doc; 02839 02840 doc = xmlReadFile(URL, NULL, 0); 02841 if (doc == NULL) 02842 return(-1); 02843 xmlFreeDoc(doc); 02844 return(1); 02845 } 02846 02858 static int 02859 uriPathTest(const char *filename ATTRIBUTE_UNUSED, 02860 const char *result ATTRIBUTE_UNUSED, 02861 const char *err ATTRIBUTE_UNUSED, 02862 int options ATTRIBUTE_UNUSED) { 02863 int parsed; 02864 int failures = 0; 02865 02866 /* 02867 * register the new I/O handlers 02868 */ 02869 if (xmlRegisterInputCallbacks(uripMatch, uripOpen, uripRead, uripClose) < 0) 02870 { 02871 fprintf(stderr, "failed to register HTTP handler\n"); 02872 return(-1); 02873 } 02874 02875 for (urip_current = 0;urip_testURLs[urip_current] != NULL;urip_current++) { 02876 urip_success = 1; 02877 parsed = urip_checkURL(urip_testURLs[urip_current]); 02878 if (urip_success != 1) { 02879 fprintf(stderr, "failed the URL passing test for %s", 02880 urip_testURLs[urip_current]); 02881 failures++; 02882 } else if (parsed != 1) { 02883 fprintf(stderr, "failed the parsing test for %s", 02884 urip_testURLs[urip_current]); 02885 failures++; 02886 } 02887 nb_tests++; 02888 } 02889 02890 xmlPopInputCallbacks(); 02891 return(failures); 02892 } 02893 02894 #ifdef LIBXML_SCHEMAS_ENABLED 02895 /************************************************************************ 02896 * * 02897 * Schemas tests * 02898 * * 02899 ************************************************************************/ 02900 static int 02901 schemasOneTest(const char *sch, 02902 const char *filename, 02903 const char *result, 02904 const char *err, 02905 int options, 02906 xmlSchemaPtr schemas) { 02907 xmlDocPtr doc; 02908 xmlSchemaValidCtxtPtr ctxt; 02909 int ret = 0; 02910 int validResult = 0; 02911 char *temp; 02912 FILE *schemasOutput; 02913 02914 doc = xmlReadFile(filename, NULL, options); 02915 if (doc == NULL) { 02916 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch); 02917 return(-1); 02918 } 02919 02920 temp = resultFilename(result, "", ".res"); 02921 if (temp == NULL) { 02922 fprintf(stderr, "Out of memory\n"); 02923 fatalError(); 02924 } 02925 schemasOutput = fopen(temp, "wb"); 02926 if (schemasOutput == NULL) { 02927 fprintf(stderr, "failed to open output file %s\n", temp); 02928 xmlFreeDoc(doc); 02929 free(temp); 02930 return(-1); 02931 } 02932 02933 ctxt = xmlSchemaNewValidCtxt(schemas); 02934 xmlSchemaSetValidErrors(ctxt, 02935 (xmlSchemaValidityErrorFunc) testErrorHandler, 02936 (xmlSchemaValidityWarningFunc) testErrorHandler, 02937 ctxt); 02938 validResult = xmlSchemaValidateDoc(ctxt, doc); 02939 if (validResult == 0) { 02940 fprintf(schemasOutput, "%s validates\n", filename); 02941 } else if (validResult > 0) { 02942 fprintf(schemasOutput, "%s fails to validate\n", filename); 02943 } else { 02944 fprintf(schemasOutput, "%s validation generated an internal error\n", 02945 filename); 02946 } 02947 fclose(schemasOutput); 02948 if (result) { 02949 if (compareFiles(temp, result)) { 02950 fprintf(stderr, "Result for %s on %s failed\n", filename, sch); 02951 ret = 1; 02952 } 02953 } 02954 if (temp != NULL) { 02955 unlink(temp); 02956 free(temp); 02957 } 02958 02959 if ((validResult != 0) && (err != NULL)) { 02960 if (compareFileMem(err, testErrors, testErrorsSize)) { 02961 fprintf(stderr, "Error for %s on %s failed\n", filename, sch); 02962 ret = 1; 02963 } 02964 } 02965 02966 xmlSchemaFreeValidCtxt(ctxt); 02967 xmlFreeDoc(doc); 02968 return(ret); 02969 } 02981 static int 02982 schemasTest(const char *filename, 02983 const char *resul ATTRIBUTE_UNUSED, 02984 const char *errr ATTRIBUTE_UNUSED, 02985 int options) { 02986 const char *base = baseFilename(filename); 02987 const char *base2; 02988 const char *instance; 02989 xmlSchemaParserCtxtPtr ctxt; 02990 xmlSchemaPtr schemas; 02991 int res = 0, len, ret; 02992 char pattern[500]; 02993 char prefix[500]; 02994 char result[500]; 02995 char err[500]; 02996 glob_t globbuf; 02997 size_t i; 02998 char count = 0; 02999 03000 /* first compile the schemas if possible */ 03001 ctxt = xmlSchemaNewParserCtxt(filename); 03002 xmlSchemaSetParserErrors(ctxt, 03003 (xmlSchemaValidityErrorFunc) testErrorHandler, 03004 (xmlSchemaValidityWarningFunc) testErrorHandler, 03005 ctxt); 03006 schemas = xmlSchemaParse(ctxt); 03007 xmlSchemaFreeParserCtxt(ctxt); 03008 03009 /* 03010 * most of the mess is about the output filenames generated by the Makefile 03011 */ 03012 len = strlen(base); 03013 if ((len > 499) || (len < 5)) { 03014 xmlSchemaFree(schemas); 03015 return(-1); 03016 } 03017 len -= 4; /* remove trailing .xsd */ 03018 if (base[len - 2] == '_') { 03019 len -= 2; /* remove subtest number */ 03020 } 03021 if (base[len - 2] == '_') { 03022 len -= 2; /* remove subtest number */ 03023 } 03024 memcpy(prefix, base, len); 03025 prefix[len] = 0; 03026 03027 snprintf(pattern, 499, "./test/schemas/%s_?.xml", prefix); 03028 pattern[499] = 0; 03029 03030 if (base[len] == '_') { 03031 len += 2; 03032 memcpy(prefix, base, len); 03033 prefix[len] = 0; 03034 } 03035 03036 globbuf.gl_offs = 0; 03037 glob(pattern, GLOB_DOOFFS, NULL, &globbuf); 03038 for (i = 0;i < globbuf.gl_pathc;i++) { 03039 testErrorsSize = 0; 03040 testErrors[0] = 0; 03041 instance = globbuf.gl_pathv[i]; 03042 base2 = baseFilename(instance); 03043 len = strlen(base2); 03044 if ((len > 6) && (base2[len - 6] == '_')) { 03045 count = base2[len - 5]; 03046 snprintf(result, 499, "result/schemas/%s_%c", 03047 prefix, count); 03048 result[499] = 0; 03049 snprintf(err, 499, "result/schemas/%s_%c.err", 03050 prefix, count); 03051 err[499] = 0; 03052 } else { 03053 fprintf(stderr, "don't know how to process %s\n", instance); 03054 continue; 03055 } 03056 if (schemas == NULL) { 03057 } else { 03058 nb_tests++; 03059 ret = schemasOneTest(filename, instance, result, err, 03060 options, schemas); 03061 if (ret != 0) 03062 res = ret; 03063 } 03064 } 03065 globfree(&globbuf); 03066 xmlSchemaFree(schemas); 03067 03068 return(res); 03069 } 03070 03071 /************************************************************************ 03072 * * 03073 * Schemas tests * 03074 * * 03075 ************************************************************************/ 03076 static int 03077 rngOneTest(const char *sch, 03078 const char *filename, 03079 const char *result, 03080 const char *err, 03081 int options, 03082 xmlRelaxNGPtr schemas) { 03083 xmlDocPtr doc; 03084 xmlRelaxNGValidCtxtPtr ctxt; 03085 int ret = 0; 03086 char *temp; 03087 FILE *schemasOutput; 03088 03089 doc = xmlReadFile(filename, NULL, options); 03090 if (doc == NULL) { 03091 fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch); 03092 return(-1); 03093 } 03094 03095 temp = resultFilename(result, "", ".res"); 03096 if (temp == NULL) { 03097 fprintf(stderr, "Out of memory\n"); 03098 fatalError(); 03099 } 03100 schemasOutput = fopen(temp, "wb"); 03101 if (schemasOutput == NULL) { 03102 fprintf(stderr, "failed to open output file %s\n", temp); 03103 xmlFreeDoc(doc); 03104 free(temp); 03105 return(-1); 03106 } 03107 03108 ctxt = xmlRelaxNGNewValidCtxt(schemas); 03109 xmlRelaxNGSetValidErrors(ctxt, 03110 (xmlRelaxNGValidityErrorFunc) testErrorHandler, 03111 (xmlRelaxNGValidityWarningFunc) testErrorHandler, 03112 ctxt); 03113 ret = xmlRelaxNGValidateDoc(ctxt, doc); 03114 if (ret == 0) { 03115 testErrorHandler(NULL, "%s validates\n", filename); 03116 } else if (ret > 0) { 03117 testErrorHandler(NULL, "%s fails to validate\n", filename); 03118 } else { 03119 testErrorHandler(NULL, "%s validation generated an internal error\n", 03120 filename); 03121 } 03122 fclose(schemasOutput); 03123 ret = 0; 03124 if (result) { 03125 if (compareFiles(temp, result)) { 03126 fprintf(stderr, "Result for %s on %s failed\n", filename, sch); 03127 ret = 1; 03128 } 03129 } 03130 if (temp != NULL) { 03131 unlink(temp); 03132 free(temp); 03133 } 03134 03135 if (err != NULL) { 03136 if (compareFileMem(err, testErrors, testErrorsSize)) { 03137 fprintf(stderr, "Error for %s on %s failed\n", filename, sch); 03138 ret = 1; 03139 printf("%s", testErrors); 03140 } 03141 } 03142 03143 03144 xmlRelaxNGFreeValidCtxt(ctxt); 03145 xmlFreeDoc(doc); 03146 return(ret); 03147 } 03158 static int 03159 rngTest(const char *filename, 03160 const char *resul ATTRIBUTE_UNUSED, 03161 const char *errr ATTRIBUTE_UNUSED, 03162 int options) { 03163 const char *base = baseFilename(filename); 03164 const char *base2; 03165 const char *instance; 03166 xmlRelaxNGParserCtxtPtr ctxt; 03167 xmlRelaxNGPtr schemas; 03168 int res = 0, len, ret = 0; 03169 char pattern[500]; 03170 char prefix[500]; 03171 char result[500]; 03172 char err[500]; 03173 glob_t globbuf; 03174 size_t i; 03175 char count = 0; 03176 03177 /* first compile the schemas if possible */ 03178 ctxt = xmlRelaxNGNewParserCtxt(filename); 03179 xmlRelaxNGSetParserErrors(ctxt, 03180 (xmlRelaxNGValidityErrorFunc) testErrorHandler, 03181 (xmlRelaxNGValidityWarningFunc) testErrorHandler, 03182 ctxt); 03183 schemas = xmlRelaxNGParse(ctxt); 03184 xmlRelaxNGFreeParserCtxt(ctxt); 03185 03186 /* 03187 * most of the mess is about the output filenames generated by the Makefile 03188 */ 03189 len = strlen(base); 03190 if ((len > 499) || (len < 5)) { 03191 xmlRelaxNGFree(schemas); 03192 return(-1); 03193 } 03194 len -= 4; /* remove trailing .rng */ 03195 memcpy(prefix, base, len); 03196 prefix[len] = 0; 03197 03198 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix); 03199 pattern[499] = 0; 03200 03201 globbuf.gl_offs = 0; 03202 glob(pattern, GLOB_DOOFFS, NULL, &globbuf); 03203 for (i = 0;i < globbuf.gl_pathc;i++) { 03204 testErrorsSize = 0; 03205 testErrors[0] = 0; 03206 instance = globbuf.gl_pathv[i]; 03207 base2 = baseFilename(instance); 03208 len = strlen(base2); 03209 if ((len > 6) && (base2[len - 6] == '_')) { 03210 count = base2[len - 5]; 03211 snprintf(result, 499, "result/relaxng/%s_%c", 03212 prefix, count); 03213 result[499] = 0; 03214 snprintf(err, 499, "result/relaxng/%s_%c.err", 03215 prefix, count); 03216 err[499] = 0; 03217 } else { 03218 fprintf(stderr, "don't know how to process %s\n", instance); 03219 continue; 03220 } 03221 if (schemas == NULL) { 03222 } else { 03223 nb_tests++; 03224 ret = rngOneTest(filename, instance, result, err, 03225 options, schemas); 03226 if (res != 0) 03227 ret = res; 03228 } 03229 } 03230 globfree(&globbuf); 03231 xmlRelaxNGFree(schemas); 03232 03233 return(ret); 03234 } 03235 03236 #ifdef LIBXML_READER_ENABLED 03237 03247 static int 03248 rngStreamTest(const char *filename, 03249 const char *resul ATTRIBUTE_UNUSED, 03250 const char *errr ATTRIBUTE_UNUSED, 03251 int options) { 03252 const char *base = baseFilename(filename); 03253 const char *base2; 03254 const char *instance; 03255 int res = 0, len, ret; 03256 char pattern[500]; 03257 char prefix[500]; 03258 char result[500]; 03259 char err[500]; 03260 glob_t globbuf; 03261 size_t i; 03262 char count = 0; 03263 xmlTextReaderPtr reader; 03264 int disable_err = 0; 03265 03266 /* 03267 * most of the mess is about the output filenames generated by the Makefile 03268 */ 03269 len = strlen(base); 03270 if ((len > 499) || (len < 5)) { 03271 fprintf(stderr, "len(base) == %d !\n", len); 03272 return(-1); 03273 } 03274 len -= 4; /* remove trailing .rng */ 03275 memcpy(prefix, base, len); 03276 prefix[len] = 0; 03277 03278 /* 03279 * strictly unifying the error messages is nearly impossible this 03280 * hack is also done in the Makefile 03281 */ 03282 if ((!strcmp(prefix, "tutor10_1")) || (!strcmp(prefix, "tutor10_2")) || 03283 (!strcmp(prefix, "tutor3_2")) || (!strcmp(prefix, "307377")) || 03284 (!strcmp(prefix, "tutor8_2"))) 03285 disable_err = 1; 03286 03287 snprintf(pattern, 499, "./test/relaxng/%s_?.xml", prefix); 03288 pattern[499] = 0; 03289 03290 globbuf.gl_offs = 0; 03291 glob(pattern, GLOB_DOOFFS, NULL, &globbuf); 03292 for (i = 0;i < globbuf.gl_pathc;i++) { 03293 testErrorsSize = 0; 03294 testErrors[0] = 0; 03295 instance = globbuf.gl_pathv[i]; 03296 base2 = baseFilename(instance); 03297 len = strlen(base2); 03298 if ((len > 6) && (base2[len - 6] == '_')) { 03299 count = base2[len - 5]; 03300 snprintf(result, 499, "result/relaxng/%s_%c", 03301 prefix, count); 03302 result[499] = 0; 03303 snprintf(err, 499, "result/relaxng/%s_%c.err", 03304 prefix, count); 03305 err[499] = 0; 03306 } else { 03307 fprintf(stderr, "don't know how to process %s\n", instance); 03308 continue; 03309 } 03310 reader = xmlReaderForFile(instance, NULL, options); 03311 if (reader == NULL) { 03312 fprintf(stderr, "Failed to build reder for %s\n", instance); 03313 } 03314 if (disable_err == 1) 03315 ret = streamProcessTest(instance, result, NULL, reader, filename); 03316 else 03317 ret = streamProcessTest(instance, result, err, reader, filename); 03318 xmlFreeTextReader(reader); 03319 if (ret != 0) { 03320 fprintf(stderr, "instance %s failed\n", instance); 03321 res = ret; 03322 } 03323 } 03324 globfree(&globbuf); 03325 03326 return(res); 03327 } 03328 #endif /* READER */ 03329 03330 #endif 03331 03332 #ifdef LIBXML_PATTERN_ENABLED 03333 #ifdef LIBXML_READER_ENABLED 03334 /************************************************************************ 03335 * * 03336 * Patterns tests * 03337 * * 03338 ************************************************************************/ 03339 static void patternNode(FILE *out, xmlTextReaderPtr reader, 03340 const char *pattern, xmlPatternPtr patternc, 03341 xmlStreamCtxtPtr patstream) { 03342 xmlChar *path = NULL; 03343 int match = -1; 03344 int type, empty; 03345 03346 type = xmlTextReaderNodeType(reader); 03347 empty = xmlTextReaderIsEmptyElement(reader); 03348 03349 if (type == XML_READER_TYPE_ELEMENT) { 03350 /* do the check only on element start */ 03351 match = xmlPatternMatch(patternc, xmlTextReaderCurrentNode(reader)); 03352 03353 if (match) { 03354 path = xmlGetNodePath(xmlTextReaderCurrentNode(reader)); 03355 fprintf(out, "Node %s matches pattern %s\n", path, pattern); 03356 } 03357 } 03358 if (patstream != NULL) { 03359 int ret; 03360 03361 if (type == XML_READER_TYPE_ELEMENT) { 03362 ret = xmlStreamPush(patstream, 03363 xmlTextReaderConstLocalName(reader), 03364 xmlTextReaderConstNamespaceUri(reader)); 03365 if (ret < 0) { 03366 fprintf(out, "xmlStreamPush() failure\n"); 03367 xmlFreeStreamCtxt(patstream); 03368 patstream = NULL; 03369 } else if (ret != match) { 03370 if (path == NULL) { 03371 path = xmlGetNodePath( 03372 xmlTextReaderCurrentNode(reader)); 03373 } 03374 fprintf(out, 03375 "xmlPatternMatch and xmlStreamPush disagree\n"); 03376 fprintf(out, 03377 " pattern %s node %s\n", 03378 pattern, path); 03379 } 03380 03381 03382 } 03383 if ((type == XML_READER_TYPE_END_ELEMENT) || 03384 ((type == XML_READER_TYPE_ELEMENT) && (empty))) { 03385 ret = xmlStreamPop(patstream); 03386 if (ret < 0) { 03387 fprintf(out, "xmlStreamPop() failure\n"); 03388 xmlFreeStreamCtxt(patstream); 03389 patstream = NULL; 03390 } 03391 } 03392 } 03393 if (path != NULL) 03394 xmlFree(path); 03395 } 03396 03407 static int 03408 patternTest(const char *filename, 03409 const char *resul ATTRIBUTE_UNUSED, 03410 const char *err ATTRIBUTE_UNUSED, 03411 int options) { 03412 xmlPatternPtr patternc = NULL; 03413 xmlStreamCtxtPtr patstream = NULL; 03414 FILE *o, *f; 03415 char str[1024]; 03416 char xml[500]; 03417 char result[500]; 03418 int len, i; 03419 int ret = 0, res; 03420 char *temp; 03421 xmlTextReaderPtr reader; 03422 xmlDocPtr doc; 03423 03424 len = strlen(filename); 03425 len -= 4; 03426 memcpy(xml, filename, len); 03427 xml[len] = 0; 03428 snprintf(result, 499, "result/pattern/%s", baseFilename(xml)); 03429 result[499] = 0; 03430 memcpy(xml + len, ".xml", 5); 03431 03432 if (!checkTestFile(xml)) { 03433 fprintf(stderr, "Missing xml file %s\n", xml); 03434 return(-1); 03435 } 03436 if (!checkTestFile(result)) { 03437 fprintf(stderr, "Missing result file %s\n", result); 03438 return(-1); 03439 } 03440 f = fopen(filename, "rb"); 03441 if (f == NULL) { 03442 fprintf(stderr, "Failed to open %s\n", filename); 03443 return(-1); 03444 } 03445 temp = resultFilename(filename, "", ".res"); 03446 if (temp == NULL) { 03447 fprintf(stderr, "Out of memory\n"); 03448 fatalError(); 03449 } 03450 o = fopen(temp, "wb"); 03451 if (o == NULL) { 03452 fprintf(stderr, "failed to open output file %s\n", temp); 03453 fclose(f); 03454 free(temp); 03455 return(-1); 03456 } 03457 while (1) { 03458 /* 03459 * read one line in string buffer. 03460 */ 03461 if (fgets (&str[0], sizeof (str) - 1, f) == NULL) 03462 break; 03463 03464 /* 03465 * remove the ending spaces 03466 */ 03467 i = strlen(str); 03468 while ((i > 0) && 03469 ((str[i - 1] == '\n') || (str[i - 1] == '\r') || 03470 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) { 03471 i--; 03472 str[i] = 0; 03473 } 03474 doc = xmlReadFile(xml, NULL, options); 03475 if (doc == NULL) { 03476 fprintf(stderr, "Failed to parse %s\n", xml); 03477 ret = 1; 03478 } else { 03479 xmlNodePtr root; 03480 const xmlChar *namespaces[22]; 03481 int j; 03482 xmlNsPtr ns; 03483 03484 root = xmlDocGetRootElement(doc); 03485 for (ns = root->nsDef, j = 0;ns != NULL && j < 20;ns=ns->next) { 03486 namespaces[j++] = ns->href; 03487 namespaces[j++] = ns->prefix; 03488 } 03489 namespaces[j++] = NULL; 03490 namespaces[j] = NULL; 03491 03492 patternc = xmlPatterncompile((const xmlChar *) str, doc->dict, 03493 0, &namespaces[0]); 03494 if (patternc == NULL) { 03495 testErrorHandler(NULL, 03496 "Pattern %s failed to compile\n", str); 03497 xmlFreeDoc(doc); 03498 ret = 1; 03499 continue; 03500 } 03501 patstream = xmlPatternGetStreamCtxt(patternc); 03502 if (patstream != NULL) { 03503 ret = xmlStreamPush(patstream, NULL, NULL); 03504 if (ret < 0) { 03505 fprintf(stderr, "xmlStreamPush() failure\n"); 03506 xmlFreeStreamCtxt(patstream); 03507 patstream = NULL; 03508 } 03509 } 03510 nb_tests++; 03511 03512 reader = xmlReaderWalker(doc); 03513 res = xmlTextReaderRead(reader); 03514 while (res == 1) { 03515 patternNode(o, reader, str, patternc, patstream); 03516 res = xmlTextReaderRead(reader); 03517 } 03518 if (res != 0) { 03519 fprintf(o, "%s : failed to parse\n", filename); 03520 } 03521 xmlFreeTextReader(reader); 03522 xmlFreeDoc(doc); 03523 xmlFreeStreamCtxt(patstream); 03524 patstream = NULL; 03525 xmlFreePattern(patternc); 03526 03527 } 03528 } 03529 03530 fclose(f); 03531 fclose(o); 03532 03533 ret = compareFiles(temp, result); 03534 if (ret) { 03535 fprintf(stderr, "Result for %s failed\n", filename); 03536 ret = 1; 03537 } 03538 if (temp != NULL) { 03539 unlink(temp); 03540 free(temp); 03541 } 03542 return(ret); 03543 } 03544 #endif /* READER */ 03545 #endif /* PATTERN */ 03546 #ifdef LIBXML_C14N_ENABLED 03547 /************************************************************************ 03548 * * 03549 * Canonicalization tests * 03550 * * 03551 ************************************************************************/ 03552 static xmlXPathObjectPtr 03553 load_xpath_expr (xmlDocPtr parent_doc, const char* filename) { 03554 xmlXPathObjectPtr xpath; 03555 xmlDocPtr doc; 03556 xmlChar *expr; 03557 xmlXPathContextPtr ctx; 03558 xmlNodePtr node; 03559 xmlNsPtr ns; 03560 03561 /* 03562 * load XPath expr as a file 03563 */ 03564 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; 03565 xmlSubstituteEntitiesDefault(1); 03566 03567 doc = xmlReadFile(filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT); 03568 if (doc == NULL) { 03569 fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename); 03570 return(NULL); 03571 } 03572 03573 /* 03574 * Check the document is of the right kind 03575 */ 03576 if(xmlDocGetRootElement(doc) == NULL) { 03577 fprintf(stderr,"Error: empty document for file \"%s\"\n", filename); 03578 xmlFreeDoc(doc); 03579 return(NULL); 03580 } 03581 03582 node = doc->children; 03583 while(node != NULL && !xmlStrEqual(node->name, (const xmlChar *)"XPath")) { 03584 node = node->next; 03585 } 03586 03587 if(node == NULL) { 03588 fprintf(stderr,"Error: XPath element expected in the file \"%s\"\n", filename); 03589 xmlFreeDoc(doc); 03590 return(NULL); 03591 } 03592 03593 expr = xmlNodeGetContent(node); 03594 if(expr == NULL) { 03595 fprintf(stderr,"Error: XPath content element is NULL \"%s\"\n", filename); 03596 xmlFreeDoc(doc); 03597 return(NULL); 03598 } 03599 03600 ctx = xmlXPathNewContext(parent_doc); 03601 if(ctx == NULL) { 03602 fprintf(stderr,"Error: unable to create new context\n"); 03603 xmlFree(expr); 03604 xmlFreeDoc(doc); 03605 return(NULL); 03606 } 03607 03608 /* 03609 * Register namespaces 03610 */ 03611 ns = node->nsDef; 03612 while(ns != NULL) { 03613 if(xmlXPathRegisterNs(ctx, ns->prefix, ns->href) != 0) { 03614 fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", ns->prefix, ns->href); 03615 xmlFree(expr); 03616 xmlXPathFreeContext(ctx); 03617 xmlFreeDoc(doc); 03618 return(NULL); 03619 } 03620 ns = ns->next; 03621 } 03622 03623 /* 03624 * Evaluate xpath 03625 */ 03626 xpath = xmlXPathEvalExpression(expr, ctx); 03627 if(xpath == NULL) { 03628 fprintf(stderr,"Error: unable to evaluate xpath expression\n"); 03629 xmlFree(expr); 03630 xmlXPathFreeContext(ctx); 03631 xmlFreeDoc(doc); 03632 return(NULL); 03633 } 03634 03635 /* print_xpath_nodes(xpath->nodesetval); */ 03636 03637 xmlFree(expr); 03638 xmlXPathFreeContext(ctx); 03639 xmlFreeDoc(doc); 03640 return(xpath); 03641 } 03642 03643 /* 03644 * Macro used to grow the current buffer. 03645 */ 03646 #define xxx_growBufferReentrant() { \ 03647 buffer_size *= 2; \ 03648 buffer = (xmlChar **) \ 03649 xmlRealloc(buffer, buffer_size * sizeof(xmlChar*)); \ 03650 if (buffer == NULL) { \ 03651 perror("realloc failed"); \ 03652 return(NULL); \ 03653 } \ 03654 } 03655 03656 static xmlChar ** 03657 parse_list(xmlChar *str) { 03658 xmlChar **buffer; 03659 xmlChar **out = NULL; 03660 int buffer_size = 0; 03661 int len; 03662 03663 if(str == NULL) { 03664 return(NULL); 03665 } 03666 03667 len = xmlStrlen(str); 03668 if((str[0] == '\'') && (str[len - 1] == '\'')) { 03669 str[len - 1] = '\0'; 03670 str++; 03671 } 03672 /* 03673 * allocate an translation buffer. 03674 */ 03675 buffer_size = 1000; 03676 buffer = (xmlChar **) xmlMalloc(buffer_size * sizeof(xmlChar*)); 03677 if (buffer == NULL) { 03678 perror("malloc failed"); 03679 return(NULL); 03680 } 03681 out = buffer; 03682 03683 while(*str != '\0') { 03684 if (out - buffer > buffer_size - 10) { 03685 int indx = out - buffer; 03686 03687 xxx_growBufferReentrant(); 03688 out = &buffer[indx]; 03689 } 03690 (*out++) = str; 03691 while(*str != ',' && *str != '\0') ++str; 03692 if(*str == ',') *(str++) = '\0'; 03693 } 03694 (*out) = NULL; 03695 return buffer; 03696 } 03697 03698 static int 03699 c14nRunTest(const char* xml_filename, int with_comments, int mode, 03700 const char* xpath_filename, const char *ns_filename, 03701 const char* result_file) { 03702 xmlDocPtr doc; 03703 xmlXPathObjectPtr xpath = NULL; 03704 xmlChar *result = NULL; 03705 int ret; 03706 xmlChar **inclusive_namespaces = NULL; 03707 const char *nslist = NULL; 03708 int nssize; 03709 03710 03711 /* 03712 * build an XML tree from a the file; we need to add default 03713 * attributes and resolve all character and entities references 03714 */ 03715 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; 03716 xmlSubstituteEntitiesDefault(1); 03717 03718 doc = xmlReadFile(xml_filename, NULL, XML_PARSE_DTDATTR | XML_PARSE_NOENT); 03719 if (doc == NULL) { 03720 fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_filename); 03721 return(-1); 03722 } 03723 03724 /* 03725 * Check the document is of the right kind 03726 */ 03727 if(xmlDocGetRootElement(doc) == NULL) { 03728 fprintf(stderr,"Error: empty document for file \"%s\"\n", xml_filename); 03729 xmlFreeDoc(doc); 03730 return(-1); 03731 } 03732 03733 /* 03734 * load xpath file if specified 03735 */ 03736 if(xpath_filename) { 03737 xpath = load_xpath_expr(doc, xpath_filename); 03738 if(xpath == NULL) { 03739 fprintf(stderr,"Error: unable to evaluate xpath expression\n"); 03740 xmlFreeDoc(doc); 03741 return(-1); 03742 } 03743 } 03744 03745 if (ns_filename != NULL) { 03746 if (loadMem(ns_filename, &nslist, &nssize)) { 03747 fprintf(stderr,"Error: unable to evaluate xpath expression\n"); 03748 if(xpath != NULL) xmlXPathFreeObject(xpath); 03749 xmlFreeDoc(doc); 03750 return(-1); 03751 } 03752 inclusive_namespaces = parse_list((xmlChar *) nslist); 03753 } 03754 03755 /* 03756 * Canonical form 03757 */ 03758 /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */ 03759 ret = xmlC14NDocDumpMemory(doc, 03760 (xpath) ? xpath->nodesetval : NULL, 03761 mode, inclusive_namespaces, 03762 with_comments, &result); 03763 if (ret >= 0) { 03764 if(result != NULL) { 03765 if (compareFileMem(result_file, (const char *) result, ret)) { 03766 fprintf(stderr, "Result mismatch for %s\n", xml_filename); 03767 fprintf(stderr, "RESULT:\n%s\n", (const char*)result); 03768 ret = -1; 03769 } 03770 } 03771 } else { 03772 fprintf(stderr,"Error: failed to canonicalize XML file \"%s\" (ret=%d)\n", xml_filename, ret); 03773 ret = -1; 03774 } 03775 03776 /* 03777 * Cleanup 03778 */ 03779 if (result != NULL) xmlFree(result); 03780 if(xpath != NULL) xmlXPathFreeObject(xpath); 03781 if (inclusive_namespaces != NULL) xmlFree(inclusive_namespaces); 03782 if (nslist != NULL) free((char *) nslist); 03783 xmlFreeDoc(doc); 03784 03785 return(ret); 03786 } 03787 03788 static int 03789 c14nCommonTest(const char *filename, int with_comments, int mode, 03790 const char *subdir) { 03791 char buf[500]; 03792 char prefix[500]; 03793 const char *base; 03794 int len; 03795 char *result = NULL; 03796 char *xpath = NULL; 03797 char *ns = NULL; 03798 int ret = 0; 03799 03800 base = baseFilename(filename); 03801 len = strlen(base); 03802 len -= 4; 03803 memcpy(prefix, base, len); 03804 prefix[len] = 0; 03805 03806 snprintf(buf, 499, "result/c14n/%s/%s", subdir,prefix); 03807 if (!checkTestFile(buf)) { 03808 fprintf(stderr, "Missing result file %s", buf); 03809 return(-1); 03810 } 03811 result = strdup(buf); 03812 snprintf(buf, 499, "test/c14n/%s/%s.xpath", subdir,prefix); 03813 if (checkTestFile(buf)) { 03814 xpath = strdup(buf); 03815 } 03816 snprintf(buf, 499, "test/c14n/%s/%s.ns", subdir,prefix); 03817 if (checkTestFile(buf)) { 03818 ns = strdup(buf); 03819 } 03820 03821 nb_tests++; 03822 if (c14nRunTest(filename, with_comments, mode, 03823 xpath, ns, result) < 0) 03824 ret = 1; 03825 03826 if (result != NULL) free(result); 03827 if (xpath != NULL) free(xpath); 03828 if (ns != NULL) free(ns); 03829 return(ret); 03830 } 03831 03832 static int 03833 c14nWithCommentTest(const char *filename, 03834 const char *resul ATTRIBUTE_UNUSED, 03835 const char *err ATTRIBUTE_UNUSED, 03836 int options ATTRIBUTE_UNUSED) { 03837 return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments")); 03838 } 03839 static int 03840 c14nWithoutCommentTest(const char *filename, 03841 const char *resul ATTRIBUTE_UNUSED, 03842 const char *err ATTRIBUTE_UNUSED, 03843 int options ATTRIBUTE_UNUSED) { 03844 return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments")); 03845 } 03846 static int 03847 c14nExcWithoutCommentTest(const char *filename, 03848 const char *resul ATTRIBUTE_UNUSED, 03849 const char *err ATTRIBUTE_UNUSED, 03850 int options ATTRIBUTE_UNUSED) { 03851 return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments")); 03852 } 03853 static int 03854 c14n11WithoutCommentTest(const char *filename, 03855 const char *resul ATTRIBUTE_UNUSED, 03856 const char *err ATTRIBUTE_UNUSED, 03857 int options ATTRIBUTE_UNUSED) { 03858 return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments")); 03859 } 03860 #endif 03861 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined (LIBXML_SAX1_ENABLED) 03862 /************************************************************************ 03863 * * 03864 * Catalog and threads test * 03865 * * 03866 ************************************************************************/ 03867 03868 /* 03869 * mostly a cut and paste from testThreads.c 03870 */ 03871 #define MAX_ARGC 20 03872 03873 static const char *catalog = "test/threads/complex.xml"; 03874 static const char *testfiles[] = { 03875 "test/threads/abc.xml", 03876 "test/threads/acb.xml", 03877 "test/threads/bac.xml", 03878 "test/threads/bca.xml", 03879 "test/threads/cab.xml", 03880 "test/threads/cba.xml", 03881 "test/threads/invalid.xml", 03882 }; 03883 03884 static const char *Okay = "OK"; 03885 static const char *Failed = "Failed"; 03886 03887 #ifndef xmlDoValidityCheckingDefaultValue 03888 #error xmlDoValidityCheckingDefaultValue is not a macro 03889 #endif 03890 #ifndef xmlGenericErrorContext 03891 #error xmlGenericErrorContext is not a macro 03892 #endif 03893 03894 static void * 03895 thread_specific_data(void *private_data) 03896 { 03897 xmlDocPtr myDoc; 03898 const char *filename = (const char *) private_data; 03899 int okay = 1; 03900 03901 if (!strcmp(filename, "test/threads/invalid.xml")) { 03902 xmlDoValidityCheckingDefaultValue = 0; 03903 xmlGenericErrorContext = stdout; 03904 } else { 03905 xmlDoValidityCheckingDefaultValue = 1; 03906 xmlGenericErrorContext = stderr; 03907 } 03908 myDoc = xmlParseFile(filename); 03909 if (myDoc) { 03910 xmlFreeDoc(myDoc); 03911 } else { 03912 printf("parse failed\n"); 03913 okay = 0; 03914 } 03915 if (!strcmp(filename, "test/threads/invalid.xml")) { 03916 if (xmlDoValidityCheckingDefaultValue != 0) { 03917 printf("ValidityCheckingDefaultValue override failed\n"); 03918 okay = 0; 03919 } 03920 if (xmlGenericErrorContext != stdout) { 03921 printf("xmlGenericErrorContext override failed\n"); 03922 okay = 0; 03923 } 03924 } else { 03925 if (xmlDoValidityCheckingDefaultValue != 1) { 03926 printf("ValidityCheckingDefaultValue override failed\n"); 03927 okay = 0; 03928 } 03929 if (xmlGenericErrorContext != stderr) { 03930 printf("xmlGenericErrorContext override failed\n"); 03931 okay = 0; 03932 } 03933 } 03934 if (okay == 0) 03935 return ((void *) Failed); 03936 return ((void *) Okay); 03937 } 03938 03939 #if defined(linux) || defined(__sun) || defined(__APPLE_CC__) 03940 03941 #include <pthread.h> 03942 03943 static pthread_t tid[MAX_ARGC]; 03944 03945 static int 03946 testThread(void) 03947 { 03948 unsigned int i, repeat; 03949 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]); 03950 void *results[MAX_ARGC]; 03951 int ret; 03952 int res = 0; 03953 03954 xmlInitParser(); 03955 03956 for (repeat = 0; repeat < 500; repeat++) { 03957 xmlLoadCatalog(catalog); 03958 nb_tests++; 03959 03960 for (i = 0; i < num_threads; i++) { 03961 results[i] = NULL; 03962 tid[i] = (pthread_t) - 1; 03963 } 03964 03965 for (i = 0; i < num_threads; i++) { 03966 ret = pthread_create(&tid[i], 0, thread_specific_data, 03967 (void *) testfiles[i]); 03968 if (ret != 0) { 03969 fprintf(stderr, "pthread_create failed\n"); 03970 return (1); 03971 } 03972 } 03973 for (i = 0; i < num_threads; i++) { 03974 ret = pthread_join(tid[i], &results[i]); 03975 if (ret != 0) { 03976 fprintf(stderr, "pthread_join failed\n"); 03977 return (1); 03978 } 03979 } 03980 03981 xmlCatalogCleanup(); 03982 for (i = 0; i < num_threads; i++) 03983 if (results[i] != (void *) Okay) { 03984 fprintf(stderr, "Thread %d handling %s failed\n", 03985 i, testfiles[i]); 03986 res = 1; 03987 } 03988 } 03989 return (res); 03990 } 03991 03992 #elif defined WIN32 03993 #include <windows.h> 03994 #include <string.h> 03995 03996 #define TEST_REPEAT_COUNT 500 03997 03998 static HANDLE tid[MAX_ARGC]; 03999 04000 static DWORD WINAPI 04001 win32_thread_specific_data(void *private_data) 04002 { 04003 return((DWORD) thread_specific_data(private_data)); 04004 } 04005 04006 static int 04007 testThread(void) 04008 { 04009 unsigned int i, repeat; 04010 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]); 04011 DWORD results[MAX_ARGC]; 04012 BOOL ret; 04013 int res = 0; 04014 04015 xmlInitParser(); 04016 for (repeat = 0; repeat < TEST_REPEAT_COUNT; repeat++) { 04017 xmlLoadCatalog(catalog); 04018 nb_tests++; 04019 04020 for (i = 0; i < num_threads; i++) { 04021 results[i] = 0; 04022 tid[i] = (HANDLE) - 1; 04023 } 04024 04025 for (i = 0; i < num_threads; i++) { 04026 DWORD useless; 04027 04028 tid[i] = CreateThread(NULL, 0, 04029 win32_thread_specific_data, 04030 (void *) testfiles[i], 0, 04031 &useless); 04032 if (tid[i] == NULL) { 04033 fprintf(stderr, "CreateThread failed\n"); 04034 return(1); 04035 } 04036 } 04037 04038 if (WaitForMultipleObjects(num_threads, tid, TRUE, INFINITE) == 04039 WAIT_FAILED) { 04040 fprintf(stderr, "WaitForMultipleObjects failed\n"); 04041 return(1); 04042 } 04043 04044 for (i = 0; i < num_threads; i++) { 04045 ret = GetExitCodeThread(tid[i], &results[i]); 04046 if (ret == 0) { 04047 fprintf(stderr, "GetExitCodeThread failed\n"); 04048 return(1); 04049 } 04050 CloseHandle(tid[i]); 04051 } 04052 04053 xmlCatalogCleanup(); 04054 for (i = 0; i < num_threads; i++) { 04055 if (results[i] != (DWORD) Okay) { 04056 fprintf(stderr, "Thread %d handling %s failed\n", 04057 i, testfiles[i]); 04058 res = 1; 04059 } 04060 } 04061 } 04062 04063 return (res); 04064 } 04065 04066 #elif defined __BEOS__ 04067 #include <OS.h> 04068 04069 static thread_id tid[MAX_ARGC]; 04070 04071 static int 04072 testThread(void) 04073 { 04074 unsigned int i, repeat; 04075 unsigned int num_threads = sizeof(testfiles) / sizeof(testfiles[0]); 04076 void *results[MAX_ARGC]; 04077 status_t ret; 04078 int res = 0; 04079 04080 xmlInitParser(); 04081 for (repeat = 0; repeat < 500; repeat++) { 04082 xmlLoadCatalog(catalog); 04083 for (i = 0; i < num_threads; i++) { 04084 results[i] = NULL; 04085 tid[i] = (thread_id) - 1; 04086 } 04087 for (i = 0; i < num_threads; i++) { 04088 tid[i] = 04089 spawn_thread(thread_specific_data, "xmlTestThread", 04090 B_NORMAL_PRIORITY, (void *) testfiles[i]); 04091 if (tid[i] < B_OK) { 04092 fprintf(stderr, "beos_thread_create failed\n"); 04093 return (1); 04094 } 04095 printf("beos_thread_create %d -> %d\n", i, tid[i]); 04096 } 04097 for (i = 0; i < num_threads; i++) { 04098 ret = wait_for_thread(tid[i], &results[i]); 04099 printf("beos_thread_wait %d -> %d\n", i, ret); 04100 if (ret != B_OK) { 04101 fprintf(stderr, "beos_thread_wait failed\n"); 04102 return (1); 04103 } 04104 } 04105 04106 xmlCatalogCleanup(); 04107 ret = B_OK; 04108 for (i = 0; i < num_threads; i++) 04109 if (results[i] != (void *) Okay) { 04110 printf("Thread %d handling %s failed\n", i, testfiles[i]); 04111 ret = B_ERROR; 04112 } 04113 } 04114 if (ret != B_OK) 04115 return(1); 04116 return (0); 04117 } 04118 #else 04119 static int 04120 testThread(void) 04121 { 04122 fprintf(stderr, 04123 "Specific platform thread support not detected\n"); 04124 return (-1); 04125 } 04126 #endif 04127 static int 04128 threadsTest(const char *filename ATTRIBUTE_UNUSED, 04129 const char *resul ATTRIBUTE_UNUSED, 04130 const char *err ATTRIBUTE_UNUSED, 04131 int options ATTRIBUTE_UNUSED) { 04132 return(testThread()); 04133 } 04134 #endif 04135 /************************************************************************ 04136 * * 04137 * Tests Descriptions * 04138 * * 04139 ************************************************************************/ 04140 04141 static 04142 testDesc testDescriptions[] = { 04143 { "XML regression tests" , 04144 oldParseTest, "./test/*", "result/", "", NULL, 04145 0 }, 04146 { "XML regression tests on memory" , 04147 memParseTest, "./test/*", "result/", "", NULL, 04148 0 }, 04149 { "XML entity subst regression tests" , 04150 noentParseTest, "./test/*", "result/noent/", "", NULL, 04151 XML_PARSE_NOENT }, 04152 { "XML Namespaces regression tests", 04153 errParseTest, "./test/namespaces/*", "result/namespaces/", "", ".err", 04154 0 }, 04155 { "Error cases regression tests", 04156 errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err", 04157 0 }, 04158 #ifdef LIBXML_READER_ENABLED 04159 { "Error cases stream regression tests", 04160 streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str", 04161 0 }, 04162 { "Reader regression tests", 04163 streamParseTest, "./test/*", "result/", ".rdr", NULL, 04164 0 }, 04165 { "Reader entities substitution regression tests", 04166 streamParseTest, "./test/*", "result/", ".rde", NULL, 04167 XML_PARSE_NOENT }, 04168 { "Reader on memory regression tests", 04169 streamMemParseTest, "./test/*", "result/", ".rdr", NULL, 04170 0 }, 04171 { "Walker regression tests", 04172 walkerParseTest, "./test/*", "result/", ".rdr", NULL, 04173 0 }, 04174 #endif 04175 #ifdef LIBXML_SAX1_ENABLED 04176 { "SAX1 callbacks regression tests" , 04177 saxParseTest, "./test/*", "result/", ".sax", NULL, 04178 XML_PARSE_SAX1 }, 04179 { "SAX2 callbacks regression tests" , 04180 saxParseTest, "./test/*", "result/", ".sax2", NULL, 04181 0 }, 04182 #endif 04183 #ifdef LIBXML_PUSH_ENABLED 04184 { "XML push regression tests" , 04185 pushParseTest, "./test/*", "result/", "", NULL, 04186 0 }, 04187 #endif 04188 #ifdef LIBXML_HTML_ENABLED 04189 { "HTML regression tests" , 04190 errParseTest, "./test/HTML/*", "result/HTML/", "", ".err", 04191 XML_PARSE_HTML }, 04192 #ifdef LIBXML_PUSH_ENABLED 04193 { "Push HTML regression tests" , 04194 pushParseTest, "./test/HTML/*", "result/HTML/", "", ".err", 04195 XML_PARSE_HTML }, 04196 #endif 04197 #ifdef LIBXML_SAX1_ENABLED 04198 { "HTML SAX regression tests" , 04199 saxParseTest, "./test/HTML/*", "result/HTML/", ".sax", NULL, 04200 XML_PARSE_HTML }, 04201 #endif 04202 #endif 04203 #ifdef LIBXML_VALID_ENABLED 04204 { "Valid documents regression tests" , 04205 errParseTest, "./test/VCM/*", NULL, NULL, NULL, 04206 XML_PARSE_DTDVALID }, 04207 { "Validity checking regression tests" , 04208 errParseTest, "./test/VC/*", "result/VC/", NULL, "", 04209 XML_PARSE_DTDVALID }, 04210 { "General documents valid regression tests" , 04211 errParseTest, "./test/valid/*", "result/valid/", "", ".err", 04212 XML_PARSE_DTDVALID }, 04213 #endif 04214 #ifdef LIBXML_XINCLUDE_ENABLED 04215 { "XInclude regression tests" , 04216 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL, 04217 /* Ignore errors at this point ".err", */ 04218 XML_PARSE_XINCLUDE }, 04219 #ifdef LIBXML_READER_ENABLED 04220 { "XInclude xmlReader regression tests", 04221 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr", 04222 /* Ignore errors at this point ".err", */ 04223 NULL, XML_PARSE_XINCLUDE }, 04224 #endif 04225 { "XInclude regression tests stripping include nodes" , 04226 errParseTest, "./test/XInclude/docs/*", "result/XInclude/", "", NULL, 04227 /* Ignore errors at this point ".err", */ 04228 XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE }, 04229 #ifdef LIBXML_READER_ENABLED 04230 { "XInclude xmlReader regression tests stripping include nodes", 04231 streamParseTest, "./test/XInclude/docs/*", "result/XInclude/", ".rdr", 04232 /* Ignore errors at this point ".err", */ 04233 NULL, XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE }, 04234 #endif 04235 #endif 04236 #ifdef LIBXML_XPATH_ENABLED 04237 #ifdef LIBXML_DEBUG_ENABLED 04238 { "XPath expressions regression tests" , 04239 xpathExprTest, "./test/XPath/expr/*", "result/XPath/expr/", "", NULL, 04240 0 }, 04241 { "XPath document queries regression tests" , 04242 xpathDocTest, "./test/XPath/docs/*", NULL, NULL, NULL, 04243 0 }, 04244 #ifdef LIBXML_XPTR_ENABLED 04245 { "XPointer document queries regression tests" , 04246 xptrDocTest, "./test/XPath/docs/*", NULL, NULL, NULL, 04247 0 }, 04248 #endif 04249 { "xml:id regression tests" , 04250 xmlidDocTest, "./test/xmlid/*", "result/xmlid/", "", ".err", 04251 0 }, 04252 #endif 04253 #endif 04254 { "URI parsing tests" , 04255 uriParseTest, "./test/URI/*.uri", "result/URI/", "", NULL, 04256 0 }, 04257 { "URI base composition tests" , 04258 uriBaseTest, "./test/URI/*.data", "result/URI/", "", NULL, 04259 0 }, 04260 { "Path URI conversion tests" , 04261 uriPathTest, NULL, NULL, NULL, NULL, 04262 0 }, 04263 #ifdef LIBXML_SCHEMAS_ENABLED 04264 { "Schemas regression tests" , 04265 schemasTest, "./test/schemas/*_*.xsd", NULL, NULL, NULL, 04266 0 }, 04267 { "Relax-NG regression tests" , 04268 rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL, 04269 XML_PARSE_DTDATTR | XML_PARSE_NOENT }, 04270 #ifdef LIBXML_READER_ENABLED 04271 { "Relax-NG streaming regression tests" , 04272 rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL, 04273 XML_PARSE_DTDATTR | XML_PARSE_NOENT }, 04274 #endif 04275 #endif 04276 #ifdef LIBXML_PATTERN_ENABLED 04277 #ifdef LIBXML_READER_ENABLED 04278 { "Pattern regression tests" , 04279 patternTest, "./test/pattern/*.pat", "result/pattern/", NULL, NULL, 04280 0 }, 04281 #endif 04282 #endif 04283 #ifdef LIBXML_C14N_ENABLED 04284 { "C14N with comments regression tests" , 04285 c14nWithCommentTest, "./test/c14n/with-comments/*.xml", NULL, NULL, NULL, 04286 0 }, 04287 { "C14N without comments regression tests" , 04288 c14nWithoutCommentTest, "./test/c14n/without-comments/*.xml", NULL, NULL, NULL, 04289 0 }, 04290 { "C14N exclusive without comments regression tests" , 04291 c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL, 04292 0 }, 04293 { "C14N 1.1 without comments regression tests" , 04294 c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL, 04295 0 }, 04296 #endif 04297 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_SAX1_ENABLED) 04298 { "Catalog and Threads regression tests" , 04299 threadsTest, NULL, NULL, NULL, NULL, 04300 0 }, 04301 #endif 04302 {NULL, NULL, NULL, NULL, NULL, NULL, 0} 04303 }; 04304 04305 /************************************************************************ 04306 * * 04307 * The main code driving the tests * 04308 * * 04309 ************************************************************************/ 04310 04311 static int 04312 launchTests(testDescPtr tst) { 04313 int res = 0, err = 0; 04314 size_t i; 04315 char *result; 04316 char *error; 04317 int mem; 04318 04319 if (tst == NULL) return(-1); 04320 if (tst->in != NULL) { 04321 glob_t globbuf; 04322 04323 globbuf.gl_offs = 0; 04324 glob(tst->in, GLOB_DOOFFS, NULL, &globbuf); 04325 for (i = 0;i < globbuf.gl_pathc;i++) { 04326 if (!checkTestFile(globbuf.gl_pathv[i])) 04327 continue; 04328 if (tst->suffix != NULL) { 04329 result = resultFilename(globbuf.gl_pathv[i], tst->out, 04330 tst->suffix); 04331 if (result == NULL) { 04332 fprintf(stderr, "Out of memory !\n"); 04333 fatalError(); 04334 } 04335 } else { 04336 result = NULL; 04337 } 04338 if (tst->err != NULL) { 04339 error = resultFilename(globbuf.gl_pathv[i], tst->out, 04340 tst->err); 04341 if (error == NULL) { 04342 fprintf(stderr, "Out of memory !\n"); 04343 fatalError(); 04344 } 04345 } else { 04346 error = NULL; 04347 } 04348 if ((result) &&(!checkTestFile(result))) { 04349 fprintf(stderr, "Missing result file %s\n", result); 04350 } else if ((error) &&(!checkTestFile(error))) { 04351 fprintf(stderr, "Missing error file %s\n", error); 04352 } else { 04353 mem = xmlMemUsed(); 04354 extraMemoryFromResolver = 0; 04355 testErrorsSize = 0; 04356 testErrors[0] = 0; 04357 res = tst->func(globbuf.gl_pathv[i], result, error, 04358 tst->options | XML_PARSE_COMPACT); 04359 xmlResetLastError(); 04360 if (res != 0) { 04361 fprintf(stderr, "File %s generated an error\n", 04362 globbuf.gl_pathv[i]); 04363 nb_errors++; 04364 err++; 04365 } 04366 else if (xmlMemUsed() != mem) { 04367 if ((xmlMemUsed() != mem) && 04368 (extraMemoryFromResolver == 0)) { 04369 fprintf(stderr, "File %s leaked %d bytes\n", 04370 globbuf.gl_pathv[i], xmlMemUsed() - mem); 04371 nb_leaks++; 04372 err++; 04373 } 04374 } 04375 testErrorsSize = 0; 04376 } 04377 if (result) 04378 free(result); 04379 if (error) 04380 free(error); 04381 } 04382 globfree(&globbuf); 04383 } else { 04384 testErrorsSize = 0; 04385 testErrors[0] = 0; 04386 extraMemoryFromResolver = 0; 04387 res = tst->func(NULL, NULL, NULL, tst->options); 04388 if (res != 0) { 04389 nb_errors++; 04390 err++; 04391 } 04392 } 04393 return(err); 04394 } 04395 04396 static int verbose = 0; 04397 static int tests_quiet = 0; 04398 04399 static int 04400 runtest(int i) { 04401 int ret = 0, res; 04402 int old_errors, old_tests, old_leaks; 04403 04404 old_errors = nb_errors; 04405 old_tests = nb_tests; 04406 old_leaks = nb_leaks; 04407 if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL)) 04408 printf("## %s\n", testDescriptions[i].desc); 04409 res = launchTests(&testDescriptions[i]); 04410 if (res != 0) 04411 ret++; 04412 if (verbose) { 04413 if ((nb_errors == old_errors) && (nb_leaks == old_leaks)) 04414 printf("Ran %d tests, no errors\n", nb_tests - old_tests); 04415 else 04416 printf("Ran %d tests, %d errors, %d leaks\n", 04417 nb_tests - old_tests, 04418 nb_errors - old_errors, 04419 nb_leaks - old_leaks); 04420 } 04421 return(ret); 04422 } 04423 04424 int 04425 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { 04426 int i, a, ret = 0; 04427 int subset = 0; 04428 04429 initializeLibxml2(); 04430 04431 for (a = 1; a < argc;a++) { 04432 if (!strcmp(argv[a], "-v")) 04433 verbose = 1; 04434 else if (!strcmp(argv[a], "-quiet")) 04435 tests_quiet = 1; 04436 else { 04437 for (i = 0; testDescriptions[i].func != NULL; i++) { 04438 if (strstr(testDescriptions[i].desc, argv[a])) { 04439 ret += runtest(i); 04440 subset++; 04441 } 04442 } 04443 } 04444 } 04445 if (subset == 0) { 04446 for (i = 0; testDescriptions[i].func != NULL; i++) { 04447 ret += runtest(i); 04448 } 04449 } 04450 if ((nb_errors == 0) && (nb_leaks == 0)) { 04451 ret = 0; 04452 printf("Total %d tests, no errors\n", 04453 nb_tests); 04454 } else { 04455 ret = 1; 04456 printf("Total %d tests, %d errors, %d leaks\n", 04457 nb_tests, nb_errors, nb_leaks); 04458 } 04459 xmlCleanupParser(); 04460 xmlMemoryDump(); 04461 04462 return(ret); 04463 } 04464 04465 #else /* ! LIBXML_OUTPUT_ENABLED */ 04466 int 04467 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { 04468 fprintf(stderr, "runtest requires output to be enabled in libxml2\n"); 04469 return(1); 04470 } 04471 #endif Generated on Sat May 26 2012 04:33:22 for ReactOS by
1.7.6.1
|