Blame check-relaxng-test-suite.py

Packit 423ecb
#!/usr/bin/python
Packit 423ecb
import sys
Packit 423ecb
import time
Packit 423ecb
import os
Packit 423ecb
import string
Packit 423ecb
import StringIO
Packit 423ecb
sys.path.insert(0, "python")
Packit 423ecb
import libxml2
Packit 423ecb
Packit 423ecb
# Memory debug specific
Packit 423ecb
libxml2.debugMemory(1)
Packit 423ecb
debug = 0
Packit 423ecb
verbose = 0
Packit 423ecb
quiet = 1
Packit 423ecb
Packit 423ecb
#
Packit 423ecb
# the testsuite description
Packit 423ecb
#
Packit 423ecb
CONF=os.path.join(os.path.dirname(__file__), "test/relaxng/OASIS/spectest.xml")
Packit 423ecb
LOG="check-relaxng-test-suite.log"
Packit 423ecb
RES="relaxng-test-results.xml"
Packit 423ecb
Packit 423ecb
log = open(LOG, "w")
Packit 423ecb
nb_schemas_tests = 0
Packit 423ecb
nb_schemas_success = 0
Packit 423ecb
nb_schemas_failed = 0
Packit 423ecb
nb_instances_tests = 0
Packit 423ecb
nb_instances_success = 0
Packit 423ecb
nb_instances_failed = 0
Packit 423ecb
Packit 423ecb
libxml2.lineNumbersDefault(1)
Packit 423ecb
#
Packit 423ecb
# Error and warnng callbacks
Packit 423ecb
#
Packit 423ecb
def callback(ctx, str):
Packit 423ecb
    global log
Packit 423ecb
    log.write("%s%s" % (ctx, str))
Packit 423ecb
Packit 423ecb
libxml2.registerErrorHandler(callback, "")
Packit 423ecb
Packit 423ecb
#
Packit 423ecb
# Resolver callback
Packit 423ecb
#
Packit 423ecb
resources = {}
Packit 423ecb
def resolver(URL, ID, ctxt):
Packit 423ecb
    global resources
Packit 423ecb
Packit 423ecb
    if string.find(URL, '#') != -1:
Packit 423ecb
        URL = URL[0:string.find(URL, '#')]
Packit 423ecb
    if resources.has_key(URL):
Packit 423ecb
        return(StringIO.StringIO(resources[URL]))
Packit 423ecb
    log.write("Resolver failure: asked %s\n" % (URL))
Packit 423ecb
    log.write("resources: %s\n" % (resources))
Packit 423ecb
    return None
Packit 423ecb
Packit 423ecb
#
Packit 423ecb
# Load the previous results
Packit 423ecb
#
Packit 423ecb
#results = {}
Packit 423ecb
#previous = {}
Packit 423ecb
#
Packit 423ecb
#try:
Packit 423ecb
#    res = libxml2.parseFile(RES)
Packit 423ecb
#except:
Packit 423ecb
#    log.write("Could not parse %s" % (RES))
Packit 423ecb
    
Packit 423ecb
#
Packit 423ecb
# handle a valid instance
Packit 423ecb
#
Packit 423ecb
def handle_valid(node, schema):
Packit 423ecb
    global log
Packit 423ecb
    global nb_instances_success
Packit 423ecb
    global nb_instances_failed
Packit 423ecb
Packit 423ecb
    instance = ""
Packit 423ecb
    child = node.children
Packit 423ecb
    while child != None:
Packit 423ecb
        if child.type != 'text':
Packit 423ecb
	    instance = instance + child.serialize()
Packit 423ecb
	child = child.next
Packit 423ecb
Packit 423ecb
    try:
Packit 423ecb
	doc = libxml2.parseDoc(instance)
Packit 423ecb
    except:
Packit 423ecb
        doc = None
Packit 423ecb
Packit 423ecb
    if doc == None:
Packit 423ecb
        log.write("\nFailed to parse correct instance:\n-----\n")
Packit 423ecb
	log.write(instance)
Packit 423ecb
        log.write("\n-----\n")
Packit 423ecb
	nb_instances_failed = nb_instances_failed + 1
Packit 423ecb
	return
Packit 423ecb
Packit 423ecb
    try:
Packit 423ecb
        ctxt = schema.relaxNGNewValidCtxt()
Packit 423ecb
	ret = doc.relaxNGValidateDoc(ctxt)
Packit 423ecb
    except:
Packit 423ecb
        ret = -1
Packit 423ecb
    if ret != 0:
Packit 423ecb
        log.write("\nFailed to validate correct instance:\n-----\n")
Packit 423ecb
	log.write(instance)
Packit 423ecb
        log.write("\n-----\n")
Packit 423ecb
	nb_instances_failed = nb_instances_failed + 1
Packit 423ecb
    else:
Packit 423ecb
	nb_instances_success = nb_instances_success + 1
Packit 423ecb
    doc.freeDoc()
Packit 423ecb
Packit 423ecb
#
Packit 423ecb
# handle an invalid instance
Packit 423ecb
#
Packit 423ecb
def handle_invalid(node, schema):
Packit 423ecb
    global log
Packit 423ecb
    global nb_instances_success
Packit 423ecb
    global nb_instances_failed
Packit 423ecb
Packit 423ecb
    instance = ""
Packit 423ecb
    child = node.children
Packit 423ecb
    while child != None:
Packit 423ecb
        if child.type != 'text':
Packit 423ecb
	    instance = instance + child.serialize()
Packit 423ecb
	child = child.next
Packit 423ecb
Packit 423ecb
    try:
Packit 423ecb
	doc = libxml2.parseDoc(instance)
Packit 423ecb
    except:
Packit 423ecb
        doc = None
Packit 423ecb
Packit 423ecb
    if doc == None:
Packit 423ecb
        log.write("\nStrange: failed to parse incorrect instance:\n-----\n")
Packit 423ecb
	log.write(instance)
Packit 423ecb
        log.write("\n-----\n")
Packit 423ecb
	return
Packit 423ecb
Packit 423ecb
    try:
Packit 423ecb
        ctxt = schema.relaxNGNewValidCtxt()
Packit 423ecb
	ret = doc.relaxNGValidateDoc(ctxt)
Packit 423ecb
    except:
Packit 423ecb
        ret = -1
Packit 423ecb
    if ret == 0:
Packit 423ecb
        log.write("\nFailed to detect validation problem in instance:\n-----\n")
Packit 423ecb
	log.write(instance)
Packit 423ecb
        log.write("\n-----\n")
Packit 423ecb
	nb_instances_failed = nb_instances_failed + 1
Packit 423ecb
    else:
Packit 423ecb
	nb_instances_success = nb_instances_success + 1
Packit 423ecb
    doc.freeDoc()
Packit 423ecb
Packit 423ecb
#
Packit 423ecb
# handle an incorrect test
Packit 423ecb
#
Packit 423ecb
def handle_correct(node):
Packit 423ecb
    global log
Packit 423ecb
    global nb_schemas_success
Packit 423ecb
    global nb_schemas_failed
Packit 423ecb
Packit 423ecb
    schema = ""
Packit 423ecb
    child = node.children
Packit 423ecb
    while child != None:
Packit 423ecb
        if child.type != 'text':
Packit 423ecb
	    schema = schema + child.serialize()
Packit 423ecb
	child = child.next
Packit 423ecb
Packit 423ecb
    try:
Packit 423ecb
	rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema))
Packit 423ecb
	rngs = rngp.relaxNGParse()
Packit 423ecb
    except:
Packit 423ecb
        rngs = None
Packit 423ecb
    if rngs == None:
Packit 423ecb
        log.write("\nFailed to compile correct schema:\n-----\n")
Packit 423ecb
	log.write(schema)
Packit 423ecb
        log.write("\n-----\n")
Packit 423ecb
	nb_schemas_failed = nb_schemas_failed + 1
Packit 423ecb
    else:
Packit 423ecb
	nb_schemas_success = nb_schemas_success + 1
Packit 423ecb
    return rngs
Packit 423ecb
        
Packit 423ecb
def handle_incorrect(node):
Packit 423ecb
    global log
Packit 423ecb
    global nb_schemas_success
Packit 423ecb
    global nb_schemas_failed
Packit 423ecb
Packit 423ecb
    schema = ""
Packit 423ecb
    child = node.children
Packit 423ecb
    while child != None:
Packit 423ecb
        if child.type != 'text':
Packit 423ecb
	    schema = schema + child.serialize()
Packit 423ecb
	child = child.next
Packit 423ecb
Packit 423ecb
    try:
Packit 423ecb
	rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema))
Packit 423ecb
	rngs = rngp.relaxNGParse()
Packit 423ecb
    except:
Packit 423ecb
        rngs = None
Packit 423ecb
    if rngs != None:
Packit 423ecb
        log.write("\nFailed to detect schema error in:\n-----\n")
Packit 423ecb
	log.write(schema)
Packit 423ecb
        log.write("\n-----\n")
Packit 423ecb
	nb_schemas_failed = nb_schemas_failed + 1
Packit 423ecb
    else:
Packit 423ecb
#	log.write("\nSuccess detecting schema error in:\n-----\n")
Packit 423ecb
#	log.write(schema)
Packit 423ecb
#	log.write("\n-----\n")
Packit 423ecb
	nb_schemas_success = nb_schemas_success + 1
Packit 423ecb
    return None
Packit 423ecb
Packit 423ecb
#
Packit 423ecb
# resource handling: keep a dictionary of URL->string mappings
Packit 423ecb
#
Packit 423ecb
def handle_resource(node, dir):
Packit 423ecb
    global resources
Packit 423ecb
Packit 423ecb
    try:
Packit 423ecb
	name = node.prop('name')
Packit 423ecb
    except:
Packit 423ecb
        name = None
Packit 423ecb
Packit 423ecb
    if name == None or name == '':
Packit 423ecb
        log.write("resource has no name")
Packit 423ecb
	return;
Packit 423ecb
        
Packit 423ecb
    if dir != None:
Packit 423ecb
#        name = libxml2.buildURI(name, dir)
Packit 423ecb
        name = dir + '/' + name
Packit 423ecb
Packit 423ecb
    res = ""
Packit 423ecb
    child = node.children
Packit 423ecb
    while child != None:
Packit 423ecb
        if child.type != 'text':
Packit 423ecb
	    res = res + child.serialize()
Packit 423ecb
	child = child.next
Packit 423ecb
    resources[name] = res
Packit 423ecb
Packit 423ecb
#
Packit 423ecb
# dir handling: pseudo directory resources
Packit 423ecb
#
Packit 423ecb
def handle_dir(node, dir):
Packit 423ecb
    try:
Packit 423ecb
	name = node.prop('name')
Packit 423ecb
    except:
Packit 423ecb
        name = None
Packit 423ecb
Packit 423ecb
    if name == None or name == '':
Packit 423ecb
        log.write("resource has no name")
Packit 423ecb
	return;
Packit 423ecb
        
Packit 423ecb
    if dir != None:
Packit 423ecb
#        name = libxml2.buildURI(name, dir)
Packit 423ecb
        name = dir + '/' + name
Packit 423ecb
Packit 423ecb
    dirs = node.xpathEval('dir')
Packit 423ecb
    for dir in dirs:
Packit 423ecb
        handle_dir(dir, name)
Packit 423ecb
    res = node.xpathEval('resource')
Packit 423ecb
    for r in res:
Packit 423ecb
        handle_resource(r, name)
Packit 423ecb
Packit 423ecb
#
Packit 423ecb
# handle a testCase element
Packit 423ecb
#
Packit 423ecb
def handle_testCase(node):
Packit 423ecb
    global nb_schemas_tests
Packit 423ecb
    global nb_instances_tests
Packit 423ecb
    global resources
Packit 423ecb
Packit 423ecb
    sections = node.xpathEval('string(section)')
Packit 423ecb
    log.write("\n    ======== test %d line %d section %s ==========\n" % (
Packit 423ecb
Packit 423ecb
              nb_schemas_tests, node.lineNo(), sections))
Packit 423ecb
    resources = {}
Packit 423ecb
    if debug:
Packit 423ecb
        print "test %d line %d" % (nb_schemas_tests, node.lineNo())
Packit 423ecb
Packit 423ecb
    dirs = node.xpathEval('dir')
Packit 423ecb
    for dir in dirs:
Packit 423ecb
        handle_dir(dir, None)
Packit 423ecb
    res = node.xpathEval('resource')
Packit 423ecb
    for r in res:
Packit 423ecb
        handle_resource(r, None)
Packit 423ecb
Packit 423ecb
    tsts = node.xpathEval('incorrect')
Packit 423ecb
    if tsts != []:
Packit 423ecb
        if len(tsts) != 1:
Packit 423ecb
	    print "warning test line %d has more than one <incorrect> example" %(node.lineNo())
Packit 423ecb
	schema = handle_incorrect(tsts[0])
Packit 423ecb
    else:
Packit 423ecb
        tsts = node.xpathEval('correct')
Packit 423ecb
	if tsts != []:
Packit 423ecb
	    if len(tsts) != 1:
Packit 423ecb
		print "warning test line %d has more than one <correct> example"% (node.lineNo())
Packit 423ecb
	    schema = handle_correct(tsts[0])
Packit 423ecb
	else:
Packit 423ecb
	    print "warning <testCase> line %d has no <correct> nor <incorrect> child" % (node.lineNo())
Packit 423ecb
Packit 423ecb
    nb_schemas_tests = nb_schemas_tests + 1;
Packit 423ecb
    
Packit 423ecb
    valids = node.xpathEval('valid')
Packit 423ecb
    invalids = node.xpathEval('invalid')
Packit 423ecb
    nb_instances_tests = nb_instances_tests + len(valids) + len(invalids)
Packit 423ecb
    if schema != None:
Packit 423ecb
        for valid in valids:
Packit 423ecb
	    handle_valid(valid, schema)
Packit 423ecb
        for invalid in invalids:
Packit 423ecb
	    handle_invalid(invalid, schema)
Packit 423ecb
Packit 423ecb
Packit 423ecb
#
Packit 423ecb
# handle a testSuite element
Packit 423ecb
#
Packit 423ecb
def handle_testSuite(node, level = 0):
Packit 423ecb
    global nb_schemas_tests, nb_schemas_success, nb_schemas_failed
Packit 423ecb
    global nb_instances_tests, nb_instances_success, nb_instances_failed
Packit 423ecb
    global quiet
Packit 423ecb
    if level >= 1:
Packit 423ecb
	old_schemas_tests = nb_schemas_tests
Packit 423ecb
	old_schemas_success = nb_schemas_success
Packit 423ecb
	old_schemas_failed = nb_schemas_failed
Packit 423ecb
	old_instances_tests = nb_instances_tests
Packit 423ecb
	old_instances_success = nb_instances_success
Packit 423ecb
	old_instances_failed = nb_instances_failed
Packit 423ecb
Packit 423ecb
    docs = node.xpathEval('documentation')
Packit 423ecb
    authors = node.xpathEval('author')
Packit 423ecb
    if docs != []:
Packit 423ecb
        msg = ""
Packit 423ecb
        for doc in docs:
Packit 423ecb
	    msg = msg + doc.content + " "
Packit 423ecb
	if authors != []:
Packit 423ecb
	    msg = msg + "written by "
Packit 423ecb
	    for author in authors:
Packit 423ecb
	        msg = msg + author.content + " "
Packit 423ecb
	if quiet == 0:
Packit 423ecb
	    print msg
Packit 423ecb
    sections = node.xpathEval('section')
Packit 423ecb
    if sections != [] and level <= 0:
Packit 423ecb
        msg = ""
Packit 423ecb
        for section in sections:
Packit 423ecb
	    msg = msg + section.content + " "
Packit 423ecb
	if quiet == 0:
Packit 423ecb
	    print "Tests for section %s" % (msg)
Packit 423ecb
    for test in node.xpathEval('testCase'):
Packit 423ecb
        handle_testCase(test)
Packit 423ecb
    for test in node.xpathEval('testSuite'):
Packit 423ecb
        handle_testSuite(test, level + 1)
Packit 423ecb
	        
Packit 423ecb
Packit 423ecb
    if verbose and level >= 1 and sections != []:
Packit 423ecb
        msg = ""
Packit 423ecb
        for section in sections:
Packit 423ecb
	    msg = msg + section.content + " "
Packit 423ecb
        print "Result of tests for section %s" % (msg)
Packit 423ecb
        if nb_schemas_tests != old_schemas_tests:
Packit 423ecb
	    print "found %d test schemas: %d success %d failures" % (
Packit 423ecb
		  nb_schemas_tests - old_schemas_tests,
Packit 423ecb
		  nb_schemas_success - old_schemas_success,
Packit 423ecb
		  nb_schemas_failed - old_schemas_failed)
Packit 423ecb
	if nb_instances_tests != old_instances_tests:
Packit 423ecb
	    print "found %d test instances: %d success %d failures" % (
Packit 423ecb
		  nb_instances_tests - old_instances_tests,
Packit 423ecb
		  nb_instances_success - old_instances_success,
Packit 423ecb
		  nb_instances_failed - old_instances_failed)
Packit 423ecb
#
Packit 423ecb
# Parse the conf file
Packit 423ecb
#
Packit 423ecb
libxml2.substituteEntitiesDefault(1);
Packit 423ecb
testsuite = libxml2.parseFile(CONF)
Packit 423ecb
libxml2.setEntityLoader(resolver)
Packit 423ecb
root = testsuite.getRootElement()
Packit 423ecb
if root.name != 'testSuite':
Packit 423ecb
    print "%s doesn't start with a testSuite element, aborting" % (CONF)
Packit 423ecb
    sys.exit(1)
Packit 423ecb
if quiet == 0:
Packit 423ecb
    print "Running Relax NG testsuite"
Packit 423ecb
handle_testSuite(root)
Packit 423ecb
Packit 423ecb
if quiet == 0:
Packit 423ecb
    print "\nTOTAL:\n"
Packit 423ecb
if quiet == 0 or nb_schemas_failed != 0:
Packit 423ecb
    print "found %d test schemas: %d success %d failures" % (
Packit 423ecb
      nb_schemas_tests, nb_schemas_success, nb_schemas_failed)
Packit 423ecb
if quiet == 0 or nb_instances_failed != 0:
Packit 423ecb
    print "found %d test instances: %d success %d failures" % (
Packit 423ecb
      nb_instances_tests, nb_instances_success, nb_instances_failed)
Packit 423ecb
Packit 423ecb
testsuite.freeDoc()
Packit 423ecb
Packit 423ecb
# Memory debug specific
Packit 423ecb
libxml2.relaxNGCleanupTypes()
Packit 423ecb
libxml2.cleanupParser()
Packit 423ecb
if libxml2.debugMemory(1) == 0:
Packit 423ecb
    if quiet == 0:
Packit 423ecb
	print "OK"
Packit 423ecb
else:
Packit 423ecb
    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
Packit 423ecb
    libxml2.dumpMemory()