1 #!/usr/bin/python 2 import sys 3 import time 4 import os 5 import string 6 import StringIO 7 sys.path.insert(0, "python") 8 import libxml2 9 10 # Memory debug specific 11 libxml2.debugMemory(1) 12 debug = 0 13 quiet = 1 14 15 # 16 # the testsuite description 17 # 18 CONF=os.path.join(os.path.dirname(__file__), "test/relaxng/testsuite.xml") 19 LOG="check-relaxng-test-suite2.log" 20 21 log = open(LOG, "w") 22 nb_schemas_tests = 0 23 nb_schemas_success = 0 24 nb_schemas_failed = 0 25 nb_instances_tests = 0 26 nb_instances_success = 0 27 nb_instances_failed = 0 28 29 libxml2.lineNumbersDefault(1) 30 # 31 # Resolver callback 32 # 33 resources = {} 34 def 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 # 57 def 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 # 110 def 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 # 165 def 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 191 def 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 # 223 def 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 # 250 def 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 # 274 def 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 # 323 def 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 # 377 libxml2.substituteEntitiesDefault(1); 378 testsuite = libxml2.parseFile(CONF) 379 380 # 381 # Error and warnng callbacks 382 # 383 def callback(ctx, str): 384 global log 385 log.write("%s%s" % (ctx, str)) 386 387 libxml2.registerErrorHandler(callback, "") 388 389 libxml2.setEntityLoader(resolver) 390 root = testsuite.getRootElement() 391 if root.name != 'testSuite': 392 print "%s doesn't start with a testSuite element, aborting" % (CONF) 393 sys.exit(1) 394 if quiet == 0: 395 print "Running Relax NG testsuite" 396 handle_testSuite(root) 397 398 if quiet == 0: 399 print "\nTOTAL:\n" 400 if 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) 403 if 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 408 testsuite.freeDoc() 409 410 # Memory debug specific 411 libxml2.relaxNGCleanupTypes() 412 libxml2.cleanupParser() 413 if libxml2.debugMemory(1) == 0: 414 if quiet == 0: 415 print "OK" 416 else: 417 print "Memory leak %d bytes" % (libxml2.debugMemory(1)) 418 libxml2.dumpMemory() 419