xstc.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. #!/usr/bin/env python
  2. #
  3. # This is the MS subset of the W3C test suite for XML Schemas.
  4. # This file is generated from the MS W3c test suite description file.
  5. #
  6. import sys, os
  7. import exceptions, optparse
  8. import libxml2
  9. opa = optparse.OptionParser()
  10. opa.add_option("-b", "--base", action="store", type="string", dest="baseDir",
  11. default="",
  12. help="""The base directory; i.e. the parent folder of the
  13. "nisttest", "suntest" and "msxsdtest" directories.""")
  14. opa.add_option("-o", "--out", action="store", type="string", dest="logFile",
  15. default="test.log",
  16. help="The filepath of the log file to be created")
  17. opa.add_option("--log", action="store_true", dest="enableLog",
  18. default=False,
  19. help="Create the log file")
  20. opa.add_option("--no-test-out", action="store_true", dest="disableTestStdOut",
  21. default=False,
  22. help="Don't output test results")
  23. opa.add_option("-s", "--silent", action="store_true", dest="silent", default=False,
  24. help="Disables display of all tests")
  25. opa.add_option("-v", "--verbose", action="store_true", dest="verbose",
  26. default=False,
  27. help="Displays all tests (only if --silent is not set)")
  28. opa.add_option("-x", "--max", type="int", dest="maxTestCount",
  29. default="-1",
  30. help="The maximum number of tests to be run")
  31. opa.add_option("-t", "--test", type="string", dest="singleTest",
  32. default=None,
  33. help="Runs the specified test only")
  34. opa.add_option("--tsw", "--test-starts-with", type="string", dest="testStartsWith",
  35. default=None,
  36. help="Runs the specified test(s), starting with the given string")
  37. opa.add_option("--rieo", "--report-internal-errors-only", action="store_true",
  38. dest="reportInternalErrOnly", default=False,
  39. help="Display erroneous tests of type 'internal' only")
  40. opa.add_option("--rueo", "--report-unimplemented-errors-only", action="store_true",
  41. dest="reportUnimplErrOnly", default=False,
  42. help="Display erroneous tests of type 'unimplemented' only")
  43. opa.add_option("--rmleo", "--report-mem-leak-errors-only", action="store_true",
  44. dest="reportMemLeakErrOnly", default=False,
  45. help="Display erroneous tests of type 'memory leak' only")
  46. opa.add_option("-c", "--combines", type="string", dest="combines",
  47. default=None,
  48. help="Combines to be run (all if omitted)")
  49. opa.add_option("--csw", "--csw", type="string", dest="combineStartsWith",
  50. default=None,
  51. help="Combines to be run (all if omitted)")
  52. opa.add_option("--rc", "--report-combines", action="store_true",
  53. dest="reportCombines", default=False,
  54. help="Display combine reports")
  55. opa.add_option("--rec", "--report-err-combines", action="store_true",
  56. dest="reportErrCombines", default=False,
  57. help="Display erroneous combine reports only")
  58. opa.add_option("--debug", action="store_true",
  59. dest="debugEnabled", default=False,
  60. help="Displays debug messages")
  61. opa.add_option("--info", action="store_true",
  62. dest="info", default=False,
  63. help="Displays info on the suite only. Does not run any test.")
  64. opa.add_option("--sax", action="store_true",
  65. dest="validationSAX", default=False,
  66. help="Use SAX2-driven validation.")
  67. opa.add_option("--tn", action="store_true",
  68. dest="displayTestName", default=False,
  69. help="Display the test name in every case.")
  70. (options, args) = opa.parse_args()
  71. if options.combines is not None:
  72. options.combines = options.combines.split()
  73. ################################################
  74. # The vars below are not intended to be changed.
  75. #
  76. msgSchemaNotValidButShould = "The schema should be valid."
  77. msgSchemaValidButShouldNot = "The schema should be invalid."
  78. msgInstanceNotValidButShould = "The instance should be valid."
  79. msgInstanceValidButShouldNot = "The instance should be invalid."
  80. vendorNIST = "NIST"
  81. vendorNIST_2 = "NIST-2"
  82. vendorSUN = "SUN"
  83. vendorMS = "MS"
  84. ###################
  85. # Helper functions.
  86. #
  87. vendor = None
  88. def handleError(test, msg):
  89. global options
  90. if not options.silent:
  91. test.addLibLog("'%s' LIB: %s" % (test.name, msg))
  92. if msg.find("Unimplemented") > -1:
  93. test.failUnimplemented()
  94. elif msg.find("Internal") > -1:
  95. test.failInternal()
  96. def fixFileNames(fileName):
  97. if (fileName is None) or (fileName == ""):
  98. return ""
  99. dirs = fileName.split("/")
  100. if dirs[1] != "Tests":
  101. fileName = os.path.join(".", "Tests")
  102. for dir in dirs[1:]:
  103. fileName = os.path.join(fileName, dir)
  104. return fileName
  105. class XSTCTestGroup:
  106. def __init__(self, name, schemaFileName, descr):
  107. global vendor, vendorNIST_2
  108. self.name = name
  109. self.descr = descr
  110. self.mainSchema = True
  111. self.schemaFileName = fixFileNames(schemaFileName)
  112. self.schemaParsed = False
  113. self.schemaTried = False
  114. def setSchema(self, schemaFileName, parsed):
  115. if not self.mainSchema:
  116. return
  117. self.mainSchema = False
  118. self.schemaParsed = parsed
  119. self.schemaTried = True
  120. class XSTCTestCase:
  121. # <!-- groupName, Name, Accepted, File, Val, Descr
  122. def __init__(self, isSchema, groupName, name, accepted, file, val, descr):
  123. global options
  124. #
  125. # Constructor.
  126. #
  127. self.testRunner = None
  128. self.isSchema = isSchema
  129. self.groupName = groupName
  130. self.name = name
  131. self.accepted = accepted
  132. self.fileName = fixFileNames(file)
  133. self.val = val
  134. self.descr = descr
  135. self.failed = False
  136. self.combineName = None
  137. self.log = []
  138. self.libLog = []
  139. self.initialMemUsed = 0
  140. self.memLeak = 0
  141. self.excepted = False
  142. self.bad = False
  143. self.unimplemented = False
  144. self.internalErr = False
  145. self.noSchemaErr = False
  146. self.failed = False
  147. #
  148. # Init the log.
  149. #
  150. if not options.silent:
  151. if self.descr is not None:
  152. self.log.append("'%s' descr: %s\n" % (self.name, self.descr))
  153. self.log.append("'%s' exp validity: %d\n" % (self.name, self.val))
  154. def initTest(self, runner):
  155. global vendorNIST, vendorSUN, vendorMS, vendorNIST_2, options, vendor
  156. #
  157. # Get the test-group.
  158. #
  159. self.runner = runner
  160. self.group = runner.getGroup(self.groupName)
  161. if vendor == vendorMS or vendor == vendorSUN:
  162. #
  163. # Use the last given directory for the combine name.
  164. #
  165. dirs = self.fileName.split("/")
  166. self.combineName = dirs[len(dirs) -2]
  167. elif vendor == vendorNIST:
  168. #
  169. # NIST files are named in the following form:
  170. # "NISTSchema-short-pattern-1.xsd"
  171. #
  172. tokens = self.name.split("-")
  173. self.combineName = tokens[1]
  174. elif vendor == vendorNIST_2:
  175. #
  176. # Group-names have the form: "atomic-normalizedString-length-1"
  177. #
  178. tokens = self.groupName.split("-")
  179. self.combineName = "%s-%s" % (tokens[0], tokens[1])
  180. else:
  181. self.combineName = "unkown"
  182. raise Exception("Could not compute the combine name of a test.")
  183. if (not options.silent) and (self.group.descr is not None):
  184. self.log.append("'%s' group-descr: %s\n" % (self.name, self.group.descr))
  185. def addLibLog(self, msg):
  186. """This one is intended to be used by the error handler
  187. function"""
  188. global options
  189. if not options.silent:
  190. self.libLog.append(msg)
  191. def fail(self, msg):
  192. global options
  193. self.failed = True
  194. if not options.silent:
  195. self.log.append("'%s' ( FAILED: %s\n" % (self.name, msg))
  196. def failNoSchema(self):
  197. global options
  198. self.failed = True
  199. self.noSchemaErr = True
  200. if not options.silent:
  201. self.log.append("'%s' X NO-SCHEMA\n" % (self.name))
  202. def failInternal(self):
  203. global options
  204. self.failed = True
  205. self.internalErr = True
  206. if not options.silent:
  207. self.log.append("'%s' * INTERNAL\n" % self.name)
  208. def failUnimplemented(self):
  209. global options
  210. self.failed = True
  211. self.unimplemented = True
  212. if not options.silent:
  213. self.log.append("'%s' ? UNIMPLEMENTED\n" % self.name)
  214. def failCritical(self, msg):
  215. global options
  216. self.failed = True
  217. self.bad = True
  218. if not options.silent:
  219. self.log.append("'%s' ! BAD: %s\n" % (self.name, msg))
  220. def failExcept(self, e):
  221. global options
  222. self.failed = True
  223. self.excepted = True
  224. if not options.silent:
  225. self.log.append("'%s' # EXCEPTION: %s\n" % (self.name, e.__str__()))
  226. def setUp(self):
  227. #
  228. # Set up Libxml2.
  229. #
  230. self.initialMemUsed = libxml2.debugMemory(1)
  231. libxml2.initParser()
  232. libxml2.lineNumbersDefault(1)
  233. libxml2.registerErrorHandler(handleError, self)
  234. def tearDown(self):
  235. libxml2.schemaCleanupTypes()
  236. libxml2.cleanupParser()
  237. self.memLeak = libxml2.debugMemory(1) - self.initialMemUsed
  238. def isIOError(self, file, docType):
  239. err = None
  240. try:
  241. err = libxml2.lastError()
  242. except:
  243. # Suppress exceptions.
  244. pass
  245. if (err is None):
  246. return False
  247. if err.domain() == libxml2.XML_FROM_IO:
  248. self.failCritical("failed to access the %s resource '%s'\n" % (docType, file))
  249. def debugMsg(self, msg):
  250. global options
  251. if options.debugEnabled:
  252. sys.stdout.write("'%s' DEBUG: %s\n" % (self.name, msg))
  253. def finalize(self):
  254. global options
  255. """Adds additional info to the log."""
  256. #
  257. # Add libxml2 messages.
  258. #
  259. if not options.silent:
  260. self.log.extend(self.libLog)
  261. #
  262. # Add memory leaks.
  263. #
  264. if self.memLeak != 0:
  265. self.log.append("%s + memory leak: %d bytes\n" % (self.name, self.memLeak))
  266. def run(self):
  267. """Runs a test."""
  268. global options
  269. ##filePath = os.path.join(options.baseDir, self.fileName)
  270. # filePath = "%s/%s/%s/%s" % (options.baseDir, self.test_Folder, self.schema_Folder, self.schema_File)
  271. if options.displayTestName:
  272. sys.stdout.write("'%s'\n" % self.name)
  273. try:
  274. self.validate()
  275. except (Exception, libxml2.parserError, libxml2.treeError), e:
  276. self.failExcept(e)
  277. def parseSchema(fileName):
  278. schema = None
  279. ctxt = libxml2.schemaNewParserCtxt(fileName)
  280. try:
  281. try:
  282. schema = ctxt.schemaParse()
  283. except:
  284. pass
  285. finally:
  286. del ctxt
  287. return schema
  288. class XSTCSchemaTest(XSTCTestCase):
  289. def __init__(self, groupName, name, accepted, file, val, descr):
  290. XSTCTestCase.__init__(self, 1, groupName, name, accepted, file, val, descr)
  291. def validate(self):
  292. global msgSchemaNotValidButShould, msgSchemaValidButShouldNot
  293. schema = None
  294. filePath = self.fileName
  295. # os.path.join(options.baseDir, self.fileName)
  296. valid = 0
  297. try:
  298. #
  299. # Parse the schema.
  300. #
  301. self.debugMsg("loading schema: %s" % filePath)
  302. schema = parseSchema(filePath)
  303. self.debugMsg("after loading schema")
  304. if schema is None:
  305. self.debugMsg("schema is None")
  306. self.debugMsg("checking for IO errors...")
  307. if self.isIOError(file, "schema"):
  308. return
  309. self.debugMsg("checking schema result")
  310. if (schema is None and self.val) or (schema is not None and self.val == 0):
  311. self.debugMsg("schema result is BAD")
  312. if (schema == None):
  313. self.fail(msgSchemaNotValidButShould)
  314. else:
  315. self.fail(msgSchemaValidButShouldNot)
  316. else:
  317. self.debugMsg("schema result is OK")
  318. finally:
  319. self.group.setSchema(self.fileName, schema is not None)
  320. del schema
  321. class XSTCInstanceTest(XSTCTestCase):
  322. def __init__(self, groupName, name, accepted, file, val, descr):
  323. XSTCTestCase.__init__(self, 0, groupName, name, accepted, file, val, descr)
  324. def validate(self):
  325. instance = None
  326. schema = None
  327. filePath = self.fileName
  328. # os.path.join(options.baseDir, self.fileName)
  329. if not self.group.schemaParsed and self.group.schemaTried:
  330. self.failNoSchema()
  331. return
  332. self.debugMsg("loading instance: %s" % filePath)
  333. parserCtxt = libxml2.newParserCtxt()
  334. if (parserCtxt is None):
  335. # TODO: Is this one necessary, or will an exception
  336. # be already raised?
  337. raise Exception("Could not create the instance parser context.")
  338. if not options.validationSAX:
  339. try:
  340. try:
  341. instance = parserCtxt.ctxtReadFile(filePath, None, libxml2.XML_PARSE_NOWARNING)
  342. except:
  343. # Suppress exceptions.
  344. pass
  345. finally:
  346. del parserCtxt
  347. self.debugMsg("after loading instance")
  348. if instance is None:
  349. self.debugMsg("instance is None")
  350. self.failCritical("Failed to parse the instance for unknown reasons.")
  351. return
  352. try:
  353. #
  354. # Validate the instance.
  355. #
  356. self.debugMsg("loading schema: %s" % self.group.schemaFileName)
  357. schema = parseSchema(self.group.schemaFileName)
  358. try:
  359. validationCtxt = schema.schemaNewValidCtxt()
  360. #validationCtxt = libxml2.schemaNewValidCtxt(None)
  361. if (validationCtxt is None):
  362. self.failCritical("Could not create the validation context.")
  363. return
  364. try:
  365. self.debugMsg("validating instance")
  366. if options.validationSAX:
  367. instance_Err = validationCtxt.schemaValidateFile(filePath, 0)
  368. else:
  369. instance_Err = validationCtxt.schemaValidateDoc(instance)
  370. self.debugMsg("after instance validation")
  371. self.debugMsg("instance-err: %d" % instance_Err)
  372. if (instance_Err != 0 and self.val == 1) or (instance_Err == 0 and self.val == 0):
  373. self.debugMsg("instance result is BAD")
  374. if (instance_Err != 0):
  375. self.fail(msgInstanceNotValidButShould)
  376. else:
  377. self.fail(msgInstanceValidButShouldNot)
  378. else:
  379. self.debugMsg("instance result is OK")
  380. finally:
  381. del validationCtxt
  382. finally:
  383. del schema
  384. finally:
  385. if instance is not None:
  386. instance.freeDoc()
  387. ####################
  388. # Test runner class.
  389. #
  390. class XSTCTestRunner:
  391. CNT_TOTAL = 0
  392. CNT_RAN = 1
  393. CNT_SUCCEEDED = 2
  394. CNT_FAILED = 3
  395. CNT_UNIMPLEMENTED = 4
  396. CNT_INTERNAL = 5
  397. CNT_BAD = 6
  398. CNT_EXCEPTED = 7
  399. CNT_MEMLEAK = 8
  400. CNT_NOSCHEMA = 9
  401. CNT_NOTACCEPTED = 10
  402. CNT_SCHEMA_TEST = 11
  403. def __init__(self):
  404. self.logFile = None
  405. self.counters = self.createCounters()
  406. self.testList = []
  407. self.combinesRan = {}
  408. self.groups = {}
  409. self.curGroup = None
  410. def createCounters(self):
  411. counters = {self.CNT_TOTAL:0, self.CNT_RAN:0, self.CNT_SUCCEEDED:0,
  412. self.CNT_FAILED:0, self.CNT_UNIMPLEMENTED:0, self.CNT_INTERNAL:0, self.CNT_BAD:0,
  413. self.CNT_EXCEPTED:0, self.CNT_MEMLEAK:0, self.CNT_NOSCHEMA:0, self.CNT_NOTACCEPTED:0,
  414. self.CNT_SCHEMA_TEST:0}
  415. return counters
  416. def addTest(self, test):
  417. self.testList.append(test)
  418. test.initTest(self)
  419. def getGroup(self, groupName):
  420. return self.groups[groupName]
  421. def addGroup(self, group):
  422. self.groups[group.name] = group
  423. def updateCounters(self, test, counters):
  424. if test.memLeak != 0:
  425. counters[self.CNT_MEMLEAK] += 1
  426. if not test.failed:
  427. counters[self.CNT_SUCCEEDED] +=1
  428. if test.failed:
  429. counters[self.CNT_FAILED] += 1
  430. if test.bad:
  431. counters[self.CNT_BAD] += 1
  432. if test.unimplemented:
  433. counters[self.CNT_UNIMPLEMENTED] += 1
  434. if test.internalErr:
  435. counters[self.CNT_INTERNAL] += 1
  436. if test.noSchemaErr:
  437. counters[self.CNT_NOSCHEMA] += 1
  438. if test.excepted:
  439. counters[self.CNT_EXCEPTED] += 1
  440. if not test.accepted:
  441. counters[self.CNT_NOTACCEPTED] += 1
  442. if test.isSchema:
  443. counters[self.CNT_SCHEMA_TEST] += 1
  444. return counters
  445. def displayResults(self, out, all, combName, counters):
  446. out.write("\n")
  447. if all:
  448. if options.combines is not None:
  449. out.write("combine(s): %s\n" % str(options.combines))
  450. elif combName is not None:
  451. out.write("combine : %s\n" % combName)
  452. out.write(" total : %d\n" % counters[self.CNT_TOTAL])
  453. if all or options.combines is not None:
  454. out.write(" ran : %d\n" % counters[self.CNT_RAN])
  455. out.write(" (schemata) : %d\n" % counters[self.CNT_SCHEMA_TEST])
  456. # out.write(" succeeded : %d\n" % counters[self.CNT_SUCCEEDED])
  457. out.write(" not accepted : %d\n" % counters[self.CNT_NOTACCEPTED])
  458. if counters[self.CNT_FAILED] > 0:
  459. out.write(" failed : %d\n" % counters[self.CNT_FAILED])
  460. out.write(" -> internal : %d\n" % counters[self.CNT_INTERNAL])
  461. out.write(" -> unimpl. : %d\n" % counters[self.CNT_UNIMPLEMENTED])
  462. out.write(" -> skip-invalid-schema : %d\n" % counters[self.CNT_NOSCHEMA])
  463. out.write(" -> bad : %d\n" % counters[self.CNT_BAD])
  464. out.write(" -> exceptions : %d\n" % counters[self.CNT_EXCEPTED])
  465. out.write(" memory leaks : %d\n" % counters[self.CNT_MEMLEAK])
  466. def displayShortResults(self, out, all, combName, counters):
  467. out.write("Ran %d of %d tests (%d schemata):" % (counters[self.CNT_RAN],
  468. counters[self.CNT_TOTAL], counters[self.CNT_SCHEMA_TEST]))
  469. # out.write(" succeeded : %d\n" % counters[self.CNT_SUCCEEDED])
  470. if counters[self.CNT_NOTACCEPTED] > 0:
  471. out.write(" %d not accepted" % (counters[self.CNT_NOTACCEPTED]))
  472. if counters[self.CNT_FAILED] > 0 or counters[self.CNT_MEMLEAK] > 0:
  473. if counters[self.CNT_FAILED] > 0:
  474. out.write(" %d failed" % (counters[self.CNT_FAILED]))
  475. out.write(" (")
  476. if counters[self.CNT_INTERNAL] > 0:
  477. out.write(" %d internal" % (counters[self.CNT_INTERNAL]))
  478. if counters[self.CNT_UNIMPLEMENTED] > 0:
  479. out.write(" %d unimplemented" % (counters[self.CNT_UNIMPLEMENTED]))
  480. if counters[self.CNT_NOSCHEMA] > 0:
  481. out.write(" %d skip-invalid-schema" % (counters[self.CNT_NOSCHEMA]))
  482. if counters[self.CNT_BAD] > 0:
  483. out.write(" %d bad" % (counters[self.CNT_BAD]))
  484. if counters[self.CNT_EXCEPTED] > 0:
  485. out.write(" %d exception" % (counters[self.CNT_EXCEPTED]))
  486. out.write(" )")
  487. if counters[self.CNT_MEMLEAK] > 0:
  488. out.write(" %d leaks" % (counters[self.CNT_MEMLEAK]))
  489. out.write("\n")
  490. else:
  491. out.write(" all passed\n")
  492. def reportCombine(self, combName):
  493. global options
  494. counters = self.createCounters()
  495. #
  496. # Compute evaluation counters.
  497. #
  498. for test in self.combinesRan[combName]:
  499. counters[self.CNT_TOTAL] += 1
  500. counters[self.CNT_RAN] += 1
  501. counters = self.updateCounters(test, counters)
  502. if options.reportErrCombines and (counters[self.CNT_FAILED] == 0) and (counters[self.CNT_MEMLEAK] == 0):
  503. pass
  504. else:
  505. if options.enableLog:
  506. self.displayResults(self.logFile, False, combName, counters)
  507. self.displayResults(sys.stdout, False, combName, counters)
  508. def displayTestLog(self, test):
  509. sys.stdout.writelines(test.log)
  510. sys.stdout.write("~~~~~~~~~~\n")
  511. def reportTest(self, test):
  512. global options
  513. error = test.failed or test.memLeak != 0
  514. #
  515. # Only erroneous tests will be written to the log,
  516. # except @verbose is switched on.
  517. #
  518. if options.enableLog and (options.verbose or error):
  519. self.logFile.writelines(test.log)
  520. self.logFile.write("~~~~~~~~~~\n")
  521. #
  522. # if not @silent, only erroneous tests will be
  523. # written to stdout, except @verbose is switched on.
  524. #
  525. if not options.silent:
  526. if options.reportInternalErrOnly and test.internalErr:
  527. self.displayTestLog(test)
  528. if options.reportMemLeakErrOnly and test.memLeak != 0:
  529. self.displayTestLog(test)
  530. if options.reportUnimplErrOnly and test.unimplemented:
  531. self.displayTestLog(test)
  532. if (options.verbose or error) and (not options.reportInternalErrOnly) and (not options.reportMemLeakErrOnly) and (not options.reportUnimplErrOnly):
  533. self.displayTestLog(test)
  534. def addToCombines(self, test):
  535. found = False
  536. if self.combinesRan.has_key(test.combineName):
  537. self.combinesRan[test.combineName].append(test)
  538. else:
  539. self.combinesRan[test.combineName] = [test]
  540. def run(self):
  541. global options
  542. if options.info:
  543. for test in self.testList:
  544. self.addToCombines(test)
  545. sys.stdout.write("Combines: %d\n" % len(self.combinesRan))
  546. sys.stdout.write("%s\n" % self.combinesRan.keys())
  547. return
  548. if options.enableLog:
  549. self.logFile = open(options.logFile, "w")
  550. try:
  551. for test in self.testList:
  552. self.counters[self.CNT_TOTAL] += 1
  553. #
  554. # Filter tests.
  555. #
  556. if options.singleTest is not None and options.singleTest != "":
  557. if (test.name != options.singleTest):
  558. continue
  559. elif options.combines is not None:
  560. if not options.combines.__contains__(test.combineName):
  561. continue
  562. elif options.testStartsWith is not None:
  563. if not test.name.startswith(options.testStartsWith):
  564. continue
  565. elif options.combineStartsWith is not None:
  566. if not test.combineName.startswith(options.combineStartsWith):
  567. continue
  568. if options.maxTestCount != -1 and self.counters[self.CNT_RAN] >= options.maxTestCount:
  569. break
  570. self.counters[self.CNT_RAN] += 1
  571. #
  572. # Run the thing, dammit.
  573. #
  574. try:
  575. test.setUp()
  576. try:
  577. test.run()
  578. finally:
  579. test.tearDown()
  580. finally:
  581. #
  582. # Evaluate.
  583. #
  584. test.finalize()
  585. self.reportTest(test)
  586. if options.reportCombines or options.reportErrCombines:
  587. self.addToCombines(test)
  588. self.counters = self.updateCounters(test, self.counters)
  589. finally:
  590. if options.reportCombines or options.reportErrCombines:
  591. #
  592. # Build a report for every single combine.
  593. #
  594. # TODO: How to sort a dict?
  595. #
  596. self.combinesRan.keys().sort(None)
  597. for key in self.combinesRan.keys():
  598. self.reportCombine(key)
  599. #
  600. # Display the final report.
  601. #
  602. if options.silent:
  603. self.displayShortResults(sys.stdout, True, None, self.counters)
  604. else:
  605. sys.stdout.write("===========================\n")
  606. self.displayResults(sys.stdout, True, None, self.counters)