Initial revision
[TestXSLT.git] / libxml2 / check-xml-test-suite.py
1 #!/usr/bin/python
2 import sys
3 import time
4 import os
5 import string
6 sys.path.append("python")
7 import libxml2
8
9 #
10 # the testsuite description
11 #
12 CONF="xml-test-suite/xmlconf/xmlconf.xml"
13 LOG="check-xml-test-suite.log"
14
15 log = open(LOG, "w")
16
17 #
18 # Error and warning handlers
19 #
20 error_nr = 0
21 error_msg = ''
22 def errorHandler(ctx, str):
23     global error_nr
24     global error_msg
25
26     if string.find(str, "error:") >= 0:
27         error_nr = error_nr + 1
28     if len(error_msg) < 300:
29         if len(error_msg) == 0 or error_msg[-1] == '\n':
30             error_msg = error_msg + "   >>" + str
31         else:
32             error_msg = error_msg + str
33
34 libxml2.registerErrorHandler(errorHandler, None)
35
36 #warning_nr = 0
37 #warning = ''
38 #def warningHandler(ctx, str):
39 #    global warning_nr
40 #    global warning
41 #
42 #    warning_nr = warning_nr + 1
43 #    warning = warning + str
44 #
45 #libxml2.registerWarningHandler(warningHandler, None)
46
47 #
48 # Used to load the XML testsuite description
49 #
50 def loadNoentDoc(filename):
51     ctxt = libxml2.createFileParserCtxt(filename)
52     if ctxt == None:
53         return None
54     ctxt.replaceEntities(1)
55     ctxt.parseDocument()
56     try:
57         doc = ctxt.doc()
58     except:
59         doc = None
60     if ctxt.wellFormed() != 1:
61         doc.freeDoc()
62         return None
63     return doc
64
65 #
66 # The conformance testing routines
67 #
68
69 def testNotWf(filename, id):
70     global error_nr
71     global error_msg
72     global log
73
74     error_nr = 0
75     error_msg = ''
76
77     ctxt = libxml2.createFileParserCtxt(filename)
78     if ctxt == None:
79         return -1
80     ctxt.parseDocument()
81
82     try:
83         doc = ctxt.doc()
84     except:
85         doc = None
86     if error_nr == 0 or ctxt.wellFormed() != 0:
87         print "%s: error: Well Formedness error not detected" % (id)
88         log.write("%s: error: Well Formedness error not detected\n" % (id))
89         doc.freeDoc()
90         return 0
91     return 1
92
93 def testNotWfEnt(filename, id):
94     global error_nr
95     global error_msg
96     global log
97
98     error_nr = 0
99     error_msg = ''
100
101     ctxt = libxml2.createFileParserCtxt(filename)
102     if ctxt == None:
103         return -1
104     ctxt.replaceEntities(1)
105     ctxt.parseDocument()
106
107     try:
108         doc = ctxt.doc()
109     except:
110         doc = None
111     if error_nr == 0 or ctxt.wellFormed() != 0:
112         print "%s: error: Well Formedness error not detected" % (id)
113         log.write("%s: error: Well Formedness error not detected\n" % (id))
114         doc.freeDoc()
115         return 0
116     return 1
117
118 def testNotWfEntDtd(filename, id):
119     global error_nr
120     global error_msg
121     global log
122
123     error_nr = 0
124     error_msg = ''
125
126     ctxt = libxml2.createFileParserCtxt(filename)
127     if ctxt == None:
128         return -1
129     ctxt.replaceEntities(1)
130     ctxt.loadSubset(1)
131     ctxt.parseDocument()
132
133     try:
134         doc = ctxt.doc()
135     except:
136         doc = None
137     if error_nr == 0 or ctxt.wellFormed() != 0:
138         print "%s: error: Well Formedness error not detected" % (id)
139         log.write("%s: error: Well Formedness error not detected\n" % (id))
140         doc.freeDoc()
141         return 0
142     return 1
143
144 def testWfEntDtd(filename, id):
145     global error_nr
146     global error_msg
147     global log
148
149     error_nr = 0
150     error_msg = ''
151
152     ctxt = libxml2.createFileParserCtxt(filename)
153     if ctxt == None:
154         return -1
155     ctxt.replaceEntities(1)
156     ctxt.loadSubset(1)
157     ctxt.parseDocument()
158
159     try:
160         doc = ctxt.doc()
161     except:
162         doc = None
163     if ctxt.wellFormed() == 0:
164         print "%s: error: wrongly failed to parse the document" % (id)
165         log.write("%s: error: wrongly failed to parse the document\n" % (id))
166         return 0
167     if error_nr != 0:
168         print "%s: warning: WF document generated an error msg" % (id)
169         log.write("%s: error: WF document generated an error msg\n" % (id))
170         doc.freeDoc()
171         return 2
172     doc.freeDoc()
173     return 1
174
175 def testError(filename, id):
176     global error_nr
177     global error_msg
178     global log
179
180     error_nr = 0
181     error_msg = ''
182
183     ctxt = libxml2.createFileParserCtxt(filename)
184     if ctxt == None:
185         return -1
186     ctxt.replaceEntities(1)
187     ctxt.loadSubset(1)
188     ctxt.parseDocument()
189
190     try:
191         doc = ctxt.doc()
192     except:
193         doc = None
194     if ctxt.wellFormed() == 0:
195         print "%s: warning: failed to parse the document but accepted" % (id)
196         log.write("%s: warning: failed to parse the document but accepte\n" % (id))
197         return 2
198     if error_nr != 0:
199         print "%s: warning: WF document generated an error msg" % (id)
200         log.write("%s: error: WF document generated an error msg\n" % (id))
201         doc.freeDoc()
202         return 2
203     doc.freeDoc()
204     return 1
205
206 def testInvalid(filename, id):
207     global error_nr
208     global error_msg
209     global log
210
211     error_nr = 0
212     error_msg = ''
213
214     ctxt = libxml2.createFileParserCtxt(filename)
215     if ctxt == None:
216         return -1
217     ctxt.validate(1)
218     ctxt.parseDocument()
219
220     try:
221         doc = ctxt.doc()
222     except:
223         doc = None
224     valid = ctxt.isValid()
225     if doc == None:
226         print "%s: error: wrongly failed to parse the document" % (id)
227         log.write("%s: error: wrongly failed to parse the document\n" % (id))
228         return 0
229     if valid == 1:
230         print "%s: error: Validity error not detected" % (id)
231         log.write("%s: error: Validity error not detected\n" % (id))
232         doc.freeDoc()
233         return 0
234     if error_nr == 0:
235         print "%s: warning: Validity error not reported" % (id)
236         log.write("%s: warning: Validity error not reported\n" % (id))
237         doc.freeDoc()
238         return 2
239         
240     doc.freeDoc()
241     return 1
242
243 def testValid(filename, id):
244     global error_nr
245     global error_msg
246
247     error_nr = 0
248     error_msg = ''
249
250     ctxt = libxml2.createFileParserCtxt(filename)
251     if ctxt == None:
252         return -1
253     ctxt.validate(1)
254     ctxt.parseDocument()
255
256     try:
257         doc = ctxt.doc()
258     except:
259         doc = None
260     valid = ctxt.isValid()
261     if doc == None:
262         print "%s: error: wrongly failed to parse the document" % (id)
263         log.write("%s: error: wrongly failed to parse the document\n" % (id))
264         return 0
265     if valid != 1:
266         print "%s: error: Validity check failed" % (id)
267         log.write("%s: error: Validity check failed\n" % (id))
268         doc.freeDoc()
269         return 0
270     if error_nr != 0 or valid != 1:
271         print "%s: warning: valid document reported an error" % (id)
272         log.write("%s: warning: valid document reported an error\n" % (id))
273         doc.freeDoc()
274         return 2
275     doc.freeDoc()
276     return 1
277
278 test_nr = 0
279 test_succeed = 0
280 test_failed = 0
281 test_error = 0
282 def runTest(test):
283     global test_nr
284     global test_failed
285     global test_error
286     global test_succeed
287     global error_msg
288     global log
289
290     uri = test.prop('URI')
291     id = test.prop('ID')
292     if uri == None:
293         print "Test without ID:", uri
294         return -1
295     if id == None:
296         print "Test without URI:", id
297         return -1
298     base = test.getBase(None)
299     URI = libxml2.buildURI(uri, base)
300     if os.access(URI, os.R_OK) == 0:
301         print "Test %s missing: base %s uri %s" % (URI, base, uri)
302         return -1
303     type = test.prop('TYPE')
304     if type == None:
305         print "Test %s missing TYPE" % (id)
306         return -1
307
308     extra = None
309     if type == "invalid":
310         res = testInvalid(URI, id)
311     elif type == "valid":
312         res = testValid(URI, id)
313     elif type == "not-wf":
314         extra =  test.prop('ENTITIES')
315         # print URI
316         #if extra == None:
317         #    res = testNotWfEntDtd(URI, id)
318         #elif extra == 'none':
319         #    res = testNotWf(URI, id)
320         #elif extra == 'general':
321         #    res = testNotWfEnt(URI, id)
322         #elif extra == 'both' or extra == 'parameter':
323         res = testNotWfEntDtd(URI, id)
324         #else:
325         #    print "Unknow value %s for an ENTITIES test value" % (extra)
326         #    return -1
327     elif type == "error":
328         res = testError(URI, id)
329     else:
330         # TODO skipped for now
331         return -1
332
333     test_nr = test_nr + 1
334     if res > 0:
335         test_succeed = test_succeed + 1
336     elif res == 0:
337         test_failed = test_failed + 1
338     elif res < 0:
339         test_error = test_error + 1
340
341     # Log the ontext
342     if res != 1:
343         log.write("   File: %s\n" % (URI))
344         content = string.strip(test.content)
345         while content[-1] == '\n':
346             content = content[0:-1]
347         if extra != None:
348             log.write("   %s:%s:%s\n" % (type, extra, content))
349         else:
350             log.write("   %s:%s\n\n" % (type, content))
351         if error_msg != '':
352             log.write("   ----\n%s   ----\n" % (error_msg))
353             error_msg = ''
354         log.write("\n")
355
356     return 0
357             
358
359 def runTestCases(case):
360     profile = case.prop('PROFILE')
361     if profile != None and \
362        string.find(profile, "IBM XML Conformance Test Suite - Production") < 0:
363         print "=>", profile
364     test = case.children
365     while test != None:
366         if test.name == 'TEST':
367             runTest(test)
368         if test.name == 'TESTCASES':
369             runTestCases(test)
370         test = test.next
371         
372 conf = loadNoentDoc(CONF)
373 if conf == None:
374     print "Unable to load %s" % CONF
375     sys.exit(1)
376
377 testsuite = conf.getRootElement()
378 if testsuite.name != 'TESTSUITE':
379     print "Expecting TESTSUITE root element: aborting"
380     sys.exit(1)
381
382 profile = testsuite.prop('PROFILE')
383 if profile != None:
384     print profile
385
386 start = time.time()
387
388 case = testsuite.children
389 while case != None:
390     global test_nr
391     global test_succeed
392     global test_failed
393     global test_error
394
395     if case.name == 'TESTCASES':
396         old_test_nr = test_nr
397         old_test_succeed = test_succeed
398         old_test_failed = test_failed
399         old_test_error = test_error
400         runTestCases(case)
401         print "   Ran %d tests: %d suceeded, %d failed and %d generated an error" % (
402                test_nr - old_test_nr, test_succeed - old_test_succeed,
403                test_failed - old_test_failed, test_error - old_test_error)
404     case = case.next
405
406 conf.freeDoc()
407 log.close()
408
409 print "Ran %d tests: %d suceeded, %d failed and %d generated an error in %.2f s." % (
410       test_nr, test_succeed, test_failed, test_error, time.time() - start)