test_terminals.py 6.2KB

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