#!/usr/bin/env python3 # # Copyright 2016 - The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import copy import shutil import tempfile import unittest import acts.controllers.relay_lib.fugu_remote as fugu_remote from acts.controllers.relay_lib.errors import RelayConfigError from acts.controllers.relay_lib.errors import RelayDeviceConnectionError from acts.controllers.relay_lib.generic_relay_device import GenericRelayDevice from acts.controllers.relay_lib.relay import Relay from acts.controllers.relay_lib.relay import RelayDict from acts.controllers.relay_lib.relay import RelayState from acts.controllers.relay_lib.relay import SynchronizeRelays from acts.controllers.relay_lib.relay_board import RelayBoard from acts.controllers.relay_lib.relay_device import RelayDevice from acts.controllers.relay_lib.relay_rig import RelayRig from acts.controllers.relay_lib.sain_smart_board import SainSmartBoard from mock import patch class MockBoard(RelayBoard): def __init__(self, config): self.relay_states = dict() self.relay_previous_states = dict() RelayBoard.__init__(self, config) def get_relay_position_list(self): return [0, 1] def get_relay_status(self, relay_position): if relay_position not in self.relay_states: self.relay_states[relay_position] = RelayState.NO self.relay_previous_states[relay_position] = RelayState.NO return self.relay_states[relay_position] def set(self, relay_position, state): self.relay_previous_states[relay_position] = self.get_relay_status( relay_position) self.relay_states[relay_position] = state return state class ActsRelayTest(unittest.TestCase): def setUp(self): Relay.transition_wait_time = 0 Relay.button_press_time = 0 self.config = { 'name': 'MockBoard', 'relays': [{ 'name': 'Relay', 'relay_pos': 0 }] } self.board = MockBoard(self.config) self.relay = Relay(self.board, 'Relay') self.board.set(self.relay.position, RelayState.NO) def tearDown(self): Relay.transition_wait_time = .2 Relay.button_press_time = .25 def test_turn_on_from_off(self): self.board.set(self.relay.position, RelayState.NO) self.relay.set_nc() self.assertEqual( self.board.get_relay_status(self.relay.position), RelayState.NC) def test_turn_on_from_on(self): self.board.set(self.relay.position, RelayState.NC) self.relay.set_nc() self.assertEqual( self.board.get_relay_status(self.relay.position), RelayState.NC) def test_turn_off_from_on(self): self.board.set(self.relay.position, RelayState.NC) self.relay.set_no() self.assertEqual( self.board.get_relay_status(self.relay.position), RelayState.NO) def test_turn_off_from_off(self): self.board.set(self.relay.position, RelayState.NO) self.relay.set_no() self.assertEqual( self.board.get_relay_status(self.relay.position), RelayState.NO) def test_toggle_off_to_on(self): self.board.set(self.relay.position, RelayState.NO) self.relay.toggle() self.assertEqual( self.board.get_relay_status(self.relay.position), RelayState.NC) def test_toggle_on_to_off(self): self.board.set(self.relay.position, RelayState.NC) self.relay.toggle() self.assertEqual( self.board.get_relay_status(self.relay.position), RelayState.NO) def test_set_on(self): self.board.set(self.relay.position, RelayState.NO) self.relay.set(RelayState.NC) self.assertEqual( self.board.get_relay_status(self.relay.position), RelayState.NC) def test_set_off(self): self.board.set(self.relay.position, RelayState.NC) self.relay.set(RelayState.NO) self.assertEqual( self.board.get_relay_status(self.relay.position), RelayState.NO) def test_set_foo(self): with self.assertRaises(ValueError): self.relay.set('FOO') def test_set_nc_for(self): # Here we set twice so relay_previous_state will also be OFF self.board.set(self.relay.position, RelayState.NO) self.board.set(self.relay.position, RelayState.NO) self.relay.set_nc_for(0) self.assertEqual( self.board.get_relay_status(self.relay.position), RelayState.NO) self.assertEqual(self.board.relay_previous_states[self.relay.position], RelayState.NC) def test_set_no_for(self): # Here we set twice so relay_previous_state will also be OFF self.board.set(self.relay.position, RelayState.NC) self.board.set(self.relay.position, RelayState.NC) self.relay.set_no_for(0) self.assertEqual( self.board.get_relay_status(self.relay.position), RelayState.NC) self.assertEqual(self.board.relay_previous_states[self.relay.position], RelayState.NO) def test_get_status_on(self): self.board.set(self.relay.position, RelayState.NC) self.assertEqual(self.relay.get_status(), RelayState.NC) def test_get_status_off(self): self.board.set(self.relay.position, RelayState.NO) self.assertEqual(self.relay.get_status(), RelayState.NO) def test_clean_up_default_on(self): new_relay = Relay(self.board, 0) new_relay._original_state = RelayState.NO self.board.set(new_relay.position, RelayState.NO) new_relay.clean_up() self.assertEqual( self.board.get_relay_status(new_relay.position), RelayState.NO) def test_clean_up_default_off(self): new_relay = Relay(self.board, 0) new_relay._original_state = RelayState.NO self.board.set(new_relay.position, RelayState.NC) new_relay.clean_up() self.assertEqual( self.board.get_relay_status(new_relay.position), RelayState.NO) def test_clean_up_original_state_none(self): val = 'STAYS_THE_SAME' new_relay = Relay(self.board, 0) # _original_state is none by default # The line below sets the dict to an impossible value. self.board.set(new_relay.position, val) new_relay.clean_up() # If the impossible value is cleared, then the test should fail. self.assertEqual(self.board.get_relay_status(new_relay.position), val) class ActsSainSmartBoardTest(unittest.TestCase): STATUS_MSG = ('' '{}TUX
') RELAY_ON_PAGE_CONTENTS = 'relay_on page' RELAY_OFF_PAGE_CONTENTS = 'relay_off page' def setUp(self): Relay.transition_wait_time = 0 Relay.button_press_time = 0 self.test_dir = 'file://' + tempfile.mkdtemp() + '/' # Creates the files used for testing self._set_status_page('0000000000000000') with open(self.test_dir[7:] + '00', 'w+') as file: file.write(self.RELAY_OFF_PAGE_CONTENTS) with open(self.test_dir[7:] + '01', 'w+') as file: file.write(self.RELAY_ON_PAGE_CONTENTS) self.config = ({ 'name': 'SSBoard', 'base_url': self.test_dir, 'relays': [{ 'name': '0', 'relay_pos': 0 }, { 'name': '1', 'relay_pos': 1 }, { 'name': '2', 'relay_pos': 7 }] }) self.ss_board = SainSmartBoard(self.config) self.r0 = Relay(self.ss_board, 0) self.r1 = Relay(self.ss_board, 1) self.r7 = Relay(self.ss_board, 7) def tearDown(self): shutil.rmtree(self.test_dir[7:]) Relay.transition_wait_time = .2 Relay.button_press_time = .25 def test_get_url_code(self): result = self.ss_board._get_relay_url_code(self.r0.position, RelayState.NO) self.assertEqual(result, '00') result = self.ss_board._get_relay_url_code(self.r0.position, RelayState.NC) self.assertEqual(result, '01') result = self.ss_board._get_relay_url_code(self.r7.position, RelayState.NO) self.assertEqual(result, '14') result = self.ss_board._get_relay_url_code(self.r7.position, RelayState.NC) self.assertEqual(result, '15') def test_load_page_status(self): self._set_status_page('0000111100001111') result = self.ss_board._load_page(SainSmartBoard.HIDDEN_STATUS_PAGE) self.assertTrue( result.endswith( '0000111100001111TUX">0000111100001111TUX
')) def test_load_page_relay(self): result = self.ss_board._load_page('00') self.assertEqual(result, self.RELAY_OFF_PAGE_CONTENTS) result = self.ss_board._load_page('01') self.assertEqual(result, self.RELAY_ON_PAGE_CONTENTS) def test_load_page_no_connection(self): with self.assertRaises(RelayDeviceConnectionError): self.ss_board._load_page('**') def _set_status_page(self, status_16_chars): with open(self.test_dir[7:] + '99', 'w+') as status_file: status_file.write( self.STATUS_MSG.format(self.test_dir[:-1], self.test_dir[:-1], status_16_chars, status_16_chars)) def _test_sync_status_dict(self, status_16_chars): self._set_status_page(status_16_chars) expected_dict = dict() for index, char in enumerate(status_16_chars): expected_dict[ index] = RelayState.NC if char == '1' else RelayState.NO self.ss_board._sync_status_dict() self.assertDictEqual(expected_dict, self.ss_board.status_dict) def test_sync_status_dict(self): self._test_sync_status_dict('0000111100001111') self._test_sync_status_dict('0000000000000000') self._test_sync_status_dict('0101010101010101') self._test_sync_status_dict('1010101010101010') self._test_sync_status_dict('1111111111111111') def test_get_relay_status_status_dict_none(self): self._set_status_page('1111111111111111') self.ss_board.status_dict = None self.assertEqual( self.ss_board.get_relay_status(self.r0.position), RelayState.NC) def test_get_relay_status_status_dict_on(self): self.r0.set(RelayState.NC) self.assertEqual( self.ss_board.get_relay_status(self.r0.position), RelayState.NC) def test_get_relay_status_status_dict_off(self): self.r0.set(RelayState.NO) self.assertEqual( self.ss_board.get_relay_status(self.r0.position), RelayState.NO) def test_set_on(self): patch_path = 'acts.controllers.relay_lib.sain_smart_board.urlopen' with patch(patch_path) as urlopen: board = SainSmartBoard(self.config) board.status_dict = {} board.set(self.r0.position, RelayState.NC) urlopen.assert_called_once_with('%s%s' % (self.ss_board.base_url, '01')) def test_set_off(self): patch_path = 'acts.controllers.relay_lib.sain_smart_board.urlopen' with patch(patch_path) as urlopen: board = SainSmartBoard(self.config) board.status_dict = {} board.set(self.r0.position, RelayState.NO) urlopen.assert_called_once_with('%s%s' % (self.ss_board.base_url, '00')) def test_connection_error_no_tux(self): default_status_msg = self.STATUS_MSG self.STATUS_MSG = self.STATUS_MSG.replace('TUX', '') try: self._set_status_page('1111111111111111') self.ss_board.get_relay_status(0) except RelayDeviceConnectionError: self.STATUS_MSG = default_status_msg return self.fail('Should have thrown an error without TUX appearing.') class ActsRelayRigTest(unittest.TestCase): def setUp(self): Relay.transition_wait_time = 0 Relay.button_press_time = 0 self.config = { 'boards': [{ 'type': 'SainSmartBoard', 'name': 'ss_control', 'base_url': 'http://192.168.1.4/30000/' }, { 'type': 'SainSmartBoard', 'name': 'ss_control_2', 'base_url': 'http://192.168.1.4/30000/' }], 'devices': [{ 'type': 'GenericRelayDevice', 'name': 'device', 'relays': { 'Relay00': 'ss_control/0', 'Relay10': 'ss_control/1' } }] } def tearDown(self): Relay.transition_wait_time = .2 Relay.button_press_time = .25 def test_init_relay_rig_missing_boards(self): flawed_config = copy.deepcopy(self.config) del flawed_config['boards'] with self.assertRaises(RelayConfigError): RelayRig(flawed_config) def test_init_relay_rig_is_not_list(self): flawed_config = copy.deepcopy(self.config) flawed_config['boards'] = self.config['boards'][0] with self.assertRaises(RelayConfigError): RelayRig(flawed_config) def test_init_relay_rig_duplicate_board_names(self): flawed_config = copy.deepcopy(self.config) flawed_config['boards'][1]['name'] = (self.config['boards'][0]['name']) with self.assertRaises(RelayConfigError): RelayRigMock(flawed_config) def test_init_relay_rig_device_gets_relays(self): modded_config = copy.deepcopy(self.config) del modded_config['devices'][0]['relays']['Relay00'] rig = RelayRigMock(modded_config) self.assertEqual(len(rig.relays), 4) self.assertEqual(len(rig.devices['device'].relays), 1) rig = RelayRigMock(self.config) self.assertEqual(len(rig.devices['device'].relays), 2) def test_init_relay_rig_correct_device_type(self): rig = RelayRigMock(self.config) self.assertEqual(len(rig.devices), 1) self.assertIsInstance(rig.devices['device'], GenericRelayDevice) def test_init_relay_rig_missing_devices_creates_generic_device(self): modded_config = copy.deepcopy(self.config) del modded_config['devices'] rig = RelayRigMock(modded_config) self.assertEqual(len(rig.devices), 1) self.assertIsInstance(rig.devices['device'], GenericRelayDevice) self.assertDictEqual(rig.devices['device'].relays, rig.relays) class RelayRigMock(RelayRig): """A RelayRig that substitutes the MockBoard for any board.""" _board_constructors = { 'SainSmartBoard': lambda x: MockBoard(x), 'FuguMockBoard': lambda x: FuguMockBoard(x) } def __init__(self, config=None): if not config: config = { "boards": [{ 'name': 'MockBoard', 'type': 'SainSmartBoard' }] } RelayRig.__init__(self, config) class ActsGenericRelayDeviceTest(unittest.TestCase): def setUp(self): Relay.transition_wait_time = 0 Relay.button_press_time = 0 self.board_config = {'name': 'MockBoard', 'type': 'SainSmartBoard'} self.board = MockBoard(self.board_config) self.r0 = self.board.relays[0] self.r1 = self.board.relays[1] self.device_config = { 'name': 'MockDevice', 'relays': { 'r0': 'MockBoard/0', 'r1': 'MockBoard/1' } } config = { 'boards': [self.board_config], 'devices': [self.device_config] } self.rig = RelayRigMock(config) self.rig.boards['MockBoard'] = self.board self.rig.relays[self.r0.relay_id] = self.r0 self.rig.relays[self.r1.relay_id] = self.r1 def tearDown(self): Relay.transition_wait_time = .2 Relay.button_press_time = .25 def test_setup_single_relay(self): self.r0.set(RelayState.NC) self.r1.set(RelayState.NC) modified_config = copy.deepcopy(self.device_config) del modified_config['relays']['r1'] grd = GenericRelayDevice(modified_config, self.rig) grd.setup() self.assertEqual(self.r0.get_status(), RelayState.NO) self.assertEqual(self.r1.get_status(), RelayState.NC) def test_setup_multiple_relays(self): self.board.set(self.r0.position, RelayState.NC) self.board.set(self.r1.position, RelayState.NC) grd = GenericRelayDevice(self.device_config, self.rig) grd.setup() self.assertEqual(self.r0.get_status(), RelayState.NO) self.assertEqual(self.r1.get_status(), RelayState.NO) def test_cleanup_single_relay(self): self.test_setup_single_relay() def test_cleanup_multiple_relays(self): self.test_setup_multiple_relays() def change_state(self, begin_state, call, end_state, previous_state=None): self.board.set(self.r0.position, begin_state) grd = GenericRelayDevice(self.device_config, self.rig) call(grd) self.assertEqual(self.r0.get_status(), end_state) if previous_state: self.assertEqual( self.board.relay_previous_states[self.r0.position], previous_state) def test_press_while_no(self): self.change_state(RelayState.NO, lambda x: x.press('r0'), RelayState.NO, RelayState.NC) def test_press_while_nc(self): self.change_state(RelayState.NC, lambda x: x.press('r0'), RelayState.NO, RelayState.NC) def test_hold_down_while_no(self): self.change_state(RelayState.NO, lambda x: x.hold_down('r0'), RelayState.NC) def test_hold_down_while_nc(self): self.change_state(RelayState.NC, lambda x: x.hold_down('r0'), RelayState.NC) def test_release_while_nc(self): self.change_state(RelayState.NC, lambda x: x.release('r0'), RelayState.NO) class ActsRelayDeviceTest(unittest.TestCase): def setUp(self): Relay.transition_wait_time = 0 Relay.button_press_time = 0 self.board_config = { 'name': 'MockBoard', 'relays': [{ 'id': 0, 'relay_pos': 0 }, { 'id': 1, 'relay_pos': 1 }] } self.board = MockBoard(self.board_config) self.r0 = Relay(self.board, 0) self.r1 = Relay(self.board, 1) self.board.set(self.r0.position, RelayState.NO) self.board.set(self.r1.position, RelayState.NO) self.rig = RelayRigMock() self.rig.boards['MockBoard'] = self.board self.rig.relays[self.r0.relay_id] = self.r0 self.rig.relays[self.r1.relay_id] = self.r1 self.device_config = { "type": "GenericRelayDevice", "name": "device", "relays": { 'r0': 'MockBoard/0', 'r1': 'MockBoard/1' } } def tearDown(self): Relay.transition_wait_time = .2 Relay.button_press_time = .25 def test_init_raise_on_name_missing(self): flawed_config = copy.deepcopy(self.device_config) del flawed_config['name'] with self.assertRaises(RelayConfigError): RelayDevice(flawed_config, self.rig) def test_init_raise_on_name_wrong_type(self): flawed_config = copy.deepcopy(self.device_config) flawed_config['name'] = {} with self.assertRaises(RelayConfigError): RelayDevice(flawed_config, self.rig) def test_init_raise_on_relays_missing(self): flawed_config = copy.deepcopy(self.device_config) del flawed_config['relays'] with self.assertRaises(RelayConfigError): RelayDevice(flawed_config, self.rig) def test_init_raise_on_relays_wrong_type(self): flawed_config = copy.deepcopy(self.device_config) flawed_config['relays'] = str with self.assertRaises(RelayConfigError): RelayDevice(flawed_config, self.rig) def test_init_raise_on_relays_is_empty(self): flawed_config = copy.deepcopy(self.device_config) flawed_config['relays'] = [] with self.assertRaises(RelayConfigError): RelayDevice(flawed_config, self.rig) def test_init_raise_on_relays_are_dicts_without_names(self): flawed_config = copy.deepcopy(self.device_config) flawed_config['relays'] = [{'id': 0}, {'id': 1}] with self.assertRaises(RelayConfigError): RelayDevice(flawed_config, self.rig) def test_init_raise_on_relays_are_dicts_without_ids(self): flawed_config = copy.deepcopy(self.device_config) flawed_config['relays'] = [{'name': 'r0'}, {'name': 'r1'}] with self.assertRaises(RelayConfigError): RelayDevice(flawed_config, self.rig) def test_init_pass_relays_have_ids_and_names(self): RelayDevice(self.device_config, self.rig) class TestRelayRigParser(unittest.TestCase): def setUp(self): Relay.transition_wait_time = 0 Relay.button_press_time = 0 self.board_config = { 'name': 'MockBoard', 'relays': [{ 'id': 'r0', 'relay_pos': 0 }, { 'id': 'r1', 'relay_pos': 1 }] } self.r0 = self.board_config['relays'][0] self.r1 = self.board_config['relays'][1] self.board = MockBoard(self.board_config) def tearDown(self): Relay.transition_wait_time = .2 Relay.button_press_time = .25 def test_create_relay_board_raise_on_missing_type(self): with self.assertRaises(RelayConfigError): RelayRigMock().create_relay_board(self.board_config) def test_create_relay_board_valid_config(self): config = copy.deepcopy(self.board_config) config['type'] = 'SainSmartBoard' RelayRigMock().create_relay_board(config) def test_create_relay_board_raise_on_type_not_found(self): flawed_config = copy.deepcopy(self.board_config) flawed_config['type'] = 'NonExistentBoard' with self.assertRaises(RelayConfigError): RelayRigMock().create_relay_board(flawed_config) def test_create_relay_device_create_generic_on_missing_type(self): rig = RelayRigMock() rig.relays['r0'] = self.r0 rig.relays['r1'] = self.r1 config = { 'name': 'name', 'relays': { 'r0': 'MockBoard/0', 'r1': 'MockBoard/1' } } device = rig.create_relay_device(config) self.assertIsInstance(device, GenericRelayDevice) def test_create_relay_device_config_with_type(self): rig = RelayRigMock() rig.relays['r0'] = self.r0 rig.relays['r1'] = self.r1 config = { 'type': 'GenericRelayDevice', 'name': '.', 'relays': { 'r0': 'MockBoard/0', 'r1': 'MockBoard/1' } } device = rig.create_relay_device(config) self.assertIsInstance(device, GenericRelayDevice) def test_create_relay_device_raise_on_type_not_found(self): rig = RelayRigMock() rig.relays['r0'] = self.r0 rig.relays['r1'] = self.r1 config = { 'type': 'SomeInvalidType', 'name': '.', 'relays': [{ 'name': 'r0', 'pos': 'MockBoard/0' }, { 'name': 'r1', 'pos': 'MockBoard/1' }] } with self.assertRaises(RelayConfigError): rig.create_relay_device(config) class TestSynchronizeRelays(unittest.TestCase): def test_synchronize_relays(self): Relay.transition_wait_time = .1 with SynchronizeRelays(): self.assertEqual(Relay.transition_wait_time, 0) self.assertEqual(Relay.transition_wait_time, .1) class FuguMockBoard(MockBoard): def get_relay_position_list(self): return range(4) class TestFuguRemote(unittest.TestCase): def setUp(self): Relay.transition_wait_time = 0 self.mock_rig = RelayRigMock({ "boards": [{ 'name': 'MockBoard', 'type': 'FuguMockBoard' }] }) self.mock_board = self.mock_rig.boards['MockBoard'] self.fugu_config = { 'type': 'FuguRemote', 'name': 'UniqueDeviceName', 'mac_address': '00:00:00:00:00:00', 'relays': { 'Power': 'MockBoard/0', fugu_remote.Buttons.BACK.value: 'MockBoard/1', fugu_remote.Buttons.HOME.value: 'MockBoard/2', fugu_remote.Buttons.PLAY_PAUSE.value: 'MockBoard/3' } } Relay.button_press_time = 0 def tearDown(self): Relay.button_press_time = .25 Relay.transition_wait_time = .2 def test_config_missing_button(self): """FuguRemote __init__ should throw an error if a relay is missing.""" flawed_config = copy.deepcopy(self.fugu_config) del flawed_config['relays']['Power'] del flawed_config['relays'][fugu_remote.Buttons.BACK.value] with self.assertRaises(RelayConfigError): fugu_remote.FuguRemote(flawed_config, self.mock_rig) def test_config_missing_mac_address(self): """FuguRemote __init__ should throw an error without a mac address.""" flawed_config = copy.deepcopy(self.fugu_config) del flawed_config['mac_address'] with self.assertRaises(RelayConfigError): fugu_remote.FuguRemote(flawed_config, self.mock_rig) def test_config_no_issues(self): """FuguRemote __init__ should not throw errors for a correct config.""" fugu_remote.FuguRemote(self.fugu_config, self.mock_rig) def test_power_nc_after_setup(self): """Power should be NORMALLY_CLOSED after calling setup if it exists.""" fugu = fugu_remote.FuguRemote(self.fugu_config, self.mock_rig) fugu.setup() self.assertEqual(self.mock_board.get_relay_status(0), RelayState.NC) pass def press_button_success(self, relay_position): self.assertEqual(self.mock_board.relay_states[relay_position], RelayState.NO) self.assertEqual(self.mock_board.relay_previous_states[relay_position], RelayState.NC) def test_press_play_pause(self): fugu = fugu_remote.FuguRemote(self.fugu_config, self.mock_rig) fugu.press_play_pause() self.press_button_success(3) def test_press_back(self): fugu = fugu_remote.FuguRemote(self.fugu_config, self.mock_rig) fugu.press_back() self.press_button_success(1) def test_press_home(self): fugu = fugu_remote.FuguRemote(self.fugu_config, self.mock_rig) fugu.press_home() self.press_button_success(2) def test_enter_pairing_mode(self): fugu = fugu_remote.FuguRemote(self.fugu_config, self.mock_rig) fugu_remote.PAIRING_MODE_WAIT_TIME = 0 fugu.enter_pairing_mode() self.press_button_success(2) self.press_button_success(1) class TestRelayDict(unittest.TestCase): def test_init(self): mock_device = object() blank_dict = dict() relay_dict = RelayDict(mock_device, blank_dict) self.assertEqual(relay_dict._store, blank_dict) self.assertEqual(relay_dict.relay_device, mock_device) def test_get_item_valid_key(self): mock_device = object() blank_dict = {'key': 'value'} relay_dict = RelayDict(mock_device, blank_dict) self.assertEqual(relay_dict['key'], 'value') def test_get_item_invalid_key(self): # Create an object with a single attribute 'name' mock_device = type('', (object, ), {'name': 'name'})() blank_dict = {'key': 'value'} relay_dict = RelayDict(mock_device, blank_dict) with self.assertRaises(RelayConfigError): value = relay_dict['not_key'] def test_iter(self): mock_device = type('', (object, ), {'name': 'name'})() data_dict = {'a': '1', 'b': '2', 'c': '3'} relay_dict = RelayDict(mock_device, data_dict) rd_set = set() for key in relay_dict: rd_set.add(key) dd_set = set() for key in data_dict: dd_set.add(key) self.assertSetEqual(rd_set, dd_set) if __name__ == "__main__": unittest.main()