tests.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import unittest
  2. import sccdc
  3. import importlib
  4. import os
  5. import xml.etree.ElementTree as ET
  6. from compiler_exceptions import CompilerException, TransitionException
  7. from code_generation import Platforms, Languages
  8. from python_runtime.statecharts_core import Event
  9. SHARED_TEST_FILES_FOLDER = "../test_files"
  10. class TestEvent(object):
  11. def __init__(self, name, port, parameters = []):
  12. self.name = name
  13. self.port = port
  14. self.parameters = parameters
  15. def matches(self, event):
  16. if event is None :
  17. return False
  18. if event.getName() != self.name :
  19. return False
  20. if event.getPort() != self.port :
  21. return False
  22. compare_parameters = event.getParameters()
  23. if len(self.parameters) != len(compare_parameters) :
  24. return False
  25. for index in xrange(len(self.parameters)) :
  26. if self.parameters[index] != str(compare_parameters[index]):
  27. return False
  28. return True
  29. def __repr__(self):
  30. representation = "(event name : " + str(self.name) + "; port : " + str(self.port)
  31. if self.parameters :
  32. representation += "; parameters : " + str(self.parameters)
  33. representation += ")"
  34. return representation
  35. class XMLTestCase(unittest.TestCase):
  36. def __init__(self, file_name):
  37. super(XMLTestCase, self).__init__()
  38. self.file_name = file_name
  39. self.name = os.path.splitext(file_name)[0]
  40. self.source_path = os.getcwd() + "/" + SHARED_TEST_FILES_FOLDER + "/" + self.file_name
  41. self.target_path = os.getcwd() + "/" + self.name + ".py"
  42. self.file_generated = False
  43. def __str__(self):
  44. return self.file_name
  45. def setUp(self):
  46. self.delete_generated_file = not os.path.isfile(self.target_path)
  47. def tearDown(self):
  48. if self.file_generated and self.delete_generated_file :
  49. os.remove(self.target_path)
  50. os.remove(self.target_path + "c")
  51. def runTest(self):
  52. test_xml = ET.parse(self.source_path).getroot().find("test")
  53. self.assertIsNot(test_xml, None, "No test data found. (A test that should just compile correctly, still needs an empthy test tag.)")
  54. #Check if the exception attribute is set and act accordingly
  55. exception_attribute = test_xml.get("exception","")
  56. if exception_attribute == "" :
  57. sccdc.generate(self.source_path, self.target_path, Languages.Python, Platforms.Threads)
  58. else :
  59. if exception_attribute == "CompilerException" :
  60. with self.assertRaises(CompilerException):
  61. sccdc.generate(self.source_path, self.target_path, Languages.Python, Platforms.Threads)
  62. elif exception_attribute == "TransitionException" :
  63. with self.assertRaises(TransitionException):
  64. sccdc.generate(self.source_path, self.target_path, Languages.Python, Platforms.Threads)
  65. else :
  66. raise AssertionError("Invalid value for the exception attribute.")
  67. return
  68. self.file_generated = True
  69. import_file = importlib.import_module(self.name)
  70. self.controller = import_file.Controller(False)
  71. #Preparing input for controller
  72. input_xml = test_xml.find("input")
  73. if input_xml is not None :
  74. for event_xml in input_xml :
  75. if event_xml.tag == "event" :
  76. self.controller.addInput(Event(event_xml.get("name"), event_xml.get("port")))
  77. expected_xml = test_xml.find("expected")
  78. if expected_xml is None :
  79. #no expected result, so we just simulate without catching output
  80. self.controller.start()
  81. self.controller.join()
  82. return
  83. #Creating a datastructure for the expected output
  84. expected_result = []
  85. output_ports = set()
  86. for slot_xml in expected_xml :
  87. if slot_xml.tag == "slot" :
  88. slot = []
  89. for event_xml in slot_xml :
  90. if event_xml.tag == "event" :
  91. event_name = event_xml.get("name")
  92. port = event_xml.get("port")
  93. parameters = []
  94. parameters_xml = event_xml.findall("parameter")
  95. for parameter_xml in parameters_xml :
  96. parameter_value = parameter_xml.get("value", None)
  97. if parameter_value is not None :
  98. parameters.append(parameter_value)
  99. slot.append(TestEvent(event_name, port,parameters))
  100. output_ports.add(port)
  101. if slot :
  102. expected_result.append(slot)
  103. #Execution
  104. output_listener = self.controller.addOutputListener(list(output_ports))
  105. self.controller.start()
  106. self.controller.join()
  107. #Check output
  108. for (slot_index, slot) in enumerate(expected_result, start=1) :
  109. remaining_options = slot[:]
  110. received_output = []
  111. while remaining_options :
  112. output_event = output_listener.fetch()
  113. received_output.append(output_event)
  114. match_index = -1
  115. for (index, option) in enumerate(remaining_options) :
  116. if option.matches(output_event) :
  117. match_index = index
  118. break
  119. self.assertNotEqual(match_index, -1, "Expected results slot " + str(slot_index) + " mismatch. Expected " + str(slot) + ", but got " + str(received_output) + " instead.") #no match found in the options
  120. remaining_options.pop(match_index)
  121. #check if there are no extra events
  122. self.assertEqual(output_listener.fetch(0), None, "More output events than expected on selected ports.")
  123. if __name__ == '__main__':
  124. suite = unittest.TestSuite()
  125. for file_name in os.listdir(os.getcwd() + "/" + SHARED_TEST_FILES_FOLDER):
  126. if file_name.endswith(".xml"):
  127. suite.addTest(XMLTestCase(file_name))
  128. unittest.TextTestRunner(verbosity=2).run(suite)