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

testrecurse.c
Go to the documentation of this file.
00001 /*
00002  * testrecurse.c: C program to run libxml2 regression tests checking entities
00003  *            recursions
00004  *
00005  * To compile on Unixes:
00006  * cc -o testrecurse `xml2-config --cflags` testrecurse.c `xml2-config --libs` -lpthread
00007  *
00008  * See Copyright for the status of this software.
00009  *
00010  * daniel@veillard.com
00011  */
00012 
00013 #ifdef HAVE_CONFIG_H
00014 #include "libxml.h"
00015 #else
00016 #include <stdio.h>
00017 #endif
00018 
00019 #if !defined(_WIN32) || defined(__CYGWIN__)
00020 #include <unistd.h>
00021 #endif
00022 #include <string.h>
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <fcntl.h>
00026 
00027 #include <libxml/parser.h>
00028 #include <libxml/tree.h>
00029 #include <libxml/uri.h>
00030 #ifdef LIBXML_READER_ENABLED
00031 #include <libxml/xmlreader.h>
00032 #endif
00033 
00034 /*
00035  * O_BINARY is just for Windows compatibility - if it isn't defined
00036  * on this system, avoid any compilation error
00037  */
00038 #ifdef  O_BINARY
00039 #define RD_FLAGS    O_RDONLY | O_BINARY
00040 #else
00041 #define RD_FLAGS    O_RDONLY
00042 #endif
00043 
00044 typedef int (*functest) (const char *filename, const char *result,
00045                          const char *error, int options);
00046 
00047 typedef struct testDesc testDesc;
00048 typedef testDesc *testDescPtr;
00049 struct testDesc {
00050     const char *desc; /* descripton of the test */
00051     functest    func; /* function implementing the test */
00052     const char *in;   /* glob to path for input files */
00053     const char *out;  /* output directory */
00054     const char *suffix;/* suffix for output files */
00055     const char *err;  /* suffix for error output files */
00056     int     options;  /* parser options for the test */
00057 };
00058 
00059 static int checkTestFile(const char *filename);
00060 
00061 
00062 #if defined(_WIN32) && !defined(__CYGWIN__)
00063 
00064 #include <windows.h>
00065 #include <io.h>
00066 
00067 typedef struct
00068 {
00069       size_t gl_pathc;    /* Count of paths matched so far  */
00070       char **gl_pathv;    /* List of matched pathnames.  */
00071       size_t gl_offs;     /* Slots to reserve in 'gl_pathv'.  */
00072 } glob_t;
00073 
00074 #define GLOB_DOOFFS 0
00075 static int glob(const char *pattern, int flags,
00076                 int errfunc(const char *epath, int eerrno),
00077                 glob_t *pglob) {
00078     glob_t *ret;
00079     WIN32_FIND_DATA FindFileData;
00080     HANDLE hFind;
00081     unsigned int nb_paths = 0;
00082     char directory[500];
00083     int len;
00084 
00085     if ((pattern == NULL) || (pglob == NULL)) return(-1);
00086 
00087     strncpy(directory, pattern, 499);
00088     for (len = strlen(directory);len >= 0;len--) {
00089         if (directory[len] == '/') {
00090         len++;
00091         directory[len] = 0;
00092         break;
00093     }
00094     }
00095     if (len <= 0)
00096         len = 0;
00097 
00098 
00099     ret = pglob;
00100     memset(ret, 0, sizeof(glob_t));
00101 
00102     hFind = FindFirstFileA(pattern, &FindFileData);
00103     if (hFind == INVALID_HANDLE_VALUE)
00104         return(0);
00105     nb_paths = 20;
00106     ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
00107     if (ret->gl_pathv == NULL) {
00108     FindClose(hFind);
00109         return(-1);
00110     }
00111     strncpy(directory + len, FindFileData.cFileName, 499 - len);
00112     ret->gl_pathv[ret->gl_pathc] = strdup(directory);
00113     if (ret->gl_pathv[ret->gl_pathc] == NULL)
00114         goto done;
00115     ret->gl_pathc++;
00116     while(FindNextFileA(hFind, &FindFileData)) {
00117         if (FindFileData.cFileName[0] == '.')
00118         continue;
00119         if (ret->gl_pathc + 2 > nb_paths) {
00120             char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
00121             if (tmp == NULL)
00122                 break;
00123             ret->gl_pathv = tmp;
00124             nb_paths *= 2;
00125     }
00126     strncpy(directory + len, FindFileData.cFileName, 499 - len);
00127     ret->gl_pathv[ret->gl_pathc] = strdup(directory);
00128         if (ret->gl_pathv[ret->gl_pathc] == NULL)
00129             break;
00130         ret->gl_pathc++;
00131     }
00132     ret->gl_pathv[ret->gl_pathc] = NULL;
00133 
00134 done:
00135     FindClose(hFind);
00136     return(0);
00137 }
00138 
00139 
00140 
00141 static void globfree(glob_t *pglob) {
00142     unsigned int i;
00143     if (pglob == NULL)
00144         return;
00145 
00146     for (i = 0;i < pglob->gl_pathc;i++) {
00147          if (pglob->gl_pathv[i] != NULL)
00148              free(pglob->gl_pathv[i]);
00149     }
00150 }
00151 #define vsnprintf _vsnprintf
00152 #define snprintf _snprintf
00153 #else
00154 #include <glob.h>
00155 #endif
00156 
00157 /************************************************************************
00158  *                                  *
00159  *      Huge document generator                 *
00160  *                                  *
00161  ************************************************************************/
00162 
00163 #include <libxml/xmlIO.h>
00164 
00165 
00166 static const char *start = "<!DOCTYPE foo [\
00167 <!ENTITY f 'some internal data'> \
00168 <!ENTITY e '&f;&f;'> \
00169 <!ENTITY d '&e;&e;'> \
00170 ]> \
00171 <foo>";
00172 
00173 static const char *segment = "  <bar>&e; &f; &d;</bar>\n";
00174 static const char *finish = "</foo>";
00175 
00176 static int curseg = 0;
00177 static const char *current;
00178 static int rlen;
00179 
00188 static int
00189 hugeMatch(const char * URI) {
00190     if ((URI != NULL) && (!strncmp(URI, "huge:", 4)))
00191         return(1);
00192     return(0);
00193 }
00194 
00204 static void *
00205 hugeOpen(const char * URI) {
00206     if ((URI == NULL) || (strncmp(URI, "huge:", 4)))
00207         return(NULL);
00208     rlen = strlen(start);
00209     current = start;
00210     return((void *) current);
00211 }
00212 
00221 static int
00222 hugeClose(void * context) {
00223     if (context == NULL) return(-1);
00224     return(0);
00225 }
00226 
00227 #define MAX_NODES 1000000
00228 
00239 static int
00240 hugeRead(void *context, char *buffer, int len)
00241 {
00242     if ((context == NULL) || (buffer == NULL) || (len < 0))
00243         return (-1);
00244 
00245     if (len >= rlen) {
00246         if (curseg >= MAX_NODES + 1) {
00247             rlen = 0;
00248             return(0);
00249         }
00250         len = rlen;
00251         rlen = 0;
00252     memcpy(buffer, current, len);
00253         curseg ++;
00254         if (curseg == MAX_NODES) {
00255         fprintf(stderr, "\n");
00256             rlen = strlen(finish);
00257             current = finish;
00258     } else {
00259         if (curseg % (MAX_NODES / 10) == 0)
00260             fprintf(stderr, ".");
00261             rlen = strlen(segment);
00262             current = segment;
00263     }
00264     } else {
00265     memcpy(buffer, current, len);
00266     rlen -= len;
00267         current += len;
00268     }
00269     return (len);
00270 }
00271 
00272 /************************************************************************
00273  *                                  *
00274  *      Libxml2 specific routines               *
00275  *                                  *
00276  ************************************************************************/
00277 
00278 static int nb_tests = 0;
00279 static int nb_errors = 0;
00280 static int nb_leaks = 0;
00281 static int extraMemoryFromResolver = 0;
00282 
00283 static int
00284 fatalError(void) {
00285     fprintf(stderr, "Exitting tests on fatal error\n");
00286     exit(1);
00287 }
00288 
00289 /*
00290  * We need to trap calls to the resolver to not account memory for the catalog
00291  * which is shared to the current running test. We also don't want to have
00292  * network downloads modifying tests.
00293  */
00294 static xmlParserInputPtr
00295 testExternalEntityLoader(const char *URL, const char *ID,
00296              xmlParserCtxtPtr ctxt) {
00297     xmlParserInputPtr ret;
00298 
00299     if (checkTestFile(URL)) {
00300     ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
00301     } else {
00302     int memused = xmlMemUsed();
00303     ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
00304     extraMemoryFromResolver += xmlMemUsed() - memused;
00305     }
00306 
00307     return(ret);
00308 }
00309 
00310 /*
00311  * Trapping the error messages at the generic level to grab the equivalent of
00312  * stderr messages on CLI tools.
00313  */
00314 static char testErrors[32769];
00315 static int testErrorsSize = 0;
00316 
00317 static void XMLCDECL
00318 channel(void *ctx  ATTRIBUTE_UNUSED, const char *msg, ...) {
00319     va_list args;
00320     int res;
00321 
00322     if (testErrorsSize >= 32768)
00323         return;
00324     va_start(args, msg);
00325     res = vsnprintf(&testErrors[testErrorsSize],
00326                     32768 - testErrorsSize,
00327             msg, args);
00328     va_end(args);
00329     if (testErrorsSize + res >= 32768) {
00330         /* buffer is full */
00331     testErrorsSize = 32768;
00332     testErrors[testErrorsSize] = 0;
00333     } else {
00334         testErrorsSize += res;
00335     }
00336     testErrors[testErrorsSize] = 0;
00337 }
00338 
00346 static void
00347 xmlParserPrintFileContextInternal(xmlParserInputPtr input ,
00348         xmlGenericErrorFunc chanl, void *data ) {
00349     const xmlChar *cur, *base;
00350     unsigned int n, col;    /* GCC warns if signed, because compared with sizeof() */
00351     xmlChar  content[81]; /* space for 80 chars + line terminator */
00352     xmlChar *ctnt;
00353 
00354     if (input == NULL) return;
00355     cur = input->cur;
00356     base = input->base;
00357     /* skip backwards over any end-of-lines */
00358     while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
00359     cur--;
00360     }
00361     n = 0;
00362     /* search backwards for beginning-of-line (to max buff size) */
00363     while ((n++ < (sizeof(content)-1)) && (cur > base) &&
00364    (*(cur) != '\n') && (*(cur) != '\r'))
00365         cur--;
00366     if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
00367     /* calculate the error position in terms of the current position */
00368     col = input->cur - cur;
00369     /* search forward for end-of-line (to max buff size) */
00370     n = 0;
00371     ctnt = content;
00372     /* copy selected text to our buffer */
00373     while ((*cur != 0) && (*(cur) != '\n') &&
00374    (*(cur) != '\r') && (n < sizeof(content)-1)) {
00375         *ctnt++ = *cur++;
00376     n++;
00377     }
00378     *ctnt = 0;
00379     /* print out the selected text */
00380     chanl(data ,"%s\n", content);
00381     /* create blank line with problem pointer */
00382     n = 0;
00383     ctnt = content;
00384     /* (leave buffer space for pointer + line terminator) */
00385     while ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
00386     if (*(ctnt) != '\t')
00387         *(ctnt) = ' ';
00388     ctnt++;
00389     }
00390     *ctnt++ = '^';
00391     *ctnt = 0;
00392     chanl(data ,"%s\n", content);
00393 }
00394 
00395 static void
00396 testStructuredErrorHandler(void *ctx  ATTRIBUTE_UNUSED, xmlErrorPtr err) {
00397     char *file = NULL;
00398     int line = 0;
00399     int code = -1;
00400     int domain;
00401     void *data = NULL;
00402     const char *str;
00403     const xmlChar *name = NULL;
00404     xmlNodePtr node;
00405     xmlErrorLevel level;
00406     xmlParserInputPtr input = NULL;
00407     xmlParserInputPtr cur = NULL;
00408     xmlParserCtxtPtr ctxt = NULL;
00409 
00410     if (err == NULL)
00411         return;
00412 
00413     file = err->file;
00414     line = err->line;
00415     code = err->code;
00416     domain = err->domain;
00417     level = err->level;
00418     node = err->node;
00419     if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
00420         (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
00421     (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
00422     ctxt = err->ctxt;
00423     }
00424     str = err->message;
00425 
00426     if (code == XML_ERR_OK)
00427         return;
00428 
00429     if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
00430         name = node->name;
00431 
00432     /*
00433      * Maintain the compatibility with the legacy error handling
00434      */
00435     if (ctxt != NULL) {
00436         input = ctxt->input;
00437         if ((input != NULL) && (input->filename == NULL) &&
00438             (ctxt->inputNr > 1)) {
00439             cur = input;
00440             input = ctxt->inputTab[ctxt->inputNr - 2];
00441         }
00442         if (input != NULL) {
00443             if (input->filename)
00444                 channel(data, "%s:%d: ", input->filename, input->line);
00445             else if ((line != 0) && (domain == XML_FROM_PARSER))
00446                 channel(data, "Entity: line %d: ", input->line);
00447         }
00448     } else {
00449         if (file != NULL)
00450             channel(data, "%s:%d: ", file, line);
00451         else if ((line != 0) && (domain == XML_FROM_PARSER))
00452             channel(data, "Entity: line %d: ", line);
00453     }
00454     if (name != NULL) {
00455         channel(data, "element %s: ", name);
00456     }
00457     if (code == XML_ERR_OK)
00458         return;
00459     switch (domain) {
00460         case XML_FROM_PARSER:
00461             channel(data, "parser ");
00462             break;
00463         case XML_FROM_NAMESPACE:
00464             channel(data, "namespace ");
00465             break;
00466         case XML_FROM_DTD:
00467         case XML_FROM_VALID:
00468             channel(data, "validity ");
00469             break;
00470         case XML_FROM_HTML:
00471             channel(data, "HTML parser ");
00472             break;
00473         case XML_FROM_MEMORY:
00474             channel(data, "memory ");
00475             break;
00476         case XML_FROM_OUTPUT:
00477             channel(data, "output ");
00478             break;
00479         case XML_FROM_IO:
00480             channel(data, "I/O ");
00481             break;
00482         case XML_FROM_XINCLUDE:
00483             channel(data, "XInclude ");
00484             break;
00485         case XML_FROM_XPATH:
00486             channel(data, "XPath ");
00487             break;
00488         case XML_FROM_XPOINTER:
00489             channel(data, "parser ");
00490             break;
00491         case XML_FROM_REGEXP:
00492             channel(data, "regexp ");
00493             break;
00494         case XML_FROM_MODULE:
00495             channel(data, "module ");
00496             break;
00497         case XML_FROM_SCHEMASV:
00498             channel(data, "Schemas validity ");
00499             break;
00500         case XML_FROM_SCHEMASP:
00501             channel(data, "Schemas parser ");
00502             break;
00503         case XML_FROM_RELAXNGP:
00504             channel(data, "Relax-NG parser ");
00505             break;
00506         case XML_FROM_RELAXNGV:
00507             channel(data, "Relax-NG validity ");
00508             break;
00509         case XML_FROM_CATALOG:
00510             channel(data, "Catalog ");
00511             break;
00512         case XML_FROM_C14N:
00513             channel(data, "C14N ");
00514             break;
00515         case XML_FROM_XSLT:
00516             channel(data, "XSLT ");
00517             break;
00518         default:
00519             break;
00520     }
00521     if (code == XML_ERR_OK)
00522         return;
00523     switch (level) {
00524         case XML_ERR_NONE:
00525             channel(data, ": ");
00526             break;
00527         case XML_ERR_WARNING:
00528             channel(data, "warning : ");
00529             break;
00530         case XML_ERR_ERROR:
00531             channel(data, "error : ");
00532             break;
00533         case XML_ERR_FATAL:
00534             channel(data, "error : ");
00535             break;
00536     }
00537     if (code == XML_ERR_OK)
00538         return;
00539     if (str != NULL) {
00540         int len;
00541     len = xmlStrlen((const xmlChar *)str);
00542     if ((len > 0) && (str[len - 1] != '\n'))
00543         channel(data, "%s\n", str);
00544     else
00545         channel(data, "%s", str);
00546     } else {
00547         channel(data, "%s\n", "out of memory error");
00548     }
00549     if (code == XML_ERR_OK)
00550         return;
00551 
00552     if (ctxt != NULL) {
00553         xmlParserPrintFileContextInternal(input, channel, data);
00554         if (cur != NULL) {
00555             if (cur->filename)
00556                 channel(data, "%s:%d: \n", cur->filename, cur->line);
00557             else if ((line != 0) && (domain == XML_FROM_PARSER))
00558                 channel(data, "Entity: line %d: \n", cur->line);
00559             xmlParserPrintFileContextInternal(cur, channel, data);
00560         }
00561     }
00562     if ((domain == XML_FROM_XPATH) && (err->str1 != NULL) &&
00563         (err->int1 < 100) &&
00564     (err->int1 < xmlStrlen((const xmlChar *)err->str1))) {
00565     xmlChar buf[150];
00566     int i;
00567 
00568     channel(data, "%s\n", err->str1);
00569     for (i=0;i < err->int1;i++)
00570          buf[i] = ' ';
00571     buf[i++] = '^';
00572     buf[i] = 0;
00573     channel(data, "%s\n", buf);
00574     }
00575 }
00576 
00577 static void
00578 initializeLibxml2(void) {
00579     xmlGetWarningsDefaultValue = 0;
00580     xmlPedanticParserDefault(0);
00581 
00582     xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
00583     xmlInitParser();
00584     xmlSetExternalEntityLoader(testExternalEntityLoader);
00585     xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
00586     /*
00587      * register the new I/O handlers
00588      */
00589     if (xmlRegisterInputCallbacks(hugeMatch, hugeOpen,
00590                                   hugeRead, hugeClose) < 0) {
00591         fprintf(stderr, "failed to register Huge handler\n");
00592     exit(1);
00593     }
00594 }
00595 
00596 /************************************************************************
00597  *                                  *
00598  *      File name and path utilities                *
00599  *                                  *
00600  ************************************************************************/
00601 
00602 static const char *baseFilename(const char *filename) {
00603     const char *cur;
00604     if (filename == NULL)
00605         return(NULL);
00606     cur = &filename[strlen(filename)];
00607     while ((cur > filename) && (*cur != '/'))
00608         cur--;
00609     if (*cur == '/')
00610         return(cur + 1);
00611     return(cur);
00612 }
00613 
00614 static char *resultFilename(const char *filename, const char *out,
00615                             const char *suffix) {
00616     const char *base;
00617     char res[500];
00618     char suffixbuff[500];
00619 
00620 /*************
00621     if ((filename[0] == 't') && (filename[1] == 'e') &&
00622         (filename[2] == 's') && (filename[3] == 't') &&
00623     (filename[4] == '/'))
00624     filename = &filename[5];
00625  *************/
00626 
00627     base = baseFilename(filename);
00628     if (suffix == NULL)
00629         suffix = ".tmp";
00630     if (out == NULL)
00631         out = "";
00632 
00633     strncpy(suffixbuff,suffix,499);
00634 #ifdef VMS
00635     if(strstr(base,".") && suffixbuff[0]=='.')
00636       suffixbuff[0]='_';
00637 #endif
00638 
00639     snprintf(res, 499, "%s%s%s", out, base, suffixbuff);
00640     res[499] = 0;
00641     return(strdup(res));
00642 }
00643 
00644 static int checkTestFile(const char *filename) {
00645     struct stat buf;
00646 
00647     if (stat(filename, &buf) == -1)
00648         return(0);
00649 
00650 #if defined(_WIN32) && !defined(__CYGWIN__)
00651     if (!(buf.st_mode & _S_IFREG))
00652         return(0);
00653 #else
00654     if (!S_ISREG(buf.st_mode))
00655         return(0);
00656 #endif
00657 
00658     return(1);
00659 }
00660 
00661 
00662 
00663 /************************************************************************
00664  *                                  *
00665  *      Test to detect or not recursive entities        *
00666  *                                  *
00667  ************************************************************************/
00679 static int
00680 recursiveDetectTest(const char *filename,
00681              const char *result ATTRIBUTE_UNUSED,
00682              const char *err ATTRIBUTE_UNUSED,
00683          int options ATTRIBUTE_UNUSED) {
00684     xmlDocPtr doc;
00685     xmlParserCtxtPtr ctxt;
00686     int res = 0;
00687     int mem;
00688 
00689     nb_tests++;
00690 
00691     ctxt = xmlNewParserCtxt();
00692     mem = xmlMemUsed();
00693     /*
00694      * base of the test, parse with the old API
00695      */
00696     doc = xmlCtxtReadFile(ctxt, filename, NULL,
00697                           XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
00698     if ((doc != NULL) || (ctxt->lastError.code != XML_ERR_ENTITY_LOOP)) {
00699         fprintf(stderr, "Failed to detect recursion in %s\n", filename);
00700     xmlFreeParserCtxt(ctxt);
00701     xmlFreeDoc(doc);
00702         return(1);
00703     }
00704     xmlFreeParserCtxt(ctxt);
00705 
00706     return(res);
00707 }
00708 
00720 static int
00721 notRecursiveDetectTest(const char *filename,
00722              const char *result ATTRIBUTE_UNUSED,
00723              const char *err ATTRIBUTE_UNUSED,
00724          int options ATTRIBUTE_UNUSED) {
00725     xmlDocPtr doc;
00726     xmlParserCtxtPtr ctxt;
00727     int res = 0;
00728     int mem;
00729 
00730     nb_tests++;
00731 
00732     ctxt = xmlNewParserCtxt();
00733     mem = xmlMemUsed();
00734     /*
00735      * base of the test, parse with the old API
00736      */
00737     doc = xmlCtxtReadFile(ctxt, filename, NULL,
00738                           XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
00739     if (doc == NULL) {
00740         fprintf(stderr, "Failed to parse correct file %s\n", filename);
00741     xmlFreeParserCtxt(ctxt);
00742         return(1);
00743     }
00744     xmlFreeDoc(doc);
00745     xmlFreeParserCtxt(ctxt);
00746 
00747     return(res);
00748 }
00749 
00750 #ifdef LIBXML_READER_ENABLED
00751 
00762 static int
00763 notRecursiveHugeTest(const char *filename ATTRIBUTE_UNUSED,
00764              const char *result ATTRIBUTE_UNUSED,
00765              const char *err ATTRIBUTE_UNUSED,
00766          int options ATTRIBUTE_UNUSED) {
00767     xmlTextReaderPtr reader;
00768     int res = 0;
00769     int ret;
00770 
00771     nb_tests++;
00772 
00773     reader = xmlReaderForFile("huge:test" , NULL,
00774                               XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
00775     if (reader == NULL) {
00776         fprintf(stderr, "Failed to open huge:test\n");
00777     return(1);
00778     }
00779     ret = xmlTextReaderRead(reader);
00780     while (ret == 1) {
00781         ret = xmlTextReaderRead(reader);
00782     }
00783     if (ret != 0) {
00784         fprintf(stderr, "Failed to parser huge:test with entities\n");
00785     res = 1;
00786     }
00787     xmlFreeTextReader(reader);
00788 
00789     return(res);
00790 }
00791 #endif
00792 
00793 /************************************************************************
00794  *                                  *
00795  *          Tests Descriptions              *
00796  *                                  *
00797  ************************************************************************/
00798 
00799 static
00800 testDesc testDescriptions[] = {
00801     { "Parsing recursive test cases" ,
00802       recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL,
00803       0 },
00804     { "Parsing non-recursive test cases" ,
00805       notRecursiveDetectTest, "./test/recurse/good*.xml", NULL, NULL, NULL,
00806       0 },
00807 #ifdef LIBXML_READER_ENABLED
00808     { "Parsing non-recursive huge case" ,
00809       notRecursiveHugeTest, NULL, NULL, NULL, NULL,
00810       0 },
00811 #endif
00812     {NULL, NULL, NULL, NULL, NULL, NULL, 0}
00813 };
00814 
00815 /************************************************************************
00816  *                                  *
00817  *      The main code driving the tests             *
00818  *                                  *
00819  ************************************************************************/
00820 
00821 static int
00822 launchTests(testDescPtr tst) {
00823     int res = 0, err = 0;
00824     size_t i;
00825     char *result;
00826     char *error;
00827     int mem;
00828 
00829     if (tst == NULL) return(-1);
00830     if (tst->in != NULL) {
00831     glob_t globbuf;
00832 
00833     globbuf.gl_offs = 0;
00834     glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
00835     for (i = 0;i < globbuf.gl_pathc;i++) {
00836         if (!checkTestFile(globbuf.gl_pathv[i]))
00837             continue;
00838         if (tst->suffix != NULL) {
00839         result = resultFilename(globbuf.gl_pathv[i], tst->out,
00840                     tst->suffix);
00841         if (result == NULL) {
00842             fprintf(stderr, "Out of memory !\n");
00843             fatalError();
00844         }
00845         } else {
00846             result = NULL;
00847         }
00848         if (tst->err != NULL) {
00849         error = resultFilename(globbuf.gl_pathv[i], tst->out,
00850                                 tst->err);
00851         if (error == NULL) {
00852             fprintf(stderr, "Out of memory !\n");
00853             fatalError();
00854         }
00855         } else {
00856             error = NULL;
00857         }
00858         if ((result) &&(!checkTestFile(result))) {
00859             fprintf(stderr, "Missing result file %s\n", result);
00860         } else if ((error) &&(!checkTestFile(error))) {
00861             fprintf(stderr, "Missing error file %s\n", error);
00862         } else {
00863         mem = xmlMemUsed();
00864         extraMemoryFromResolver = 0;
00865         testErrorsSize = 0;
00866         testErrors[0] = 0;
00867         res = tst->func(globbuf.gl_pathv[i], result, error,
00868                         tst->options | XML_PARSE_COMPACT);
00869         xmlResetLastError();
00870         if (res != 0) {
00871             fprintf(stderr, "File %s generated an error\n",
00872                     globbuf.gl_pathv[i]);
00873             nb_errors++;
00874             err++;
00875         }
00876         else if (xmlMemUsed() != mem) {
00877             if ((xmlMemUsed() != mem) &&
00878                 (extraMemoryFromResolver == 0)) {
00879             fprintf(stderr, "File %s leaked %d bytes\n",
00880                 globbuf.gl_pathv[i], xmlMemUsed() - mem);
00881             nb_leaks++;
00882             err++;
00883             }
00884         }
00885         testErrorsSize = 0;
00886         }
00887         if (result)
00888         free(result);
00889         if (error)
00890         free(error);
00891     }
00892     globfree(&globbuf);
00893     } else {
00894         testErrorsSize = 0;
00895     testErrors[0] = 0;
00896     extraMemoryFromResolver = 0;
00897         res = tst->func(NULL, NULL, NULL, tst->options);
00898     if (res != 0) {
00899         nb_errors++;
00900         err++;
00901     }
00902     }
00903     return(err);
00904 }
00905 
00906 static int verbose = 0;
00907 static int tests_quiet = 0;
00908 
00909 static int
00910 runtest(int i) {
00911     int ret = 0, res;
00912     int old_errors, old_tests, old_leaks;
00913 
00914     old_errors = nb_errors;
00915     old_tests = nb_tests;
00916     old_leaks = nb_leaks;
00917     if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
00918     printf("## %s\n", testDescriptions[i].desc);
00919     res = launchTests(&testDescriptions[i]);
00920     if (res != 0)
00921     ret++;
00922     if (verbose) {
00923     if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
00924         printf("Ran %d tests, no errors\n", nb_tests - old_tests);
00925     else
00926         printf("Ran %d tests, %d errors, %d leaks\n",
00927            nb_tests - old_tests,
00928            nb_errors - old_errors,
00929            nb_leaks - old_leaks);
00930     }
00931     return(ret);
00932 }
00933 
00934 int
00935 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
00936     int i, a, ret = 0;
00937     int subset = 0;
00938 
00939     initializeLibxml2();
00940 
00941     for (a = 1; a < argc;a++) {
00942         if (!strcmp(argv[a], "-v"))
00943         verbose = 1;
00944         else if (!strcmp(argv[a], "-quiet"))
00945         tests_quiet = 1;
00946     else {
00947         for (i = 0; testDescriptions[i].func != NULL; i++) {
00948             if (strstr(testDescriptions[i].desc, argv[a])) {
00949             ret += runtest(i);
00950             subset++;
00951         }
00952         }
00953     }
00954     }
00955     if (subset == 0) {
00956     for (i = 0; testDescriptions[i].func != NULL; i++) {
00957         ret += runtest(i);
00958     }
00959     }
00960     if ((nb_errors == 0) && (nb_leaks == 0)) {
00961         ret = 0;
00962     printf("Total %d tests, no errors\n",
00963            nb_tests);
00964     } else {
00965         ret = 1;
00966     printf("Total %d tests, %d errors, %d leaks\n",
00967            nb_tests, nb_errors, nb_leaks);
00968     }
00969     xmlCleanupParser();
00970     xmlMemoryDump();
00971 
00972     return(ret);
00973 }

Generated on Fri May 25 2012 04:33:10 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.