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