1#!/usr/bin/env python3 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 17import copy 18import os 19import tempfile 20import shutil 21import unittest 22 23from acts.controllers.relay_lib import generic_relay_device 24from acts.controllers.relay_lib import relay 25from acts.controllers.relay_lib import relay_board 26from acts.controllers.relay_lib import relay_device 27from acts.controllers.relay_lib import relay_rig 28from acts.controllers.relay_lib import sain_smart_board 29 30import acts.controllers.relay_lib.errors as errors 31import acts.controllers.relay_lib.fugu_remote as fugu_remote 32 33# Shorthand versions of the long class names. 34GenericRelayDevice = generic_relay_device.GenericRelayDevice 35Relay = relay.Relay 36RelayDict = relay.RelayDict 37RelayState = relay.RelayState 38SynchronizeRelays = relay.SynchronizeRelays 39RelayBoard = relay_board.RelayBoard 40RelayDevice = relay_device.RelayDevice 41RelayRig = relay_rig.RelayRig 42SainSmartBoard = sain_smart_board.SainSmartBoard 43RelayDeviceConnectionError = errors.RelayDeviceConnectionError 44 45 46class 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 68class ActsRelayTest(unittest.TestCase): 69 def setUp(self): 70 Relay.transition_wait_time = 0 71 Relay.button_press_time = 0 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 83 def tearDown(self): 84 Relay.transition_wait_time = .2 85 Relay.button_press_time = .25 86 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) 173 new_relay._original_state = RelayState.NO 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) 182 new_relay._original_state = RelayState.NO 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 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 199 200class 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 209 Relay.button_press_time = 0 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 = ({ 220 'name': 'SSBoard', 221 'base_url': self.test_dir, 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:]) 240 Relay.transition_wait_time = .2 241 Relay.button_press_time = .25 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 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 340 341class ActsRelayRigTest(unittest.TestCase): 342 def setUp(self): 343 Relay.transition_wait_time = 0 344 Relay.button_press_time = 0 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': [{ 356 'type': 'GenericRelayDevice', 357 'name': 'device', 358 'relays': { 359 'Relay00': 'ss_control/0', 360 'Relay10': 'ss_control/1' 361 } 362 }] 363 } 364 365 def tearDown(self): 366 Relay.transition_wait_time = .2 367 Relay.button_press_time = .25 368 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) 389 del modded_config['devices'][0]['relays']['Relay00'] 390 rig = RelayRigMock(modded_config) 391 self.assertEqual(len(rig.relays), 4) 392 self.assertEqual(len(rig.devices['device'].relays), 1) 393 394 rig = RelayRigMock(self.config) 395 self.assertEqual(len(rig.devices['device'].relays), 2) 396 397 def test_init_relay_rig_correct_device_type(self): 398 rig = RelayRigMock(self.config) 399 self.assertEqual(len(rig.devices), 1) 400 self.assertIsInstance(rig.devices['device'], GenericRelayDevice) 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'] 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) 409 410 411class RelayRigMock(RelayRig): 412 """A RelayRig that substitutes the MockBoard for any board.""" 413 414 _board_constructors = { 415 'SainSmartBoard': lambda x: MockBoard(x), 416 'FuguMockBoard': lambda x: FuguMockBoard(x) 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 431class ActsGenericRelayDeviceTest(unittest.TestCase): 432 def setUp(self): 433 Relay.transition_wait_time = 0 434 Relay.button_press_time = 0 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 = { 442 'name': 'MockDevice', 443 'relays': { 444 'r0': 'MockBoard/0', 445 'r1': 'MockBoard/1' 446 } 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 457 def tearDown(self): 458 Relay.transition_wait_time = .2 459 Relay.button_press_time = .25 460 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) 466 del modified_config['relays']['r1'] 467 468 grd = GenericRelayDevice(modified_config, self.rig) 469 grd.setup() 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 478 grd = GenericRelayDevice(self.device_config, self.rig) 479 grd.setup() 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 490 def change_state(self, begin_state, call, end_state, previous_state=None): 491 self.board.set(self.r0.position, begin_state) 492 grd = GenericRelayDevice(self.device_config, self.rig) 493 call(grd) 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 520 521class ActsRelayDeviceTest(unittest.TestCase): 522 def setUp(self): 523 Relay.transition_wait_time = 0 524 Relay.button_press_time = 0 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 = { 549 "type": "GenericRelayDevice", 550 "name": "device", 551 "relays": { 552 'r0': 'MockBoard/0', 553 'r1': 'MockBoard/1' 554 } 555 } 556 557 def tearDown(self): 558 Relay.transition_wait_time = .2 559 Relay.button_press_time = .25 560 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 607class TestRelayRigParser(unittest.TestCase): 608 def setUp(self): 609 Relay.transition_wait_time = 0 610 Relay.button_press_time = 0 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 625 def tearDown(self): 626 Relay.transition_wait_time = .2 627 Relay.button_press_time = .25 628 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' 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 = { 649 'name': 'name', 650 'relays': { 651 'r0': 'MockBoard/0', 652 'r1': 'MockBoard/1' 653 } 654 } 655 device = rig.create_relay_device(config) 656 self.assertIsInstance(device, GenericRelayDevice) 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 = { 663 'type': 'GenericRelayDevice', 664 'name': '.', 665 'relays': { 666 'r0': 'MockBoard/0', 667 'r1': 'MockBoard/1' 668 } 669 } 670 device = rig.create_relay_device(config) 671 self.assertIsInstance(device, GenericRelayDevice) 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 = { 678 'type': 'SomeInvalidType', 679 'name': '.', 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 692class 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 700class FuguMockBoard(MockBoard): 701 def get_relay_position_list(self): 702 return range(4) 703 704 705class 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 = { 716 'type': 'FuguRemote', 717 'name': 'UniqueDeviceName', 718 'mac_address': '00:00:00:00:00:00', 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 } 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) 735 del flawed_config['relays']['Power'] 736 del flawed_config['relays'][fugu_remote.Buttons.BACK.value] 737 with self.assertRaises(errors.RelayConfigError): 738 fugu_remote.FuguRemote(flawed_config, self.mock_rig) 739 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 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 787class 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 824if __name__ == "__main__": 825 unittest.main() 826