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