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