Home | History | Annotate | Download | only in libxml2
      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