ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

runtest.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.