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