Home | History | Annotate | Download | only in tests
      1 #!/usr/bin/env python3.4
      2 #
      3 #   Copyright 2016 - The Android Open Source Project
      4 #
      5 #   Licensed under the Apache License, Version 2.0 (the "License");
      6 #   you may not use this file except in compliance with the License.
      7 #   You may obtain a copy of the License at
      8 #
      9 #       http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 #   Unless required by applicable law or agreed to in writing, software
     12 #   distributed under the License is distributed on an "AS IS" BASIS,
     13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 #   See the License for the specific language governing permissions and
     15 #   limitations under the License.
     16 
     17 import copy
     18 import os
     19 import tempfile
     20 import shutil
     21 import unittest
     22 
     23 from acts.controllers.relay_lib import generic_relay_device
     24 from acts.controllers.relay_lib import relay
     25 from acts.controllers.relay_lib import relay_board
     26 from acts.controllers.relay_lib import relay_device
     27 from acts.controllers.relay_lib import relay_rig
     28 from acts.controllers.relay_lib import sain_smart_board
     29 
     30 import acts.controllers.relay_lib.errors as errors
     31 import acts.controllers.relay_lib.fugu_remote as fugu_remote
     32 
     33 # Shorthand versions of the long class names.
     34 GenericRelayDevice = generic_relay_device.GenericRelayDevice
     35 Relay = relay.Relay
     36 RelayDict = relay.RelayDict
     37 RelayState = relay.RelayState
     38 SynchronizeRelays = relay.SynchronizeRelays
     39 RelayBoard = relay_board.RelayBoard
     40 RelayDevice = relay_device.RelayDevice
     41 RelayRig = relay_rig.RelayRig
     42 SainSmartBoard = sain_smart_board.SainSmartBoard
     43 
     44 
     45 class MockBoard(RelayBoard):
     46     def __init__(self, config):
     47         self.relay_states = dict()
     48         self.relay_previous_states = dict()
     49         RelayBoard.__init__(self, config)
     50 
     51     def get_relay_position_list(self):
     52         return [0, 1]
     53 
     54     def get_relay_status(self, relay_position):
     55         if relay_position not in self.relay_states:
     56             self.relay_states[relay_position] = RelayState.NO
     57             self.relay_previous_states[relay_position] = RelayState.NO
     58         return self.relay_states[relay_position]
     59 
     60     def set(self, relay_position, state):
     61         self.relay_previous_states[relay_position] = self.get_relay_status(
     62             relay_position)
     63         self.relay_states[relay_position] = state
     64         return state
     65 
     66 
     67 class ActsRelayTest(unittest.TestCase):
     68     def setUp(self):
     69         Relay.transition_wait_time = 0
     70         Relay.button_press_time = 0
     71         self.config = {
     72             'name': 'MockBoard',
     73             'relays': [{
     74                 'name': 'Relay',
     75                 'relay_pos': 0
     76             }]
     77         }
     78         self.board = MockBoard(self.config)
     79         self.relay = Relay(self.board, 'Relay')
     80         self.board.set(self.relay.position, RelayState.NO)
     81 
     82     def tearDown(self):
     83         Relay.transition_wait_time = .2
     84         Relay.button_press_time = .25
     85 
     86     def test_turn_on_from_off(self):
     87         self.board.set(self.relay.position, RelayState.NO)
     88         self.relay.set_nc()
     89         self.assertEqual(
     90             self.board.get_relay_status(self.relay.position), RelayState.NC)
     91 
     92     def test_turn_on_from_on(self):
     93         self.board.set(self.relay.position, RelayState.NC)
     94         self.relay.set_nc()
     95         self.assertEqual(
     96             self.board.get_relay_status(self.relay.position), RelayState.NC)
     97 
     98     def test_turn_off_from_on(self):
     99         self.board.set(self.relay.position, RelayState.NC)
    100         self.relay.set_no()
    101         self.assertEqual(
    102             self.board.get_relay_status(self.relay.position), RelayState.NO)
    103 
    104     def test_turn_off_from_off(self):
    105         self.board.set(self.relay.position, RelayState.NO)
    106         self.relay.set_no()
    107         self.assertEqual(
    108             self.board.get_relay_status(self.relay.position), RelayState.NO)
    109 
    110     def test_toggle_off_to_on(self):
    111         self.board.set(self.relay.position, RelayState.NO)
    112         self.relay.toggle()
    113         self.assertEqual(
    114             self.board.get_relay_status(self.relay.position), RelayState.NC)
    115 
    116     def test_toggle_on_to_off(self):
    117         self.board.set(self.relay.position, RelayState.NC)
    118         self.relay.toggle()
    119         self.assertEqual(
    120             self.board.get_relay_status(self.relay.position), RelayState.NO)
    121 
    122     def test_set_on(self):
    123         self.board.set(self.relay.position, RelayState.NO)
    124         self.relay.set(RelayState.NC)
    125         self.assertEqual(
    126             self.board.get_relay_status(self.relay.position), RelayState.NC)
    127 
    128     def test_set_off(self):
    129         self.board.set(self.relay.position, RelayState.NC)
    130         self.relay.set(RelayState.NO)
    131         self.assertEqual(
    132             self.board.get_relay_status(self.relay.position), RelayState.NO)
    133 
    134     def test_set_foo(self):
    135         with self.assertRaises(ValueError):
    136             self.relay.set('FOO')
    137 
    138     def test_set_nc_for(self):
    139         # Here we set twice so relay_previous_state will also be OFF
    140         self.board.set(self.relay.position, RelayState.NO)
    141         self.board.set(self.relay.position, RelayState.NO)
    142 
    143         self.relay.set_nc_for(0)
    144 
    145         self.assertEqual(
    146             self.board.get_relay_status(self.relay.position), RelayState.NO)
    147         self.assertEqual(self.board.relay_previous_states[self.relay.position],
    148                          RelayState.NC)
    149 
    150     def test_set_no_for(self):
    151         # Here we set twice so relay_previous_state will also be OFF
    152         self.board.set(self.relay.position, RelayState.NC)
    153         self.board.set(self.relay.position, RelayState.NC)
    154 
    155         self.relay.set_no_for(0)
    156 
    157         self.assertEqual(
    158             self.board.get_relay_status(self.relay.position), RelayState.NC)
    159         self.assertEqual(self.board.relay_previous_states[self.relay.position],
    160                          RelayState.NO)
    161 
    162     def test_get_status_on(self):
    163         self.board.set(self.relay.position, RelayState.NC)
    164         self.assertEqual(self.relay.get_status(), RelayState.NC)
    165 
    166     def test_get_status_off(self):
    167         self.board.set(self.relay.position, RelayState.NO)
    168         self.assertEqual(self.relay.get_status(), RelayState.NO)
    169 
    170     def test_clean_up_default_on(self):
    171         new_relay = Relay(self.board, 0)
    172         new_relay._original_state = RelayState.NO
    173         self.board.set(new_relay.position, RelayState.NO)
    174         new_relay.clean_up()
    175 
    176         self.assertEqual(
    177             self.board.get_relay_status(new_relay.position), RelayState.NO)
    178 
    179     def test_clean_up_default_off(self):
    180         new_relay = Relay(self.board, 0)
    181         new_relay._original_state = RelayState.NO
    182         self.board.set(new_relay.position, RelayState.NC)
    183         new_relay.clean_up()
    184 
    185         self.assertEqual(
    186             self.board.get_relay_status(new_relay.position), RelayState.NO)
    187 
    188     def test_clean_up_original_state_none(self):
    189         val = 'STAYS_THE_SAME'
    190         new_relay = Relay(self.board, 0)
    191         # _original_state is none by default
    192         # The line below sets the dict to an impossible value.
    193         self.board.set(new_relay.position, val)
    194         new_relay.clean_up()
    195         # If the impossible value is cleared, then the test should fail.
    196         self.assertEqual(self.board.get_relay_status(new_relay.position), val)
    197 
    198 
    199 class ActsSainSmartBoardTest(unittest.TestCase):
    200     STATUS_MSG = ('<small><a href="{}"></a>'
    201                   '</small><a href="{}/{}TUX">{}TUX</a><p>')
    202 
    203     RELAY_ON_PAGE_CONTENTS = 'relay_on page'
    204     RELAY_OFF_PAGE_CONTENTS = 'relay_off page'
    205 
    206     def setUp(self):
    207         Relay.transition_wait_time = 0
    208         Relay.button_press_time = 0
    209         self.test_dir = 'file://' + tempfile.mkdtemp() + '/'
    210 
    211         # Creates the files used for testing
    212         self._set_status_page('0000000000000000')
    213         with open(self.test_dir[7:] + '00', 'w+') as file:
    214             file.write(self.RELAY_OFF_PAGE_CONTENTS)
    215         with open(self.test_dir[7:] + '01', 'w+') as file:
    216             file.write(self.RELAY_ON_PAGE_CONTENTS)
    217 
    218         self.config = ({
    219             'name': 'SSBoard',
    220             'base_url': self.test_dir,
    221             'relays': [{
    222                 'name': '0',
    223                 'relay_pos': 0
    224             }, {
    225                 'name': '1',
    226                 'relay_pos': 1
    227             }, {
    228                 'name': '2',
    229                 'relay_pos': 7
    230             }]
    231         })
    232         self.ss_board = SainSmartBoard(self.config)
    233         self.r0 = Relay(self.ss_board, 0)
    234         self.r1 = Relay(self.ss_board, 1)
    235         self.r7 = Relay(self.ss_board, 7)
    236 
    237     def tearDown(self):
    238         shutil.rmtree(self.test_dir[7:])
    239         Relay.transition_wait_time = .2
    240         Relay.button_press_time = .25
    241 
    242     def test_get_url_code(self):
    243         result = self.ss_board._get_relay_url_code(self.r0.position,
    244                                                    RelayState.NO)
    245         self.assertEqual(result, '00')
    246 
    247         result = self.ss_board._get_relay_url_code(self.r0.position,
    248                                                    RelayState.NC)
    249         self.assertEqual(result, '01')
    250 
    251         result = self.ss_board._get_relay_url_code(self.r7.position,
    252                                                    RelayState.NO)
    253         self.assertEqual(result, '14')
    254 
    255         result = self.ss_board._get_relay_url_code(self.r7.position,
    256                                                    RelayState.NC)
    257         self.assertEqual(result, '15')
    258 
    259     def test_load_page_status(self):
    260         self._set_status_page('0000111100001111')
    261         result = self.ss_board._load_page(SainSmartBoard.HIDDEN_STATUS_PAGE)
    262         self.assertTrue(
    263             result.endswith(
    264                 '0000111100001111TUX">0000111100001111TUX</a><p>'))
    265 
    266     def test_load_page_relay(self):
    267         result = self.ss_board._load_page('00')
    268         self.assertEqual(result, self.RELAY_OFF_PAGE_CONTENTS)
    269 
    270         result = self.ss_board._load_page('01')
    271         self.assertEqual(result, self.RELAY_ON_PAGE_CONTENTS)
    272 
    273     def test_load_page_no_connection(self):
    274         with self.assertRaises(errors.RelayDeviceConnectionError):
    275             self.ss_board._load_page('**')
    276 
    277     def _set_status_page(self, status_16_chars):
    278         with open(self.test_dir[7:] + '99', 'w+') as status_file:
    279             status_file.write(
    280                 self.STATUS_MSG.format(self.test_dir[:-1], self.test_dir[:-1],
    281                                        status_16_chars, status_16_chars))
    282 
    283     def _test_sync_status_dict(self, status_16_chars):
    284         self._set_status_page(status_16_chars)
    285         expected_dict = dict()
    286 
    287         for index, char in enumerate(status_16_chars):
    288             expected_dict[
    289                 index] = RelayState.NC if char == '1' else RelayState.NO
    290 
    291         self.ss_board._sync_status_dict()
    292         self.assertDictEqual(expected_dict, self.ss_board.status_dict)
    293 
    294     def test_sync_status_dict(self):
    295         self._test_sync_status_dict('0000111100001111')
    296         self._test_sync_status_dict('0000000000000000')
    297         self._test_sync_status_dict('0101010101010101')
    298         self._test_sync_status_dict('1010101010101010')
    299         self._test_sync_status_dict('1111111111111111')
    300 
    301     def test_get_relay_status_status_dict_none(self):
    302         self._set_status_page('1111111111111111')
    303         self.ss_board.status_dict = None
    304         self.assertEqual(
    305             self.ss_board.get_relay_status(self.r0.position), RelayState.NC)
    306 
    307     def test_get_relay_status_status_dict_on(self):
    308         self.r0.set(RelayState.NC)
    309         self.assertEqual(
    310             self.ss_board.get_relay_status(self.r0.position), RelayState.NC)
    311 
    312     def test_get_relay_status_status_dict_off(self):
    313         self.r0.set(RelayState.NO)
    314         self.assertEqual(
    315             self.ss_board.get_relay_status(self.r0.position), RelayState.NO)
    316 
    317     def test_set_on(self):
    318         os.utime(self.test_dir[7:] + '01', (0, 0))
    319         self.ss_board.set(self.r0.position, RelayState.NC)
    320         self.assertNotEqual(os.stat(self.test_dir[7:] + '01').st_atime, 0)
    321 
    322     def test_set_off(self):
    323         os.utime(self.test_dir[7:] + '00', (0, 0))
    324         self.ss_board.set(self.r0.position, RelayState.NO)
    325         self.assertNotEqual(os.stat(self.test_dir[7:] + '00').st_atime, 0)
    326 
    327 
    328 class ActsRelayRigTest(unittest.TestCase):
    329     def setUp(self):
    330         Relay.transition_wait_time = 0
    331         Relay.button_press_time = 0
    332         self.config = {
    333             'boards': [{
    334                 'type': 'SainSmartBoard',
    335                 'name': 'ss_control',
    336                 'base_url': 'http://192.168.1.4/30000/'
    337             }, {
    338                 'type': 'SainSmartBoard',
    339                 'name': 'ss_control_2',
    340                 'base_url': 'http://192.168.1.4/30000/'
    341             }],
    342             'devices': [{
    343                 'type': 'GenericRelayDevice',
    344                 'name': 'device',
    345                 'relays': {
    346                     'Relay00': 'ss_control/0',
    347                     'Relay10': 'ss_control/1'
    348                 }
    349             }]
    350         }
    351 
    352     def tearDown(self):
    353         Relay.transition_wait_time = .2
    354         Relay.button_press_time = .25
    355 
    356     def test_init_relay_rig_missing_boards(self):
    357         flawed_config = copy.deepcopy(self.config)
    358         del flawed_config['boards']
    359         with self.assertRaises(errors.RelayConfigError):
    360             RelayRig(flawed_config)
    361 
    362     def test_init_relay_rig_is_not_list(self):
    363         flawed_config = copy.deepcopy(self.config)
    364         flawed_config['boards'] = self.config['boards'][0]
    365         with self.assertRaises(errors.RelayConfigError):
    366             RelayRig(flawed_config)
    367 
    368     def test_init_relay_rig_duplicate_board_names(self):
    369         flawed_config = copy.deepcopy(self.config)
    370         flawed_config['boards'][1]['name'] = (self.config['boards'][0]['name'])
    371         with self.assertRaises(errors.RelayConfigError):
    372             RelayRigMock(flawed_config)
    373 
    374     def test_init_relay_rig_device_gets_relays(self):
    375         modded_config = copy.deepcopy(self.config)
    376         del modded_config['devices'][0]['relays']['Relay00']
    377         rig = RelayRigMock(modded_config)
    378         self.assertEqual(len(rig.relays), 4)
    379         self.assertEqual(len(rig.devices['device'].relays), 1)
    380 
    381         rig = RelayRigMock(self.config)
    382         self.assertEqual(len(rig.devices['device'].relays), 2)
    383 
    384     def test_init_relay_rig_correct_device_type(self):
    385         rig = RelayRigMock(self.config)
    386         self.assertEqual(len(rig.devices), 1)
    387         self.assertIsInstance(rig.devices['device'], GenericRelayDevice)
    388 
    389     def test_init_relay_rig_missing_devices_creates_generic_device(self):
    390         modded_config = copy.deepcopy(self.config)
    391         del modded_config['devices']
    392         rig = RelayRigMock(modded_config)
    393         self.assertEqual(len(rig.devices), 1)
    394         self.assertIsInstance(rig.devices['device'], GenericRelayDevice)
    395         self.assertDictEqual(rig.devices['device'].relays, rig.relays)
    396 
    397 
    398 class RelayRigMock(RelayRig):
    399     """A RelayRig that substitutes the MockBoard for any board."""
    400 
    401     _board_constructors = {
    402         'SainSmartBoard': lambda x: MockBoard(x),
    403         'FuguMockBoard': lambda x: FuguMockBoard(x)
    404     }
    405 
    406     def __init__(self, config=None):
    407         if not config:
    408             config = {
    409                 "boards": [{
    410                     'name': 'MockBoard',
    411                     'type': 'SainSmartBoard'
    412                 }]
    413             }
    414 
    415         RelayRig.__init__(self, config)
    416 
    417 
    418 class ActsGenericRelayDeviceTest(unittest.TestCase):
    419     def setUp(self):
    420         Relay.transition_wait_time = 0
    421         Relay.button_press_time = 0
    422         self.board_config = {'name': 'MockBoard', 'type': 'SainSmartBoard'}
    423 
    424         self.board = MockBoard(self.board_config)
    425         self.r0 = self.board.relays[0]
    426         self.r1 = self.board.relays[1]
    427 
    428         self.device_config = {
    429             'name': 'MockDevice',
    430             'relays': {
    431                 'r0': 'MockBoard/0',
    432                 'r1': 'MockBoard/1'
    433             }
    434         }
    435         config = {
    436             'boards': [self.board_config],
    437             'devices': [self.device_config]
    438         }
    439         self.rig = RelayRigMock(config)
    440         self.rig.boards['MockBoard'] = self.board
    441         self.rig.relays[self.r0.relay_id] = self.r0
    442         self.rig.relays[self.r1.relay_id] = self.r1
    443 
    444     def tearDown(self):
    445         Relay.transition_wait_time = .2
    446         Relay.button_press_time = .25
    447 
    448     def test_setup_single_relay(self):
    449         self.r0.set(RelayState.NC)
    450         self.r1.set(RelayState.NC)
    451 
    452         modified_config = copy.deepcopy(self.device_config)
    453         del modified_config['relays']['r1']
    454 
    455         grd = GenericRelayDevice(modified_config, self.rig)
    456         grd.setup()
    457 
    458         self.assertEqual(self.r0.get_status(), RelayState.NO)
    459         self.assertEqual(self.r1.get_status(), RelayState.NC)
    460 
    461     def test_setup_multiple_relays(self):
    462         self.board.set(self.r0.position, RelayState.NC)
    463         self.board.set(self.r1.position, RelayState.NC)
    464 
    465         grd = GenericRelayDevice(self.device_config, self.rig)
    466         grd.setup()
    467 
    468         self.assertEqual(self.r0.get_status(), RelayState.NO)
    469         self.assertEqual(self.r1.get_status(), RelayState.NO)
    470 
    471     def test_cleanup_single_relay(self):
    472         self.test_setup_single_relay()
    473 
    474     def test_cleanup_multiple_relays(self):
    475         self.test_setup_multiple_relays()
    476 
    477     def change_state(self, begin_state, call, end_state, previous_state=None):
    478         self.board.set(self.r0.position, begin_state)
    479         grd = GenericRelayDevice(self.device_config, self.rig)
    480         call(grd)
    481         self.assertEqual(self.r0.get_status(), end_state)
    482         if previous_state:
    483             self.assertEqual(
    484                 self.board.relay_previous_states[self.r0.position],
    485                 previous_state)
    486 
    487     def test_press_while_no(self):
    488         self.change_state(RelayState.NO, lambda x: x.press('r0'),
    489                           RelayState.NO, RelayState.NC)
    490 
    491     def test_press_while_nc(self):
    492         self.change_state(RelayState.NC, lambda x: x.press('r0'),
    493                           RelayState.NO, RelayState.NC)
    494 
    495     def test_hold_down_while_no(self):
    496         self.change_state(RelayState.NO, lambda x: x.hold_down('r0'),
    497                           RelayState.NC)
    498 
    499     def test_hold_down_while_nc(self):
    500         self.change_state(RelayState.NC, lambda x: x.hold_down('r0'),
    501                           RelayState.NC)
    502 
    503     def test_release_while_nc(self):
    504         self.change_state(RelayState.NC, lambda x: x.release('r0'),
    505                           RelayState.NO)
    506 
    507 
    508 class ActsRelayDeviceTest(unittest.TestCase):
    509     def setUp(self):
    510         Relay.transition_wait_time = 0
    511         Relay.button_press_time = 0
    512 
    513         self.board_config = {
    514             'name': 'MockBoard',
    515             'relays': [{
    516                 'id': 0,
    517                 'relay_pos': 0
    518             }, {
    519                 'id': 1,
    520                 'relay_pos': 1
    521             }]
    522         }
    523 
    524         self.board = MockBoard(self.board_config)
    525         self.r0 = Relay(self.board, 0)
    526         self.r1 = Relay(self.board, 1)
    527         self.board.set(self.r0.position, RelayState.NO)
    528         self.board.set(self.r1.position, RelayState.NO)
    529 
    530         self.rig = RelayRigMock()
    531         self.rig.boards['MockBoard'] = self.board
    532         self.rig.relays[self.r0.relay_id] = self.r0
    533         self.rig.relays[self.r1.relay_id] = self.r1
    534 
    535         self.device_config = {
    536             "type": "GenericRelayDevice",
    537             "name": "device",
    538             "relays": {
    539                 'r0': 'MockBoard/0',
    540                 'r1': 'MockBoard/1'
    541             }
    542         }
    543 
    544     def tearDown(self):
    545         Relay.transition_wait_time = .2
    546         Relay.button_press_time = .25
    547 
    548     def test_init_raise_on_name_missing(self):
    549         flawed_config = copy.deepcopy(self.device_config)
    550         del flawed_config['name']
    551         with self.assertRaises(errors.RelayConfigError):
    552             RelayDevice(flawed_config, self.rig)
    553 
    554     def test_init_raise_on_name_wrong_type(self):
    555         flawed_config = copy.deepcopy(self.device_config)
    556         flawed_config['name'] = {}
    557         with self.assertRaises(errors.RelayConfigError):
    558             RelayDevice(flawed_config, self.rig)
    559 
    560     def test_init_raise_on_relays_missing(self):
    561         flawed_config = copy.deepcopy(self.device_config)
    562         del flawed_config['relays']
    563         with self.assertRaises(errors.RelayConfigError):
    564             RelayDevice(flawed_config, self.rig)
    565 
    566     def test_init_raise_on_relays_wrong_type(self):
    567         flawed_config = copy.deepcopy(self.device_config)
    568         flawed_config['relays'] = str
    569         with self.assertRaises(errors.RelayConfigError):
    570             RelayDevice(flawed_config, self.rig)
    571 
    572     def test_init_raise_on_relays_is_empty(self):
    573         flawed_config = copy.deepcopy(self.device_config)
    574         flawed_config['relays'] = []
    575         with self.assertRaises(errors.RelayConfigError):
    576             RelayDevice(flawed_config, self.rig)
    577 
    578     def test_init_raise_on_relays_are_dicts_without_names(self):
    579         flawed_config = copy.deepcopy(self.device_config)
    580         flawed_config['relays'] = [{'id': 0}, {'id': 1}]
    581         with self.assertRaises(errors.RelayConfigError):
    582             RelayDevice(flawed_config, self.rig)
    583 
    584     def test_init_raise_on_relays_are_dicts_without_ids(self):
    585         flawed_config = copy.deepcopy(self.device_config)
    586         flawed_config['relays'] = [{'name': 'r0'}, {'name': 'r1'}]
    587         with self.assertRaises(errors.RelayConfigError):
    588             RelayDevice(flawed_config, self.rig)
    589 
    590     def test_init_pass_relays_have_ids_and_names(self):
    591         RelayDevice(self.device_config, self.rig)
    592 
    593 
    594 class TestRelayRigParser(unittest.TestCase):
    595     def setUp(self):
    596         Relay.transition_wait_time = 0
    597         Relay.button_press_time = 0
    598         self.board_config = {
    599             'name': 'MockBoard',
    600             'relays': [{
    601                 'id': 'r0',
    602                 'relay_pos': 0
    603             }, {
    604                 'id': 'r1',
    605                 'relay_pos': 1
    606             }]
    607         }
    608         self.r0 = self.board_config['relays'][0]
    609         self.r1 = self.board_config['relays'][1]
    610         self.board = MockBoard(self.board_config)
    611 
    612     def tearDown(self):
    613         Relay.transition_wait_time = .2
    614         Relay.button_press_time = .25
    615 
    616     def test_create_relay_board_raise_on_missing_type(self):
    617         with self.assertRaises(errors.RelayConfigError):
    618             RelayRigMock().create_relay_board(self.board_config)
    619 
    620     def test_create_relay_board_valid_config(self):
    621         config = copy.deepcopy(self.board_config)
    622         config['type'] = 'SainSmartBoard'
    623         RelayRigMock().create_relay_board(config)
    624 
    625     def test_create_relay_board_raise_on_type_not_found(self):
    626         flawed_config = copy.deepcopy(self.board_config)
    627         flawed_config['type'] = 'NonExistentBoard'
    628         with self.assertRaises(errors.RelayConfigError):
    629             RelayRigMock().create_relay_board(flawed_config)
    630 
    631     def test_create_relay_device_create_generic_on_missing_type(self):
    632         rig = RelayRigMock()
    633         rig.relays['r0'] = self.r0
    634         rig.relays['r1'] = self.r1
    635         config = {
    636             'name': 'name',
    637             'relays': {
    638                 'r0': 'MockBoard/0',
    639                 'r1': 'MockBoard/1'
    640             }
    641         }
    642         device = rig.create_relay_device(config)
    643         self.assertIsInstance(device, GenericRelayDevice)
    644 
    645     def test_create_relay_device_config_with_type(self):
    646         rig = RelayRigMock()
    647         rig.relays['r0'] = self.r0
    648         rig.relays['r1'] = self.r1
    649         config = {
    650             'type': 'GenericRelayDevice',
    651             'name': '.',
    652             'relays': {
    653                 'r0': 'MockBoard/0',
    654                 'r1': 'MockBoard/1'
    655             }
    656         }
    657         device = rig.create_relay_device(config)
    658         self.assertIsInstance(device, GenericRelayDevice)
    659 
    660     def test_create_relay_device_raise_on_type_not_found(self):
    661         rig = RelayRigMock()
    662         rig.relays['r0'] = self.r0
    663         rig.relays['r1'] = self.r1
    664         config = {
    665             'type': 'SomeInvalidType',
    666             'name': '.',
    667             'relays': [{
    668                 'name': 'r0',
    669                 'pos': 'MockBoard/0'
    670             }, {
    671                 'name': 'r1',
    672                 'pos': 'MockBoard/1'
    673             }]
    674         }
    675         with self.assertRaises(errors.RelayConfigError):
    676             rig.create_relay_device(config)
    677 
    678 
    679 class TestSynchronizeRelays(unittest.TestCase):
    680     def test_synchronize_relays(self):
    681         Relay.transition_wait_time = .1
    682         with SynchronizeRelays():
    683             self.assertEqual(Relay.transition_wait_time, 0)
    684         self.assertEqual(Relay.transition_wait_time, .1)
    685 
    686 
    687 class FuguMockBoard(MockBoard):
    688     def get_relay_position_list(self):
    689         return range(4)
    690 
    691 
    692 class TestFuguRemote(unittest.TestCase):
    693     def setUp(self):
    694         Relay.transition_wait_time = 0
    695         self.mock_rig = RelayRigMock({
    696             "boards": [{
    697                 'name': 'MockBoard',
    698                 'type': 'FuguMockBoard'
    699             }]
    700         })
    701         self.mock_board = self.mock_rig.boards['MockBoard']
    702         self.fugu_config = {
    703             'type': 'GenericRelayDevice',
    704             'name': 'UniqueDeviceName',
    705             'mac_address': '00:00:00:00:00:00',
    706             'relays': {
    707                 'Power': 'MockBoard/0',
    708                 fugu_remote.Buttons.BACK.value: 'MockBoard/1',
    709                 fugu_remote.Buttons.HOME.value: 'MockBoard/2',
    710                 fugu_remote.Buttons.PLAY_PAUSE.value: 'MockBoard/3'
    711             }
    712         }
    713         Relay.button_press_time = 0
    714 
    715     def tearDown(self):
    716         Relay.button_press_time = .25
    717         Relay.transition_wait_time = .2
    718 
    719     def test_config_missing_button(self):
    720         """FuguRemote __init__ should throw an error if a relay is missing."""
    721         flawed_config = copy.deepcopy(self.fugu_config)
    722         del flawed_config['relays']['Power']
    723         del flawed_config['relays'][fugu_remote.Buttons.BACK.value]
    724         with self.assertRaises(errors.RelayConfigError):
    725             fugu_remote.FuguRemote(flawed_config, self.mock_rig)
    726 
    727     def test_config_missing_mac_address(self):
    728         """FuguRemote __init__ should throw an error without a mac address."""
    729         flawed_config = copy.deepcopy(self.fugu_config)
    730         del flawed_config['mac_address']
    731         with self.assertRaises(errors.RelayConfigError):
    732             fugu_remote.FuguRemote(flawed_config, self.mock_rig)
    733 
    734     def test_config_no_issues(self):
    735         """FuguRemote __init__ should not throw errors for a correct config."""
    736         fugu_remote.FuguRemote(self.fugu_config, self.mock_rig)
    737 
    738     def test_power_nc_after_setup(self):
    739         """Power should be NORMALLY_CLOSED after calling setup if it exists."""
    740         fugu = fugu_remote.FuguRemote(self.fugu_config, self.mock_rig)
    741         fugu.setup()
    742         self.assertEqual(self.mock_board.get_relay_status(0), RelayState.NC)
    743         pass
    744 
    745     def press_button_success(self, relay_position):
    746         self.assertEqual(self.mock_board.relay_states[relay_position],
    747                          RelayState.NO)
    748         self.assertEqual(self.mock_board.relay_previous_states[relay_position],
    749                          RelayState.NC)
    750 
    751     def test_press_play_pause(self):
    752         fugu = fugu_remote.FuguRemote(self.fugu_config, self.mock_rig)
    753         fugu.press_play_pause()
    754         self.press_button_success(3)
    755 
    756     def test_press_back(self):
    757         fugu = fugu_remote.FuguRemote(self.fugu_config, self.mock_rig)
    758         fugu.press_back()
    759         self.press_button_success(1)
    760 
    761     def test_press_home(self):
    762         fugu = fugu_remote.FuguRemote(self.fugu_config, self.mock_rig)
    763         fugu.press_home()
    764         self.press_button_success(2)
    765 
    766     def test_enter_pairing_mode(self):
    767         fugu = fugu_remote.FuguRemote(self.fugu_config, self.mock_rig)
    768         fugu_remote.PAIRING_MODE_WAIT_TIME = 0
    769         fugu.enter_pairing_mode()
    770         self.press_button_success(2)
    771         self.press_button_success(1)
    772 
    773 
    774 class TestRelayDict(unittest.TestCase):
    775     def test_init(self):
    776         mock_device = object()
    777         blank_dict = dict()
    778         relay_dict = RelayDict(mock_device, blank_dict)
    779         self.assertEqual(relay_dict._store, blank_dict)
    780         self.assertEqual(relay_dict.relay_device, mock_device)
    781 
    782     def test_get_item_valid_key(self):
    783         mock_device = object()
    784         blank_dict = {'key': 'value'}
    785         relay_dict = RelayDict(mock_device, blank_dict)
    786         self.assertEqual(relay_dict['key'], 'value')
    787 
    788     def test_get_item_invalid_key(self):
    789         # Create an object with a single attribute 'name'
    790         mock_device = type('', (object, ), {'name': 'name'})()
    791         blank_dict = {'key': 'value'}
    792         relay_dict = RelayDict(mock_device, blank_dict)
    793         with self.assertRaises(errors.RelayConfigError):
    794             value = relay_dict['not_key']
    795 
    796     def test_iter(self):
    797         mock_device = type('', (object, ), {'name': 'name'})()
    798         data_dict = {'a': '1', 'b': '2', 'c': '3'}
    799         relay_dict = RelayDict(mock_device, data_dict)
    800 
    801         rd_set = set()
    802         for key in relay_dict:
    803             rd_set.add(key)
    804         dd_set = set()
    805         for key in data_dict:
    806             dd_set.add(key)
    807 
    808         self.assertSetEqual(rd_set, dd_set)
    809 
    810 
    811 if __name__ == "__main__":
    812     unittest.main()
    813