test.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import unittest
  2. import argparse
  3. import threading
  4. import queue
  5. from sccd.runtime.event import Event
  6. from sccd.runtime.controller import Controller
  7. from lib.loader import Loader
  8. from lib.os_tools import *
  9. class PyTestCase(unittest.TestCase):
  10. def __init__(self, src_file, builder):
  11. unittest.TestCase.__init__(self)
  12. self.src_file = src_file
  13. self.builder = builder
  14. def __str__(self):
  15. return self.src_file
  16. def runTest(self):
  17. # Build & load
  18. module = self.builder.build_and_load(self.src_file)
  19. inputs = module.Test.input_events
  20. expected = module.Test.expected_events # list of lists of Event objects
  21. model = module.Model()
  22. controller = Controller(model)
  23. # generate input
  24. for i in inputs:
  25. controller.add_input(i)
  26. pipe = queue.Queue()
  27. def model_thread():
  28. try:
  29. # Run as-fast-as-possible, always advancing time to the next item in event queue, no sleeping.
  30. # The call returns when the event queue is empty and therefore the simulation is finished.
  31. controller.run_until(None, pipe)
  32. except Exception as e:
  33. pipe.put(e, block=True, timeout=None)
  34. return
  35. pipe.put(None, block=True, timeout=None)
  36. # start the controller
  37. thread = threading.Thread(target=model_thread)
  38. thread.start()
  39. # check output
  40. slot_index = 0
  41. while True:
  42. output = pipe.get(block=True, timeout=None)
  43. if isinstance(output, Exception):
  44. thread.join()
  45. raise output # Exception was caught in Controller thread, throw it here instead.
  46. elif output is None:
  47. self.assertEqual(slot_index, len(expected), "Less output was received than expected.")
  48. thread.join()
  49. return
  50. else:
  51. self.assertLess(slot_index, len(expected), "More output was received than expected.")
  52. exp_slot = expected[slot_index]
  53. # print("slot:", slot_index, ", events: ", output)
  54. self.assertEqual(len(exp_slot), len(output), "Slot %d length differs: Expected %s, but got %s instead." % (slot_index, exp_slot, output))
  55. # sort both expected and actual lists of events before comparing,
  56. # in theory the set of events at the end of a big step is unordered
  57. key_f = lambda e: "%s.%s"%(e.port, e.name)
  58. exp_slot.sort(key=key_f)
  59. output.sort(key=key_f)
  60. for (exp_event, event) in zip(exp_slot, output):
  61. matches = True
  62. if exp_event.name != event.name :
  63. matches = False
  64. if exp_event.port != event.port :
  65. matches = False
  66. if len(exp_event.parameters) != len(event.parameters) :
  67. matches = False
  68. for index in range(len(exp_event.parameters)) :
  69. if exp_event.parameters[index] != event.parameters[index]:
  70. matches = False
  71. self.assertTrue(matches, "Slot %d entry differs: Expected %s, but got %s instead." % (slot_index, exp_slot, output))
  72. slot_index += 1
  73. if __name__ == '__main__':
  74. parser = argparse.ArgumentParser(
  75. description="Run SCCD tests.",
  76. epilog="Set environment variable SCCDDEBUG=1 to display debug information about the inner workings of the runtime.")
  77. parser.add_argument('path', metavar='PATH', type=str, nargs='*', help="Tests to run. Can be a XML file or a directory. If a directory, it will be recursively scanned for XML files.")
  78. parser.add_argument('--build-dir', metavar='BUILD_DIR', type=str, default='build', help="Directory for built tests. Defaults to 'build'")
  79. args = parser.parse_args()
  80. src_files = get_files(args.path, filter=filter_xml)
  81. # builder = Builder(args.build_dir)
  82. builder = Loader()
  83. suite = unittest.TestSuite()
  84. for src_file in src_files:
  85. suite.addTest(PyTestCase(src_file, builder))
  86. if len(src_files) == 0:
  87. print("No input files specified.")
  88. print()
  89. parser.print_usage()
  90. else:
  91. unittest.TextTestRunner(verbosity=2).run(suite)