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