Exemplo n.º 1
0
    def save_global_led_feedback_configuration(
            global_feedbacks,
            activate=True):  # type: (List[GlobalFeedbackDTO], bool) -> None
        # Important assumption in the below code to make this strategy solvable: If any of the 4 feedbacks is
        # given, they all are assumed to be given.
        global_configuration = GlobalConfiguration()
        if global_configuration.groupaction_any_output_changed > 255:
            group_action = GroupActionController.get_unused_group_action()
            if group_action is None:
                raise ValueError(
                    'No GroupAction available to store LED feedback configuration'
                )
        else:
            group_action = GroupActionController.load_group_action(
                global_configuration.groupaction_any_output_changed)

        for global_feedback_dto in global_feedbacks:
            holds_data, holds_configuration = CANFeedbackController._available_led_data(
                global_feedback_dto)
            if not holds_data:
                continue  # No change required
            # First, delete everything related to this global_feedback_dto
            if global_feedback_dto.id in [0, 16]:
                action = 73
                extra_parametery_msb = 0 if global_feedback_dto.id == 16 else 1
            else:
                action = 71 if 0 < global_feedback_dto.id < 16 else 70
                extra_parametery_msb = global_feedback_dto.id - (
                    1 if global_feedback_dto.id < 16 else 17)
            for basic_action in group_action.actions[:]:
                if basic_action.action_type == 20 and basic_action.action == action:
                    if basic_action.extra_parameter_msb == extra_parametery_msb:
                        group_action.actions.remove(basic_action)
            # Then, add the relevant entries back again
            if holds_configuration:
                for field in CANFeedbackController.FIELDS:
                    feedback_led_dto = getattr(global_feedback_dto, field)
                    if field in global_feedback_dto.loaded_fields and feedback_led_dto.id is not None:
                        basic_action = BasicAction(
                            action_type=20,
                            action=action,
                            device_nr=feedback_led_dto.id)
                        basic_action.extra_parameter_msb = extra_parametery_msb
                        basic_action.extra_parameter_lsb = CANFeedbackController._blinking_string_to_byte(
                            feedback_led_dto.function)
                        group_action.actions.append(basic_action)
        # Save changes
        if group_action.actions:
            if group_action.name == '':
                group_action.name = 'Global feedback'
            global_configuration.groupaction_any_output_changed = group_action.id
        else:
            group_action.name = ''
            global_configuration.groupaction_any_output_changed = CANFeedbackController.WORD_MAX
        global_configuration.save(activate=False)
        GroupActionController.save_group_action(group_action,
                                                ['name', 'actions'],
                                                activate=False)
        if activate:
            MemoryActivator.activate()
Exemplo n.º 2
0
    def test_save_configuration(self):
        memory = {}
        for page in range(256, 381):
            memory[page] = bytearray([255] * 256)
        GroupActionTest._setup_master_communicator(memory)

        group_action = GroupAction(id=5, name='five')
        GroupActionController.save_group_action(group_action, ['name'])

        self.assertEqual(GroupActionTest._encode_string('five'), memory[GroupActionTest.GANAMES_START_PAGE][5 * 16:5 * 16 + 5])
Exemplo n.º 3
0
 def save_output_led_feedback_configuration(output,
                                            output_dto,
                                            activate=True):
     # type: (OutputConfiguration, OutputDTO, bool) -> None
     holds_data, holds_configuration = CANFeedbackController._available_led_data(
         output_dto)
     if not holds_data:
         return  # No change required
     group_action_id = output.output_groupaction_follow
     group_action = None  # type: Optional[GroupAction]  # Needed for keeping Mypy happy...
     if group_action_id <= 255:
         group_action = GroupActionController.load_group_action(
             group_action_id)
         for basic_action in group_action.actions[:]:
             if basic_action.action_type == 20 and basic_action.action in [
                     50, 51
             ]:
                 group_action.actions.remove(basic_action)
     else:
         if not holds_configuration:
             return  # No GroupAction configured, and no configurion. Nothing to do.
         group_action = GroupActionController.get_unused_group_action()
         if group_action is None:
             raise ValueError(
                 'No GroupAction available to store LED feedback configuration'
             )
     for field in CANFeedbackController.FIELDS:
         feedback_led_dto = getattr(output_dto, field)
         if field in output_dto.loaded_fields and feedback_led_dto.id is not None:
             action = CANFeedbackController._inverted_string_to_action(
                 feedback_led_dto.function)
             basic_action = BasicAction(action_type=20,
                                        action=action,
                                        device_nr=feedback_led_dto.id)
             basic_action.extra_parameter_lsb = CANFeedbackController._blinking_string_to_byte(
                 feedback_led_dto.function)
             basic_action.extra_parameter_msb = CANFeedbackController._brightness_string_to_byte(
                 feedback_led_dto.function)
             group_action.actions.append(basic_action)
     if group_action.actions:
         if group_action.name == '':
             group_action.name = 'Output {0}'.format(output.id)
         output.output_groupaction_follow = group_action.id
     else:
         group_action.name = ''
         output.output_groupaction_follow = CANFeedbackController.WORD_MAX
     output.save(activate=False)
     GroupActionController.save_group_action(group_action,
                                             ['name', 'actions'],
                                             activate=False)
     if activate:
         MemoryActivator.activate()
Exemplo n.º 4
0
 def load_output_led_feedback_configuration(output, output_dto):
     # type: (OutputConfiguration, OutputDTO) -> None
     if output.output_groupaction_follow > 255:
         output_dto.can_led_1 = FeedbackLedDTO(
             id=None, function=FeedbackLedDTO.Functions.UNKNOWN)
         output_dto.can_led_2 = FeedbackLedDTO(
             id=None, function=FeedbackLedDTO.Functions.UNKNOWN)
         output_dto.can_led_3 = FeedbackLedDTO(
             id=None, function=FeedbackLedDTO.Functions.UNKNOWN)
         output_dto.can_led_4 = FeedbackLedDTO(
             id=None, function=FeedbackLedDTO.Functions.UNKNOWN)
         return
     group_action = GroupActionController.load_group_action(
         output.output_groupaction_follow)
     led_counter = 1
     for basic_action in group_action.actions:
         if basic_action.action_type == 20 and basic_action.action in [
                 50, 51
         ]:
             brightness = CANFeedbackController._byte_to_brightness_string(
                 basic_action.extra_parameter_msb)
             blinking = CANFeedbackController._byte_to_blinking_string(
                 basic_action.extra_parameter_lsb)
             inverted = CANFeedbackController._action_to_inverted_string(
                 basic_action.action)
             function = '{0} {1}{2}'.format(blinking, brightness, inverted)
             setattr(
                 output_dto, 'can_led_{0}'.format(led_counter),
                 FeedbackLedDTO(id=basic_action.device_nr,
                                function=function))
             led_counter += 1
             if led_counter > 4:
                 break
Exemplo n.º 5
0
    def test_space_map(self):
        memory = {}
        for page in range(256, 381):
            memory[page] = bytearray([255] * 256)
        GroupActionTest._setup_master_communicator(memory)

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual({4200: [0]}, space_map, 'An empty map is expected')

        # Write a single start address
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 0 * 4, self._word_helper.encode(0))

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual({4200: [0]}, space_map, 'There should still be an empty map')

        # Write an end address
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 0 * 4 + 2, self._word_helper.encode(0))

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual({4199: [1]}, space_map, 'First address is used')

        # Write a few more addresses:
        # Range 0-0 already used by above code
        # Range 1-9 (0)
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 1 * 4, self._word_helper.encode(10) + self._word_helper.encode(14))
        # Range 15-19 (5)
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 2 * 4, self._word_helper.encode(20) + self._word_helper.encode(24))
        # Range 25-29 (5)
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 4 * 4, self._word_helper.encode(30) + self._word_helper.encode(34))
        # Range 35-99 (65)
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 3 * 4, self._word_helper.encode(100) + self._word_helper.encode(163))
        # Range 164-4199 (4036)

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual({9: [1],
                          5: [15, 25],
                          65: [35],
                          4036: [164]}, space_map, 'Expect a few gaps')
Exemplo n.º 6
0
 def load_global_led_feedback_configuration(
 ):  # type: () -> Dict[int, GlobalFeedbackDTO]
     global_feedbacks = {}  # type: Dict[int, GlobalFeedbackDTO]
     global_feedback_led_counter = {}
     global_configuration = GlobalConfiguration()
     if global_configuration.groupaction_any_output_changed > 255:
         return global_feedbacks
     group_action = GroupActionController.load_group_action(
         global_configuration.groupaction_any_output_changed)
     for basic_action in group_action.actions:
         if basic_action.action_type != 20 or basic_action.action not in [
                 70, 71, 73
         ]:  # 70 = # outputs, 71 = # lights, 72 = # outputs + lights
             continue
         # For the calculation of this `global_feedback_id`, see `master.classic.eeprom_models.CanLedConfiguration` docstring
         if basic_action.action == 73:
             # 73 is the "zero-case": extra_parametery.msb = 0 -> # outputs,
             #                        extra_parametery.msb = 1 -> # lights,
             #                        extra_parametery.msb = 2 -> # outputs + lights
             appliance_type = basic_action.extra_parameter_msb
             if appliance_type not in [0, 1]:
                 continue  # Unsupported
             global_feedback_id = 0 if appliance_type == 1 else 16
         else:
             nr_of_appliances = basic_action.extra_parameter_msb
             if nr_of_appliances > 14:
                 continue  # Unsupported
             global_feedback_id = nr_of_appliances + 1 + (
                 0 if basic_action.action == 71 else 16)
         if global_feedback_id not in global_feedbacks:
             global_feedbacks[global_feedback_id] = GlobalFeedbackDTO(
                 id=global_feedback_id)
             global_feedback_led_counter[global_feedback_id] = 1
         global_feedback_dto = global_feedbacks[global_feedback_id]
         led_counter = global_feedback_led_counter[global_feedback_id]
         if led_counter > 4:
             continue  # No space remaining
         blinking = CANFeedbackController._byte_to_blinking_string(
             basic_action.extra_parameter_lsb)
         function = '{0} B16'.format(blinking)
         setattr(
             global_feedback_dto, 'can_led_{0}'.format(led_counter),
             FeedbackLedDTO(id=basic_action.device_nr, function=function))
         led_counter += 1
         global_feedbacks[global_feedback_id] = global_feedback_dto
         global_feedback_led_counter[global_feedback_id] = led_counter
     return global_feedbacks
Exemplo n.º 7
0
    def test_individual_feedback_leds(self):
        output = OutputConfiguration.deserialize({'id': 0})
        # Setup basic LED feedback
        output_dto = OutputDTO(
            id=0,
            can_led_1=FeedbackLedDTO(
                id=5, function=FeedbackLedDTO.Functions.ON_B16_NORMAL),
            can_led_3=FeedbackLedDTO(
                id=7, function=FeedbackLedDTO.Functions.MB_B8_INVERTED))

        # Save led feedback config
        CANFeedbackController.save_output_led_feedback_configuration(
            output, output_dto)

        # Validate correct data in created GA
        self.assertEqual(0, output.output_groupaction_follow)
        group_action = GroupActionController.load_group_action(0)
        self.assertEqual([
            BasicAction(
                action_type=20, action=50, device_nr=5, extra_parameter=65280),
            BasicAction(
                action_type=20, action=51, device_nr=7, extra_parameter=32514)
        ], group_action.actions)
        self.assertEqual('Output 0', group_action.name)

        # Alter GA
        extra_ba = BasicAction(action_type=123, action=123)  # Some random BA
        group_action.actions.append(extra_ba)
        group_action.name = 'Foobar'
        GroupActionController.save_group_action(group_action,
                                                ['name', 'actions'])

        # Validate loading data
        output_dto = OutputDTO(id=0)
        CANFeedbackController.load_output_led_feedback_configuration(
            output, output_dto)
        self.assertEqual(
            FeedbackLedDTO(id=5,
                           function=FeedbackLedDTO.Functions.ON_B16_NORMAL),
            output_dto.can_led_1)
        self.assertEqual(
            FeedbackLedDTO(id=7,
                           function=FeedbackLedDTO.Functions.MB_B8_INVERTED),
            output_dto.can_led_2)  # Moved to 2

        # Change led feedback config
        output_dto.can_led_2.function = FeedbackLedDTO.Functions.ON_B8_INVERTED
        CANFeedbackController.save_output_led_feedback_configuration(
            output, output_dto)

        # Validate stored led feedback data
        output_dto = OutputDTO(id=0)
        CANFeedbackController.load_output_led_feedback_configuration(
            output, output_dto)
        self.assertEqual(
            FeedbackLedDTO(id=5,
                           function=FeedbackLedDTO.Functions.ON_B16_NORMAL),
            output_dto.can_led_1)
        self.assertEqual(
            FeedbackLedDTO(id=7,
                           function=FeedbackLedDTO.Functions.ON_B8_INVERTED),
            output_dto.can_led_2)

        # Validate GA changes
        group_action = GroupActionController.load_group_action(0)
        self.assertEqual([extra_ba] + [
            BasicAction(
                action_type=20, action=50, device_nr=5, extra_parameter=65280),
            BasicAction(
                action_type=20, action=51, device_nr=7, extra_parameter=32512)
        ], group_action.actions)
        self.assertEqual('Foobar', group_action.name)
Exemplo n.º 8
0
    def test_global_feedback_leds(self):
        global_configuration = GlobalConfiguration()

        # Verify base
        self.assertEqual(65535,
                         global_configuration.groupaction_any_output_changed)
        self.assertEqual(
            {}, CANFeedbackController.load_global_led_feedback_configuration())

        # Store feedback "0" (nr of lights == 0)
        global_feedback_0 = GlobalFeedbackDTO(
            id=0,
            can_led_1=FeedbackLedDTO(
                id=5, function=FeedbackLedDTO.Functions.ON_B16_NORMAL),
            can_led_3=FeedbackLedDTO(
                id=7, function=FeedbackLedDTO.Functions.ON_B8_INVERTED),
            can_led_4=FeedbackLedDTO(
                id=9, function=FeedbackLedDTO.Functions.FB_B8_NORMAL))
        CANFeedbackController.save_global_led_feedback_configuration(
            [global_feedback_0])

        #                                                                                                 +- 256 = MSB is 1 = lights
        # Validate                                                                                        |   +- 0 = Solid on, 1 = Fast blinking
        expected_basic_actions_0 = [
            BasicAction(action_type=20,
                        action=73,
                        device_nr=5,
                        extra_parameter=256 + 0),
            BasicAction(action_type=20,
                        action=73,
                        device_nr=7,
                        extra_parameter=256 + 0),
            BasicAction(action_type=20,
                        action=73,
                        device_nr=9,
                        extra_parameter=256 + 1)
        ]
        expected_global_feedback_0 = GlobalFeedbackDTO(
            id=0,
            can_led_1=FeedbackLedDTO(
                id=5, function=FeedbackLedDTO.Functions.ON_B16_NORMAL),
            can_led_2=FeedbackLedDTO(
                id=7, function=FeedbackLedDTO.Functions.ON_B16_NORMAL),
            can_led_3=FeedbackLedDTO(
                id=9, function=FeedbackLedDTO.Functions.FB_B16_NORMAL))
        global_configuration = GlobalConfiguration()
        group_action = GroupActionController.load_group_action(0)
        self.assertEqual(0,
                         global_configuration.groupaction_any_output_changed)
        self.assertEqual('Global feedback', group_action.name)
        self.assertEqual(expected_basic_actions_0, group_action.actions)
        self.assertEqual(
            {0: expected_global_feedback_0},
            CANFeedbackController.load_global_led_feedback_configuration())

        # Prepare feedback "3" (nr of lights > 2)
        global_feedback_3 = GlobalFeedbackDTO(
            id=3,
            can_led_1=FeedbackLedDTO(
                id=11, function=FeedbackLedDTO.Functions.ON_B16_NORMAL),
            can_led_3=FeedbackLedDTO(
                id=13, function=FeedbackLedDTO.Functions.FB_B8_INVERTED))
        expected_global_feedback_3 = GlobalFeedbackDTO(
            id=3,
            can_led_1=FeedbackLedDTO(
                id=11, function=FeedbackLedDTO.Functions.ON_B16_NORMAL),
            can_led_2=FeedbackLedDTO(
                id=13, function=FeedbackLedDTO.Functions.FB_B16_NORMAL))
        expected_basic_actions_3 = [
            BasicAction(action_type=20,
                        action=71,
                        device_nr=11,
                        extra_parameter=512 + 0),
            BasicAction(action_type=20,
                        action=71,
                        device_nr=13,
                        extra_parameter=512 + 1)
        ]
        #                                                                                                |   +- 0 = Solid on, 1 = Fast blinking
        #                                                                                                +- 512 = MSB is 2 = nr of lights

        # Store in various scenarios, all should yield the same response
        save_scenarios = [[global_feedback_3],
                          [global_feedback_0, global_feedback_3]]
        for save_scenario in save_scenarios:
            CANFeedbackController.save_global_led_feedback_configuration(
                save_scenario)

            global_configuration = GlobalConfiguration()
            group_action = GroupActionController.load_group_action(0)
            self.assertEqual(
                0, global_configuration.groupaction_any_output_changed)
            self.assertEqual(
                expected_basic_actions_0 + expected_basic_actions_3,
                group_action.actions)
            self.assertEqual(
                {
                    0: expected_global_feedback_0,
                    3: expected_global_feedback_3
                },
                CANFeedbackController.load_global_led_feedback_configuration())

        # Add extra BA that should not be removed by altering global feedback
        extra_basic_actions = [BasicAction(action_type=123, action=123)]
        group_action.actions += extra_basic_actions
        group_action.name = 'Foobar'
        GroupActionController.save_group_action(group_action,
                                                ['name', 'actions'])

        # Save without scenario (will re-save data, but should not alter)
        CANFeedbackController.save_global_led_feedback_configuration([])
        group_action = GroupActionController.load_group_action(0)
        self.assertEqual('Foobar', group_action.name)
        self.assertEqual(
            expected_basic_actions_0 + expected_basic_actions_3 +
            extra_basic_actions, group_action.actions)

        # Save full scenario (will remove feedback BAs and save them again at the end of the GA)
        CANFeedbackController.save_global_led_feedback_configuration(
            save_scenarios[1])
        group_action = GroupActionController.load_group_action(0)
        self.assertEqual('Foobar', group_action.name)
        self.assertEqual(
            extra_basic_actions + expected_basic_actions_0 +
            expected_basic_actions_3, group_action.actions)

        # Prepare feedbacks "16" (nr of outputs == 0) and "20" (nr of outputs > 3)
        global_feedback_16 = GlobalFeedbackDTO(
            id=16,
            can_led_1=FeedbackLedDTO(
                id=15, function=FeedbackLedDTO.Functions.ON_B16_NORMAL))
        global_feedback_20 = GlobalFeedbackDTO(
            id=20,
            can_led_1=FeedbackLedDTO(
                id=17, function=FeedbackLedDTO.Functions.ON_B16_NORMAL))
        expected_global_feedback_16 = GlobalFeedbackDTO(
            id=16,
            can_led_1=FeedbackLedDTO(
                id=15, function=FeedbackLedDTO.Functions.ON_B16_NORMAL))
        expected_global_feedback_20 = GlobalFeedbackDTO(
            id=20,
            can_led_1=FeedbackLedDTO(
                id=17, function=FeedbackLedDTO.Functions.ON_B16_NORMAL))
        expected_basic_actions_16 = [
            BasicAction(action_type=20,
                        action=73,
                        device_nr=15,
                        extra_parameter=0 + 0)
        ]  # 0 = MSB is 0 = outputs
        expected_basic_actions_20 = [
            BasicAction(action_type=20,
                        action=70,
                        device_nr=17,
                        extra_parameter=768 + 0)
        ]  # 768 = MSB is 3 = nr of outputs

        # Store
        CANFeedbackController.save_global_led_feedback_configuration([
            global_feedback_0, global_feedback_3, global_feedback_16,
            global_feedback_20
        ])

        # Validate
        global_configuration = GlobalConfiguration()
        group_action = GroupActionController.load_group_action(0)
        self.assertEqual(0,
                         global_configuration.groupaction_any_output_changed)
        self.assertEqual(
            extra_basic_actions + expected_basic_actions_0 +
            expected_basic_actions_3 + expected_basic_actions_16 +
            expected_basic_actions_20, group_action.actions)
        self.assertEqual(
            {
                0: expected_global_feedback_0,
                3: expected_global_feedback_3,
                16: expected_global_feedback_16,
                20: expected_global_feedback_20
            }, CANFeedbackController.load_global_led_feedback_configuration())

        # Remove 3
        empty_global_feedback_3 = GlobalFeedbackDTO(id=3,
                                                    can_led_1=None,
                                                    can_led_2=None,
                                                    can_led_3=None,
                                                    can_led_4=None)
        CANFeedbackController.save_global_led_feedback_configuration(
            [empty_global_feedback_3, global_feedback_20])

        # Validate
        global_configuration = GlobalConfiguration()
        group_action = GroupActionController.load_group_action(0)
        self.assertEqual(0,
                         global_configuration.groupaction_any_output_changed)
        self.assertEqual(
            extra_basic_actions + expected_basic_actions_0 +
            expected_basic_actions_16 + expected_basic_actions_20,
            group_action.actions)
        self.assertEqual(
            {
                0: expected_global_feedback_0,
                16: expected_global_feedback_16,
                20: expected_global_feedback_20
            }, CANFeedbackController.load_global_led_feedback_configuration())
Exemplo n.º 9
0
    def test_save_allocations(self):
        """
        This test validates whether writing a GA will store its BAs in the appropriate location. This
        is checked on two ways:
        1. A free space map is generated that is used to validate where the free slots are located
        2. A human readable / visual overview is generated of all BA's action type values in the first 42 addresses
           Legend: X = Used by a few pre-defined GAs
                   n = Actual data, as every insert uses different action types, this can be used to verify
                       whether data is written correctly, as whether the old data is overwritten when needed.
                   _ = Slot that was never used
        Note: As an allocation table is used, the BA space is not cleared, only the reference is removed!
        """
        memory = {}
        for page in range(256, 381):
            memory[page] = bytearray([255] * 256)
        GroupActionTest._setup_master_communicator(memory)

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('__________________________________________', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({4200: [0]}, space_map)

        # Generate "pre-defined" GAs
        for group_action_id, address in {10: 0, 11: 2, 12: 5, 13: 8, 14: 14, 15: 25, 16: (41, 4199)}.items():
            start, end = (address[0], address[1]) if isinstance(address, tuple) else (address, address)
            GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], group_action_id * 4, self._word_helper.encode(start) + self._word_helper.encode(end))
            memory[GroupActionTest.ACTIONS_START_PAGE][start * 6] = 100 + group_action_id

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X_X__X__X_____X__________X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({1: [1],
                          2: [3, 6],
                          5: [9],
                          10: [15],
                          15: [26]}, space_map)

        # Store GA with 1 BA
        group_action_1 = GroupAction(id=1, actions=[BasicAction(1, 0)])
        GroupActionController.save_group_action(group_action_1, ['actions'])

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X1X__X__X_____X__________X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({2: [3, 6],
                          5: [9],
                          10: [15],
                          15: [26]}, space_map)

        # Store another GA with 1 BA
        group_action_2 = GroupAction(id=2, actions=[BasicAction(2, 0)])
        GroupActionController.save_group_action(group_action_2, ['actions'])

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X1X2_X__X_____X__________X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({1: [4],
                          2: [6],
                          5: [9],
                          10: [15],
                          15: [26]}, space_map)

        # GA is update dto two BAs
        group_action_2 = GroupAction(id=2, actions=[BasicAction(3, 0),
                                                    BasicAction(3, 0)])
        GroupActionController.save_group_action(group_action_2, ['actions'])

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X1X33X__X_____X__________X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({2: [6],
                          5: [9],
                          10: [15],
                          15: [26]}, space_map)

        # First GA is extended
        group_action_1 = GroupAction(id=1, actions=[BasicAction(4, 0),
                                                    BasicAction(4, 0)])
        GroupActionController.save_group_action(group_action_1, ['actions'])

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X1X33X44X_____X__________X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({1: [1],
                          5: [9],
                          10: [15],
                          15: [26]}, space_map)

        # Add large GA
        group_action_3 = GroupAction(id=3, actions=[BasicAction(5, 0), BasicAction(5, 0), BasicAction(5, 0),
                                                    BasicAction(5, 0), BasicAction(5, 0), BasicAction(5, 0)])
        GroupActionController.save_group_action(group_action_3, ['actions'])

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X1X33X44X_____X555555____X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({1: [1],
                          4: [21],
                          5: [9],
                          15: [26]}, space_map)

        # Large GA is reduced
        group_action_3 = GroupAction(id=3, actions=[BasicAction(6, 0), BasicAction(6, 0), BasicAction(6, 0)])
        GroupActionController.save_group_action(group_action_3, ['actions'])

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X1X33X44X666__X555555____X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({1: [1],
                          2: [12],
                          10: [15],
                          15: [26]}, space_map, 'Reduced GA should be moved')

        # Another GA is added with only one BA
        group_action_4 = GroupAction(id=4, actions=[BasicAction(7, 0)])
        GroupActionController.save_group_action(group_action_4, ['actions'])

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X7X33X44X666__X555555____X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({2: [12],
                          10: [15],
                          15: [26]}, space_map, 'Reduced GA should be moved')

        # Another large GA is added
        group_action_5 = GroupAction(id=5, actions=[BasicAction(8, 0), BasicAction(8, 0), BasicAction(8, 0),
                                                    BasicAction(8, 0)])
        GroupActionController.save_group_action(group_action_5, ['actions'])

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X7X33X44X666__X888855____X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({2: [12],
                          6: [19],
                          15: [26]}, space_map, 'Reduced GA should be moved')

        # Large GA is "deleted"
        group_action_5 = GroupAction(id=5, actions=[])
        GroupActionController.save_group_action(group_action_5, ['actions'])

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X7X33X44X666__X888855____X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({2: [12],
                          10: [15],
                          15: [26]}, space_map, 'Reduced GA should be moved')

        # A GA with too many BAs is added
        group_action_6 = GroupAction(id=6, actions=[BasicAction(8, 0)] * 16)
        with self.assertRaises(RuntimeError):
            GroupActionController.save_group_action(group_action_6, ['actions'])

        space_map = GroupActionController._free_address_space_map()
        self.assertEqual('X7X33X44X666__X888855____X_______________X', GroupActionTest._get_readable_ba_block(memory))
        #                 |    |    |    |    |    |    |    |    |
        #                 0    5    10   15   20   25   30   35   40
        self.assertEqual({2: [12],
                          10: [15],
                          15: [26]}, space_map, 'Memory is not changed')
Exemplo n.º 10
0
    def test_list_group_actions(self):
        memory = {}
        for page in range(256, 381):
            memory[page] = bytearray([255] * 256)
        GroupActionTest._setup_master_communicator(memory)

        group_actions = GroupActionController.load_group_actions()
        self.assertEqual(256, len(group_actions), 'There should be 256 GAs')
        for i in range(256):
            self.assertFalse(group_actions[i].in_use, 'GA {0} should not be in use'.format(i))

        # Set valid start address
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 0 * 4, self._word_helper.encode(0))

        group_actions = GroupActionController.load_group_actions()
        self.assertEqual(256, len(group_actions), 'There should still be 256 GAs')
        for i in range(256):
            self.assertFalse(group_actions[i].in_use, 'GA {0} should not be in use'.format(i))

        group_action = GroupActionController.load_group_action(0)
        self.assertEqual(group_actions[0], group_action, 'The GA is equal (same id, same name, same in_use state)')
        self.assertFalse(group_action.in_use, 'The GA is still not in use')

        # Add BA at start address and set a name
        basic_action_1 = BasicAction(0, 0)
        GroupActionTest._write(memory[GroupActionTest.ACTIONS_START_PAGE], 0 * 6, basic_action_1.encode())
        GroupActionTest._write(memory[GroupActionTest.GANAMES_START_PAGE], 0 * 16, GroupActionTest._encode_string('test'))

        group_action = GroupActionController.load_group_action(0)
        self.assertNotEqual(group_actions[0], group_action, 'The GA changed (name is set)')
        self.assertEqual('test', group_action.name)
        self.assertFalse(group_action.in_use, 'The GA is still not in use')

        # Write valid end address but remove BA
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 0 * 4 + 2, self._word_helper.encode(0))
        GroupActionTest._write(memory[GroupActionTest.ACTIONS_START_PAGE], 0 * 6, [255, 255, 255, 255, 255, 255])

        group_action = GroupActionController.load_group_action(0)
        self.assertFalse(group_action.in_use, 'The GA is not in use yet (no BAs defined)')

        # Restore BA
        GroupActionTest._write(memory[GroupActionTest.ACTIONS_START_PAGE], 0 * 6, basic_action_1.encode())

        group_action = GroupActionController.load_group_action(0)
        self.assertTrue(group_action.in_use, 'The GA is now in use (has name and BA)')
        self.assertEqual(1, len(group_action.actions), 'There should be one GA')
        self.assertEqual(basic_action_1, group_action.actions[0], 'The expected BA should be configured')

        # Make the GA point to two BAs
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 0 * 4 + 2, self._word_helper.encode(1))

        group_action = GroupActionController.load_group_action(0)
        self.assertTrue(group_action.in_use, 'The GA is still in use')
        self.assertEqual(1, len(group_action.actions), 'An empty BA should be excluded')
        self.assertEqual(basic_action_1, group_action.actions[0], 'The valid BA should still be included')

        # Write second BA
        basic_action_2 = BasicAction(0, 1)
        GroupActionTest._write(memory[GroupActionTest.ACTIONS_START_PAGE], 1 * 6, basic_action_2.encode())

        group_action = GroupActionController.load_group_action(0)
        self.assertTrue(group_action.in_use, 'The GA is still in use')
        self.assertEqual(2, len(group_action.actions), 'Both BAs should be included')
        self.assertEqual([basic_action_1, basic_action_2], group_action.actions, 'The valid BAs should be included')

        group_actions = GroupActionController.load_group_actions()
        self.assertEqual(256, len(group_actions), 'There should be 256 GAs')
        for i in range(1, 256):
            self.assertFalse(group_actions[i].in_use, 'GA {0} should not be in use'.format(i))
        self.assertEqual(group_action, group_actions[0], 'The list should correctly point to the first GA')

        # Set name of third GA, store BA and set addresses
        basic_action_3 = BasicAction(0, 2)
        GroupActionTest._write(memory[GroupActionTest.ACTIONS_START_PAGE], 2 * 6, basic_action_3.encode())
        GroupActionTest._write(memory[GroupActionTest.GANAMES_START_PAGE], 2 * 16, GroupActionTest._encode_string('three'))
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 2 * 4, self._word_helper.encode(2))
        GroupActionTest._write(memory[GroupActionTest.ADDRESS_START_PAGE], 2 * 4 + 2, self._word_helper.encode(2))

        group_action_2 = GroupActionController.load_group_action(2)
        group_actions = GroupActionController.load_group_actions()
        self.assertEqual(256, len(group_actions), 'There should be 256 GAs')
        for i in range(0, 256):
            if i in [0, 2]:
                continue
            self.assertFalse(group_actions[i].in_use, 'GA {0} should not be in use'.format(i))
        self.assertEqual(group_action, group_actions[0], 'The list should correctly point to the first GA')
        self.assertEqual(group_action_2, group_actions[2], 'The list should correctly point to the first GA')