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