123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544 |
- import datetime
- import time
-
- from synergine2.config import Config
- from synergine2.cycle import CycleManager
- from synergine2.log import SynergineLogger
- from synergine2.processing import ProcessManager
- from synergine2.share import shared
- from synergine2.simulation import Simulation
- from synergine2.simulation import Subjects
- from synergine2.simulation import SubjectBehaviour
- from synergine2.simulation import SubjectMechanism
- from synergine2.simulation import Subject
- from synergine2.simulation import SimulationMechanism
- from synergine2.simulation import SimulationBehaviour
- from tests import BaseTest
-
- from freezegun import freeze_time
-
- config = Config()
- logger = SynergineLogger('test')
-
-
- class MySubjectMechanism(SubjectMechanism):
- def run(self):
- return {'foo': 42}
-
-
- class MySimulationMechanism(SimulationMechanism):
- def run(self, process_number: int=None, process_count: int=None):
- return {'foo': 42}
-
-
- class MySubjectBehaviour(SubjectBehaviour):
- use = [MySubjectMechanism]
-
- def run(self, data):
- return {'bar': data[MySubjectMechanism]['foo'] + 100}
-
-
- class MySimulationBehaviour(SimulationBehaviour):
- use = [MySimulationMechanism]
-
- def run(self, data):
- return {'bar': data[MySimulationMechanism]['foo'] + 100}
-
-
- class MySimulation(Simulation):
- behaviours_classes = [MySimulationBehaviour]
-
-
- class MyCycledSubjectBehaviour(MySubjectBehaviour):
- @property
- def cycle_frequency(self):
- return 2
-
-
- class MyCycledSimulationBehaviour(MySimulationBehaviour):
- @property
- def cycle_frequency(self):
- return 2
-
-
- class MyTimedSubjectBehaviour(MySubjectBehaviour):
- @property
- def seconds_frequency(self):
- return 1.0
-
- def run(self, data):
- self.last_execution_time = time.time()
- return super().run(data)
-
-
- class MyTimedSimulationBehaviour(MySimulationBehaviour):
- @property
- def seconds_frequency(self):
- return 1.0
-
- def run(self, data):
- self.last_execution_time = time.time()
- return super().run(data)
-
-
- class TestBehaviours(BaseTest):
- def test_subject_behaviour_produce_data(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
-
- class MySubject(Subject):
- behaviours_classes = [MySubjectBehaviour]
-
- simulation = Simulation(config)
- my_subject = MySubject(config, simulation)
- subjects = Subjects(simulation=simulation)
- subjects.append(my_subject)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
- results_by_subjects = cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert results_by_subjects
- assert id(my_subject) in results_by_subjects
- assert MySubjectBehaviour in results_by_subjects[id(my_subject)]
- assert 'bar' in results_by_subjects[id(my_subject)][MySubjectBehaviour]
- assert 142 == results_by_subjects[id(my_subject)][MySubjectBehaviour]['bar']
-
- def test_simulation_behaviour_produce_data(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
- simulation = MySimulation(config)
- subjects = Subjects(simulation=simulation)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
- data = cycle_manager._job_simulation(worker_id=0, process_count=1)
- assert data
- assert MySimulationBehaviour in data
- assert 'bar' in data[MySimulationBehaviour]
- assert 142 == data[MySimulationBehaviour]['bar']
-
- def test_subject_behaviour_cycle_frequency(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
-
- class MySubject(Subject):
- behaviours_classes = [MyCycledSubjectBehaviour]
-
- simulation = Simulation(config)
- my_subject = MySubject(config, simulation)
- subjects = Subjects(simulation=simulation)
- subjects.append(my_subject)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
-
- # Cycle 0: behaviour IS executed
- cycle_manager.current_cycle = 0
- results_by_subjects = cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert results_by_subjects
-
- # Cycle 1: behaviour IS NOT executed
- cycle_manager.current_cycle = 1
- results_by_subjects = cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert not results_by_subjects
-
- def test_subject_behaviour_seconds_frequency(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
-
- class MySubject(Subject):
- behaviours_classes = [MyTimedSubjectBehaviour]
-
- simulation = Simulation(config)
- my_subject = MySubject(config, simulation)
- subjects = Subjects(simulation=simulation)
- subjects.append(my_subject)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
-
- # Thirst time, behaviour IS executed
- with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0)):
- data = cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert data
- assert id(my_subject) in data
- assert data[id(my_subject)]
-
- # Less second after: NOT executed
- with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0, 500000)):
- data = cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert not data
-
- # Less second after: NOT executed
- with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0, 700000)):
- data = cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert not data
-
- # Less second after: IS executed
- with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 1, 500000)):
- data = cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert data
-
- def test_simulation_behaviour_cycle_frequency(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
-
- class MyCycledSimulation(Simulation):
- behaviours_classes = [MyCycledSimulationBehaviour]
-
- simulation = MyCycledSimulation(config)
- subjects = Subjects(simulation=simulation)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
-
- # Cycle 0: behaviour IS executed
- cycle_manager.current_cycle = 0
- data = cycle_manager._job_simulation(worker_id=0, process_count=1)
- assert data
-
- # Cycle 1: behaviour IS NOT executed
- cycle_manager.current_cycle = 1
- data = cycle_manager._job_simulation(worker_id=0, process_count=1)
- assert not data
-
- def test_simulation_behaviour_seconds_frequency(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
-
- class MyTimedSimulation(Simulation):
- behaviours_classes = [MyTimedSimulationBehaviour]
-
- simulation = MyTimedSimulation(config)
- subjects = Subjects(simulation=simulation)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
-
- # Thirst time, behaviour IS executed
- with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0)):
- data = cycle_manager._job_simulation(worker_id=0, process_count=1)
- assert data
-
- # Less second after: NOT executed
- with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0, 500000)):
- data = cycle_manager._job_simulation(worker_id=0, process_count=1)
- assert not data
-
- # Less second after: NOT executed
- with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0, 700000)):
- data = cycle_manager._job_simulation(worker_id=0, process_count=1)
- assert not data
-
- # More second after: IS executed
- with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 1, 500000)):
- data = cycle_manager._job_simulation(worker_id=0, process_count=1)
- assert data
-
- def test_subject_behavior_not_called_if_no_more_subjects(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
-
- class MySubject(Subject):
- behaviours_classes = [MySubjectBehaviour]
-
- simulation = Simulation(config)
- my_subject = MySubject(config, simulation)
- subjects = Subjects(simulation=simulation)
- subjects.append(my_subject)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
- results_by_subjects = cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert results_by_subjects
- assert id(my_subject) in results_by_subjects
- assert results_by_subjects[id(my_subject)]
-
- # If we remove subject, no more data generated
- subjects.remove(my_subject)
- results_by_subjects = cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert not results_by_subjects
-
-
- class TestMechanisms(BaseTest):
- def test_mechanism_called_once_for_multiple_subject_behaviors(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
- called = 0
- global called
-
- class MySubjectMechanism(SubjectMechanism):
- def run(self):
- global called
- called += 1
- return {'foo': 42}
-
- class MySubjectBehaviour1(SubjectBehaviour):
- use = [MySubjectMechanism]
-
- def run(self, data):
- return {'bar': data[MySubjectMechanism]['foo'] + 100}
-
- class MySubjectBehaviour2(SubjectBehaviour):
- use = [MySubjectMechanism]
-
- def run(self, data):
- return {'bar': data[MySubjectMechanism]['foo'] + 100}
-
- class MySubject(Subject):
- behaviours_classes = [MySubjectBehaviour1, MySubjectBehaviour2]
-
- simulation = Simulation(config)
- my_subject = MySubject(config, simulation)
- subjects = Subjects(simulation=simulation)
- subjects.append(my_subject)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
- cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert called == 1
-
- def test_mechanism_called_once_for_multiple_simulation_behaviors(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
- called = 0
- global called
-
- class MySimulationMechanism(SimulationMechanism):
- def run(self, process_number: int = None, process_count: int = None):
- global called
- called += 1
- return {'foo': 42}
-
- class MySimulationBehaviour1(SimulationBehaviour):
- use = [MySimulationMechanism]
-
- def run(self, data):
- return {'bar': data[MySimulationMechanism]['foo'] + 100}
-
- class MySimulationBehaviour2(SimulationBehaviour):
- use = [MySimulationMechanism]
-
- def run(self, data):
- return {'bar': data[MySimulationMechanism]['foo'] + 100}
-
- class MySimulation(Simulation):
- behaviours_classes = [MySimulationBehaviour1, MySimulationBehaviour2]
-
- simulation = MySimulation(config)
- subjects = Subjects(simulation=simulation)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
- cycle_manager._job_simulation(worker_id=0, process_count=1)
- assert called == 1
-
- def test_mechanism_not_called_if_no_subject_behavior(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
- called = 0
- global called
-
- class MySubjectMechanism(SubjectMechanism):
- def run(self):
- global called
- called += 1
- return {'foo': 42}
-
- class MySubject(Subject):
- behaviours_classes = []
-
- simulation = Simulation(config)
- my_subject = MySubject(config, simulation)
- subjects = Subjects(simulation=simulation)
- subjects.append(my_subject)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
- cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert called == 0
-
- def test_mechanism_not_called_if_no_simulation_behavior(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
- called = 0
- global called
-
- class MySimulationMechanism(SimulationMechanism):
- def run(self, process_number: int = None, process_count: int = None):
- global called
- called += 1
- return {'foo': 42}
-
- class MySimulation(Simulation):
- pass
-
- simulation = MySimulation(config)
- subjects = Subjects(simulation=simulation)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
- cycle_manager._job_simulation(worker_id=0, process_count=1)
- assert called == 0
-
- def test_mechanism_not_called_if_subject_behavior_cycled_not_active_yet(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
- called = 0
- global called
-
- class MySubjectMechanism(SubjectMechanism):
- def run(self):
- global called
- called += 1
- return {'foo': 42}
-
- class MySubjectBehaviour1(SubjectBehaviour):
- use = [MySubjectMechanism]
-
- @property
- def cycle_frequency(self):
- return 2
-
- def run(self, data):
- return {'bar': data[MySubjectMechanism]['foo'] + 100}
-
- class MySubject(Subject):
- behaviours_classes = [MySubjectBehaviour1]
-
- simulation = Simulation(config)
- my_subject = MySubject(config, simulation)
- subjects = Subjects(simulation=simulation)
- subjects.append(my_subject)
- simulation.subjects = subjects
-
- cycle_manager = CycleManager(
- config,
- logger,
- simulation=simulation,
- process_manager=do_nothing_process_manager,
- )
-
- cycle_manager.current_cycle = 0
- cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert called == 1
-
- cycle_manager.current_cycle = 1
- cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert called == 1
-
- cycle_manager.current_cycle = 2
- cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert called == 2
-
- cycle_manager.current_cycle = 3
- cycle_manager._job_subjects(worker_id=0, process_count=1)
- assert called == 2
-
- def test_mechanism_not_called_if_simulation_behavior_cycled_not_active_yet(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
-
- pass
-
- def test_mechanism_not_called_if_subject_behavior_timebase_not_active_yet(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
-
- pass
-
- def test_mechanism_not_called_if_simulation_behavior_timebase_not_active_yet(
- self,
- do_nothing_process_manager: ProcessManager,
- ):
- shared.reset()
-
- pass
-
-
- # TODO: Test Simulation mechanism parralelisation
- # TODO: Test behaviour actions generation
|