test_terminals.py 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. # coding: utf-8
  2. import time
  3. import pytest
  4. from synergine2.config import Config
  5. from synergine2.core import Core
  6. from synergine2.cycle import CycleManager
  7. from synergine2.log import SynergineLogger
  8. from synergine2.simulation import Event
  9. from synergine2.simulation import Simulation
  10. from synergine2.simulation import Subjects
  11. from synergine2.terminals import Terminal
  12. from synergine2.terminals import TerminalPackage
  13. from synergine2.terminals import TerminalManager
  14. from tests import BaseTest
  15. class ValueTerminalPackage(TerminalPackage):
  16. def __init__(self, value, *args, **kwargs):
  17. super().__init__(*args, **kwargs)
  18. self.value = value
  19. class MultiplyTerminal(Terminal):
  20. def receive(self, package: ValueTerminalPackage):
  21. self.send(ValueTerminalPackage(value=package.value * 2))
  22. self.send(ValueTerminalPackage(value=package.value * 4))
  23. class DivideTerminal(Terminal):
  24. def receive(self, package: ValueTerminalPackage):
  25. self.send(ValueTerminalPackage(value=package.value / 2))
  26. self.send(ValueTerminalPackage(value=package.value / 4))
  27. class AnEvent(Event):
  28. pass
  29. class AnOtherEvent(Event):
  30. pass
  31. class SendBackTerminal(Terminal):
  32. def receive(self, package: ValueTerminalPackage):
  33. self.send(package)
  34. class TestTerminals(BaseTest):
  35. def test_terminal_communications(self):
  36. terminals_manager = TerminalManager(
  37. Config(),
  38. SynergineLogger('test'),
  39. terminals=[
  40. MultiplyTerminal(Config(), SynergineLogger('test')),
  41. ]
  42. )
  43. terminals_manager.start()
  44. terminals_manager.send(ValueTerminalPackage(value=42))
  45. # We wait max 2s (see time.sleep) to consider
  46. # process have finished. If not, it will fail
  47. packages = []
  48. for i in range(200):
  49. packages.extend(terminals_manager.receive())
  50. if len(packages) == 2:
  51. break
  52. time.sleep(0.01)
  53. assert 2 == len(packages)
  54. values = [p.value for p in packages]
  55. assert 84 in values
  56. assert 168 in values
  57. terminals_manager.stop() # pytest must execute this if have fail
  58. def test_terminals_communications(self):
  59. terminals_manager = TerminalManager(
  60. Config(),
  61. SynergineLogger('test'),
  62. terminals=[
  63. MultiplyTerminal(Config(), SynergineLogger('test')),
  64. DivideTerminal(Config(), SynergineLogger('test')),
  65. ]
  66. )
  67. terminals_manager.start()
  68. terminals_manager.send(ValueTerminalPackage(value=42))
  69. # We wait max 2s (see time.sleep) to consider
  70. # process have finished. If not, it will fail
  71. packages = []
  72. for i in range(200):
  73. packages.extend(terminals_manager.receive())
  74. if len(packages) == 4:
  75. break
  76. time.sleep(0.01)
  77. assert 4 == len(packages)
  78. values = [p.value for p in packages]
  79. assert 84 in values
  80. assert 168 in values
  81. assert 21 in values
  82. assert 10.5 in values
  83. terminals_manager.stop() # TODO pytest must execute this if have fail
  84. def test_event_listen_everything(self):
  85. class ListenEverythingTerminal(SendBackTerminal):
  86. pass
  87. terminals_manager = TerminalManager(
  88. Config(),
  89. SynergineLogger('test'),
  90. terminals=[ListenEverythingTerminal(Config(), SynergineLogger('test'))]
  91. )
  92. terminals_manager.start()
  93. terminals_manager.send(ValueTerminalPackage(value=42))
  94. an_event = AnEvent()
  95. terminals_manager.send(TerminalPackage(events=[an_event]))
  96. # We wait max 2s (see time.sleep) to consider
  97. # process have finished. If not, it will fail
  98. packages = []
  99. for i in range(200):
  100. packages.extend(terminals_manager.receive())
  101. if len(packages) == 2:
  102. break
  103. time.sleep(0.01)
  104. assert 2 == len(packages)
  105. assert 42 == packages[0].value
  106. assert AnEvent == type(packages[1].events[0])
  107. terminals_manager.stop() # TODO pytest must execute this if have fail
  108. def test_event_listen_specified(self):
  109. class ListenAnEventTerminal(SendBackTerminal):
  110. subscribed_events = [AnOtherEvent]
  111. terminals_manager = TerminalManager(
  112. Config(),
  113. SynergineLogger('test'),
  114. terminals=[ListenAnEventTerminal(Config(), SynergineLogger('test'))]
  115. )
  116. terminals_manager.start()
  117. terminals_manager.send(ValueTerminalPackage(value=42))
  118. an_event = AnEvent()
  119. an_other_event = AnOtherEvent()
  120. terminals_manager.send(TerminalPackage(events=[an_event, an_other_event]))
  121. # We wait max 10s (see time.sleep) to consider
  122. # process have finished. If not, it will fail
  123. packages = []
  124. for i in range(1000):
  125. packages.extend(terminals_manager.receive())
  126. if len(packages) == 2:
  127. break
  128. time.sleep(0.01)
  129. assert 2 == len(packages)
  130. assert AnOtherEvent == type(packages[1].events[0])
  131. terminals_manager.stop() # TODO pytest must execute this if have fail
  132. @pytest.mark.skip(reason="Buggy ! Never terminate, all processes closed ?")
  133. def test_terminal_as_main_process(self):
  134. config = Config()
  135. logger = SynergineLogger('test')
  136. simulation = Simulation(config)
  137. simulation.subjects = Subjects(simulation=simulation)
  138. cycle_manager = CycleManager(
  139. config=config,
  140. logger=logger,
  141. simulation=simulation,
  142. )
  143. class MyMainTerminal(Terminal):
  144. main_process = True
  145. terminal = MyMainTerminal(config, logger)
  146. class Terminated(Exception):
  147. pass
  148. class MyCore(Core):
  149. def _end_cycle(self):
  150. self._continue = False
  151. core = MyCore(
  152. config=config,
  153. logger=logger,
  154. simulation=simulation,
  155. cycle_manager=cycle_manager,
  156. terminal_manager=TerminalManager(
  157. config=config,
  158. logger=logger,
  159. terminals=[terminal],
  160. ),
  161. )
  162. core.run()
  163. pass