check-xsddata-test-suite.py 10 KB

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