check-xml-test-suite.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. #!/usr/bin/python
  2. import sys
  3. import time
  4. import os
  5. import string
  6. sys.path.insert(0, "python")
  7. import libxml2
  8. test_nr = 0
  9. test_succeed = 0
  10. test_failed = 0
  11. test_error = 0
  12. #
  13. # the testsuite description
  14. #
  15. CONF="xml-test-suite/xmlconf/xmlconf.xml"
  16. LOG="check-xml-test-suite.log"
  17. log = open(LOG, "w")
  18. #
  19. # Error and warning handlers
  20. #
  21. error_nr = 0
  22. error_msg = ''
  23. def errorHandler(ctx, str):
  24. global error_nr
  25. global error_msg
  26. error_nr = error_nr + 1
  27. if len(error_msg) < 300:
  28. if len(error_msg) == 0 or error_msg[-1] == '\n':
  29. error_msg = error_msg + " >>" + str
  30. else:
  31. error_msg = error_msg + str
  32. libxml2.registerErrorHandler(errorHandler, None)
  33. #warning_nr = 0
  34. #warning = ''
  35. #def warningHandler(ctx, str):
  36. # global warning_nr
  37. # global warning
  38. #
  39. # warning_nr = warning_nr + 1
  40. # warning = warning + str
  41. #
  42. #libxml2.registerWarningHandler(warningHandler, None)
  43. #
  44. # Used to load the XML testsuite description
  45. #
  46. def loadNoentDoc(filename):
  47. ctxt = libxml2.createFileParserCtxt(filename)
  48. if ctxt == None:
  49. return None
  50. ctxt.replaceEntities(1)
  51. ctxt.parseDocument()
  52. try:
  53. doc = ctxt.doc()
  54. except:
  55. doc = None
  56. if ctxt.wellFormed() != 1:
  57. doc.freeDoc()
  58. return None
  59. return doc
  60. #
  61. # The conformance testing routines
  62. #
  63. def testNotWf(filename, id):
  64. global error_nr
  65. global error_msg
  66. global log
  67. error_nr = 0
  68. error_msg = ''
  69. ctxt = libxml2.createFileParserCtxt(filename)
  70. if ctxt == None:
  71. return -1
  72. ret = ctxt.parseDocument()
  73. try:
  74. doc = ctxt.doc()
  75. except:
  76. doc = None
  77. if doc != None:
  78. doc.freeDoc()
  79. if ret == 0 or ctxt.wellFormed() != 0:
  80. print "%s: error: Well Formedness error not detected" % (id)
  81. log.write("%s: error: Well Formedness error not detected\n" % (id))
  82. return 0
  83. return 1
  84. def testNotWfEnt(filename, id):
  85. global error_nr
  86. global error_msg
  87. global log
  88. error_nr = 0
  89. error_msg = ''
  90. ctxt = libxml2.createFileParserCtxt(filename)
  91. if ctxt == None:
  92. return -1
  93. ctxt.replaceEntities(1)
  94. ret = ctxt.parseDocument()
  95. try:
  96. doc = ctxt.doc()
  97. except:
  98. doc = None
  99. if doc != None:
  100. doc.freeDoc()
  101. if ret == 0 or ctxt.wellFormed() != 0:
  102. print "%s: error: Well Formedness error not detected" % (id)
  103. log.write("%s: error: Well Formedness error not detected\n" % (id))
  104. return 0
  105. return 1
  106. def testNotWfEntDtd(filename, id):
  107. global error_nr
  108. global error_msg
  109. global log
  110. error_nr = 0
  111. error_msg = ''
  112. ctxt = libxml2.createFileParserCtxt(filename)
  113. if ctxt == None:
  114. return -1
  115. ctxt.replaceEntities(1)
  116. ctxt.loadSubset(1)
  117. ret = ctxt.parseDocument()
  118. try:
  119. doc = ctxt.doc()
  120. except:
  121. doc = None
  122. if doc != None:
  123. doc.freeDoc()
  124. if ret == 0 or ctxt.wellFormed() != 0:
  125. print "%s: error: Well Formedness error not detected" % (id)
  126. log.write("%s: error: Well Formedness error not detected\n" % (id))
  127. return 0
  128. return 1
  129. def testWfEntDtd(filename, id):
  130. global error_nr
  131. global error_msg
  132. global log
  133. error_nr = 0
  134. error_msg = ''
  135. ctxt = libxml2.createFileParserCtxt(filename)
  136. if ctxt == None:
  137. return -1
  138. ctxt.replaceEntities(1)
  139. ctxt.loadSubset(1)
  140. ret = ctxt.parseDocument()
  141. try:
  142. doc = ctxt.doc()
  143. except:
  144. doc = None
  145. if doc == None or ret != 0 or ctxt.wellFormed() == 0:
  146. print "%s: error: wrongly failed to parse the document" % (id)
  147. log.write("%s: error: wrongly failed to parse the document\n" % (id))
  148. if doc != None:
  149. doc.freeDoc()
  150. return 0
  151. if error_nr != 0:
  152. print "%s: warning: WF document generated an error msg" % (id)
  153. log.write("%s: error: WF document generated an error msg\n" % (id))
  154. doc.freeDoc()
  155. return 2
  156. doc.freeDoc()
  157. return 1
  158. def testError(filename, id):
  159. global error_nr
  160. global error_msg
  161. global log
  162. error_nr = 0
  163. error_msg = ''
  164. ctxt = libxml2.createFileParserCtxt(filename)
  165. if ctxt == None:
  166. return -1
  167. ctxt.replaceEntities(1)
  168. ctxt.loadSubset(1)
  169. ret = ctxt.parseDocument()
  170. try:
  171. doc = ctxt.doc()
  172. except:
  173. doc = None
  174. if doc != None:
  175. doc.freeDoc()
  176. if ctxt.wellFormed() == 0:
  177. print "%s: warning: failed to parse the document but accepted" % (id)
  178. log.write("%s: warning: failed to parse the document but accepte\n" % (id))
  179. return 2
  180. if error_nr != 0:
  181. print "%s: warning: WF document generated an error msg" % (id)
  182. log.write("%s: error: WF document generated an error msg\n" % (id))
  183. return 2
  184. return 1
  185. def testInvalid(filename, id):
  186. global error_nr
  187. global error_msg
  188. global log
  189. error_nr = 0
  190. error_msg = ''
  191. ctxt = libxml2.createFileParserCtxt(filename)
  192. if ctxt == None:
  193. return -1
  194. ctxt.validate(1)
  195. ret = ctxt.parseDocument()
  196. try:
  197. doc = ctxt.doc()
  198. except:
  199. doc = None
  200. valid = ctxt.isValid()
  201. if doc == None:
  202. print "%s: error: wrongly failed to parse the document" % (id)
  203. log.write("%s: error: wrongly failed to parse the document\n" % (id))
  204. return 0
  205. if valid == 1:
  206. print "%s: error: Validity error not detected" % (id)
  207. log.write("%s: error: Validity error not detected\n" % (id))
  208. doc.freeDoc()
  209. return 0
  210. if error_nr == 0:
  211. print "%s: warning: Validity error not reported" % (id)
  212. log.write("%s: warning: Validity error not reported\n" % (id))
  213. doc.freeDoc()
  214. return 2
  215. doc.freeDoc()
  216. return 1
  217. def testValid(filename, id):
  218. global error_nr
  219. global error_msg
  220. error_nr = 0
  221. error_msg = ''
  222. ctxt = libxml2.createFileParserCtxt(filename)
  223. if ctxt == None:
  224. return -1
  225. ctxt.validate(1)
  226. ctxt.parseDocument()
  227. try:
  228. doc = ctxt.doc()
  229. except:
  230. doc = None
  231. valid = ctxt.isValid()
  232. if doc == None:
  233. print "%s: error: wrongly failed to parse the document" % (id)
  234. log.write("%s: error: wrongly failed to parse the document\n" % (id))
  235. return 0
  236. if valid != 1:
  237. print "%s: error: Validity check failed" % (id)
  238. log.write("%s: error: Validity check failed\n" % (id))
  239. doc.freeDoc()
  240. return 0
  241. if error_nr != 0 or valid != 1:
  242. print "%s: warning: valid document reported an error" % (id)
  243. log.write("%s: warning: valid document reported an error\n" % (id))
  244. doc.freeDoc()
  245. return 2
  246. doc.freeDoc()
  247. return 1
  248. def runTest(test):
  249. global test_nr
  250. global test_succeed
  251. global test_failed
  252. global error_msg
  253. global log
  254. uri = test.prop('URI')
  255. id = test.prop('ID')
  256. if uri == None:
  257. print "Test without ID:", uri
  258. return -1
  259. if id == None:
  260. print "Test without URI:", id
  261. return -1
  262. base = test.getBase(None)
  263. URI = libxml2.buildURI(uri, base)
  264. if os.access(URI, os.R_OK) == 0:
  265. print "Test %s missing: base %s uri %s" % (URI, base, uri)
  266. return -1
  267. type = test.prop('TYPE')
  268. if type == None:
  269. print "Test %s missing TYPE" % (id)
  270. return -1
  271. extra = None
  272. if type == "invalid":
  273. res = testInvalid(URI, id)
  274. elif type == "valid":
  275. res = testValid(URI, id)
  276. elif type == "not-wf":
  277. extra = test.prop('ENTITIES')
  278. # print URI
  279. #if extra == None:
  280. # res = testNotWfEntDtd(URI, id)
  281. #elif extra == 'none':
  282. # res = testNotWf(URI, id)
  283. #elif extra == 'general':
  284. # res = testNotWfEnt(URI, id)
  285. #elif extra == 'both' or extra == 'parameter':
  286. res = testNotWfEntDtd(URI, id)
  287. #else:
  288. # print "Unknow value %s for an ENTITIES test value" % (extra)
  289. # return -1
  290. elif type == "error":
  291. res = testError(URI, id)
  292. else:
  293. # TODO skipped for now
  294. return -1
  295. test_nr = test_nr + 1
  296. if res > 0:
  297. test_succeed = test_succeed + 1
  298. elif res == 0:
  299. test_failed = test_failed + 1
  300. elif res < 0:
  301. test_error = test_error + 1
  302. # Log the ontext
  303. if res != 1:
  304. log.write(" File: %s\n" % (URI))
  305. content = string.strip(test.content)
  306. while content[-1] == '\n':
  307. content = content[0:-1]
  308. if extra != None:
  309. log.write(" %s:%s:%s\n" % (type, extra, content))
  310. else:
  311. log.write(" %s:%s\n\n" % (type, content))
  312. if error_msg != '':
  313. log.write(" ----\n%s ----\n" % (error_msg))
  314. error_msg = ''
  315. log.write("\n")
  316. return 0
  317. def runTestCases(case):
  318. profile = case.prop('PROFILE')
  319. if profile != None and \
  320. string.find(profile, "IBM XML Conformance Test Suite - Production") < 0:
  321. print "=>", profile
  322. test = case.children
  323. while test != None:
  324. if test.name == 'TEST':
  325. runTest(test)
  326. if test.name == 'TESTCASES':
  327. runTestCases(test)
  328. test = test.next
  329. conf = loadNoentDoc(CONF)
  330. if conf == None:
  331. print "Unable to load %s" % CONF
  332. sys.exit(1)
  333. testsuite = conf.getRootElement()
  334. if testsuite.name != 'TESTSUITE':
  335. print "Expecting TESTSUITE root element: aborting"
  336. sys.exit(1)
  337. profile = testsuite.prop('PROFILE')
  338. if profile != None:
  339. print profile
  340. start = time.time()
  341. case = testsuite.children
  342. while case != None:
  343. if case.name == 'TESTCASES':
  344. old_test_nr = test_nr
  345. old_test_succeed = test_succeed
  346. old_test_failed = test_failed
  347. old_test_error = test_error
  348. runTestCases(case)
  349. print " Ran %d tests: %d suceeded, %d failed and %d generated an error" % (
  350. test_nr - old_test_nr, test_succeed - old_test_succeed,
  351. test_failed - old_test_failed, test_error - old_test_error)
  352. case = case.next
  353. conf.freeDoc()
  354. log.close()
  355. print "Ran %d tests: %d suceeded, %d failed and %d generated an error in %.2f s." % (
  356. test_nr, test_succeed, test_failed, test_error, time.time() - start)