xref: /aosp_15_r20/external/cronet/third_party/libxml/src/runxmlconf.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker /*
2*6777b538SAndroid Build Coastguard Worker  * runxmlconf.c: C program to run XML W3C conformance testsuites
3*6777b538SAndroid Build Coastguard Worker  *
4*6777b538SAndroid Build Coastguard Worker  * See Copyright for the status of this software.
5*6777b538SAndroid Build Coastguard Worker  *
6*6777b538SAndroid Build Coastguard Worker  * [email protected]
7*6777b538SAndroid Build Coastguard Worker  */
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include "config.h"
10*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
11*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlversion.h>
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_VALID_ENABLED)
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #include <string.h>
16*6777b538SAndroid Build Coastguard Worker #include <sys/stat.h>
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker #include <libxml/parser.h>
19*6777b538SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
20*6777b538SAndroid Build Coastguard Worker #include <libxml/tree.h>
21*6777b538SAndroid Build Coastguard Worker #include <libxml/uri.h>
22*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlreader.h>
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker #include <libxml/xpath.h>
25*6777b538SAndroid Build Coastguard Worker #include <libxml/xpathInternals.h>
26*6777b538SAndroid Build Coastguard Worker 
27*6777b538SAndroid Build Coastguard Worker #define LOGFILE "runxmlconf.log"
28*6777b538SAndroid Build Coastguard Worker static FILE *logfile = NULL;
29*6777b538SAndroid Build Coastguard Worker static int verbose = 0;
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker #define NB_EXPECTED_ERRORS 15
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker 
34*6777b538SAndroid Build Coastguard Worker const char *skipped_tests[] = {
35*6777b538SAndroid Build Coastguard Worker /* http://lists.w3.org/Archives/Public/public-xml-testsuite/2008Jul/0000.html */
36*6777b538SAndroid Build Coastguard Worker     "rmt-ns10-035",
37*6777b538SAndroid Build Coastguard Worker     NULL
38*6777b538SAndroid Build Coastguard Worker };
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker /************************************************************************
41*6777b538SAndroid Build Coastguard Worker  *									*
42*6777b538SAndroid Build Coastguard Worker  *		File name and path utilities				*
43*6777b538SAndroid Build Coastguard Worker  *									*
44*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
45*6777b538SAndroid Build Coastguard Worker 
checkTestFile(const char * filename)46*6777b538SAndroid Build Coastguard Worker static int checkTestFile(const char *filename) {
47*6777b538SAndroid Build Coastguard Worker     struct stat buf;
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker     if (stat(filename, &buf) == -1)
50*6777b538SAndroid Build Coastguard Worker         return(0);
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker #if defined(_WIN32)
53*6777b538SAndroid Build Coastguard Worker     if (!(buf.st_mode & _S_IFREG))
54*6777b538SAndroid Build Coastguard Worker         return(0);
55*6777b538SAndroid Build Coastguard Worker #else
56*6777b538SAndroid Build Coastguard Worker     if (!S_ISREG(buf.st_mode))
57*6777b538SAndroid Build Coastguard Worker         return(0);
58*6777b538SAndroid Build Coastguard Worker #endif
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker     return(1);
61*6777b538SAndroid Build Coastguard Worker }
62*6777b538SAndroid Build Coastguard Worker 
composeDir(const xmlChar * dir,const xmlChar * path)63*6777b538SAndroid Build Coastguard Worker static xmlChar *composeDir(const xmlChar *dir, const xmlChar *path) {
64*6777b538SAndroid Build Coastguard Worker     char buf[500];
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker     if (dir == NULL) return(xmlStrdup(path));
67*6777b538SAndroid Build Coastguard Worker     if (path == NULL) return(NULL);
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker     snprintf(buf, 500, "%s/%s", (const char *) dir, (const char *) path);
70*6777b538SAndroid Build Coastguard Worker     return(xmlStrdup((const xmlChar *) buf));
71*6777b538SAndroid Build Coastguard Worker }
72*6777b538SAndroid Build Coastguard Worker 
73*6777b538SAndroid Build Coastguard Worker /************************************************************************
74*6777b538SAndroid Build Coastguard Worker  *									*
75*6777b538SAndroid Build Coastguard Worker  *		Libxml2 specific routines				*
76*6777b538SAndroid Build Coastguard Worker  *									*
77*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
78*6777b538SAndroid Build Coastguard Worker 
79*6777b538SAndroid Build Coastguard Worker static int nb_skipped = 0;
80*6777b538SAndroid Build Coastguard Worker static int nb_tests = 0;
81*6777b538SAndroid Build Coastguard Worker static int nb_errors = 0;
82*6777b538SAndroid Build Coastguard Worker static int nb_leaks = 0;
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker /*
85*6777b538SAndroid Build Coastguard Worker  * We need to trap calls to the resolver to not account memory for the catalog
86*6777b538SAndroid Build Coastguard Worker  * and not rely on any external resources.
87*6777b538SAndroid Build Coastguard Worker  */
88*6777b538SAndroid Build Coastguard Worker static xmlParserInputPtr
testExternalEntityLoader(const char * URL,const char * ID ATTRIBUTE_UNUSED,xmlParserCtxtPtr ctxt)89*6777b538SAndroid Build Coastguard Worker testExternalEntityLoader(const char *URL, const char *ID ATTRIBUTE_UNUSED,
90*6777b538SAndroid Build Coastguard Worker 			 xmlParserCtxtPtr ctxt) {
91*6777b538SAndroid Build Coastguard Worker     xmlParserInputPtr ret;
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker     ret = xmlNewInputFromFile(ctxt, (const char *) URL);
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker     return(ret);
96*6777b538SAndroid Build Coastguard Worker }
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker /*
99*6777b538SAndroid Build Coastguard Worker  * Trapping the error messages at the generic level to grab the equivalent of
100*6777b538SAndroid Build Coastguard Worker  * stderr messages on CLI tools.
101*6777b538SAndroid Build Coastguard Worker  */
102*6777b538SAndroid Build Coastguard Worker static char testErrors[32769];
103*6777b538SAndroid Build Coastguard Worker static int testErrorsSize = 0;
104*6777b538SAndroid Build Coastguard Worker static int nbError = 0;
105*6777b538SAndroid Build Coastguard Worker static int nbFatal = 0;
106*6777b538SAndroid Build Coastguard Worker 
test_log(const char * msg,...)107*6777b538SAndroid Build Coastguard Worker static void test_log(const char *msg, ...) {
108*6777b538SAndroid Build Coastguard Worker     va_list args;
109*6777b538SAndroid Build Coastguard Worker     if (logfile != NULL) {
110*6777b538SAndroid Build Coastguard Worker         fprintf(logfile, "\n------------\n");
111*6777b538SAndroid Build Coastguard Worker 	va_start(args, msg);
112*6777b538SAndroid Build Coastguard Worker 	vfprintf(logfile, msg, args);
113*6777b538SAndroid Build Coastguard Worker 	va_end(args);
114*6777b538SAndroid Build Coastguard Worker 	fprintf(logfile, "%s", testErrors);
115*6777b538SAndroid Build Coastguard Worker 	testErrorsSize = 0; testErrors[0] = 0;
116*6777b538SAndroid Build Coastguard Worker     }
117*6777b538SAndroid Build Coastguard Worker     if (verbose) {
118*6777b538SAndroid Build Coastguard Worker 	va_start(args, msg);
119*6777b538SAndroid Build Coastguard Worker 	vfprintf(stderr, msg, args);
120*6777b538SAndroid Build Coastguard Worker 	va_end(args);
121*6777b538SAndroid Build Coastguard Worker     }
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker static void
testErrorHandler(void * userData ATTRIBUTE_UNUSED,const xmlError * error)125*6777b538SAndroid Build Coastguard Worker testErrorHandler(void *userData ATTRIBUTE_UNUSED, const xmlError *error) {
126*6777b538SAndroid Build Coastguard Worker     int res;
127*6777b538SAndroid Build Coastguard Worker 
128*6777b538SAndroid Build Coastguard Worker     if (testErrorsSize >= 32768)
129*6777b538SAndroid Build Coastguard Worker         return;
130*6777b538SAndroid Build Coastguard Worker     res = snprintf(&testErrors[testErrorsSize],
131*6777b538SAndroid Build Coastguard Worker                     32768 - testErrorsSize,
132*6777b538SAndroid Build Coastguard Worker 		   "%s:%d: %s\n", (error->file ? error->file : "entity"),
133*6777b538SAndroid Build Coastguard Worker 		   error->line, error->message);
134*6777b538SAndroid Build Coastguard Worker     if (error->level == XML_ERR_FATAL)
135*6777b538SAndroid Build Coastguard Worker         nbFatal++;
136*6777b538SAndroid Build Coastguard Worker     else if (error->level == XML_ERR_ERROR)
137*6777b538SAndroid Build Coastguard Worker         nbError++;
138*6777b538SAndroid Build Coastguard Worker     if (testErrorsSize + res >= 32768) {
139*6777b538SAndroid Build Coastguard Worker         /* buffer is full */
140*6777b538SAndroid Build Coastguard Worker 	testErrorsSize = 32768;
141*6777b538SAndroid Build Coastguard Worker 	testErrors[testErrorsSize] = 0;
142*6777b538SAndroid Build Coastguard Worker     } else {
143*6777b538SAndroid Build Coastguard Worker         testErrorsSize += res;
144*6777b538SAndroid Build Coastguard Worker     }
145*6777b538SAndroid Build Coastguard Worker     testErrors[testErrorsSize] = 0;
146*6777b538SAndroid Build Coastguard Worker }
147*6777b538SAndroid Build Coastguard Worker 
148*6777b538SAndroid Build Coastguard Worker static xmlXPathContextPtr ctxtXPath;
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker static void
initializeLibxml2(void)151*6777b538SAndroid Build Coastguard Worker initializeLibxml2(void) {
152*6777b538SAndroid Build Coastguard Worker     xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
153*6777b538SAndroid Build Coastguard Worker     xmlInitParser();
154*6777b538SAndroid Build Coastguard Worker     xmlSetExternalEntityLoader(testExternalEntityLoader);
155*6777b538SAndroid Build Coastguard Worker     ctxtXPath = xmlXPathNewContext(NULL);
156*6777b538SAndroid Build Coastguard Worker     /*
157*6777b538SAndroid Build Coastguard Worker     * Deactivate the cache if created; otherwise we have to create/free it
158*6777b538SAndroid Build Coastguard Worker     * for every test, since it will confuse the memory leak detection.
159*6777b538SAndroid Build Coastguard Worker     * Note that normally this need not be done, since the cache is not
160*6777b538SAndroid Build Coastguard Worker     * created until set explicitly with xmlXPathContextSetCache();
161*6777b538SAndroid Build Coastguard Worker     * but for test purposes it is sometimes useful to activate the
162*6777b538SAndroid Build Coastguard Worker     * cache by default for the whole library.
163*6777b538SAndroid Build Coastguard Worker     */
164*6777b538SAndroid Build Coastguard Worker     if (ctxtXPath->cache != NULL)
165*6777b538SAndroid Build Coastguard Worker 	xmlXPathContextSetCache(ctxtXPath, 0, -1, 0);
166*6777b538SAndroid Build Coastguard Worker }
167*6777b538SAndroid Build Coastguard Worker 
168*6777b538SAndroid Build Coastguard Worker /************************************************************************
169*6777b538SAndroid Build Coastguard Worker  *									*
170*6777b538SAndroid Build Coastguard Worker  *		Run the xmlconf test if found				*
171*6777b538SAndroid Build Coastguard Worker  *									*
172*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
173*6777b538SAndroid Build Coastguard Worker 
174*6777b538SAndroid Build Coastguard Worker static int
xmlconfTestInvalid(const char * id,const char * filename,int options)175*6777b538SAndroid Build Coastguard Worker xmlconfTestInvalid(const char *id, const char *filename, int options) {
176*6777b538SAndroid Build Coastguard Worker     xmlDocPtr doc;
177*6777b538SAndroid Build Coastguard Worker     xmlParserCtxtPtr ctxt;
178*6777b538SAndroid Build Coastguard Worker     int ret = 1;
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker     ctxt = xmlNewParserCtxt();
181*6777b538SAndroid Build Coastguard Worker     if (ctxt == NULL) {
182*6777b538SAndroid Build Coastguard Worker         test_log("test %s : %s out of memory\n",
183*6777b538SAndroid Build Coastguard Worker 	         id, filename);
184*6777b538SAndroid Build Coastguard Worker         return(0);
185*6777b538SAndroid Build Coastguard Worker     }
186*6777b538SAndroid Build Coastguard Worker     xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL);
187*6777b538SAndroid Build Coastguard Worker     doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
188*6777b538SAndroid Build Coastguard Worker     if (doc == NULL) {
189*6777b538SAndroid Build Coastguard Worker         test_log("test %s : %s invalid document turned not well-formed too\n",
190*6777b538SAndroid Build Coastguard Worker 	         id, filename);
191*6777b538SAndroid Build Coastguard Worker     } else {
192*6777b538SAndroid Build Coastguard Worker     /* invalidity should be reported both in the context and in the document */
193*6777b538SAndroid Build Coastguard Worker         if ((ctxt->valid != 0) || (doc->properties & XML_DOC_DTDVALID)) {
194*6777b538SAndroid Build Coastguard Worker 	    test_log("test %s : %s failed to detect invalid document\n",
195*6777b538SAndroid Build Coastguard Worker 		     id, filename);
196*6777b538SAndroid Build Coastguard Worker 	    nb_errors++;
197*6777b538SAndroid Build Coastguard Worker 	    ret = 0;
198*6777b538SAndroid Build Coastguard Worker 	}
199*6777b538SAndroid Build Coastguard Worker 	xmlFreeDoc(doc);
200*6777b538SAndroid Build Coastguard Worker     }
201*6777b538SAndroid Build Coastguard Worker     xmlFreeParserCtxt(ctxt);
202*6777b538SAndroid Build Coastguard Worker     return(ret);
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker 
205*6777b538SAndroid Build Coastguard Worker static int
xmlconfTestValid(const char * id,const char * filename,int options)206*6777b538SAndroid Build Coastguard Worker xmlconfTestValid(const char *id, const char *filename, int options) {
207*6777b538SAndroid Build Coastguard Worker     xmlDocPtr doc;
208*6777b538SAndroid Build Coastguard Worker     xmlParserCtxtPtr ctxt;
209*6777b538SAndroid Build Coastguard Worker     int ret = 1;
210*6777b538SAndroid Build Coastguard Worker 
211*6777b538SAndroid Build Coastguard Worker     ctxt = xmlNewParserCtxt();
212*6777b538SAndroid Build Coastguard Worker     if (ctxt == NULL) {
213*6777b538SAndroid Build Coastguard Worker         test_log("test %s : %s out of memory\n",
214*6777b538SAndroid Build Coastguard Worker 	         id, filename);
215*6777b538SAndroid Build Coastguard Worker         return(0);
216*6777b538SAndroid Build Coastguard Worker     }
217*6777b538SAndroid Build Coastguard Worker     xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL);
218*6777b538SAndroid Build Coastguard Worker     doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
219*6777b538SAndroid Build Coastguard Worker     if (doc == NULL) {
220*6777b538SAndroid Build Coastguard Worker         test_log("test %s : %s failed to parse a valid document\n",
221*6777b538SAndroid Build Coastguard Worker 	         id, filename);
222*6777b538SAndroid Build Coastguard Worker         nb_errors++;
223*6777b538SAndroid Build Coastguard Worker 	ret = 0;
224*6777b538SAndroid Build Coastguard Worker     } else {
225*6777b538SAndroid Build Coastguard Worker     /* validity should be reported both in the context and in the document */
226*6777b538SAndroid Build Coastguard Worker         if ((ctxt->valid == 0) || ((doc->properties & XML_DOC_DTDVALID) == 0)) {
227*6777b538SAndroid Build Coastguard Worker 	    test_log("test %s : %s failed to validate a valid document\n",
228*6777b538SAndroid Build Coastguard Worker 		     id, filename);
229*6777b538SAndroid Build Coastguard Worker 	    nb_errors++;
230*6777b538SAndroid Build Coastguard Worker 	    ret = 0;
231*6777b538SAndroid Build Coastguard Worker 	}
232*6777b538SAndroid Build Coastguard Worker 	xmlFreeDoc(doc);
233*6777b538SAndroid Build Coastguard Worker     }
234*6777b538SAndroid Build Coastguard Worker     xmlFreeParserCtxt(ctxt);
235*6777b538SAndroid Build Coastguard Worker     return(ret);
236*6777b538SAndroid Build Coastguard Worker }
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker static int
xmlconfTestNotNSWF(const char * id,const char * filename,int options)239*6777b538SAndroid Build Coastguard Worker xmlconfTestNotNSWF(const char *id, const char *filename, int options) {
240*6777b538SAndroid Build Coastguard Worker     xmlParserCtxtPtr ctxt;
241*6777b538SAndroid Build Coastguard Worker     xmlDocPtr doc;
242*6777b538SAndroid Build Coastguard Worker     int ret = 1;
243*6777b538SAndroid Build Coastguard Worker 
244*6777b538SAndroid Build Coastguard Worker     ctxt = xmlNewParserCtxt();
245*6777b538SAndroid Build Coastguard Worker     xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL);
246*6777b538SAndroid Build Coastguard Worker     /*
247*6777b538SAndroid Build Coastguard Worker      * In case of Namespace errors, libxml2 will still parse the document
248*6777b538SAndroid Build Coastguard Worker      * but log a Namespace error.
249*6777b538SAndroid Build Coastguard Worker      */
250*6777b538SAndroid Build Coastguard Worker     doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
251*6777b538SAndroid Build Coastguard Worker     if (doc == NULL) {
252*6777b538SAndroid Build Coastguard Worker         test_log("test %s : %s failed to parse the XML\n",
253*6777b538SAndroid Build Coastguard Worker 	         id, filename);
254*6777b538SAndroid Build Coastguard Worker         nb_errors++;
255*6777b538SAndroid Build Coastguard Worker 	ret = 0;
256*6777b538SAndroid Build Coastguard Worker     } else {
257*6777b538SAndroid Build Coastguard Worker         const xmlError *error = xmlGetLastError();
258*6777b538SAndroid Build Coastguard Worker 
259*6777b538SAndroid Build Coastguard Worker 	if ((error->code == XML_ERR_OK) ||
260*6777b538SAndroid Build Coastguard Worker 	    (error->domain != XML_FROM_NAMESPACE)) {
261*6777b538SAndroid Build Coastguard Worker 	    test_log("test %s : %s failed to detect namespace error\n",
262*6777b538SAndroid Build Coastguard Worker 		     id, filename);
263*6777b538SAndroid Build Coastguard Worker 	    nb_errors++;
264*6777b538SAndroid Build Coastguard Worker 	    ret = 0;
265*6777b538SAndroid Build Coastguard Worker 	}
266*6777b538SAndroid Build Coastguard Worker 	xmlFreeDoc(doc);
267*6777b538SAndroid Build Coastguard Worker     }
268*6777b538SAndroid Build Coastguard Worker     xmlFreeParserCtxt(ctxt);
269*6777b538SAndroid Build Coastguard Worker     return(ret);
270*6777b538SAndroid Build Coastguard Worker }
271*6777b538SAndroid Build Coastguard Worker 
272*6777b538SAndroid Build Coastguard Worker static int
xmlconfTestNotWF(const char * id,const char * filename,int options)273*6777b538SAndroid Build Coastguard Worker xmlconfTestNotWF(const char *id, const char *filename, int options) {
274*6777b538SAndroid Build Coastguard Worker     xmlParserCtxtPtr ctxt;
275*6777b538SAndroid Build Coastguard Worker     xmlDocPtr doc;
276*6777b538SAndroid Build Coastguard Worker     int ret = 1;
277*6777b538SAndroid Build Coastguard Worker 
278*6777b538SAndroid Build Coastguard Worker     ctxt = xmlNewParserCtxt();
279*6777b538SAndroid Build Coastguard Worker     xmlCtxtSetErrorHandler(ctxt, testErrorHandler, NULL);
280*6777b538SAndroid Build Coastguard Worker     doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
281*6777b538SAndroid Build Coastguard Worker     if (doc != NULL) {
282*6777b538SAndroid Build Coastguard Worker         test_log("test %s : %s failed to detect not well formedness\n",
283*6777b538SAndroid Build Coastguard Worker 	         id, filename);
284*6777b538SAndroid Build Coastguard Worker         nb_errors++;
285*6777b538SAndroid Build Coastguard Worker 	xmlFreeDoc(doc);
286*6777b538SAndroid Build Coastguard Worker 	ret = 0;
287*6777b538SAndroid Build Coastguard Worker     }
288*6777b538SAndroid Build Coastguard Worker     xmlFreeParserCtxt(ctxt);
289*6777b538SAndroid Build Coastguard Worker     return(ret);
290*6777b538SAndroid Build Coastguard Worker }
291*6777b538SAndroid Build Coastguard Worker 
292*6777b538SAndroid Build Coastguard Worker static int
xmlconfTestItem(xmlDocPtr doc,xmlNodePtr cur)293*6777b538SAndroid Build Coastguard Worker xmlconfTestItem(xmlDocPtr doc, xmlNodePtr cur) {
294*6777b538SAndroid Build Coastguard Worker     int ret = -1;
295*6777b538SAndroid Build Coastguard Worker     xmlChar *type = NULL;
296*6777b538SAndroid Build Coastguard Worker     xmlChar *filename = NULL;
297*6777b538SAndroid Build Coastguard Worker     xmlChar *uri = NULL;
298*6777b538SAndroid Build Coastguard Worker     xmlChar *base = NULL;
299*6777b538SAndroid Build Coastguard Worker     xmlChar *id = NULL;
300*6777b538SAndroid Build Coastguard Worker     xmlChar *rec = NULL;
301*6777b538SAndroid Build Coastguard Worker     xmlChar *version = NULL;
302*6777b538SAndroid Build Coastguard Worker     xmlChar *entities = NULL;
303*6777b538SAndroid Build Coastguard Worker     xmlChar *edition = NULL;
304*6777b538SAndroid Build Coastguard Worker     int options = 0;
305*6777b538SAndroid Build Coastguard Worker     int nstest = 0;
306*6777b538SAndroid Build Coastguard Worker     int mem, final;
307*6777b538SAndroid Build Coastguard Worker     int i;
308*6777b538SAndroid Build Coastguard Worker 
309*6777b538SAndroid Build Coastguard Worker     testErrorsSize = 0; testErrors[0] = 0;
310*6777b538SAndroid Build Coastguard Worker     nbError = 0;
311*6777b538SAndroid Build Coastguard Worker     nbFatal = 0;
312*6777b538SAndroid Build Coastguard Worker     id = xmlGetProp(cur, BAD_CAST "ID");
313*6777b538SAndroid Build Coastguard Worker     if (id == NULL) {
314*6777b538SAndroid Build Coastguard Worker         test_log("test missing ID, line %ld\n", xmlGetLineNo(cur));
315*6777b538SAndroid Build Coastguard Worker 	goto error;
316*6777b538SAndroid Build Coastguard Worker     }
317*6777b538SAndroid Build Coastguard Worker     for (i = 0;skipped_tests[i] != NULL;i++) {
318*6777b538SAndroid Build Coastguard Worker         if (!strcmp(skipped_tests[i], (char *) id)) {
319*6777b538SAndroid Build Coastguard Worker 	    test_log("Skipping test %s from skipped list\n", (char *) id);
320*6777b538SAndroid Build Coastguard Worker 	    ret = 0;
321*6777b538SAndroid Build Coastguard Worker 	    nb_skipped++;
322*6777b538SAndroid Build Coastguard Worker 	    goto error;
323*6777b538SAndroid Build Coastguard Worker 	}
324*6777b538SAndroid Build Coastguard Worker     }
325*6777b538SAndroid Build Coastguard Worker     type = xmlGetProp(cur, BAD_CAST "TYPE");
326*6777b538SAndroid Build Coastguard Worker     if (type == NULL) {
327*6777b538SAndroid Build Coastguard Worker         test_log("test %s missing TYPE\n", (char *) id);
328*6777b538SAndroid Build Coastguard Worker 	goto error;
329*6777b538SAndroid Build Coastguard Worker     }
330*6777b538SAndroid Build Coastguard Worker     uri = xmlGetProp(cur, BAD_CAST "URI");
331*6777b538SAndroid Build Coastguard Worker     if (uri == NULL) {
332*6777b538SAndroid Build Coastguard Worker         test_log("test %s missing URI\n", (char *) id);
333*6777b538SAndroid Build Coastguard Worker 	goto error;
334*6777b538SAndroid Build Coastguard Worker     }
335*6777b538SAndroid Build Coastguard Worker     base = xmlNodeGetBase(doc, cur);
336*6777b538SAndroid Build Coastguard Worker     filename = composeDir(base, uri);
337*6777b538SAndroid Build Coastguard Worker     if (!checkTestFile((char *) filename)) {
338*6777b538SAndroid Build Coastguard Worker         test_log("test %s missing file %s \n", id,
339*6777b538SAndroid Build Coastguard Worker 	         (filename ? (char *)filename : "NULL"));
340*6777b538SAndroid Build Coastguard Worker 	goto error;
341*6777b538SAndroid Build Coastguard Worker     }
342*6777b538SAndroid Build Coastguard Worker 
343*6777b538SAndroid Build Coastguard Worker     version = xmlGetProp(cur, BAD_CAST "VERSION");
344*6777b538SAndroid Build Coastguard Worker 
345*6777b538SAndroid Build Coastguard Worker     entities = xmlGetProp(cur, BAD_CAST "ENTITIES");
346*6777b538SAndroid Build Coastguard Worker     if (!xmlStrEqual(entities, BAD_CAST "none")) {
347*6777b538SAndroid Build Coastguard Worker         options |= XML_PARSE_DTDLOAD;
348*6777b538SAndroid Build Coastguard Worker         options |= XML_PARSE_NOENT;
349*6777b538SAndroid Build Coastguard Worker     }
350*6777b538SAndroid Build Coastguard Worker     rec = xmlGetProp(cur, BAD_CAST "RECOMMENDATION");
351*6777b538SAndroid Build Coastguard Worker     if ((rec == NULL) ||
352*6777b538SAndroid Build Coastguard Worker         (xmlStrEqual(rec, BAD_CAST "XML1.0")) ||
353*6777b538SAndroid Build Coastguard Worker 	(xmlStrEqual(rec, BAD_CAST "XML1.0-errata2e")) ||
354*6777b538SAndroid Build Coastguard Worker 	(xmlStrEqual(rec, BAD_CAST "XML1.0-errata3e")) ||
355*6777b538SAndroid Build Coastguard Worker 	(xmlStrEqual(rec, BAD_CAST "XML1.0-errata4e"))) {
356*6777b538SAndroid Build Coastguard Worker 	if ((version != NULL) && (!xmlStrEqual(version, BAD_CAST "1.0"))) {
357*6777b538SAndroid Build Coastguard Worker 	    test_log("Skipping test %s for %s\n", (char *) id,
358*6777b538SAndroid Build Coastguard Worker 	             (char *) version);
359*6777b538SAndroid Build Coastguard Worker 	    ret = 0;
360*6777b538SAndroid Build Coastguard Worker 	    nb_skipped++;
361*6777b538SAndroid Build Coastguard Worker 	    goto error;
362*6777b538SAndroid Build Coastguard Worker 	}
363*6777b538SAndroid Build Coastguard Worker 	ret = 1;
364*6777b538SAndroid Build Coastguard Worker     } else if ((xmlStrEqual(rec, BAD_CAST "NS1.0")) ||
365*6777b538SAndroid Build Coastguard Worker 	       (xmlStrEqual(rec, BAD_CAST "NS1.0-errata1e"))) {
366*6777b538SAndroid Build Coastguard Worker 	ret = 1;
367*6777b538SAndroid Build Coastguard Worker 	nstest = 1;
368*6777b538SAndroid Build Coastguard Worker     } else {
369*6777b538SAndroid Build Coastguard Worker         test_log("Skipping test %s for REC %s\n", (char *) id, (char *) rec);
370*6777b538SAndroid Build Coastguard Worker 	ret = 0;
371*6777b538SAndroid Build Coastguard Worker 	nb_skipped++;
372*6777b538SAndroid Build Coastguard Worker 	goto error;
373*6777b538SAndroid Build Coastguard Worker     }
374*6777b538SAndroid Build Coastguard Worker     edition = xmlGetProp(cur, BAD_CAST "EDITION");
375*6777b538SAndroid Build Coastguard Worker     if ((edition != NULL) && (xmlStrchr(edition, '5') == NULL)) {
376*6777b538SAndroid Build Coastguard Worker         /* test limited to all versions before 5th */
377*6777b538SAndroid Build Coastguard Worker 	options |= XML_PARSE_OLD10;
378*6777b538SAndroid Build Coastguard Worker     }
379*6777b538SAndroid Build Coastguard Worker 
380*6777b538SAndroid Build Coastguard Worker     /*
381*6777b538SAndroid Build Coastguard Worker      * Reset errors and check memory usage before the test
382*6777b538SAndroid Build Coastguard Worker      */
383*6777b538SAndroid Build Coastguard Worker     xmlResetLastError();
384*6777b538SAndroid Build Coastguard Worker     testErrorsSize = 0; testErrors[0] = 0;
385*6777b538SAndroid Build Coastguard Worker     mem = xmlMemUsed();
386*6777b538SAndroid Build Coastguard Worker 
387*6777b538SAndroid Build Coastguard Worker     if (xmlStrEqual(type, BAD_CAST "not-wf")) {
388*6777b538SAndroid Build Coastguard Worker         if (nstest == 0)
389*6777b538SAndroid Build Coastguard Worker 	    xmlconfTestNotWF((char *) id, (char *) filename, options);
390*6777b538SAndroid Build Coastguard Worker         else
391*6777b538SAndroid Build Coastguard Worker 	    xmlconfTestNotNSWF((char *) id, (char *) filename, options);
392*6777b538SAndroid Build Coastguard Worker     } else if (xmlStrEqual(type, BAD_CAST "valid")) {
393*6777b538SAndroid Build Coastguard Worker         options |= XML_PARSE_DTDVALID;
394*6777b538SAndroid Build Coastguard Worker 	xmlconfTestValid((char *) id, (char *) filename, options);
395*6777b538SAndroid Build Coastguard Worker     } else if (xmlStrEqual(type, BAD_CAST "invalid")) {
396*6777b538SAndroid Build Coastguard Worker         options |= XML_PARSE_DTDVALID;
397*6777b538SAndroid Build Coastguard Worker 	xmlconfTestInvalid((char *) id, (char *) filename, options);
398*6777b538SAndroid Build Coastguard Worker     } else if (xmlStrEqual(type, BAD_CAST "error")) {
399*6777b538SAndroid Build Coastguard Worker         test_log("Skipping error test %s \n", (char *) id);
400*6777b538SAndroid Build Coastguard Worker 	ret = 0;
401*6777b538SAndroid Build Coastguard Worker 	nb_skipped++;
402*6777b538SAndroid Build Coastguard Worker 	goto error;
403*6777b538SAndroid Build Coastguard Worker     } else {
404*6777b538SAndroid Build Coastguard Worker         test_log("test %s unknown TYPE value %s\n", (char *) id, (char *)type);
405*6777b538SAndroid Build Coastguard Worker 	ret = -1;
406*6777b538SAndroid Build Coastguard Worker 	goto error;
407*6777b538SAndroid Build Coastguard Worker     }
408*6777b538SAndroid Build Coastguard Worker 
409*6777b538SAndroid Build Coastguard Worker     /*
410*6777b538SAndroid Build Coastguard Worker      * Reset errors and check memory usage after the test
411*6777b538SAndroid Build Coastguard Worker      */
412*6777b538SAndroid Build Coastguard Worker     xmlResetLastError();
413*6777b538SAndroid Build Coastguard Worker     final = xmlMemUsed();
414*6777b538SAndroid Build Coastguard Worker     if (final > mem) {
415*6777b538SAndroid Build Coastguard Worker         test_log("test %s : %s leaked %d bytes\n",
416*6777b538SAndroid Build Coastguard Worker 	         id, filename, final - mem);
417*6777b538SAndroid Build Coastguard Worker         nb_leaks++;
418*6777b538SAndroid Build Coastguard Worker 	xmlMemDisplayLast(logfile, final - mem);
419*6777b538SAndroid Build Coastguard Worker     }
420*6777b538SAndroid Build Coastguard Worker     nb_tests++;
421*6777b538SAndroid Build Coastguard Worker 
422*6777b538SAndroid Build Coastguard Worker error:
423*6777b538SAndroid Build Coastguard Worker     if (type != NULL)
424*6777b538SAndroid Build Coastguard Worker         xmlFree(type);
425*6777b538SAndroid Build Coastguard Worker     if (entities != NULL)
426*6777b538SAndroid Build Coastguard Worker         xmlFree(entities);
427*6777b538SAndroid Build Coastguard Worker     if (edition != NULL)
428*6777b538SAndroid Build Coastguard Worker         xmlFree(edition);
429*6777b538SAndroid Build Coastguard Worker     if (version != NULL)
430*6777b538SAndroid Build Coastguard Worker         xmlFree(version);
431*6777b538SAndroid Build Coastguard Worker     if (filename != NULL)
432*6777b538SAndroid Build Coastguard Worker         xmlFree(filename);
433*6777b538SAndroid Build Coastguard Worker     if (uri != NULL)
434*6777b538SAndroid Build Coastguard Worker         xmlFree(uri);
435*6777b538SAndroid Build Coastguard Worker     if (base != NULL)
436*6777b538SAndroid Build Coastguard Worker         xmlFree(base);
437*6777b538SAndroid Build Coastguard Worker     if (id != NULL)
438*6777b538SAndroid Build Coastguard Worker         xmlFree(id);
439*6777b538SAndroid Build Coastguard Worker     if (rec != NULL)
440*6777b538SAndroid Build Coastguard Worker         xmlFree(rec);
441*6777b538SAndroid Build Coastguard Worker     return(ret);
442*6777b538SAndroid Build Coastguard Worker }
443*6777b538SAndroid Build Coastguard Worker 
444*6777b538SAndroid Build Coastguard Worker static int
xmlconfTestCases(xmlDocPtr doc,xmlNodePtr cur,int level)445*6777b538SAndroid Build Coastguard Worker xmlconfTestCases(xmlDocPtr doc, xmlNodePtr cur, int level) {
446*6777b538SAndroid Build Coastguard Worker     xmlChar *profile;
447*6777b538SAndroid Build Coastguard Worker     int ret = 0;
448*6777b538SAndroid Build Coastguard Worker     int tests = 0;
449*6777b538SAndroid Build Coastguard Worker     int output = 0;
450*6777b538SAndroid Build Coastguard Worker 
451*6777b538SAndroid Build Coastguard Worker     if (level == 1) {
452*6777b538SAndroid Build Coastguard Worker 	profile = xmlGetProp(cur, BAD_CAST "PROFILE");
453*6777b538SAndroid Build Coastguard Worker 	if (profile != NULL) {
454*6777b538SAndroid Build Coastguard Worker 	    output = 1;
455*6777b538SAndroid Build Coastguard Worker 	    level++;
456*6777b538SAndroid Build Coastguard Worker 	    printf("Test cases: %s\n", (char *) profile);
457*6777b538SAndroid Build Coastguard Worker 	    xmlFree(profile);
458*6777b538SAndroid Build Coastguard Worker 	}
459*6777b538SAndroid Build Coastguard Worker     }
460*6777b538SAndroid Build Coastguard Worker     cur = cur->children;
461*6777b538SAndroid Build Coastguard Worker     while (cur != NULL) {
462*6777b538SAndroid Build Coastguard Worker         /* look only at elements we ignore everything else */
463*6777b538SAndroid Build Coastguard Worker         if (cur->type == XML_ELEMENT_NODE) {
464*6777b538SAndroid Build Coastguard Worker 	    if (xmlStrEqual(cur->name, BAD_CAST "TESTCASES")) {
465*6777b538SAndroid Build Coastguard Worker 	        ret += xmlconfTestCases(doc, cur, level);
466*6777b538SAndroid Build Coastguard Worker 	    } else if (xmlStrEqual(cur->name, BAD_CAST "TEST")) {
467*6777b538SAndroid Build Coastguard Worker 	        if (xmlconfTestItem(doc, cur) >= 0)
468*6777b538SAndroid Build Coastguard Worker 		    ret++;
469*6777b538SAndroid Build Coastguard Worker 		tests++;
470*6777b538SAndroid Build Coastguard Worker 	    } else {
471*6777b538SAndroid Build Coastguard Worker 	        fprintf(stderr, "Unhandled element %s\n", (char *)cur->name);
472*6777b538SAndroid Build Coastguard Worker 	    }
473*6777b538SAndroid Build Coastguard Worker 	}
474*6777b538SAndroid Build Coastguard Worker         cur = cur->next;
475*6777b538SAndroid Build Coastguard Worker     }
476*6777b538SAndroid Build Coastguard Worker     if (output == 1) {
477*6777b538SAndroid Build Coastguard Worker 	if (tests > 0)
478*6777b538SAndroid Build Coastguard Worker 	    printf("Test cases: %d tests\n", tests);
479*6777b538SAndroid Build Coastguard Worker     }
480*6777b538SAndroid Build Coastguard Worker     return(ret);
481*6777b538SAndroid Build Coastguard Worker }
482*6777b538SAndroid Build Coastguard Worker 
483*6777b538SAndroid Build Coastguard Worker static int
xmlconfTestSuite(xmlDocPtr doc,xmlNodePtr cur)484*6777b538SAndroid Build Coastguard Worker xmlconfTestSuite(xmlDocPtr doc, xmlNodePtr cur) {
485*6777b538SAndroid Build Coastguard Worker     xmlChar *profile;
486*6777b538SAndroid Build Coastguard Worker     int ret = 0;
487*6777b538SAndroid Build Coastguard Worker 
488*6777b538SAndroid Build Coastguard Worker     profile = xmlGetProp(cur, BAD_CAST "PROFILE");
489*6777b538SAndroid Build Coastguard Worker     if (profile != NULL) {
490*6777b538SAndroid Build Coastguard Worker         printf("Test suite: %s\n", (char *) profile);
491*6777b538SAndroid Build Coastguard Worker 	xmlFree(profile);
492*6777b538SAndroid Build Coastguard Worker     } else
493*6777b538SAndroid Build Coastguard Worker         printf("Test suite\n");
494*6777b538SAndroid Build Coastguard Worker     cur = cur->children;
495*6777b538SAndroid Build Coastguard Worker     while (cur != NULL) {
496*6777b538SAndroid Build Coastguard Worker         /* look only at elements we ignore everything else */
497*6777b538SAndroid Build Coastguard Worker         if (cur->type == XML_ELEMENT_NODE) {
498*6777b538SAndroid Build Coastguard Worker 	    if (xmlStrEqual(cur->name, BAD_CAST "TESTCASES")) {
499*6777b538SAndroid Build Coastguard Worker 	        ret += xmlconfTestCases(doc, cur, 1);
500*6777b538SAndroid Build Coastguard Worker 	    } else {
501*6777b538SAndroid Build Coastguard Worker 	        fprintf(stderr, "Unhandled element %s\n", (char *)cur->name);
502*6777b538SAndroid Build Coastguard Worker 	    }
503*6777b538SAndroid Build Coastguard Worker 	}
504*6777b538SAndroid Build Coastguard Worker         cur = cur->next;
505*6777b538SAndroid Build Coastguard Worker     }
506*6777b538SAndroid Build Coastguard Worker     return(ret);
507*6777b538SAndroid Build Coastguard Worker }
508*6777b538SAndroid Build Coastguard Worker 
509*6777b538SAndroid Build Coastguard Worker static void
xmlconfInfo(void)510*6777b538SAndroid Build Coastguard Worker xmlconfInfo(void) {
511*6777b538SAndroid Build Coastguard Worker     fprintf(stderr, "  you need to fetch and extract the\n");
512*6777b538SAndroid Build Coastguard Worker     fprintf(stderr, "  latest XML Conformance Test Suites\n");
513*6777b538SAndroid Build Coastguard Worker     fprintf(stderr, "  http://www.w3.org/XML/Test/xmlts20080827.tar.gz\n");
514*6777b538SAndroid Build Coastguard Worker     fprintf(stderr, "  see http://www.w3.org/XML/Test/ for information\n");
515*6777b538SAndroid Build Coastguard Worker }
516*6777b538SAndroid Build Coastguard Worker 
517*6777b538SAndroid Build Coastguard Worker static int
xmlconfTest(void)518*6777b538SAndroid Build Coastguard Worker xmlconfTest(void) {
519*6777b538SAndroid Build Coastguard Worker     const char *confxml = "xmlconf/xmlconf.xml";
520*6777b538SAndroid Build Coastguard Worker     xmlDocPtr doc;
521*6777b538SAndroid Build Coastguard Worker     xmlNodePtr cur;
522*6777b538SAndroid Build Coastguard Worker     int ret = 0;
523*6777b538SAndroid Build Coastguard Worker 
524*6777b538SAndroid Build Coastguard Worker     if (!checkTestFile(confxml)) {
525*6777b538SAndroid Build Coastguard Worker         fprintf(stderr, "%s is missing \n", confxml);
526*6777b538SAndroid Build Coastguard Worker 	xmlconfInfo();
527*6777b538SAndroid Build Coastguard Worker 	return(-1);
528*6777b538SAndroid Build Coastguard Worker     }
529*6777b538SAndroid Build Coastguard Worker     doc = xmlReadFile(confxml, NULL, XML_PARSE_NOENT);
530*6777b538SAndroid Build Coastguard Worker     if (doc == NULL) {
531*6777b538SAndroid Build Coastguard Worker         fprintf(stderr, "%s is corrupted \n", confxml);
532*6777b538SAndroid Build Coastguard Worker 	xmlconfInfo();
533*6777b538SAndroid Build Coastguard Worker 	return(-1);
534*6777b538SAndroid Build Coastguard Worker     }
535*6777b538SAndroid Build Coastguard Worker 
536*6777b538SAndroid Build Coastguard Worker     cur = xmlDocGetRootElement(doc);
537*6777b538SAndroid Build Coastguard Worker     if ((cur == NULL) || (!xmlStrEqual(cur->name, BAD_CAST "TESTSUITE"))) {
538*6777b538SAndroid Build Coastguard Worker         fprintf(stderr, "Unexpected format %s\n", confxml);
539*6777b538SAndroid Build Coastguard Worker 	xmlconfInfo();
540*6777b538SAndroid Build Coastguard Worker 	ret = -1;
541*6777b538SAndroid Build Coastguard Worker     } else {
542*6777b538SAndroid Build Coastguard Worker         ret = xmlconfTestSuite(doc, cur);
543*6777b538SAndroid Build Coastguard Worker     }
544*6777b538SAndroid Build Coastguard Worker     xmlFreeDoc(doc);
545*6777b538SAndroid Build Coastguard Worker     return(ret);
546*6777b538SAndroid Build Coastguard Worker }
547*6777b538SAndroid Build Coastguard Worker 
548*6777b538SAndroid Build Coastguard Worker /************************************************************************
549*6777b538SAndroid Build Coastguard Worker  *									*
550*6777b538SAndroid Build Coastguard Worker  *		The driver for the tests				*
551*6777b538SAndroid Build Coastguard Worker  *									*
552*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
553*6777b538SAndroid Build Coastguard Worker 
554*6777b538SAndroid Build Coastguard Worker int
main(int argc ATTRIBUTE_UNUSED,char ** argv ATTRIBUTE_UNUSED)555*6777b538SAndroid Build Coastguard Worker main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
556*6777b538SAndroid Build Coastguard Worker     int ret = 0;
557*6777b538SAndroid Build Coastguard Worker     int old_errors, old_tests, old_leaks;
558*6777b538SAndroid Build Coastguard Worker 
559*6777b538SAndroid Build Coastguard Worker     logfile = fopen(LOGFILE, "w");
560*6777b538SAndroid Build Coastguard Worker     if (logfile == NULL) {
561*6777b538SAndroid Build Coastguard Worker         fprintf(stderr,
562*6777b538SAndroid Build Coastguard Worker 	        "Could not open the log file, running in verbose mode\n");
563*6777b538SAndroid Build Coastguard Worker 	verbose = 1;
564*6777b538SAndroid Build Coastguard Worker     }
565*6777b538SAndroid Build Coastguard Worker     initializeLibxml2();
566*6777b538SAndroid Build Coastguard Worker 
567*6777b538SAndroid Build Coastguard Worker     if ((argc >= 2) && (!strcmp(argv[1], "-v")))
568*6777b538SAndroid Build Coastguard Worker         verbose = 1;
569*6777b538SAndroid Build Coastguard Worker 
570*6777b538SAndroid Build Coastguard Worker 
571*6777b538SAndroid Build Coastguard Worker     old_errors = nb_errors;
572*6777b538SAndroid Build Coastguard Worker     old_tests = nb_tests;
573*6777b538SAndroid Build Coastguard Worker     old_leaks = nb_leaks;
574*6777b538SAndroid Build Coastguard Worker     xmlconfTest();
575*6777b538SAndroid Build Coastguard Worker     if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
576*6777b538SAndroid Build Coastguard Worker 	printf("Ran %d tests, no errors\n", nb_tests - old_tests);
577*6777b538SAndroid Build Coastguard Worker     else
578*6777b538SAndroid Build Coastguard Worker 	printf("Ran %d tests, %d errors, %d leaks\n",
579*6777b538SAndroid Build Coastguard Worker 	       nb_tests - old_tests,
580*6777b538SAndroid Build Coastguard Worker 	       nb_errors - old_errors,
581*6777b538SAndroid Build Coastguard Worker 	       nb_leaks - old_leaks);
582*6777b538SAndroid Build Coastguard Worker     if ((nb_errors == 0) && (nb_leaks == 0)) {
583*6777b538SAndroid Build Coastguard Worker         ret = 0;
584*6777b538SAndroid Build Coastguard Worker 	printf("Total %d tests, no errors\n",
585*6777b538SAndroid Build Coastguard Worker 	       nb_tests);
586*6777b538SAndroid Build Coastguard Worker     } else {
587*6777b538SAndroid Build Coastguard Worker 	ret = 1;
588*6777b538SAndroid Build Coastguard Worker 	printf("Total %d tests, %d errors, %d leaks\n",
589*6777b538SAndroid Build Coastguard Worker 	       nb_tests, nb_errors, nb_leaks);
590*6777b538SAndroid Build Coastguard Worker 	printf("See %s for detailed output\n", LOGFILE);
591*6777b538SAndroid Build Coastguard Worker 	if ((nb_leaks == 0) && (nb_errors == NB_EXPECTED_ERRORS)) {
592*6777b538SAndroid Build Coastguard Worker 	    printf("%d errors were expected\n", nb_errors);
593*6777b538SAndroid Build Coastguard Worker 	    ret = 0;
594*6777b538SAndroid Build Coastguard Worker 	}
595*6777b538SAndroid Build Coastguard Worker     }
596*6777b538SAndroid Build Coastguard Worker     xmlXPathFreeContext(ctxtXPath);
597*6777b538SAndroid Build Coastguard Worker     xmlCleanupParser();
598*6777b538SAndroid Build Coastguard Worker 
599*6777b538SAndroid Build Coastguard Worker     if (logfile != NULL)
600*6777b538SAndroid Build Coastguard Worker         fclose(logfile);
601*6777b538SAndroid Build Coastguard Worker     return(ret);
602*6777b538SAndroid Build Coastguard Worker }
603*6777b538SAndroid Build Coastguard Worker 
604*6777b538SAndroid Build Coastguard Worker #else /* ! LIBXML_XPATH_ENABLED */
605*6777b538SAndroid Build Coastguard Worker int
main(int argc ATTRIBUTE_UNUSED,char ** argv)606*6777b538SAndroid Build Coastguard Worker main(int argc ATTRIBUTE_UNUSED, char **argv) {
607*6777b538SAndroid Build Coastguard Worker     fprintf(stderr, "%s need XPath and validation support\n", argv[0]);
608*6777b538SAndroid Build Coastguard Worker     return(0);
609*6777b538SAndroid Build Coastguard Worker }
610*6777b538SAndroid Build Coastguard Worker #endif
611