blob: 5363a8185fcb18e26a738b43b2a4f1bdd5a607b9 [file] [log] [blame]
Daniel Veillard1703c5f2003-02-10 14:28:44 +00001#!/usr/bin/python
2import sys
3import time
4import os
5import string
6import StringIO
7sys.path.append("python")
8import libxml2
9
Daniel Veillardd4310742003-02-18 21:12:46 +000010debug = 0
11
Daniel Veillard1703c5f2003-02-10 14:28:44 +000012#
13# the testsuite description
14#
15CONF="test/relaxng/OASIS/spectest.xml"
16LOG="check-relaxng-test-suite.log"
Daniel Veillard416589a2003-02-17 17:25:42 +000017RES="relaxng-test-results.xml"
18
Daniel Veillard1703c5f2003-02-10 14:28:44 +000019log = open(LOG, "w")
20nb_schemas_tests = 0
21nb_schemas_success = 0
22nb_schemas_failed = 0
23nb_instances_tests = 0
24nb_instances_success = 0
25nb_instances_failed = 0
26
27libxml2.lineNumbersDefault(1)
28#
29# Error and warnng callbacks
30#
31def callback(ctx, str):
32 global log
33 log.write("%s%s" % (ctx, str))
34
35libxml2.registerErrorHandler(callback, "")
36
37#
38# Resolver callback
39#
40resources = {}
41def resolver(URL, ID, ctxt):
42 global resources
43
44 if resources.has_key(URL):
45 return(StringIO.StringIO(resources[URL]))
46 log.write("Resolver failure: asked %s\n" % (URL))
47 log.write("resources: %s\n" % (resources))
48 return None
49
Daniel Veillard416589a2003-02-17 17:25:42 +000050#
51# Load the previous results
52#
53#results = {}
54#previous = {}
55#
56#try:
57# res = libxml2.parseFile(RES)
58#except:
59# log.write("Could not parse %s" % (RES))
60
Daniel Veillard1703c5f2003-02-10 14:28:44 +000061#
62# handle a valid instance
63#
64def handle_valid(node, schema):
65 global log
66 global nb_instances_success
67 global nb_instances_failed
68
69 instance = ""
70 child = node.children
71 while child != None:
72 if child.type != 'text':
73 instance = instance + child.serialize()
74 child = child.next
75
76 try:
77 doc = libxml2.parseDoc(instance)
78 except:
79 doc = None
80
81 if doc == None:
82 log.write("\nFailed to parse correct instance:\n-----\n")
83 log.write(instance)
84 log.write("\n-----\n")
85 nb_instances_failed = nb_instances_failed + 1
86 return
87
88 try:
89 ctxt = schema.relaxNGNewValidCtxt()
90 ret = doc.relaxNGValidateDoc(ctxt)
91 except:
92 ret = -1
93 if ret != 0:
94 log.write("\nFailed to validate correct instance:\n-----\n")
95 log.write(instance)
96 log.write("\n-----\n")
97 nb_instances_failed = nb_instances_failed + 1
98 else:
99 nb_instances_success = nb_instances_success + 1
100
101#
102# handle an invalid instance
103#
104def handle_invalid(node, schema):
105 global log
106 global nb_instances_success
107 global nb_instances_failed
108
109 instance = ""
110 child = node.children
111 while child != None:
112 if child.type != 'text':
113 instance = instance + child.serialize()
114 child = child.next
115
116 try:
117 doc = libxml2.parseDoc(instance)
118 except:
119 doc = None
120
121 if doc == None:
122 log.write("\nStrange: failed to parse incorrect instance:\n-----\n")
123 log.write(instance)
124 log.write("\n-----\n")
125 return
126
127 try:
128 ctxt = schema.relaxNGNewValidCtxt()
129 ret = doc.relaxNGValidateDoc(ctxt)
130 except:
131 ret = -1
132 if ret == 0:
133 log.write("\nFailed to detect validation problem in instance:\n-----\n")
134 log.write(instance)
135 log.write("\n-----\n")
136 nb_instances_failed = nb_instances_failed + 1
137 else:
138 nb_instances_success = nb_instances_success + 1
139
140#
141# handle an incorrect test
142#
143def handle_correct(node):
144 global log
145 global nb_schemas_success
146 global nb_schemas_failed
147
148 schema = ""
149 child = node.children
150 while child != None:
151 if child.type != 'text':
152 schema = schema + child.serialize()
153 child = child.next
154
155 try:
156 rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema))
157 rngs = rngp.relaxNGParse()
158 except:
159 rngs = None
160 if rngs == None:
161 log.write("\nFailed to compile correct schema:\n-----\n")
162 log.write(schema)
163 log.write("\n-----\n")
164 nb_schemas_failed = nb_schemas_failed + 1
165 else:
166 nb_schemas_success = nb_schemas_success + 1
167 return rngs
168
169def handle_incorrect(node):
170 global log
171 global nb_schemas_success
172 global nb_schemas_failed
173
174 schema = ""
175 child = node.children
176 while child != None:
177 if child.type != 'text':
178 schema = schema + child.serialize()
179 child = child.next
180
181 try:
182 rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema))
183 rngs = rngp.relaxNGParse()
184 except:
185 rngs = None
186 if rngs != None:
187 log.write("\nFailed to detect schema error in:\n-----\n")
188 log.write(schema)
189 log.write("\n-----\n")
190 nb_schemas_failed = nb_schemas_failed + 1
191 else:
192# log.write("\nSuccess detecting schema error in:\n-----\n")
193# log.write(schema)
194# log.write("\n-----\n")
195 nb_schemas_success = nb_schemas_success + 1
196 return None
197
198#
199# resource handling: keep a dictionary of URL->string mappings
200#
201def handle_resource(node, dir):
202 global resources
203
204 try:
205 name = node.prop('name')
206 except:
207 name = None
208
209 if name == None or name == '':
210 log.write("resource has no name")
211 return;
212
213 if dir != None:
214# name = libxml2.buildURI(name, dir)
215 name = dir + '/' + name
216
217 res = ""
218 child = node.children
219 while child != None:
220 if child.type != 'text':
221 res = res + child.serialize()
222 child = child.next
223 resources[name] = res
224
225#
226# dir handling: pseudo directory resources
227#
228def handle_dir(node, dir):
229 try:
230 name = node.prop('name')
231 except:
232 name = None
233
234 if name == None or name == '':
235 log.write("resource has no name")
236 return;
237
238 if dir != None:
239# name = libxml2.buildURI(name, dir)
240 name = dir + '/' + name
241
242 dirs = node.xpathEval('dir')
243 for dir in dirs:
244 handle_dir(dir, name)
245 res = node.xpathEval('resource')
246 for r in res:
247 handle_resource(r, name)
248
Daniel Veillard1703c5f2003-02-10 14:28:44 +0000249#
250# handle a testCase element
251#
252def handle_testCase(node):
253 global nb_schemas_tests
254 global nb_instances_tests
255 global resources
256
Daniel Veillard77648bb2003-02-20 15:03:22 +0000257 sections = node.xpathEval('string(section)')
258 log.write("\n ======== test %d line %d section %s ==========\n" % (
Daniel Veillard1703c5f2003-02-10 14:28:44 +0000259
Daniel Veillard77648bb2003-02-20 15:03:22 +0000260 nb_schemas_tests, node.lineNo(), sections))
Daniel Veillard1703c5f2003-02-10 14:28:44 +0000261 resources = {}
Daniel Veillardd4310742003-02-18 21:12:46 +0000262 if debug:
263 print "test %d line %d" % (nb_schemas_tests, node.lineNo())
Daniel Veillard1703c5f2003-02-10 14:28:44 +0000264
265 dirs = node.xpathEval('dir')
266 for dir in dirs:
267 handle_dir(dir, None)
268 res = node.xpathEval('resource')
269 for r in res:
270 handle_resource(r, None)
271
272 tsts = node.xpathEval('incorrect')
273 if tsts != []:
274 if len(tsts) != 1:
275 print "warning test line %d has more than one <incorrect> example" %(node.lineNo())
276 schema = handle_incorrect(tsts[0])
277 else:
278 tsts = node.xpathEval('correct')
279 if tsts != []:
280 if len(tsts) != 1:
281 print "warning test line %d has more than one <correct> example"% (node.lineNo())
282 schema = handle_correct(tsts[0])
283 else:
284 print "warning <testCase> line %d has no <correct> nor <incorrect> child" % (node.lineNo())
285
286 nb_schemas_tests = nb_schemas_tests + 1;
287
288 valids = node.xpathEval('valid')
289 invalids = node.xpathEval('invalid')
290 nb_instances_tests = nb_instances_tests + len(valids) + len(invalids)
291 if schema != None:
292 for valid in valids:
293 handle_valid(valid, schema)
294 for invalid in invalids:
295 handle_invalid(invalid, schema)
296
297
298#
299# handle a testSuite element
300#
Daniel Veillardd2298792003-02-14 16:54:11 +0000301def handle_testSuite(node, level = 0):
302 global nb_schemas_tests, nb_schemas_success, nb_schemas_failed
303 global nb_instances_tests, nb_instances_success, nb_instances_failed
304 if level >= 1:
305 old_schemas_tests = nb_schemas_tests
306 old_schemas_success = nb_schemas_success
307 old_schemas_failed = nb_schemas_failed
308 old_instances_tests = nb_instances_tests
309 old_instances_success = nb_instances_success
310 old_instances_failed = nb_instances_failed
311
Daniel Veillard1703c5f2003-02-10 14:28:44 +0000312 docs = node.xpathEval('documentation')
313 authors = node.xpathEval('author')
314 if docs != []:
315 msg = ""
316 for doc in docs:
317 msg = msg + doc.content + " "
318 if authors != []:
319 msg = msg + "written by "
320 for author in authors:
321 msg = msg + author.content + " "
322 print msg
323 sections = node.xpathEval('section')
Daniel Veillard77648bb2003-02-20 15:03:22 +0000324 if sections != [] and level <= 0:
Daniel Veillard1703c5f2003-02-10 14:28:44 +0000325 msg = ""
326 for section in sections:
327 msg = msg + section.content + " "
328 print "Tests for section %s" % (msg)
329 for test in node.xpathEval('testCase'):
330 handle_testCase(test)
331 for test in node.xpathEval('testSuite'):
Daniel Veillardd2298792003-02-14 16:54:11 +0000332 handle_testSuite(test, level + 1)
Daniel Veillard1703c5f2003-02-10 14:28:44 +0000333
334
Daniel Veillardd2298792003-02-14 16:54:11 +0000335 if level >= 1 and sections != []:
Daniel Veillard77648bb2003-02-20 15:03:22 +0000336 msg = ""
337 for section in sections:
338 msg = msg + section.content + " "
339 print "Result of tests for section %s" % (msg)
Daniel Veillardd2298792003-02-14 16:54:11 +0000340 if nb_schemas_tests != old_schemas_tests:
341 print "found %d test schemas: %d success %d failures" % (
342 nb_schemas_tests - old_schemas_tests,
343 nb_schemas_success - old_schemas_success,
344 nb_schemas_failed - old_schemas_failed)
345 if nb_instances_tests != old_instances_tests:
346 print "found %d test instances: %d success %d failures" % (
347 nb_instances_tests - old_instances_tests,
348 nb_instances_success - old_instances_success,
349 nb_instances_failed - old_instances_failed)
Daniel Veillard1703c5f2003-02-10 14:28:44 +0000350#
351# Parse the conf file
352#
Daniel Veillardd2298792003-02-14 16:54:11 +0000353libxml2.substituteEntitiesDefault(1);
Daniel Veillard1703c5f2003-02-10 14:28:44 +0000354testsuite = libxml2.parseFile(CONF)
Daniel Veillardd2298792003-02-14 16:54:11 +0000355libxml2.setEntityLoader(resolver)
Daniel Veillard1703c5f2003-02-10 14:28:44 +0000356root = testsuite.getRootElement()
357if root.name != 'testSuite':
358 print "%s doesn't start with a testSuite element, aborting" % (CONF)
359 sys.exit(1)
360print "Running Relax NG testsuite"
361handle_testSuite(root)
362
363print "\nTOTAL:\nfound %d test schemas: %d success %d failures" % (
364 nb_schemas_tests, nb_schemas_success, nb_schemas_failed)
365print "found %d test instances: %d success %d failures" % (
366 nb_instances_tests, nb_instances_success, nb_instances_failed)