blob: 9fca112a52fd860167309c2d75927b9ba1eab0d0 [file] [log] [blame]
Daniel Veillardbb7ddb32002-02-17 21:26:33 +00001#!/usr/bin/python
2import sys
Daniel Veillard878eab02002-02-19 13:46:09 +00003import time
Daniel Veillardbb7ddb32002-02-17 21:26:33 +00004import os
5import string
6sys.path.append("python")
7import libxml2
8
9#
10# the testsuite description
11#
12CONF="xml-test-suite/xmlconf/xmlconf.xml"
13LOG="check-xml-test-suite.log"
14
15log = open(LOG, "w")
16
17#
18# Error and warning handlers
19#
20error_nr = 0
Daniel Veillardc7612992002-02-17 22:47:37 +000021error_msg = ''
Daniel Veillardbb7ddb32002-02-17 21:26:33 +000022def errorHandler(ctx, str):
23 global error_nr
Daniel Veillardc7612992002-02-17 22:47:37 +000024 global error_msg
Daniel Veillardbb7ddb32002-02-17 21:26:33 +000025
Daniel Veillard55253e22002-02-18 14:32:39 +000026 if string.find(str, "error:") >= 0:
27 error_nr = error_nr + 1
Daniel Veillardc7612992002-02-17 22:47:37 +000028 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
Daniel Veillardbb7ddb32002-02-17 21:26:33 +000033
34libxml2.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#
50def loadNoentDoc(filename):
51 ctxt = libxml2.createFileParserCtxt(filename)
52 if ctxt == None:
53 return None
54 ctxt.replaceEntities(1)
55 ctxt.parseDocument()
Daniel Veillardfa49d872002-03-09 10:20:00 +000056 try:
57 doc = ctxt.doc()
58 except:
59 doc = None
Daniel Veillardbb7ddb32002-02-17 21:26:33 +000060 if ctxt.wellFormed() != 1:
61 doc.freeDoc()
62 return None
63 return doc
64
65#
66# The conformance testing routines
67#
68
69def testNotWf(filename, id):
70 global error_nr
Daniel Veillardc7612992002-02-17 22:47:37 +000071 global error_msg
Daniel Veillardbb7ddb32002-02-17 21:26:33 +000072 global log
73
74 error_nr = 0
Daniel Veillardc7612992002-02-17 22:47:37 +000075 error_msg = ''
Daniel Veillardbb7ddb32002-02-17 21:26:33 +000076
77 ctxt = libxml2.createFileParserCtxt(filename)
78 if ctxt == None:
79 return -1
80 ctxt.parseDocument()
81
Daniel Veillardfa49d872002-03-09 10:20:00 +000082 try:
83 doc = ctxt.doc()
84 except:
85 doc = None
Daniel Veillardbb7ddb32002-02-17 21:26:33 +000086 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
93def testNotWfEnt(filename, id):
94 global error_nr
Daniel Veillardc7612992002-02-17 22:47:37 +000095 global error_msg
Daniel Veillardbb7ddb32002-02-17 21:26:33 +000096 global log
97
98 error_nr = 0
Daniel Veillardc7612992002-02-17 22:47:37 +000099 error_msg = ''
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000100
101 ctxt = libxml2.createFileParserCtxt(filename)
102 if ctxt == None:
103 return -1
104 ctxt.replaceEntities(1)
105 ctxt.parseDocument()
106
Daniel Veillardfa49d872002-03-09 10:20:00 +0000107 try:
108 doc = ctxt.doc()
109 except:
110 doc = None
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000111 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
118def testNotWfEntDtd(filename, id):
119 global error_nr
Daniel Veillardc7612992002-02-17 22:47:37 +0000120 global error_msg
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000121 global log
122
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000123 error_nr = 0
Daniel Veillardc7612992002-02-17 22:47:37 +0000124 error_msg = ''
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000125
126 ctxt = libxml2.createFileParserCtxt(filename)
127 if ctxt == None:
128 return -1
129 ctxt.replaceEntities(1)
130 ctxt.loadSubset(1)
131 ctxt.parseDocument()
132
Daniel Veillardfa49d872002-03-09 10:20:00 +0000133 try:
134 doc = ctxt.doc()
135 except:
136 doc = None
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000137 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
144def testWfEntDtd(filename, id):
145 global error_nr
Daniel Veillardc7612992002-02-17 22:47:37 +0000146 global error_msg
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000147 global log
148
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000149 error_nr = 0
Daniel Veillardc7612992002-02-17 22:47:37 +0000150 error_msg = ''
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000151
152 ctxt = libxml2.createFileParserCtxt(filename)
153 if ctxt == None:
154 return -1
155 ctxt.replaceEntities(1)
156 ctxt.loadSubset(1)
157 ctxt.parseDocument()
158
Daniel Veillardfa49d872002-03-09 10:20:00 +0000159 try:
160 doc = ctxt.doc()
161 except:
162 doc = None
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000163 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
Daniel Veillard55253e22002-02-18 14:32:39 +0000175def 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
Daniel Veillardfa49d872002-03-09 10:20:00 +0000190 try:
191 doc = ctxt.doc()
192 except:
193 doc = None
Daniel Veillard55253e22002-02-18 14:32:39 +0000194 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
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000206def testInvalid(filename, id):
207 global error_nr
Daniel Veillardc7612992002-02-17 22:47:37 +0000208 global error_msg
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000209 global log
210
211 error_nr = 0
Daniel Veillardc7612992002-02-17 22:47:37 +0000212 error_msg = ''
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000213
214 ctxt = libxml2.createFileParserCtxt(filename)
215 if ctxt == None:
216 return -1
217 ctxt.validate(1)
218 ctxt.parseDocument()
219
Daniel Veillardfa49d872002-03-09 10:20:00 +0000220 try:
221 doc = ctxt.doc()
222 except:
223 doc = None
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000224 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
243def testValid(filename, id):
244 global error_nr
Daniel Veillardc7612992002-02-17 22:47:37 +0000245 global error_msg
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000246
247 error_nr = 0
Daniel Veillardc7612992002-02-17 22:47:37 +0000248 error_msg = ''
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000249
250 ctxt = libxml2.createFileParserCtxt(filename)
251 if ctxt == None:
252 return -1
253 ctxt.validate(1)
254 ctxt.parseDocument()
255
Daniel Veillardfa49d872002-03-09 10:20:00 +0000256 try:
257 doc = ctxt.doc()
258 except:
259 doc = None
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000260 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
278test_nr = 0
279test_succeed = 0
280test_failed = 0
281test_error = 0
282def runTest(test):
283 global test_nr
284 global test_failed
285 global test_error
286 global test_succeed
Daniel Veillardc7612992002-02-17 22:47:37 +0000287 global error_msg
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000288 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":
Daniel Veillard55253e22002-02-18 14:32:39 +0000328 res = testError(URI, id)
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000329 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))
Daniel Veillardc7612992002-02-17 22:47:37 +0000344 content = string.strip(test.content)
345 while content[-1] == '\n':
346 content = content[0:-1]
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000347 if extra != None:
Daniel Veillardc7612992002-02-17 22:47:37 +0000348 log.write(" %s:%s:%s\n" % (type, extra, content))
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000349 else:
350 log.write(" %s:%s\n\n" % (type, content))
Daniel Veillardc7612992002-02-17 22:47:37 +0000351 if error_msg != '':
352 log.write(" ----\n%s ----\n" % (error_msg))
353 error_msg = ''
354 log.write("\n")
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000355
356 return 0
357
358
359def 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
372conf = loadNoentDoc(CONF)
373if conf == None:
374 print "Unable to load %s" % CONF
375 sys.exit(1)
376
377testsuite = conf.getRootElement()
378if testsuite.name != 'TESTSUITE':
379 print "Expecting TESTSUITE root element: aborting"
380 sys.exit(1)
381
382profile = testsuite.prop('PROFILE')
383if profile != None:
384 print profile
385
Daniel Veillard878eab02002-02-19 13:46:09 +0000386start = time.time()
387
Daniel Veillardbb7ddb32002-02-17 21:26:33 +0000388case = testsuite.children
389while 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
406conf.freeDoc()
407log.close()
408
Daniel Veillard878eab02002-02-19 13:46:09 +0000409print "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)