Browse Source

add simulation behaviour tests

Bastien Sevajol 7 years ago
parent
commit
cc386e280c
2 changed files with 176 additions and 5 deletions
  1. 30 2
      synergine2/cycle.py
  2. 146 3
      tests/test_simulation.py

+ 30 - 2
synergine2/cycle.py View File

13
 from synergine2.simulation import Subject
13
 from synergine2.simulation import Subject
14
 from synergine2.simulation import Simulation
14
 from synergine2.simulation import Simulation
15
 from synergine2.simulation import SubjectBehaviour
15
 from synergine2.simulation import SubjectBehaviour
16
+from synergine2.simulation import SimulationBehaviour
16
 from synergine2.simulation import SubjectMechanism
17
 from synergine2.simulation import SubjectMechanism
18
+from synergine2.simulation import SimulationMechanism
17
 from synergine2.simulation import Event
19
 from synergine2.simulation import Event
18
 from synergine2.utils import time_it
20
 from synergine2.utils import time_it
19
 
21
 
84
     def _job_simulation(self, worker_id: int, process_count: int) -> typing.Dict[int, typing.Dict[str, typing.Any]]:
86
     def _job_simulation(self, worker_id: int, process_count: int) -> typing.Dict[int, typing.Dict[str, typing.Any]]:
85
         self.logger.info('Simulation computing (worker {})'.format(worker_id))
87
         self.logger.info('Simulation computing (worker {})'.format(worker_id))
86
 
88
 
87
-        mechanisms = self.simulation.mechanisms.values()
89
+        behaviours = self.get_simulation_active_behaviours()
90
+        mechanisms = self.get_mechanisms_from_behaviours(behaviours)
88
         mechanisms_data = {}
91
         mechanisms_data = {}
89
         behaviours_data = {}
92
         behaviours_data = {}
90
 
93
 
420
         behaviours = []
423
         behaviours = []
421
         for behaviour in subject.behaviours.values():
424
         for behaviour in subject.behaviours.values():
422
             if behaviour.is_skip(self.current_cycle):
425
             if behaviour.is_skip(self.current_cycle):
423
-                self.logger.debug('Simulation: behaviour {} skip'.format(
426
+                self.logger.debug('Subject {}: behaviour {} skip'.format(
427
+                    str(subject.id),
424
                     str(type(behaviour)),
428
                     str(type(behaviour)),
425
                 ))
429
                 ))
426
             else:
430
             else:
440
                     if isinstance(subject_mechanism, behaviour_mechanism_class):
444
                     if isinstance(subject_mechanism, behaviour_mechanism_class):
441
                         mechanisms.add(subject_mechanism)
445
                         mechanisms.add(subject_mechanism)
442
         return list(mechanisms)
446
         return list(mechanisms)
447
+
448
+    def get_simulation_active_behaviours(self) -> typing.List[SimulationBehaviour]:
449
+        behaviours = []
450
+        for behaviour in self.simulation.behaviours.values():
451
+            if behaviour.is_skip(self.current_cycle):
452
+                self.logger.debug('Simulation: behaviour {} skip'.format(
453
+                    str(type(behaviour)),
454
+                ))
455
+            else:
456
+                behaviours.append(behaviour)
457
+        return behaviours
458
+
459
+    def get_mechanisms_from_behaviours(
460
+        self,
461
+        behaviours: typing.List[SimulationBehaviour],
462
+    ) -> typing.List[SimulationMechanism]:
463
+        # TODO BS 20180109: Not very optimized ... could be enhanced
464
+        mechanisms = set()
465
+        for simulation_mechanism in self.simulation.mechanisms.values():
466
+            for simulation_behaviour in behaviours:
467
+                for simulation_mechanism_class in simulation_behaviour.use:
468
+                    if isinstance(simulation_mechanism, simulation_mechanism_class):
469
+                        mechanisms.add(simulation_mechanism)
470
+        return list(mechanisms)

+ 146 - 3
tests/test_simulation.py View File

519
         do_nothing_process_manager: ProcessManager,
519
         do_nothing_process_manager: ProcessManager,
520
     ):
520
     ):
521
         shared.reset()
521
         shared.reset()
522
+        global called
523
+        called = 0
524
+
525
+        class MySimulationMechanism(SimulationMechanism):
526
+            def run(self, process_number: int = None, process_count: int = None):
527
+                global called
528
+                called += 1
529
+                return {'foo': 42}
522
 
530
 
523
-        pass
531
+        class MySimulationBehaviour1(SimulationBehaviour):
532
+            use = [MySimulationMechanism]
533
+
534
+            @property
535
+            def cycle_frequency(self):
536
+                return 2
537
+
538
+            def run(self, data):
539
+                return {'bar': data[MySimulationMechanism]['foo'] + 100}
540
+
541
+        class MySimulation(Simulation):
542
+            behaviours_classes = [MySimulationBehaviour1]
543
+
544
+        simulation = MySimulation(config)
545
+        subjects = Subjects(simulation=simulation)
546
+        simulation.subjects = subjects
547
+
548
+        cycle_manager = CycleManager(
549
+            config,
550
+            logger,
551
+            simulation=simulation,
552
+            process_manager=do_nothing_process_manager,
553
+        )
554
+
555
+        cycle_manager.current_cycle = 0
556
+        cycle_manager._job_simulation(worker_id=0, process_count=1)
557
+        assert called == 1
558
+
559
+        cycle_manager.current_cycle = 1
560
+        cycle_manager._job_simulation(worker_id=0, process_count=1)
561
+        assert called == 1
562
+
563
+        cycle_manager.current_cycle = 2
564
+        cycle_manager._job_simulation(worker_id=0, process_count=1)
565
+        assert called == 2
566
+
567
+        cycle_manager.current_cycle = 3
568
+        cycle_manager._job_simulation(worker_id=0, process_count=1)
569
+        assert called == 2
524
 
570
 
525
     def test_mechanism_not_called_if_subject_behavior_timebase_not_active_yet(
571
     def test_mechanism_not_called_if_subject_behavior_timebase_not_active_yet(
526
         self,
572
         self,
527
         do_nothing_process_manager: ProcessManager,
573
         do_nothing_process_manager: ProcessManager,
528
     ):
574
     ):
529
         shared.reset()
575
         shared.reset()
576
+        global called
577
+        called = 0
578
+
579
+        class MySubjectMechanism(SubjectMechanism):
580
+            def run(self):
581
+                global called
582
+                called += 1
583
+                return {'foo': 42}
530
 
584
 
531
-        pass
585
+        class MySubjectBehaviour1(SubjectBehaviour):
586
+            use = [MySubjectMechanism]
587
+
588
+            @property
589
+            def seconds_frequency(self):
590
+                return 1.0
591
+
592
+            def run(self, data):
593
+                self.last_execution_time = time.time()
594
+                return {'bar': data[MySubjectMechanism]['foo'] + 100}
595
+
596
+        class MySubject(Subject):
597
+            behaviours_classes = [MySubjectBehaviour1]
598
+
599
+        simulation = Simulation(config)
600
+        my_subject = MySubject(config, simulation)
601
+        subjects = Subjects(simulation=simulation)
602
+        subjects.append(my_subject)
603
+        simulation.subjects = subjects
604
+
605
+        cycle_manager = CycleManager(
606
+            config,
607
+            logger,
608
+            simulation=simulation,
609
+            process_manager=do_nothing_process_manager,
610
+        )
611
+
612
+        with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0)):
613
+            cycle_manager._job_subjects(worker_id=0, process_count=1)
614
+            assert called == 1
615
+
616
+        with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0, 500000)):
617
+            cycle_manager._job_subjects(worker_id=0, process_count=1)
618
+            assert called == 1
619
+
620
+        with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0, 700000)):
621
+            cycle_manager._job_subjects(worker_id=0, process_count=1)
622
+            assert called == 1
623
+
624
+        with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 1, 500000)):
625
+            cycle_manager._job_subjects(worker_id=0, process_count=1)
626
+            assert called == 2
532
 
627
 
533
     def test_mechanism_not_called_if_simulation_behavior_timebase_not_active_yet(
628
     def test_mechanism_not_called_if_simulation_behavior_timebase_not_active_yet(
534
         self,
629
         self,
535
         do_nothing_process_manager: ProcessManager,
630
         do_nothing_process_manager: ProcessManager,
536
     ):
631
     ):
632
+
537
         shared.reset()
633
         shared.reset()
634
+        global called
635
+        called = 0
636
+
637
+        class MySimulationMechanism(SimulationMechanism):
638
+            def run(self, process_number: int = None, process_count: int = None):
639
+                global called
640
+                called += 1
641
+                return {'foo': 42}
642
+
643
+        class MySimulationBehaviour1(SimulationBehaviour):
644
+            use = [MySimulationMechanism]
645
+
646
+            @property
647
+            def seconds_frequency(self):
648
+                return 1.0
649
+
650
+            def run(self, data):
651
+                self.last_execution_time = time.time()
652
+                return {'bar': data[MySimulationMechanism]['foo'] + 100}
653
+
654
+        class MySimulation(Simulation):
655
+            behaviours_classes = [MySimulationBehaviour1]
656
+
657
+        simulation = MySimulation(config)
658
+        subjects = Subjects(simulation=simulation)
659
+        simulation.subjects = subjects
538
 
660
 
539
-        pass
661
+        cycle_manager = CycleManager(
662
+            config,
663
+            logger,
664
+            simulation=simulation,
665
+            process_manager=do_nothing_process_manager,
666
+        )
667
+
668
+        with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0, 0)):
669
+            cycle_manager._job_simulation(worker_id=0, process_count=1)
670
+            assert called == 1
671
+
672
+        with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0, 500000)):
673
+            cycle_manager._job_simulation(worker_id=0, process_count=1)
674
+            assert called == 1
675
+
676
+        with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 0, 700000)):
677
+            cycle_manager._job_simulation(worker_id=0, process_count=1)
678
+            assert called == 1
679
+
680
+        with freeze_time(datetime.datetime(2000, 12, 1, 0, 0, 1, 500000)):
681
+            cycle_manager._job_simulation(worker_id=0, process_count=1)
682
+            assert called == 2
540
 
683
 
541
 
684
 
542
 # TODO: Test Simulation mechanism parralelisation
685
 # TODO: Test Simulation mechanism parralelisation