xref: /aosp_15_r20/external/cronet/third_party/libxml/src/testrecurse.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker /*
2*6777b538SAndroid Build Coastguard Worker  * testrecurse.c: C program to run libxml2 regression tests checking entities
3*6777b538SAndroid Build Coastguard Worker  *            recursions
4*6777b538SAndroid Build Coastguard Worker  *
5*6777b538SAndroid Build Coastguard Worker  * To compile on Unixes:
6*6777b538SAndroid Build Coastguard Worker  * cc -o testrecurse `xml2-config --cflags` testrecurse.c `xml2-config --libs` -lpthread
7*6777b538SAndroid Build Coastguard Worker  *
8*6777b538SAndroid Build Coastguard Worker  * See Copyright for the status of this software.
9*6777b538SAndroid Build Coastguard Worker  *
10*6777b538SAndroid Build Coastguard Worker  * [email protected]
11*6777b538SAndroid Build Coastguard Worker  */
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #include "config.h"
14*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
17*6777b538SAndroid Build Coastguard Worker #include <string.h>
18*6777b538SAndroid Build Coastguard Worker #include <sys/stat.h>
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker #include <libxml/parser.h>
21*6777b538SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
22*6777b538SAndroid Build Coastguard Worker #include <libxml/tree.h>
23*6777b538SAndroid Build Coastguard Worker #include <libxml/uri.h>
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker /*
26*6777b538SAndroid Build Coastguard Worker  * O_BINARY is just for Windows compatibility - if it isn't defined
27*6777b538SAndroid Build Coastguard Worker  * on this system, avoid any compilation error
28*6777b538SAndroid Build Coastguard Worker  */
29*6777b538SAndroid Build Coastguard Worker #ifdef	O_BINARY
30*6777b538SAndroid Build Coastguard Worker #define RD_FLAGS	O_RDONLY | O_BINARY
31*6777b538SAndroid Build Coastguard Worker #else
32*6777b538SAndroid Build Coastguard Worker #define	RD_FLAGS	O_RDONLY
33*6777b538SAndroid Build Coastguard Worker #endif
34*6777b538SAndroid Build Coastguard Worker 
35*6777b538SAndroid Build Coastguard Worker #define OPT_SAX         (1<<0)
36*6777b538SAndroid Build Coastguard Worker #define OPT_NO_SUBST    (1<<1)
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker typedef int (*functest) (const char *filename, const char *result,
39*6777b538SAndroid Build Coastguard Worker                          const char *error, int options);
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker typedef struct testDesc testDesc;
42*6777b538SAndroid Build Coastguard Worker typedef testDesc *testDescPtr;
43*6777b538SAndroid Build Coastguard Worker struct testDesc {
44*6777b538SAndroid Build Coastguard Worker     const char *desc; /* description of the test */
45*6777b538SAndroid Build Coastguard Worker     functest    func; /* function implementing the test */
46*6777b538SAndroid Build Coastguard Worker     const char *in;   /* glob to path for input files */
47*6777b538SAndroid Build Coastguard Worker     const char *out;  /* output directory */
48*6777b538SAndroid Build Coastguard Worker     const char *suffix;/* suffix for output files */
49*6777b538SAndroid Build Coastguard Worker     const char *err;  /* suffix for error output files */
50*6777b538SAndroid Build Coastguard Worker     int     options;  /* parser options for the test */
51*6777b538SAndroid Build Coastguard Worker };
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker static int checkTestFile(const char *filename);
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker #if defined(_WIN32)
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker #include <windows.h>
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker typedef struct
61*6777b538SAndroid Build Coastguard Worker {
62*6777b538SAndroid Build Coastguard Worker       size_t gl_pathc;    /* Count of paths matched so far  */
63*6777b538SAndroid Build Coastguard Worker       char **gl_pathv;    /* List of matched pathnames.  */
64*6777b538SAndroid Build Coastguard Worker       size_t gl_offs;     /* Slots to reserve in 'gl_pathv'.  */
65*6777b538SAndroid Build Coastguard Worker } glob_t;
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker #define GLOB_DOOFFS 0
glob(const char * pattern,ATTRIBUTE_UNUSED int flags,ATTRIBUTE_UNUSED int errfunc (const char * epath,int eerrno),glob_t * pglob)68*6777b538SAndroid Build Coastguard Worker static int glob(const char *pattern, ATTRIBUTE_UNUSED int flags,
69*6777b538SAndroid Build Coastguard Worker                 ATTRIBUTE_UNUSED int errfunc(const char *epath, int eerrno),
70*6777b538SAndroid Build Coastguard Worker                 glob_t *pglob) {
71*6777b538SAndroid Build Coastguard Worker     glob_t *ret;
72*6777b538SAndroid Build Coastguard Worker     WIN32_FIND_DATA FindFileData;
73*6777b538SAndroid Build Coastguard Worker     HANDLE hFind;
74*6777b538SAndroid Build Coastguard Worker     unsigned int nb_paths = 0;
75*6777b538SAndroid Build Coastguard Worker     char directory[500];
76*6777b538SAndroid Build Coastguard Worker     int len;
77*6777b538SAndroid Build Coastguard Worker 
78*6777b538SAndroid Build Coastguard Worker     if ((pattern == NULL) || (pglob == NULL)) return(-1);
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker     strncpy(directory, pattern, 499);
81*6777b538SAndroid Build Coastguard Worker     for (len = strlen(directory);len >= 0;len--) {
82*6777b538SAndroid Build Coastguard Worker         if (directory[len] == '/') {
83*6777b538SAndroid Build Coastguard Worker 	    len++;
84*6777b538SAndroid Build Coastguard Worker 	    directory[len] = 0;
85*6777b538SAndroid Build Coastguard Worker 	    break;
86*6777b538SAndroid Build Coastguard Worker 	}
87*6777b538SAndroid Build Coastguard Worker     }
88*6777b538SAndroid Build Coastguard Worker     if (len <= 0)
89*6777b538SAndroid Build Coastguard Worker         len = 0;
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker 
92*6777b538SAndroid Build Coastguard Worker     ret = pglob;
93*6777b538SAndroid Build Coastguard Worker     memset(ret, 0, sizeof(glob_t));
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker     hFind = FindFirstFileA(pattern, &FindFileData);
96*6777b538SAndroid Build Coastguard Worker     if (hFind == INVALID_HANDLE_VALUE)
97*6777b538SAndroid Build Coastguard Worker         return(0);
98*6777b538SAndroid Build Coastguard Worker     nb_paths = 20;
99*6777b538SAndroid Build Coastguard Worker     ret->gl_pathv = (char **) malloc(nb_paths * sizeof(char *));
100*6777b538SAndroid Build Coastguard Worker     if (ret->gl_pathv == NULL) {
101*6777b538SAndroid Build Coastguard Worker 	FindClose(hFind);
102*6777b538SAndroid Build Coastguard Worker         return(-1);
103*6777b538SAndroid Build Coastguard Worker     }
104*6777b538SAndroid Build Coastguard Worker     strncpy(directory + len, FindFileData.cFileName, 499 - len);
105*6777b538SAndroid Build Coastguard Worker     ret->gl_pathv[ret->gl_pathc] = strdup(directory);
106*6777b538SAndroid Build Coastguard Worker     if (ret->gl_pathv[ret->gl_pathc] == NULL)
107*6777b538SAndroid Build Coastguard Worker         goto done;
108*6777b538SAndroid Build Coastguard Worker     ret->gl_pathc++;
109*6777b538SAndroid Build Coastguard Worker     while(FindNextFileA(hFind, &FindFileData)) {
110*6777b538SAndroid Build Coastguard Worker         if (FindFileData.cFileName[0] == '.')
111*6777b538SAndroid Build Coastguard Worker 	    continue;
112*6777b538SAndroid Build Coastguard Worker         if (ret->gl_pathc + 2 > nb_paths) {
113*6777b538SAndroid Build Coastguard Worker             char **tmp = realloc(ret->gl_pathv, nb_paths * 2 * sizeof(char *));
114*6777b538SAndroid Build Coastguard Worker             if (tmp == NULL)
115*6777b538SAndroid Build Coastguard Worker                 break;
116*6777b538SAndroid Build Coastguard Worker             ret->gl_pathv = tmp;
117*6777b538SAndroid Build Coastguard Worker             nb_paths *= 2;
118*6777b538SAndroid Build Coastguard Worker 	}
119*6777b538SAndroid Build Coastguard Worker 	strncpy(directory + len, FindFileData.cFileName, 499 - len);
120*6777b538SAndroid Build Coastguard Worker 	ret->gl_pathv[ret->gl_pathc] = strdup(directory);
121*6777b538SAndroid Build Coastguard Worker         if (ret->gl_pathv[ret->gl_pathc] == NULL)
122*6777b538SAndroid Build Coastguard Worker             break;
123*6777b538SAndroid Build Coastguard Worker         ret->gl_pathc++;
124*6777b538SAndroid Build Coastguard Worker     }
125*6777b538SAndroid Build Coastguard Worker     ret->gl_pathv[ret->gl_pathc] = NULL;
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker done:
128*6777b538SAndroid Build Coastguard Worker     FindClose(hFind);
129*6777b538SAndroid Build Coastguard Worker     return(0);
130*6777b538SAndroid Build Coastguard Worker }
131*6777b538SAndroid Build Coastguard Worker 
132*6777b538SAndroid Build Coastguard Worker 
133*6777b538SAndroid Build Coastguard Worker 
globfree(glob_t * pglob)134*6777b538SAndroid Build Coastguard Worker static void globfree(glob_t *pglob) {
135*6777b538SAndroid Build Coastguard Worker     unsigned int i;
136*6777b538SAndroid Build Coastguard Worker     if (pglob == NULL)
137*6777b538SAndroid Build Coastguard Worker         return;
138*6777b538SAndroid Build Coastguard Worker 
139*6777b538SAndroid Build Coastguard Worker     for (i = 0;i < pglob->gl_pathc;i++) {
140*6777b538SAndroid Build Coastguard Worker          if (pglob->gl_pathv[i] != NULL)
141*6777b538SAndroid Build Coastguard Worker              free(pglob->gl_pathv[i]);
142*6777b538SAndroid Build Coastguard Worker     }
143*6777b538SAndroid Build Coastguard Worker }
144*6777b538SAndroid Build Coastguard Worker 
145*6777b538SAndroid Build Coastguard Worker #else
146*6777b538SAndroid Build Coastguard Worker #include <glob.h>
147*6777b538SAndroid Build Coastguard Worker #endif
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker /************************************************************************
150*6777b538SAndroid Build Coastguard Worker  *									*
151*6777b538SAndroid Build Coastguard Worker  *		Huge document generator					*
152*6777b538SAndroid Build Coastguard Worker  *									*
153*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlIO.h>
156*6777b538SAndroid Build Coastguard Worker 
157*6777b538SAndroid Build Coastguard Worker typedef struct {
158*6777b538SAndroid Build Coastguard Worker     const char *URL;
159*6777b538SAndroid Build Coastguard Worker     const char *start;
160*6777b538SAndroid Build Coastguard Worker     const char *segment;
161*6777b538SAndroid Build Coastguard Worker     const char *finish;
162*6777b538SAndroid Build Coastguard Worker } xmlHugeDocParts;
163*6777b538SAndroid Build Coastguard Worker 
164*6777b538SAndroid Build Coastguard Worker static const xmlHugeDocParts hugeDocTable[] = {
165*6777b538SAndroid Build Coastguard Worker     {
166*6777b538SAndroid Build Coastguard Worker         "test/recurse/huge.xml",
167*6777b538SAndroid Build Coastguard Worker 
168*6777b538SAndroid Build Coastguard Worker         "<!DOCTYPE foo ["
169*6777b538SAndroid Build Coastguard Worker         "<!ELEMENT foo (bar*)> "
170*6777b538SAndroid Build Coastguard Worker         "<!ELEMENT bar (#PCDATA)> "
171*6777b538SAndroid Build Coastguard Worker         "<!ATTLIST bar attr CDATA #IMPLIED> "
172*6777b538SAndroid Build Coastguard Worker         "<!ENTITY a SYSTEM 'ga.ent'> "
173*6777b538SAndroid Build Coastguard Worker         "<!ENTITY b SYSTEM 'gb.ent'> "
174*6777b538SAndroid Build Coastguard Worker         "<!ENTITY c SYSTEM 'gc.ent'> "
175*6777b538SAndroid Build Coastguard Worker         "<!ENTITY f 'some internal data'> "
176*6777b538SAndroid Build Coastguard Worker         "<!ENTITY e '&f;&f;'> "
177*6777b538SAndroid Build Coastguard Worker         "<!ENTITY d '&e;&e;'> "
178*6777b538SAndroid Build Coastguard Worker         "]> "
179*6777b538SAndroid Build Coastguard Worker         "<foo>",
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker         "  <bar attr='&e; &f; &d;'>&a; &b; &c; &e; &f; &d;</bar>\n"
182*6777b538SAndroid Build Coastguard Worker         "  <bar>_123456789_123456789_123456789_123456789</bar>\n"
183*6777b538SAndroid Build Coastguard Worker         "  <bar>_123456789_123456789_123456789_123456789</bar>\n"
184*6777b538SAndroid Build Coastguard Worker         "  <bar>_123456789_123456789_123456789_123456789</bar>\n"
185*6777b538SAndroid Build Coastguard Worker         "  <bar>_123456789_123456789_123456789_123456789</bar>\n",
186*6777b538SAndroid Build Coastguard Worker 
187*6777b538SAndroid Build Coastguard Worker         "</foo>"
188*6777b538SAndroid Build Coastguard Worker     },
189*6777b538SAndroid Build Coastguard Worker     {
190*6777b538SAndroid Build Coastguard Worker         "test/recurse/huge_dtd.dtd",
191*6777b538SAndroid Build Coastguard Worker 
192*6777b538SAndroid Build Coastguard Worker         "<!ELEMENT foo (#PCDATA)>\n"
193*6777b538SAndroid Build Coastguard Worker         "<!ENTITY ent 'success'>\n"
194*6777b538SAndroid Build Coastguard Worker         "<!ENTITY % a SYSTEM 'pa.ent'>\n"
195*6777b538SAndroid Build Coastguard Worker         "<!ENTITY % b SYSTEM 'pb.ent'>\n"
196*6777b538SAndroid Build Coastguard Worker         "<!ENTITY % c SYSTEM 'pc.ent'>\n"
197*6777b538SAndroid Build Coastguard Worker         "<!ENTITY % d '<!-- comment -->'>\n"
198*6777b538SAndroid Build Coastguard Worker         "<!ENTITY % e '%d;%d;'>\n"
199*6777b538SAndroid Build Coastguard Worker         "<!ENTITY % f '%e;%e;'>\n",
200*6777b538SAndroid Build Coastguard Worker 
201*6777b538SAndroid Build Coastguard Worker         "<!ENTITY ent '%a; %b; %c; %d; %e; %f;'>\n"
202*6777b538SAndroid Build Coastguard Worker         "%a; %b; %c; %d; %e; %f;\n"
203*6777b538SAndroid Build Coastguard Worker         "<!-- _123456789_123456789_123456789_123456789 -->\n"
204*6777b538SAndroid Build Coastguard Worker         "<!-- _123456789_123456789_123456789_123456789 -->\n"
205*6777b538SAndroid Build Coastguard Worker         "<!-- _123456789_123456789_123456789_123456789 -->\n",
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker         ""
208*6777b538SAndroid Build Coastguard Worker     },
209*6777b538SAndroid Build Coastguard Worker     { NULL, NULL, NULL, NULL }
210*6777b538SAndroid Build Coastguard Worker };
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker static const xmlHugeDocParts *hugeDocParts;
213*6777b538SAndroid Build Coastguard Worker static int curseg = 0;
214*6777b538SAndroid Build Coastguard Worker static const char *current;
215*6777b538SAndroid Build Coastguard Worker static int rlen;
216*6777b538SAndroid Build Coastguard Worker 
217*6777b538SAndroid Build Coastguard Worker /**
218*6777b538SAndroid Build Coastguard Worker  * hugeMatch:
219*6777b538SAndroid Build Coastguard Worker  * @URI: an URI to test
220*6777b538SAndroid Build Coastguard Worker  *
221*6777b538SAndroid Build Coastguard Worker  * Check for a huge query
222*6777b538SAndroid Build Coastguard Worker  *
223*6777b538SAndroid Build Coastguard Worker  * Returns 1 if yes and 0 if another Input module should be used
224*6777b538SAndroid Build Coastguard Worker  */
225*6777b538SAndroid Build Coastguard Worker static int
hugeMatch(const char * URI)226*6777b538SAndroid Build Coastguard Worker hugeMatch(const char * URI) {
227*6777b538SAndroid Build Coastguard Worker     int i;
228*6777b538SAndroid Build Coastguard Worker 
229*6777b538SAndroid Build Coastguard Worker     if (URI == NULL)
230*6777b538SAndroid Build Coastguard Worker         return(0);
231*6777b538SAndroid Build Coastguard Worker 
232*6777b538SAndroid Build Coastguard Worker     for (i = 0; hugeDocTable[i].URL; i++) {
233*6777b538SAndroid Build Coastguard Worker         if (strcmp(URI, hugeDocTable[i].URL) == 0)
234*6777b538SAndroid Build Coastguard Worker             return(1);
235*6777b538SAndroid Build Coastguard Worker     }
236*6777b538SAndroid Build Coastguard Worker 
237*6777b538SAndroid Build Coastguard Worker     return(0);
238*6777b538SAndroid Build Coastguard Worker }
239*6777b538SAndroid Build Coastguard Worker 
240*6777b538SAndroid Build Coastguard Worker /**
241*6777b538SAndroid Build Coastguard Worker  * hugeOpen:
242*6777b538SAndroid Build Coastguard Worker  * @URI: an URI to test
243*6777b538SAndroid Build Coastguard Worker  *
244*6777b538SAndroid Build Coastguard Worker  * Return a pointer to the huge query handler, in this example simply
245*6777b538SAndroid Build Coastguard Worker  * the current pointer...
246*6777b538SAndroid Build Coastguard Worker  *
247*6777b538SAndroid Build Coastguard Worker  * Returns an Input context or NULL in case or error
248*6777b538SAndroid Build Coastguard Worker  */
249*6777b538SAndroid Build Coastguard Worker static void *
hugeOpen(const char * URI)250*6777b538SAndroid Build Coastguard Worker hugeOpen(const char * URI) {
251*6777b538SAndroid Build Coastguard Worker     int i;
252*6777b538SAndroid Build Coastguard Worker 
253*6777b538SAndroid Build Coastguard Worker     if (URI == NULL)
254*6777b538SAndroid Build Coastguard Worker         return(NULL);
255*6777b538SAndroid Build Coastguard Worker 
256*6777b538SAndroid Build Coastguard Worker     for (i = 0; hugeDocTable[i].URL; i++) {
257*6777b538SAndroid Build Coastguard Worker         if (strcmp(URI, hugeDocTable[i].URL) == 0) {
258*6777b538SAndroid Build Coastguard Worker             hugeDocParts = hugeDocTable + i;
259*6777b538SAndroid Build Coastguard Worker             curseg = 0;
260*6777b538SAndroid Build Coastguard Worker             current = hugeDocParts->start;
261*6777b538SAndroid Build Coastguard Worker             rlen = strlen(current);
262*6777b538SAndroid Build Coastguard Worker             return((void *) current);
263*6777b538SAndroid Build Coastguard Worker         }
264*6777b538SAndroid Build Coastguard Worker     }
265*6777b538SAndroid Build Coastguard Worker 
266*6777b538SAndroid Build Coastguard Worker     return(NULL);
267*6777b538SAndroid Build Coastguard Worker }
268*6777b538SAndroid Build Coastguard Worker 
269*6777b538SAndroid Build Coastguard Worker /**
270*6777b538SAndroid Build Coastguard Worker  * hugeClose:
271*6777b538SAndroid Build Coastguard Worker  * @context: the read context
272*6777b538SAndroid Build Coastguard Worker  *
273*6777b538SAndroid Build Coastguard Worker  * Close the huge query handler
274*6777b538SAndroid Build Coastguard Worker  *
275*6777b538SAndroid Build Coastguard Worker  * Returns 0 or -1 in case of error
276*6777b538SAndroid Build Coastguard Worker  */
277*6777b538SAndroid Build Coastguard Worker static int
hugeClose(void * context)278*6777b538SAndroid Build Coastguard Worker hugeClose(void * context) {
279*6777b538SAndroid Build Coastguard Worker     if (context == NULL) return(-1);
280*6777b538SAndroid Build Coastguard Worker     return(0);
281*6777b538SAndroid Build Coastguard Worker }
282*6777b538SAndroid Build Coastguard Worker 
283*6777b538SAndroid Build Coastguard Worker #define MAX_NODES 1000
284*6777b538SAndroid Build Coastguard Worker 
285*6777b538SAndroid Build Coastguard Worker /**
286*6777b538SAndroid Build Coastguard Worker  * hugeRead:
287*6777b538SAndroid Build Coastguard Worker  * @context: the read context
288*6777b538SAndroid Build Coastguard Worker  * @buffer: where to store data
289*6777b538SAndroid Build Coastguard Worker  * @len: number of bytes to read
290*6777b538SAndroid Build Coastguard Worker  *
291*6777b538SAndroid Build Coastguard Worker  * Implement an huge query read.
292*6777b538SAndroid Build Coastguard Worker  *
293*6777b538SAndroid Build Coastguard Worker  * Returns the number of bytes read or -1 in case of error
294*6777b538SAndroid Build Coastguard Worker  */
295*6777b538SAndroid Build Coastguard Worker static int
hugeRead(void * context,char * buffer,int len)296*6777b538SAndroid Build Coastguard Worker hugeRead(void *context, char *buffer, int len)
297*6777b538SAndroid Build Coastguard Worker {
298*6777b538SAndroid Build Coastguard Worker     if ((context == NULL) || (buffer == NULL) || (len < 0))
299*6777b538SAndroid Build Coastguard Worker         return (-1);
300*6777b538SAndroid Build Coastguard Worker 
301*6777b538SAndroid Build Coastguard Worker     if (len >= rlen) {
302*6777b538SAndroid Build Coastguard Worker         if (curseg >= MAX_NODES + 1) {
303*6777b538SAndroid Build Coastguard Worker             rlen = 0;
304*6777b538SAndroid Build Coastguard Worker             return(0);
305*6777b538SAndroid Build Coastguard Worker         }
306*6777b538SAndroid Build Coastguard Worker         len = rlen;
307*6777b538SAndroid Build Coastguard Worker         rlen = 0;
308*6777b538SAndroid Build Coastguard Worker 	memcpy(buffer, current, len);
309*6777b538SAndroid Build Coastguard Worker         curseg ++;
310*6777b538SAndroid Build Coastguard Worker         if (curseg == MAX_NODES) {
311*6777b538SAndroid Build Coastguard Worker             current = hugeDocParts->finish;
312*6777b538SAndroid Build Coastguard Worker 	} else {
313*6777b538SAndroid Build Coastguard Worker             current = hugeDocParts->segment;
314*6777b538SAndroid Build Coastguard Worker 	}
315*6777b538SAndroid Build Coastguard Worker         rlen = strlen(current);
316*6777b538SAndroid Build Coastguard Worker     } else {
317*6777b538SAndroid Build Coastguard Worker 	memcpy(buffer, current, len);
318*6777b538SAndroid Build Coastguard Worker 	rlen -= len;
319*6777b538SAndroid Build Coastguard Worker         current += len;
320*6777b538SAndroid Build Coastguard Worker     }
321*6777b538SAndroid Build Coastguard Worker     return (len);
322*6777b538SAndroid Build Coastguard Worker }
323*6777b538SAndroid Build Coastguard Worker 
324*6777b538SAndroid Build Coastguard Worker /************************************************************************
325*6777b538SAndroid Build Coastguard Worker  *									*
326*6777b538SAndroid Build Coastguard Worker  *		Libxml2 specific routines				*
327*6777b538SAndroid Build Coastguard Worker  *									*
328*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
329*6777b538SAndroid Build Coastguard Worker 
330*6777b538SAndroid Build Coastguard Worker static int nb_tests = 0;
331*6777b538SAndroid Build Coastguard Worker static int nb_errors = 0;
332*6777b538SAndroid Build Coastguard Worker static int nb_leaks = 0;
333*6777b538SAndroid Build Coastguard Worker static int extraMemoryFromResolver = 0;
334*6777b538SAndroid Build Coastguard Worker 
335*6777b538SAndroid Build Coastguard Worker static int
fatalError(void)336*6777b538SAndroid Build Coastguard Worker fatalError(void) {
337*6777b538SAndroid Build Coastguard Worker     fprintf(stderr, "Exitting tests on fatal error\n");
338*6777b538SAndroid Build Coastguard Worker     exit(1);
339*6777b538SAndroid Build Coastguard Worker }
340*6777b538SAndroid Build Coastguard Worker 
341*6777b538SAndroid Build Coastguard Worker /*
342*6777b538SAndroid Build Coastguard Worker  * We need to trap calls to the resolver to not account memory for the catalog
343*6777b538SAndroid Build Coastguard Worker  * which is shared to the current running test. We also don't want to have
344*6777b538SAndroid Build Coastguard Worker  * network downloads modifying tests.
345*6777b538SAndroid Build Coastguard Worker  */
346*6777b538SAndroid Build Coastguard Worker static xmlParserInputPtr
testExternalEntityLoader(const char * URL,const char * ID,xmlParserCtxtPtr ctxt)347*6777b538SAndroid Build Coastguard Worker testExternalEntityLoader(const char *URL, const char *ID,
348*6777b538SAndroid Build Coastguard Worker 			 xmlParserCtxtPtr ctxt) {
349*6777b538SAndroid Build Coastguard Worker     xmlParserInputPtr ret;
350*6777b538SAndroid Build Coastguard Worker 
351*6777b538SAndroid Build Coastguard Worker     if (checkTestFile(URL)) {
352*6777b538SAndroid Build Coastguard Worker 	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
353*6777b538SAndroid Build Coastguard Worker     } else {
354*6777b538SAndroid Build Coastguard Worker 	int memused = xmlMemUsed();
355*6777b538SAndroid Build Coastguard Worker 	ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
356*6777b538SAndroid Build Coastguard Worker 	extraMemoryFromResolver += xmlMemUsed() - memused;
357*6777b538SAndroid Build Coastguard Worker     }
358*6777b538SAndroid Build Coastguard Worker 
359*6777b538SAndroid Build Coastguard Worker     return(ret);
360*6777b538SAndroid Build Coastguard Worker }
361*6777b538SAndroid Build Coastguard Worker 
362*6777b538SAndroid Build Coastguard Worker static void
initializeLibxml2(void)363*6777b538SAndroid Build Coastguard Worker initializeLibxml2(void) {
364*6777b538SAndroid Build Coastguard Worker     xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
365*6777b538SAndroid Build Coastguard Worker     xmlInitParser();
366*6777b538SAndroid Build Coastguard Worker     xmlSetExternalEntityLoader(testExternalEntityLoader);
367*6777b538SAndroid Build Coastguard Worker     /*
368*6777b538SAndroid Build Coastguard Worker      * register the new I/O handlers
369*6777b538SAndroid Build Coastguard Worker      */
370*6777b538SAndroid Build Coastguard Worker     if (xmlRegisterInputCallbacks(hugeMatch, hugeOpen,
371*6777b538SAndroid Build Coastguard Worker                                   hugeRead, hugeClose) < 0) {
372*6777b538SAndroid Build Coastguard Worker         fprintf(stderr, "failed to register Huge handler\n");
373*6777b538SAndroid Build Coastguard Worker 	exit(1);
374*6777b538SAndroid Build Coastguard Worker     }
375*6777b538SAndroid Build Coastguard Worker }
376*6777b538SAndroid Build Coastguard Worker 
377*6777b538SAndroid Build Coastguard Worker static void
initSAX(xmlParserCtxtPtr ctxt)378*6777b538SAndroid Build Coastguard Worker initSAX(xmlParserCtxtPtr ctxt) {
379*6777b538SAndroid Build Coastguard Worker     ctxt->sax->startElementNs = NULL;
380*6777b538SAndroid Build Coastguard Worker     ctxt->sax->endElementNs = NULL;
381*6777b538SAndroid Build Coastguard Worker     ctxt->sax->startElement = NULL;
382*6777b538SAndroid Build Coastguard Worker     ctxt->sax->endElement = NULL;
383*6777b538SAndroid Build Coastguard Worker     ctxt->sax->characters = NULL;
384*6777b538SAndroid Build Coastguard Worker     ctxt->sax->cdataBlock = NULL;
385*6777b538SAndroid Build Coastguard Worker     ctxt->sax->ignorableWhitespace = NULL;
386*6777b538SAndroid Build Coastguard Worker     ctxt->sax->processingInstruction = NULL;
387*6777b538SAndroid Build Coastguard Worker     ctxt->sax->comment = NULL;
388*6777b538SAndroid Build Coastguard Worker }
389*6777b538SAndroid Build Coastguard Worker 
390*6777b538SAndroid Build Coastguard Worker /************************************************************************
391*6777b538SAndroid Build Coastguard Worker  *									*
392*6777b538SAndroid Build Coastguard Worker  *		File name and path utilities				*
393*6777b538SAndroid Build Coastguard Worker  *									*
394*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
395*6777b538SAndroid Build Coastguard Worker 
baseFilename(const char * filename)396*6777b538SAndroid Build Coastguard Worker static const char *baseFilename(const char *filename) {
397*6777b538SAndroid Build Coastguard Worker     const char *cur;
398*6777b538SAndroid Build Coastguard Worker     if (filename == NULL)
399*6777b538SAndroid Build Coastguard Worker         return(NULL);
400*6777b538SAndroid Build Coastguard Worker     cur = &filename[strlen(filename)];
401*6777b538SAndroid Build Coastguard Worker     while ((cur > filename) && (*cur != '/'))
402*6777b538SAndroid Build Coastguard Worker         cur--;
403*6777b538SAndroid Build Coastguard Worker     if (*cur == '/')
404*6777b538SAndroid Build Coastguard Worker         return(cur + 1);
405*6777b538SAndroid Build Coastguard Worker     return(cur);
406*6777b538SAndroid Build Coastguard Worker }
407*6777b538SAndroid Build Coastguard Worker 
resultFilename(const char * filename,const char * out,const char * suffix)408*6777b538SAndroid Build Coastguard Worker static char *resultFilename(const char *filename, const char *out,
409*6777b538SAndroid Build Coastguard Worker                             const char *suffix) {
410*6777b538SAndroid Build Coastguard Worker     const char *base;
411*6777b538SAndroid Build Coastguard Worker     char res[500];
412*6777b538SAndroid Build Coastguard Worker     char suffixbuff[500];
413*6777b538SAndroid Build Coastguard Worker 
414*6777b538SAndroid Build Coastguard Worker /*************
415*6777b538SAndroid Build Coastguard Worker     if ((filename[0] == 't') && (filename[1] == 'e') &&
416*6777b538SAndroid Build Coastguard Worker         (filename[2] == 's') && (filename[3] == 't') &&
417*6777b538SAndroid Build Coastguard Worker 	(filename[4] == '/'))
418*6777b538SAndroid Build Coastguard Worker 	filename = &filename[5];
419*6777b538SAndroid Build Coastguard Worker  *************/
420*6777b538SAndroid Build Coastguard Worker 
421*6777b538SAndroid Build Coastguard Worker     base = baseFilename(filename);
422*6777b538SAndroid Build Coastguard Worker     if (suffix == NULL)
423*6777b538SAndroid Build Coastguard Worker         suffix = ".tmp";
424*6777b538SAndroid Build Coastguard Worker     if (out == NULL)
425*6777b538SAndroid Build Coastguard Worker         out = "";
426*6777b538SAndroid Build Coastguard Worker 
427*6777b538SAndroid Build Coastguard Worker     strncpy(suffixbuff,suffix,499);
428*6777b538SAndroid Build Coastguard Worker 
429*6777b538SAndroid Build Coastguard Worker     if (snprintf(res, 499, "%s%s%s", out, base, suffixbuff) >= 499)
430*6777b538SAndroid Build Coastguard Worker         res[499] = 0;
431*6777b538SAndroid Build Coastguard Worker     return(strdup(res));
432*6777b538SAndroid Build Coastguard Worker }
433*6777b538SAndroid Build Coastguard Worker 
checkTestFile(const char * filename)434*6777b538SAndroid Build Coastguard Worker static int checkTestFile(const char *filename) {
435*6777b538SAndroid Build Coastguard Worker     struct stat buf;
436*6777b538SAndroid Build Coastguard Worker 
437*6777b538SAndroid Build Coastguard Worker     if (stat(filename, &buf) == -1)
438*6777b538SAndroid Build Coastguard Worker         return(0);
439*6777b538SAndroid Build Coastguard Worker 
440*6777b538SAndroid Build Coastguard Worker #if defined(_WIN32)
441*6777b538SAndroid Build Coastguard Worker     if (!(buf.st_mode & _S_IFREG))
442*6777b538SAndroid Build Coastguard Worker         return(0);
443*6777b538SAndroid Build Coastguard Worker #else
444*6777b538SAndroid Build Coastguard Worker     if (!S_ISREG(buf.st_mode))
445*6777b538SAndroid Build Coastguard Worker         return(0);
446*6777b538SAndroid Build Coastguard Worker #endif
447*6777b538SAndroid Build Coastguard Worker 
448*6777b538SAndroid Build Coastguard Worker     return(1);
449*6777b538SAndroid Build Coastguard Worker }
450*6777b538SAndroid Build Coastguard Worker 
451*6777b538SAndroid Build Coastguard Worker 
452*6777b538SAndroid Build Coastguard Worker 
453*6777b538SAndroid Build Coastguard Worker /************************************************************************
454*6777b538SAndroid Build Coastguard Worker  *									*
455*6777b538SAndroid Build Coastguard Worker  *		Test to detect or not recursive entities		*
456*6777b538SAndroid Build Coastguard Worker  *									*
457*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
458*6777b538SAndroid Build Coastguard Worker /**
459*6777b538SAndroid Build Coastguard Worker  * recursiveDetectTest:
460*6777b538SAndroid Build Coastguard Worker  * @filename: the file to parse
461*6777b538SAndroid Build Coastguard Worker  * @result: the file with expected result
462*6777b538SAndroid Build Coastguard Worker  * @err: the file with error messages: unused
463*6777b538SAndroid Build Coastguard Worker  *
464*6777b538SAndroid Build Coastguard Worker  * Parse a file loading DTD and replacing entities check it fails for
465*6777b538SAndroid Build Coastguard Worker  * lol cases
466*6777b538SAndroid Build Coastguard Worker  *
467*6777b538SAndroid Build Coastguard Worker  * Returns 0 in case of success, an error code otherwise
468*6777b538SAndroid Build Coastguard Worker  */
469*6777b538SAndroid Build Coastguard Worker static int
recursiveDetectTest(const char * filename,const char * result ATTRIBUTE_UNUSED,const char * err ATTRIBUTE_UNUSED,int options)470*6777b538SAndroid Build Coastguard Worker recursiveDetectTest(const char *filename,
471*6777b538SAndroid Build Coastguard Worker              const char *result ATTRIBUTE_UNUSED,
472*6777b538SAndroid Build Coastguard Worker              const char *err ATTRIBUTE_UNUSED,
473*6777b538SAndroid Build Coastguard Worker 	     int options) {
474*6777b538SAndroid Build Coastguard Worker     xmlDocPtr doc;
475*6777b538SAndroid Build Coastguard Worker     xmlParserCtxtPtr ctxt;
476*6777b538SAndroid Build Coastguard Worker     int res = 0;
477*6777b538SAndroid Build Coastguard Worker     /*
478*6777b538SAndroid Build Coastguard Worker      * XML_PARSE_DTDVALID is the only way to load external entities
479*6777b538SAndroid Build Coastguard Worker      * without XML_PARSE_NOENT. The validation result doesn't matter
480*6777b538SAndroid Build Coastguard Worker      * anyway.
481*6777b538SAndroid Build Coastguard Worker      */
482*6777b538SAndroid Build Coastguard Worker     int parserOptions = XML_PARSE_DTDVALID | XML_PARSE_NOERROR;
483*6777b538SAndroid Build Coastguard Worker 
484*6777b538SAndroid Build Coastguard Worker     nb_tests++;
485*6777b538SAndroid Build Coastguard Worker 
486*6777b538SAndroid Build Coastguard Worker     ctxt = xmlNewParserCtxt();
487*6777b538SAndroid Build Coastguard Worker     if (options & OPT_SAX)
488*6777b538SAndroid Build Coastguard Worker         initSAX(ctxt);
489*6777b538SAndroid Build Coastguard Worker     if ((options & OPT_NO_SUBST) == 0)
490*6777b538SAndroid Build Coastguard Worker         parserOptions |= XML_PARSE_NOENT;
491*6777b538SAndroid Build Coastguard Worker     /*
492*6777b538SAndroid Build Coastguard Worker      * base of the test, parse with the old API
493*6777b538SAndroid Build Coastguard Worker      */
494*6777b538SAndroid Build Coastguard Worker     doc = xmlCtxtReadFile(ctxt, filename, NULL, parserOptions);
495*6777b538SAndroid Build Coastguard Worker     if ((doc != NULL) || (ctxt->lastError.code != XML_ERR_RESOURCE_LIMIT)) {
496*6777b538SAndroid Build Coastguard Worker         fprintf(stderr, "Failed to detect recursion in %s\n", filename);
497*6777b538SAndroid Build Coastguard Worker 	xmlFreeParserCtxt(ctxt);
498*6777b538SAndroid Build Coastguard Worker 	xmlFreeDoc(doc);
499*6777b538SAndroid Build Coastguard Worker         return(1);
500*6777b538SAndroid Build Coastguard Worker     }
501*6777b538SAndroid Build Coastguard Worker     xmlFreeParserCtxt(ctxt);
502*6777b538SAndroid Build Coastguard Worker 
503*6777b538SAndroid Build Coastguard Worker     return(res);
504*6777b538SAndroid Build Coastguard Worker }
505*6777b538SAndroid Build Coastguard Worker 
506*6777b538SAndroid Build Coastguard Worker /**
507*6777b538SAndroid Build Coastguard Worker  * notRecursiveDetectTest:
508*6777b538SAndroid Build Coastguard Worker  * @filename: the file to parse
509*6777b538SAndroid Build Coastguard Worker  * @result: the file with expected result
510*6777b538SAndroid Build Coastguard Worker  * @err: the file with error messages: unused
511*6777b538SAndroid Build Coastguard Worker  *
512*6777b538SAndroid Build Coastguard Worker  * Parse a file loading DTD and replacing entities check it works for
513*6777b538SAndroid Build Coastguard Worker  * good cases
514*6777b538SAndroid Build Coastguard Worker  *
515*6777b538SAndroid Build Coastguard Worker  * Returns 0 in case of success, an error code otherwise
516*6777b538SAndroid Build Coastguard Worker  */
517*6777b538SAndroid Build Coastguard Worker static int
notRecursiveDetectTest(const char * filename,const char * result ATTRIBUTE_UNUSED,const char * err ATTRIBUTE_UNUSED,int options)518*6777b538SAndroid Build Coastguard Worker notRecursiveDetectTest(const char *filename,
519*6777b538SAndroid Build Coastguard Worker              const char *result ATTRIBUTE_UNUSED,
520*6777b538SAndroid Build Coastguard Worker              const char *err ATTRIBUTE_UNUSED,
521*6777b538SAndroid Build Coastguard Worker 	     int options) {
522*6777b538SAndroid Build Coastguard Worker     xmlDocPtr doc;
523*6777b538SAndroid Build Coastguard Worker     xmlParserCtxtPtr ctxt;
524*6777b538SAndroid Build Coastguard Worker     int res = 0;
525*6777b538SAndroid Build Coastguard Worker     int parserOptions = XML_PARSE_DTDLOAD;
526*6777b538SAndroid Build Coastguard Worker 
527*6777b538SAndroid Build Coastguard Worker     nb_tests++;
528*6777b538SAndroid Build Coastguard Worker 
529*6777b538SAndroid Build Coastguard Worker     ctxt = xmlNewParserCtxt();
530*6777b538SAndroid Build Coastguard Worker     if (options & OPT_SAX)
531*6777b538SAndroid Build Coastguard Worker         initSAX(ctxt);
532*6777b538SAndroid Build Coastguard Worker     if ((options & OPT_NO_SUBST) == 0)
533*6777b538SAndroid Build Coastguard Worker         parserOptions |= XML_PARSE_NOENT;
534*6777b538SAndroid Build Coastguard Worker     /*
535*6777b538SAndroid Build Coastguard Worker      * base of the test, parse with the old API
536*6777b538SAndroid Build Coastguard Worker      */
537*6777b538SAndroid Build Coastguard Worker     doc = xmlCtxtReadFile(ctxt, filename, NULL, parserOptions);
538*6777b538SAndroid Build Coastguard Worker     if (doc == NULL) {
539*6777b538SAndroid Build Coastguard Worker         fprintf(stderr, "Failed to parse correct file %s\n", filename);
540*6777b538SAndroid Build Coastguard Worker 	xmlFreeParserCtxt(ctxt);
541*6777b538SAndroid Build Coastguard Worker         return(1);
542*6777b538SAndroid Build Coastguard Worker     }
543*6777b538SAndroid Build Coastguard Worker     xmlFreeDoc(doc);
544*6777b538SAndroid Build Coastguard Worker     xmlFreeParserCtxt(ctxt);
545*6777b538SAndroid Build Coastguard Worker 
546*6777b538SAndroid Build Coastguard Worker     return(res);
547*6777b538SAndroid Build Coastguard Worker }
548*6777b538SAndroid Build Coastguard Worker 
549*6777b538SAndroid Build Coastguard Worker /**
550*6777b538SAndroid Build Coastguard Worker  * notRecursiveHugeTest:
551*6777b538SAndroid Build Coastguard Worker  * @filename: the file to parse
552*6777b538SAndroid Build Coastguard Worker  * @result: the file with expected result
553*6777b538SAndroid Build Coastguard Worker  * @err: the file with error messages: unused
554*6777b538SAndroid Build Coastguard Worker  *
555*6777b538SAndroid Build Coastguard Worker  * Parse a memory generated file
556*6777b538SAndroid Build Coastguard Worker  * good cases
557*6777b538SAndroid Build Coastguard Worker  *
558*6777b538SAndroid Build Coastguard Worker  * Returns 0 in case of success, an error code otherwise
559*6777b538SAndroid Build Coastguard Worker  */
560*6777b538SAndroid Build Coastguard Worker static int
notRecursiveHugeTest(const char * filename ATTRIBUTE_UNUSED,const char * result ATTRIBUTE_UNUSED,const char * err ATTRIBUTE_UNUSED,int options)561*6777b538SAndroid Build Coastguard Worker notRecursiveHugeTest(const char *filename ATTRIBUTE_UNUSED,
562*6777b538SAndroid Build Coastguard Worker              const char *result ATTRIBUTE_UNUSED,
563*6777b538SAndroid Build Coastguard Worker              const char *err ATTRIBUTE_UNUSED,
564*6777b538SAndroid Build Coastguard Worker 	     int options) {
565*6777b538SAndroid Build Coastguard Worker     xmlParserCtxtPtr ctxt;
566*6777b538SAndroid Build Coastguard Worker     xmlDocPtr doc;
567*6777b538SAndroid Build Coastguard Worker     int res = 0;
568*6777b538SAndroid Build Coastguard Worker     int parserOptions = XML_PARSE_DTDVALID;
569*6777b538SAndroid Build Coastguard Worker 
570*6777b538SAndroid Build Coastguard Worker     nb_tests++;
571*6777b538SAndroid Build Coastguard Worker 
572*6777b538SAndroid Build Coastguard Worker     ctxt = xmlNewParserCtxt();
573*6777b538SAndroid Build Coastguard Worker     if (options & OPT_SAX)
574*6777b538SAndroid Build Coastguard Worker         initSAX(ctxt);
575*6777b538SAndroid Build Coastguard Worker     if ((options & OPT_NO_SUBST) == 0)
576*6777b538SAndroid Build Coastguard Worker         parserOptions |= XML_PARSE_NOENT;
577*6777b538SAndroid Build Coastguard Worker     doc = xmlCtxtReadFile(ctxt, "test/recurse/huge.xml", NULL, parserOptions);
578*6777b538SAndroid Build Coastguard Worker     if (doc == NULL) {
579*6777b538SAndroid Build Coastguard Worker         fprintf(stderr, "Failed to parse huge.xml\n");
580*6777b538SAndroid Build Coastguard Worker 	res = 1;
581*6777b538SAndroid Build Coastguard Worker     } else {
582*6777b538SAndroid Build Coastguard Worker         xmlEntityPtr ent;
583*6777b538SAndroid Build Coastguard Worker         unsigned long fixed_cost = 20;
584*6777b538SAndroid Build Coastguard Worker         unsigned long allowed_expansion = 1000000;
585*6777b538SAndroid Build Coastguard Worker         unsigned long f_size = xmlStrlen(BAD_CAST "some internal data");
586*6777b538SAndroid Build Coastguard Worker         unsigned long e_size;
587*6777b538SAndroid Build Coastguard Worker         unsigned long d_size;
588*6777b538SAndroid Build Coastguard Worker         unsigned long total_size;
589*6777b538SAndroid Build Coastguard Worker 
590*6777b538SAndroid Build Coastguard Worker         ent = xmlGetDocEntity(doc, BAD_CAST "e");
591*6777b538SAndroid Build Coastguard Worker         e_size = f_size * 2 +
592*6777b538SAndroid Build Coastguard Worker                  xmlStrlen(BAD_CAST "&f;") * 2 +
593*6777b538SAndroid Build Coastguard Worker                  fixed_cost * 2;
594*6777b538SAndroid Build Coastguard Worker         if (ent->expandedSize != e_size) {
595*6777b538SAndroid Build Coastguard Worker             fprintf(stderr, "Wrong size for entity e: %lu (expected %lu)\n",
596*6777b538SAndroid Build Coastguard Worker                     ent->expandedSize, e_size);
597*6777b538SAndroid Build Coastguard Worker             res = 1;
598*6777b538SAndroid Build Coastguard Worker         }
599*6777b538SAndroid Build Coastguard Worker 
600*6777b538SAndroid Build Coastguard Worker         ent = xmlGetDocEntity(doc, BAD_CAST "b");
601*6777b538SAndroid Build Coastguard Worker         if (ent->expandedSize != e_size) {
602*6777b538SAndroid Build Coastguard Worker             fprintf(stderr, "Wrong size for entity b: %lu (expected %lu)\n",
603*6777b538SAndroid Build Coastguard Worker                     ent->expandedSize, e_size);
604*6777b538SAndroid Build Coastguard Worker             res = 1;
605*6777b538SAndroid Build Coastguard Worker         }
606*6777b538SAndroid Build Coastguard Worker 
607*6777b538SAndroid Build Coastguard Worker         ent = xmlGetDocEntity(doc, BAD_CAST "d");
608*6777b538SAndroid Build Coastguard Worker         d_size = e_size * 2 +
609*6777b538SAndroid Build Coastguard Worker                  xmlStrlen(BAD_CAST "&e;") * 2 +
610*6777b538SAndroid Build Coastguard Worker                  fixed_cost * 2;
611*6777b538SAndroid Build Coastguard Worker         if (ent->expandedSize != d_size) {
612*6777b538SAndroid Build Coastguard Worker             fprintf(stderr, "Wrong size for entity d: %lu (expected %lu)\n",
613*6777b538SAndroid Build Coastguard Worker                     ent->expandedSize, d_size);
614*6777b538SAndroid Build Coastguard Worker             res = 1;
615*6777b538SAndroid Build Coastguard Worker         }
616*6777b538SAndroid Build Coastguard Worker 
617*6777b538SAndroid Build Coastguard Worker         ent = xmlGetDocEntity(doc, BAD_CAST "c");
618*6777b538SAndroid Build Coastguard Worker         if (ent->expandedSize != d_size) {
619*6777b538SAndroid Build Coastguard Worker             fprintf(stderr, "Wrong size for entity c: %lu (expected %lu)\n",
620*6777b538SAndroid Build Coastguard Worker                     ent->expandedSize, d_size);
621*6777b538SAndroid Build Coastguard Worker             res = 1;
622*6777b538SAndroid Build Coastguard Worker         }
623*6777b538SAndroid Build Coastguard Worker 
624*6777b538SAndroid Build Coastguard Worker         if (ctxt->sizeentcopy < allowed_expansion) {
625*6777b538SAndroid Build Coastguard Worker             fprintf(stderr, "Total entity size too small: %lu\n",
626*6777b538SAndroid Build Coastguard Worker                     ctxt->sizeentcopy);
627*6777b538SAndroid Build Coastguard Worker             res = 1;
628*6777b538SAndroid Build Coastguard Worker         }
629*6777b538SAndroid Build Coastguard Worker 
630*6777b538SAndroid Build Coastguard Worker         total_size = (f_size + e_size + d_size + 3 * fixed_cost) *
631*6777b538SAndroid Build Coastguard Worker                      (MAX_NODES - 1) * 3;
632*6777b538SAndroid Build Coastguard Worker         if (ctxt->sizeentcopy != total_size) {
633*6777b538SAndroid Build Coastguard Worker             fprintf(stderr, "Wrong total entity size: %lu (expected %lu)\n",
634*6777b538SAndroid Build Coastguard Worker                     ctxt->sizeentcopy, total_size);
635*6777b538SAndroid Build Coastguard Worker             res = 1;
636*6777b538SAndroid Build Coastguard Worker         }
637*6777b538SAndroid Build Coastguard Worker 
638*6777b538SAndroid Build Coastguard Worker         if (ctxt->sizeentities != 30) {
639*6777b538SAndroid Build Coastguard Worker             fprintf(stderr, "Wrong parsed entity size: %lu (expected %lu)\n",
640*6777b538SAndroid Build Coastguard Worker                     ctxt->sizeentities, 30lu);
641*6777b538SAndroid Build Coastguard Worker             res = 1;
642*6777b538SAndroid Build Coastguard Worker         }
643*6777b538SAndroid Build Coastguard Worker     }
644*6777b538SAndroid Build Coastguard Worker 
645*6777b538SAndroid Build Coastguard Worker     xmlFreeDoc(doc);
646*6777b538SAndroid Build Coastguard Worker     xmlFreeParserCtxt(ctxt);
647*6777b538SAndroid Build Coastguard Worker 
648*6777b538SAndroid Build Coastguard Worker     return(res);
649*6777b538SAndroid Build Coastguard Worker }
650*6777b538SAndroid Build Coastguard Worker 
651*6777b538SAndroid Build Coastguard Worker /**
652*6777b538SAndroid Build Coastguard Worker  * notRecursiveHugeTest:
653*6777b538SAndroid Build Coastguard Worker  * @filename: the file to parse
654*6777b538SAndroid Build Coastguard Worker  * @result: the file with expected result
655*6777b538SAndroid Build Coastguard Worker  * @err: the file with error messages: unused
656*6777b538SAndroid Build Coastguard Worker  *
657*6777b538SAndroid Build Coastguard Worker  * Parse a memory generated file
658*6777b538SAndroid Build Coastguard Worker  * good cases
659*6777b538SAndroid Build Coastguard Worker  *
660*6777b538SAndroid Build Coastguard Worker  * Returns 0 in case of success, an error code otherwise
661*6777b538SAndroid Build Coastguard Worker  */
662*6777b538SAndroid Build Coastguard Worker static int
hugeDtdTest(const char * filename ATTRIBUTE_UNUSED,const char * result ATTRIBUTE_UNUSED,const char * err ATTRIBUTE_UNUSED,int options)663*6777b538SAndroid Build Coastguard Worker hugeDtdTest(const char *filename ATTRIBUTE_UNUSED,
664*6777b538SAndroid Build Coastguard Worker             const char *result ATTRIBUTE_UNUSED,
665*6777b538SAndroid Build Coastguard Worker             const char *err ATTRIBUTE_UNUSED,
666*6777b538SAndroid Build Coastguard Worker             int options) {
667*6777b538SAndroid Build Coastguard Worker     xmlParserCtxtPtr ctxt;
668*6777b538SAndroid Build Coastguard Worker     xmlDocPtr doc;
669*6777b538SAndroid Build Coastguard Worker     int res = 0;
670*6777b538SAndroid Build Coastguard Worker     int parserOptions = XML_PARSE_DTDVALID;
671*6777b538SAndroid Build Coastguard Worker 
672*6777b538SAndroid Build Coastguard Worker     nb_tests++;
673*6777b538SAndroid Build Coastguard Worker 
674*6777b538SAndroid Build Coastguard Worker     ctxt = xmlNewParserCtxt();
675*6777b538SAndroid Build Coastguard Worker     if (options & OPT_SAX)
676*6777b538SAndroid Build Coastguard Worker         initSAX(ctxt);
677*6777b538SAndroid Build Coastguard Worker     if ((options & OPT_NO_SUBST) == 0)
678*6777b538SAndroid Build Coastguard Worker         parserOptions |= XML_PARSE_NOENT;
679*6777b538SAndroid Build Coastguard Worker     doc = xmlCtxtReadFile(ctxt, "test/recurse/huge_dtd.xml", NULL,
680*6777b538SAndroid Build Coastguard Worker                           parserOptions);
681*6777b538SAndroid Build Coastguard Worker     if (doc == NULL) {
682*6777b538SAndroid Build Coastguard Worker         fprintf(stderr, "Failed to parse huge_dtd.xml\n");
683*6777b538SAndroid Build Coastguard Worker 	res = 1;
684*6777b538SAndroid Build Coastguard Worker     } else {
685*6777b538SAndroid Build Coastguard Worker         unsigned long fixed_cost = 20;
686*6777b538SAndroid Build Coastguard Worker         unsigned long allowed_expansion = 1000000;
687*6777b538SAndroid Build Coastguard Worker         unsigned long a_size = xmlStrlen(BAD_CAST "<!-- comment -->");
688*6777b538SAndroid Build Coastguard Worker         unsigned long b_size;
689*6777b538SAndroid Build Coastguard Worker         unsigned long c_size;
690*6777b538SAndroid Build Coastguard Worker         unsigned long e_size;
691*6777b538SAndroid Build Coastguard Worker         unsigned long f_size;
692*6777b538SAndroid Build Coastguard Worker         unsigned long total_size;
693*6777b538SAndroid Build Coastguard Worker 
694*6777b538SAndroid Build Coastguard Worker         if (ctxt->sizeentcopy < allowed_expansion) {
695*6777b538SAndroid Build Coastguard Worker             fprintf(stderr, "Total entity size too small: %lu\n",
696*6777b538SAndroid Build Coastguard Worker                     ctxt->sizeentcopy);
697*6777b538SAndroid Build Coastguard Worker             res = 1;
698*6777b538SAndroid Build Coastguard Worker         }
699*6777b538SAndroid Build Coastguard Worker 
700*6777b538SAndroid Build Coastguard Worker         b_size = (a_size + strlen("&a;") + fixed_cost) * 2;
701*6777b538SAndroid Build Coastguard Worker         c_size = (b_size + strlen("&b;") + fixed_cost) * 2;
702*6777b538SAndroid Build Coastguard Worker         /*
703*6777b538SAndroid Build Coastguard Worker          * Internal parameter entites are substitued eagerly and
704*6777b538SAndroid Build Coastguard Worker          * need different accounting.
705*6777b538SAndroid Build Coastguard Worker          */
706*6777b538SAndroid Build Coastguard Worker         e_size = a_size * 2;
707*6777b538SAndroid Build Coastguard Worker         f_size = e_size * 2;
708*6777b538SAndroid Build Coastguard Worker         total_size = /* internal */
709*6777b538SAndroid Build Coastguard Worker                      e_size + f_size + fixed_cost * 4 +
710*6777b538SAndroid Build Coastguard Worker                      (a_size + e_size + f_size + fixed_cost * 3) *
711*6777b538SAndroid Build Coastguard Worker                      (MAX_NODES - 1) * 2 +
712*6777b538SAndroid Build Coastguard Worker                      /* external */
713*6777b538SAndroid Build Coastguard Worker                      (a_size + b_size + c_size + fixed_cost * 3) *
714*6777b538SAndroid Build Coastguard Worker                      (MAX_NODES - 1) * 2 +
715*6777b538SAndroid Build Coastguard Worker                      /* final reference in main doc */
716*6777b538SAndroid Build Coastguard Worker                      strlen("success") + fixed_cost;
717*6777b538SAndroid Build Coastguard Worker         if (ctxt->sizeentcopy != total_size) {
718*6777b538SAndroid Build Coastguard Worker             fprintf(stderr, "Wrong total entity size: %lu (expected %lu)\n",
719*6777b538SAndroid Build Coastguard Worker                     ctxt->sizeentcopy, total_size);
720*6777b538SAndroid Build Coastguard Worker             res = 1;
721*6777b538SAndroid Build Coastguard Worker         }
722*6777b538SAndroid Build Coastguard Worker 
723*6777b538SAndroid Build Coastguard Worker         total_size = strlen(hugeDocParts->start) +
724*6777b538SAndroid Build Coastguard Worker                      strlen(hugeDocParts->segment) * (MAX_NODES - 1) +
725*6777b538SAndroid Build Coastguard Worker                      strlen(hugeDocParts->finish) +
726*6777b538SAndroid Build Coastguard Worker                      /*
727*6777b538SAndroid Build Coastguard Worker                       * Other external entities pa.ent, pb.ent, pc.ent.
728*6777b538SAndroid Build Coastguard Worker                       * These are currently counted twice because they're
729*6777b538SAndroid Build Coastguard Worker                       * used both in DTD and EntityValue.
730*6777b538SAndroid Build Coastguard Worker                       */
731*6777b538SAndroid Build Coastguard Worker                      (16 + 6 + 6) * 2;
732*6777b538SAndroid Build Coastguard Worker         if (ctxt->sizeentities != total_size) {
733*6777b538SAndroid Build Coastguard Worker             fprintf(stderr, "Wrong parsed entity size: %lu (expected %lu)\n",
734*6777b538SAndroid Build Coastguard Worker                     ctxt->sizeentities, total_size);
735*6777b538SAndroid Build Coastguard Worker             res = 1;
736*6777b538SAndroid Build Coastguard Worker         }
737*6777b538SAndroid Build Coastguard Worker     }
738*6777b538SAndroid Build Coastguard Worker 
739*6777b538SAndroid Build Coastguard Worker     xmlFreeDoc(doc);
740*6777b538SAndroid Build Coastguard Worker     xmlFreeParserCtxt(ctxt);
741*6777b538SAndroid Build Coastguard Worker 
742*6777b538SAndroid Build Coastguard Worker     return(res);
743*6777b538SAndroid Build Coastguard Worker }
744*6777b538SAndroid Build Coastguard Worker 
745*6777b538SAndroid Build Coastguard Worker /************************************************************************
746*6777b538SAndroid Build Coastguard Worker  *									*
747*6777b538SAndroid Build Coastguard Worker  *			Tests Descriptions				*
748*6777b538SAndroid Build Coastguard Worker  *									*
749*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
750*6777b538SAndroid Build Coastguard Worker 
751*6777b538SAndroid Build Coastguard Worker static
752*6777b538SAndroid Build Coastguard Worker testDesc testDescriptions[] = {
753*6777b538SAndroid Build Coastguard Worker     { "Parsing recursive test cases" ,
754*6777b538SAndroid Build Coastguard Worker       recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL,
755*6777b538SAndroid Build Coastguard Worker       0 },
756*6777b538SAndroid Build Coastguard Worker     { "Parsing recursive test cases (no substitution)" ,
757*6777b538SAndroid Build Coastguard Worker       recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL,
758*6777b538SAndroid Build Coastguard Worker       OPT_NO_SUBST },
759*6777b538SAndroid Build Coastguard Worker     { "Parsing recursive test cases (SAX)" ,
760*6777b538SAndroid Build Coastguard Worker       recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL,
761*6777b538SAndroid Build Coastguard Worker       OPT_SAX },
762*6777b538SAndroid Build Coastguard Worker     { "Parsing recursive test cases (SAX, no substitution)" ,
763*6777b538SAndroid Build Coastguard Worker       recursiveDetectTest, "./test/recurse/lol*.xml", NULL, NULL, NULL,
764*6777b538SAndroid Build Coastguard Worker       OPT_SAX | OPT_NO_SUBST },
765*6777b538SAndroid Build Coastguard Worker     { "Parsing non-recursive test cases" ,
766*6777b538SAndroid Build Coastguard Worker       notRecursiveDetectTest, "./test/recurse/good*.xml", NULL, NULL, NULL,
767*6777b538SAndroid Build Coastguard Worker       0 },
768*6777b538SAndroid Build Coastguard Worker     { "Parsing non-recursive test cases (SAX)" ,
769*6777b538SAndroid Build Coastguard Worker       notRecursiveDetectTest, "./test/recurse/good*.xml", NULL, NULL, NULL,
770*6777b538SAndroid Build Coastguard Worker       OPT_SAX },
771*6777b538SAndroid Build Coastguard Worker     { "Parsing non-recursive huge case" ,
772*6777b538SAndroid Build Coastguard Worker       notRecursiveHugeTest, NULL, NULL, NULL, NULL,
773*6777b538SAndroid Build Coastguard Worker       0 },
774*6777b538SAndroid Build Coastguard Worker     { "Parsing non-recursive huge case (no substitution)" ,
775*6777b538SAndroid Build Coastguard Worker       notRecursiveHugeTest, NULL, NULL, NULL, NULL,
776*6777b538SAndroid Build Coastguard Worker       OPT_NO_SUBST },
777*6777b538SAndroid Build Coastguard Worker     { "Parsing non-recursive huge case (SAX)" ,
778*6777b538SAndroid Build Coastguard Worker       notRecursiveHugeTest, NULL, NULL, NULL, NULL,
779*6777b538SAndroid Build Coastguard Worker       OPT_SAX },
780*6777b538SAndroid Build Coastguard Worker     { "Parsing non-recursive huge case (SAX, no substitution)" ,
781*6777b538SAndroid Build Coastguard Worker       notRecursiveHugeTest, NULL, NULL, NULL, NULL,
782*6777b538SAndroid Build Coastguard Worker       OPT_SAX | OPT_NO_SUBST },
783*6777b538SAndroid Build Coastguard Worker     { "Parsing non-recursive huge DTD case" ,
784*6777b538SAndroid Build Coastguard Worker       hugeDtdTest, NULL, NULL, NULL, NULL,
785*6777b538SAndroid Build Coastguard Worker       0 },
786*6777b538SAndroid Build Coastguard Worker     {NULL, NULL, NULL, NULL, NULL, NULL, 0}
787*6777b538SAndroid Build Coastguard Worker };
788*6777b538SAndroid Build Coastguard Worker 
789*6777b538SAndroid Build Coastguard Worker /************************************************************************
790*6777b538SAndroid Build Coastguard Worker  *									*
791*6777b538SAndroid Build Coastguard Worker  *		The main code driving the tests				*
792*6777b538SAndroid Build Coastguard Worker  *									*
793*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
794*6777b538SAndroid Build Coastguard Worker 
795*6777b538SAndroid Build Coastguard Worker static int
launchTests(testDescPtr tst)796*6777b538SAndroid Build Coastguard Worker launchTests(testDescPtr tst) {
797*6777b538SAndroid Build Coastguard Worker     int res = 0, err = 0;
798*6777b538SAndroid Build Coastguard Worker     size_t i;
799*6777b538SAndroid Build Coastguard Worker     char *result;
800*6777b538SAndroid Build Coastguard Worker     char *error;
801*6777b538SAndroid Build Coastguard Worker     int mem;
802*6777b538SAndroid Build Coastguard Worker 
803*6777b538SAndroid Build Coastguard Worker     if (tst == NULL) return(-1);
804*6777b538SAndroid Build Coastguard Worker     if (tst->in != NULL) {
805*6777b538SAndroid Build Coastguard Worker 	glob_t globbuf;
806*6777b538SAndroid Build Coastguard Worker 
807*6777b538SAndroid Build Coastguard Worker 	globbuf.gl_offs = 0;
808*6777b538SAndroid Build Coastguard Worker 	glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
809*6777b538SAndroid Build Coastguard Worker 	for (i = 0;i < globbuf.gl_pathc;i++) {
810*6777b538SAndroid Build Coastguard Worker 	    if (!checkTestFile(globbuf.gl_pathv[i]))
811*6777b538SAndroid Build Coastguard Worker 	        continue;
812*6777b538SAndroid Build Coastguard Worker 	    if (tst->suffix != NULL) {
813*6777b538SAndroid Build Coastguard Worker 		result = resultFilename(globbuf.gl_pathv[i], tst->out,
814*6777b538SAndroid Build Coastguard Worker 					tst->suffix);
815*6777b538SAndroid Build Coastguard Worker 		if (result == NULL) {
816*6777b538SAndroid Build Coastguard Worker 		    fprintf(stderr, "Out of memory !\n");
817*6777b538SAndroid Build Coastguard Worker 		    fatalError();
818*6777b538SAndroid Build Coastguard Worker 		}
819*6777b538SAndroid Build Coastguard Worker 	    } else {
820*6777b538SAndroid Build Coastguard Worker 	        result = NULL;
821*6777b538SAndroid Build Coastguard Worker 	    }
822*6777b538SAndroid Build Coastguard Worker 	    if (tst->err != NULL) {
823*6777b538SAndroid Build Coastguard Worker 		error = resultFilename(globbuf.gl_pathv[i], tst->out,
824*6777b538SAndroid Build Coastguard Worker 		                        tst->err);
825*6777b538SAndroid Build Coastguard Worker 		if (error == NULL) {
826*6777b538SAndroid Build Coastguard Worker 		    fprintf(stderr, "Out of memory !\n");
827*6777b538SAndroid Build Coastguard Worker 		    fatalError();
828*6777b538SAndroid Build Coastguard Worker 		}
829*6777b538SAndroid Build Coastguard Worker 	    } else {
830*6777b538SAndroid Build Coastguard Worker 	        error = NULL;
831*6777b538SAndroid Build Coastguard Worker 	    }
832*6777b538SAndroid Build Coastguard Worker 	    if ((result) &&(!checkTestFile(result))) {
833*6777b538SAndroid Build Coastguard Worker 	        fprintf(stderr, "Missing result file %s\n", result);
834*6777b538SAndroid Build Coastguard Worker 	    } else if ((error) &&(!checkTestFile(error))) {
835*6777b538SAndroid Build Coastguard Worker 	        fprintf(stderr, "Missing error file %s\n", error);
836*6777b538SAndroid Build Coastguard Worker 	    } else {
837*6777b538SAndroid Build Coastguard Worker 		mem = xmlMemUsed();
838*6777b538SAndroid Build Coastguard Worker 		extraMemoryFromResolver = 0;
839*6777b538SAndroid Build Coastguard Worker 		res = tst->func(globbuf.gl_pathv[i], result, error,
840*6777b538SAndroid Build Coastguard Worker 		                tst->options | XML_PARSE_COMPACT);
841*6777b538SAndroid Build Coastguard Worker 		xmlResetLastError();
842*6777b538SAndroid Build Coastguard Worker 		if (res != 0) {
843*6777b538SAndroid Build Coastguard Worker 		    fprintf(stderr, "File %s generated an error\n",
844*6777b538SAndroid Build Coastguard Worker 		            globbuf.gl_pathv[i]);
845*6777b538SAndroid Build Coastguard Worker 		    nb_errors++;
846*6777b538SAndroid Build Coastguard Worker 		    err++;
847*6777b538SAndroid Build Coastguard Worker 		}
848*6777b538SAndroid Build Coastguard Worker 		else if (xmlMemUsed() != mem) {
849*6777b538SAndroid Build Coastguard Worker 		    if ((xmlMemUsed() != mem) &&
850*6777b538SAndroid Build Coastguard Worker 		        (extraMemoryFromResolver == 0)) {
851*6777b538SAndroid Build Coastguard Worker 			fprintf(stderr, "File %s leaked %d bytes\n",
852*6777b538SAndroid Build Coastguard Worker 				globbuf.gl_pathv[i], xmlMemUsed() - mem);
853*6777b538SAndroid Build Coastguard Worker 			nb_leaks++;
854*6777b538SAndroid Build Coastguard Worker 			err++;
855*6777b538SAndroid Build Coastguard Worker 		    }
856*6777b538SAndroid Build Coastguard Worker 		}
857*6777b538SAndroid Build Coastguard Worker 	    }
858*6777b538SAndroid Build Coastguard Worker 	    if (result)
859*6777b538SAndroid Build Coastguard Worker 		free(result);
860*6777b538SAndroid Build Coastguard Worker 	    if (error)
861*6777b538SAndroid Build Coastguard Worker 		free(error);
862*6777b538SAndroid Build Coastguard Worker 	}
863*6777b538SAndroid Build Coastguard Worker 	globfree(&globbuf);
864*6777b538SAndroid Build Coastguard Worker     } else {
865*6777b538SAndroid Build Coastguard Worker 	extraMemoryFromResolver = 0;
866*6777b538SAndroid Build Coastguard Worker         res = tst->func(NULL, NULL, NULL, tst->options);
867*6777b538SAndroid Build Coastguard Worker 	if (res != 0) {
868*6777b538SAndroid Build Coastguard Worker 	    nb_errors++;
869*6777b538SAndroid Build Coastguard Worker 	    err++;
870*6777b538SAndroid Build Coastguard Worker 	}
871*6777b538SAndroid Build Coastguard Worker     }
872*6777b538SAndroid Build Coastguard Worker     return(err);
873*6777b538SAndroid Build Coastguard Worker }
874*6777b538SAndroid Build Coastguard Worker 
875*6777b538SAndroid Build Coastguard Worker static int verbose = 0;
876*6777b538SAndroid Build Coastguard Worker static int tests_quiet = 0;
877*6777b538SAndroid Build Coastguard Worker 
878*6777b538SAndroid Build Coastguard Worker static int
runtest(int i)879*6777b538SAndroid Build Coastguard Worker runtest(int i) {
880*6777b538SAndroid Build Coastguard Worker     int ret = 0, res;
881*6777b538SAndroid Build Coastguard Worker     int old_errors, old_tests, old_leaks;
882*6777b538SAndroid Build Coastguard Worker 
883*6777b538SAndroid Build Coastguard Worker     old_errors = nb_errors;
884*6777b538SAndroid Build Coastguard Worker     old_tests = nb_tests;
885*6777b538SAndroid Build Coastguard Worker     old_leaks = nb_leaks;
886*6777b538SAndroid Build Coastguard Worker     if ((tests_quiet == 0) && (testDescriptions[i].desc != NULL))
887*6777b538SAndroid Build Coastguard Worker 	printf("## %s\n", testDescriptions[i].desc);
888*6777b538SAndroid Build Coastguard Worker     res = launchTests(&testDescriptions[i]);
889*6777b538SAndroid Build Coastguard Worker     if (res != 0)
890*6777b538SAndroid Build Coastguard Worker 	ret++;
891*6777b538SAndroid Build Coastguard Worker     if (verbose) {
892*6777b538SAndroid Build Coastguard Worker 	if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
893*6777b538SAndroid Build Coastguard Worker 	    printf("Ran %d tests, no errors\n", nb_tests - old_tests);
894*6777b538SAndroid Build Coastguard Worker 	else
895*6777b538SAndroid Build Coastguard Worker 	    printf("Ran %d tests, %d errors, %d leaks\n",
896*6777b538SAndroid Build Coastguard Worker 		   nb_tests - old_tests,
897*6777b538SAndroid Build Coastguard Worker 		   nb_errors - old_errors,
898*6777b538SAndroid Build Coastguard Worker 		   nb_leaks - old_leaks);
899*6777b538SAndroid Build Coastguard Worker     }
900*6777b538SAndroid Build Coastguard Worker     return(ret);
901*6777b538SAndroid Build Coastguard Worker }
902*6777b538SAndroid Build Coastguard Worker 
903*6777b538SAndroid Build Coastguard Worker int
main(int argc ATTRIBUTE_UNUSED,char ** argv ATTRIBUTE_UNUSED)904*6777b538SAndroid Build Coastguard Worker main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
905*6777b538SAndroid Build Coastguard Worker     int i, a, ret = 0;
906*6777b538SAndroid Build Coastguard Worker     int subset = 0;
907*6777b538SAndroid Build Coastguard Worker 
908*6777b538SAndroid Build Coastguard Worker     initializeLibxml2();
909*6777b538SAndroid Build Coastguard Worker 
910*6777b538SAndroid Build Coastguard Worker     for (a = 1; a < argc;a++) {
911*6777b538SAndroid Build Coastguard Worker         if (!strcmp(argv[a], "-v"))
912*6777b538SAndroid Build Coastguard Worker 	    verbose = 1;
913*6777b538SAndroid Build Coastguard Worker         else if (!strcmp(argv[a], "-quiet"))
914*6777b538SAndroid Build Coastguard Worker 	    tests_quiet = 1;
915*6777b538SAndroid Build Coastguard Worker 	else {
916*6777b538SAndroid Build Coastguard Worker 	    for (i = 0; testDescriptions[i].func != NULL; i++) {
917*6777b538SAndroid Build Coastguard Worker 	        if (strstr(testDescriptions[i].desc, argv[a])) {
918*6777b538SAndroid Build Coastguard Worker 		    ret += runtest(i);
919*6777b538SAndroid Build Coastguard Worker 		    subset++;
920*6777b538SAndroid Build Coastguard Worker 		}
921*6777b538SAndroid Build Coastguard Worker 	    }
922*6777b538SAndroid Build Coastguard Worker 	}
923*6777b538SAndroid Build Coastguard Worker     }
924*6777b538SAndroid Build Coastguard Worker     if (subset == 0) {
925*6777b538SAndroid Build Coastguard Worker 	for (i = 0; testDescriptions[i].func != NULL; i++) {
926*6777b538SAndroid Build Coastguard Worker 	    ret += runtest(i);
927*6777b538SAndroid Build Coastguard Worker 	}
928*6777b538SAndroid Build Coastguard Worker     }
929*6777b538SAndroid Build Coastguard Worker     if ((nb_errors == 0) && (nb_leaks == 0)) {
930*6777b538SAndroid Build Coastguard Worker         ret = 0;
931*6777b538SAndroid Build Coastguard Worker 	printf("Total %d tests, no errors\n",
932*6777b538SAndroid Build Coastguard Worker 	       nb_tests);
933*6777b538SAndroid Build Coastguard Worker     } else {
934*6777b538SAndroid Build Coastguard Worker         ret = 1;
935*6777b538SAndroid Build Coastguard Worker 	printf("Total %d tests, %d errors, %d leaks\n",
936*6777b538SAndroid Build Coastguard Worker 	       nb_tests, nb_errors, nb_leaks);
937*6777b538SAndroid Build Coastguard Worker     }
938*6777b538SAndroid Build Coastguard Worker     xmlCleanupParser();
939*6777b538SAndroid Build Coastguard Worker 
940*6777b538SAndroid Build Coastguard Worker     return(ret);
941*6777b538SAndroid Build Coastguard Worker }
942