1#!/usr/bin/python 2import sys 3import time 4import os 5import string 6import StringIO 7sys.path.insert(0, "python") 8import libxml2 9 10# Memory debug specific 11libxml2.debugMemory(1) 12debug = 0 13quiet = 1 14 15# 16# the testsuite description 17# 18CONF=os.path.join(os.path.dirname(__file__), "test/relaxng/testsuite.xml") 19LOG="check-relaxng-test-suite2.log" 20 21log = open(LOG, "w") 22nb_schemas_tests = 0 23nb_schemas_success = 0 24nb_schemas_failed = 0 25nb_instances_tests = 0 26nb_instances_success = 0 27nb_instances_failed = 0 28 29libxml2.lineNumbersDefault(1) 30# 31# Resolver callback 32# 33resources = {} 34def resolver(URL, ID, ctxt): 35 global resources 36 37 if resources.has_key(URL): 38 return(StringIO.StringIO(resources[URL])) 39 log.write("Resolver failure: asked %s\n" % (URL)) 40 log.write("resources: %s\n" % (resources)) 41 return None 42 43# 44# Load the previous results 45# 46#results = {} 47#previous = {} 48# 49#try: 50# res = libxml2.parseFile(RES) 51#except: 52# log.write("Could not parse %s" % (RES)) 53 54# 55# handle a valid instance 56# 57def handle_valid(node, schema): 58 global log 59 global nb_instances_success 60 global nb_instances_failed 61 62 instance = node.prop("dtd") 63 if instance == None: 64 instance = "" 65 child = node.children 66 while child != None: 67 if child.type != 'text': 68 instance = instance + child.serialize() 69 child = child.next 70 71# mem = libxml2.debugMemory(1); 72 try: 73 doc = libxml2.parseDoc(instance) 74 except: 75 doc = None 76 77 if doc == None: 78 log.write("\nFailed to parse correct instance:\n-----\n") 79 log.write(instance) 80 log.write("\n-----\n") 81 nb_instances_failed = nb_instances_failed + 1 82 return 83 84 if debug: 85 print "instance line %d" % (node.lineNo()) 86 87 try: 88 ctxt = schema.relaxNGNewValidCtxt() 89 ret = doc.relaxNGValidateDoc(ctxt) 90 del ctxt 91 except: 92 ret = -1 93 94 doc.freeDoc() 95# if mem != libxml2.debugMemory(1): 96# print "validating instance %d line %d leaks" % ( 97# nb_instances_tests, node.lineNo()) 98 99 if ret != 0: 100 log.write("\nFailed to validate correct instance:\n-----\n") 101 log.write(instance) 102 log.write("\n-----\n") 103 nb_instances_failed = nb_instances_failed + 1 104 else: 105 nb_instances_success = nb_instances_success + 1 106 107# 108# handle an invalid instance 109# 110def handle_invalid(node, schema): 111 global log 112 global nb_instances_success 113 global nb_instances_failed 114 115 instance = node.prop("dtd") 116 if instance == None: 117 instance = "" 118 child = node.children 119 while child != None: 120 if child.type != 'text': 121 instance = instance + child.serialize() 122 child = child.next 123 124# mem = libxml2.debugMemory(1); 125 126 try: 127 doc = libxml2.parseDoc(instance) 128 except: 129 doc = None 130 131 if doc == None: 132 log.write("\nStrange: failed to parse incorrect instance:\n-----\n") 133 log.write(instance) 134 log.write("\n-----\n") 135 return 136 137 if debug: 138 print "instance line %d" % (node.lineNo()) 139 140 try: 141 ctxt = schema.relaxNGNewValidCtxt() 142 ret = doc.relaxNGValidateDoc(ctxt) 143 del ctxt 144 145 except: 146 ret = -1 147 148 doc.freeDoc() 149# mem2 = libxml2.debugMemory(1) 150# if mem != mem2: 151# print "validating instance %d line %d leaks %d bytes" % ( 152# nb_instances_tests, node.lineNo(), mem2 - mem) 153 154 if ret == 0: 155 log.write("\nFailed to detect validation problem in instance:\n-----\n") 156 log.write(instance) 157 log.write("\n-----\n") 158 nb_instances_failed = nb_instances_failed + 1 159 else: 160 nb_instances_success = nb_instances_success + 1 161 162# 163# handle an incorrect test 164# 165def handle_correct(node): 166 global log 167 global nb_schemas_success 168 global nb_schemas_failed 169 170 schema = "" 171 child = node.children 172 while child != None: 173 if child.type != 'text': 174 schema = schema + child.serialize() 175 child = child.next 176 177 try: 178 rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema)) 179 rngs = rngp.relaxNGParse() 180 except: 181 rngs = None 182 if rngs == None: 183 log.write("\nFailed to compile correct schema:\n-----\n") 184 log.write(schema) 185 log.write("\n-----\n") 186 nb_schemas_failed = nb_schemas_failed + 1 187 else: 188 nb_schemas_success = nb_schemas_success + 1 189 return rngs 190 191def handle_incorrect(node): 192 global log 193 global nb_schemas_success 194 global nb_schemas_failed 195 196 schema = "" 197 child = node.children 198 while child != None: 199 if child.type != 'text': 200 schema = schema + child.serialize() 201 child = child.next 202 203 try: 204 rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema)) 205 rngs = rngp.relaxNGParse() 206 except: 207 rngs = None 208 if rngs != None: 209 log.write("\nFailed to detect schema error in:\n-----\n") 210 log.write(schema) 211 log.write("\n-----\n") 212 nb_schemas_failed = nb_schemas_failed + 1 213 else: 214# log.write("\nSuccess detecting schema error in:\n-----\n") 215# log.write(schema) 216# log.write("\n-----\n") 217 nb_schemas_success = nb_schemas_success + 1 218 return None 219 220# 221# resource handling: keep a dictionary of URL->string mappings 222# 223def handle_resource(node, dir): 224 global resources 225 226 try: 227 name = node.prop('name') 228 except: 229 name = None 230 231 if name == None or name == '': 232 log.write("resource has no name") 233 return; 234 235 if dir != None: 236# name = libxml2.buildURI(name, dir) 237 name = dir + '/' + name 238 239 res = "" 240 child = node.children 241 while child != None: 242 if child.type != 'text': 243 res = res + child.serialize() 244 child = child.next 245 resources[name] = res 246 247# 248# dir handling: pseudo directory resources 249# 250def handle_dir(node, dir): 251 try: 252 name = node.prop('name') 253 except: 254 name = None 255 256 if name == None or name == '': 257 log.write("resource has no name") 258 return; 259 260 if dir != None: 261# name = libxml2.buildURI(name, dir) 262 name = dir + '/' + name 263 264 dirs = node.xpathEval('dir') 265 for dir in dirs: 266 handle_dir(dir, name) 267 res = node.xpathEval('resource') 268 for r in res: 269 handle_resource(r, name) 270 271# 272# handle a testCase element 273# 274def handle_testCase(node): 275 global nb_schemas_tests 276 global nb_instances_tests 277 global resources 278 279 sections = node.xpathEval('string(section)') 280 log.write("\n ======== test %d line %d section %s ==========\n" % ( 281 282 nb_schemas_tests, node.lineNo(), sections)) 283 resources = {} 284 if debug: 285 print "test %d line %d" % (nb_schemas_tests, node.lineNo()) 286 287 dirs = node.xpathEval('dir') 288 for dir in dirs: 289 handle_dir(dir, None) 290 res = node.xpathEval('resource') 291 for r in res: 292 handle_resource(r, None) 293 294 tsts = node.xpathEval('incorrect') 295 if tsts != []: 296 if len(tsts) != 1: 297 print "warning test line %d has more than one <incorrect> example" %(node.lineNo()) 298 schema = handle_incorrect(tsts[0]) 299 else: 300 tsts = node.xpathEval('correct') 301 if tsts != []: 302 if len(tsts) != 1: 303 print "warning test line %d has more than one <correct> example"% (node.lineNo()) 304 schema = handle_correct(tsts[0]) 305 else: 306 print "warning <testCase> line %d has no <correct> nor <incorrect> child" % (node.lineNo()) 307 308 nb_schemas_tests = nb_schemas_tests + 1; 309 310 valids = node.xpathEval('valid') 311 invalids = node.xpathEval('invalid') 312 nb_instances_tests = nb_instances_tests + len(valids) + len(invalids) 313 if schema != None: 314 for valid in valids: 315 handle_valid(valid, schema) 316 for invalid in invalids: 317 handle_invalid(invalid, schema) 318 319 320# 321# handle a testSuite element 322# 323def handle_testSuite(node, level = 0): 324 global nb_schemas_tests, nb_schemas_success, nb_schemas_failed 325 global nb_instances_tests, nb_instances_success, nb_instances_failed 326 if level >= 1: 327 old_schemas_tests = nb_schemas_tests 328 old_schemas_success = nb_schemas_success 329 old_schemas_failed = nb_schemas_failed 330 old_instances_tests = nb_instances_tests 331 old_instances_success = nb_instances_success 332 old_instances_failed = nb_instances_failed 333 334 docs = node.xpathEval('documentation') 335 authors = node.xpathEval('author') 336 if docs != []: 337 msg = "" 338 for doc in docs: 339 msg = msg + doc.content + " " 340 if authors != []: 341 msg = msg + "written by " 342 for author in authors: 343 msg = msg + author.content + " " 344 if quiet == 0: 345 print msg 346 sections = node.xpathEval('section') 347 if sections != [] and level <= 0: 348 msg = "" 349 for section in sections: 350 msg = msg + section.content + " " 351 if quiet == 0: 352 print "Tests for section %s" % (msg) 353 for test in node.xpathEval('testCase'): 354 handle_testCase(test) 355 for test in node.xpathEval('testSuite'): 356 handle_testSuite(test, level + 1) 357 358 359 if level >= 1 and sections != []: 360 msg = "" 361 for section in sections: 362 msg = msg + section.content + " " 363 print "Result of tests for section %s" % (msg) 364 if nb_schemas_tests != old_schemas_tests: 365 print "found %d test schemas: %d success %d failures" % ( 366 nb_schemas_tests - old_schemas_tests, 367 nb_schemas_success - old_schemas_success, 368 nb_schemas_failed - old_schemas_failed) 369 if nb_instances_tests != old_instances_tests: 370 print "found %d test instances: %d success %d failures" % ( 371 nb_instances_tests - old_instances_tests, 372 nb_instances_success - old_instances_success, 373 nb_instances_failed - old_instances_failed) 374# 375# Parse the conf file 376# 377libxml2.substituteEntitiesDefault(1); 378testsuite = libxml2.parseFile(CONF) 379 380# 381# Error and warnng callbacks 382# 383def callback(ctx, str): 384 global log 385 log.write("%s%s" % (ctx, str)) 386 387libxml2.registerErrorHandler(callback, "") 388 389libxml2.setEntityLoader(resolver) 390root = testsuite.getRootElement() 391if root.name != 'testSuite': 392 print "%s doesn't start with a testSuite element, aborting" % (CONF) 393 sys.exit(1) 394if quiet == 0: 395 print "Running Relax NG testsuite" 396handle_testSuite(root) 397 398if quiet == 0: 399 print "\nTOTAL:\n" 400if quiet == 0 or nb_schemas_failed != 0: 401 print "found %d test schemas: %d success %d failures" % ( 402 nb_schemas_tests, nb_schemas_success, nb_schemas_failed) 403if quiet == 0 or nb_instances_failed != 0: 404 print "found %d test instances: %d success %d failures" % ( 405 nb_instances_tests, nb_instances_success, nb_instances_failed) 406 407 408testsuite.freeDoc() 409 410# Memory debug specific 411libxml2.relaxNGCleanupTypes() 412libxml2.cleanupParser() 413if libxml2.debugMemory(1) == 0: 414 if quiet == 0: 415 print "OK" 416else: 417 print "Memory leak %d bytes" % (libxml2.debugMemory(1)) 418 libxml2.dumpMemory() 419