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