def test_plant(self): '''Tests sensing a plant.''' world = World() database = MemcachedDatabase() new_robot = Robot("poeiekfm98871", "123") plant = Plant() plant.set_age(12) plant.set_water_level(60) world.plant(plant, (11, 4)) database.commit() world.add_robot(new_robot, (11, 4)) database.commit() action_manager = ActionManager() info = action_manager.do_action(new_robot.get_password(), "sense", [new_robot.get_id()]) self.assertEqual( info["11,4"], { "surface_type": MapSquareTypes.SOIL, "robot": True, "plant": { "age": 12, "water_level": 60, "matured": True } })
def test_specific_point(self): '''Gets information of a specific point, and check its result.''' database = MemcachedDatabase() new_robot = Robot("oie982736hhjf", "lo098173635") new_robot.set_location((9, 4)) database.add_robot(new_robot, (9, 4)) database.commit() action_manager = ActionManager() info = action_manager.do_action(new_robot.get_password(), "sense", [new_robot.get_id()]) self.assertEqual(len(info), 9) self.assertEqual(info["9,4"], { "surface_type": MapSquareTypes.SOIL, "robot": True, "plant": None }) self.assertEqual(info["9,3"], { "surface_type": MapSquareTypes.WATER, "robot": False, "plant": None }) self.assertEqual(info["10,5"], { "surface_type": MapSquareTypes.SOIL, "robot": False, "plant": None }) self.assertEqual(info["8,4"], { "surface_type": MapSquareTypes.SOIL, "robot": False, "plant": None })
def test_specific_point(self): '''Gets information of a specific point, and check its result.''' database = MemcachedDatabase() new_robot = Robot("oie982736hhjf", "lo098173635") new_robot.set_location((9, 4)) database.add_robot(new_robot, (9, 4)) database.commit() action_manager = ActionManager() info = action_manager.do_action(new_robot.get_password(), "sense", [new_robot.get_id()]) self.assertEqual(len(info), 9) self.assertEqual(info["9,4"], {"surface_type": MapSquareTypes.SOIL, "robot": True, "plant": None}) self.assertEqual(info["9,3"], {"surface_type": MapSquareTypes.WATER, "robot": False, "plant": None}) self.assertEqual(info["10,5"], {"surface_type": MapSquareTypes.SOIL, "robot": False, "plant": None}) self.assertEqual(info["8,4"], {"surface_type": MapSquareTypes.SOIL, "robot": False, "plant": None})
def test_bad_direction(self): '''Sends an invalid direction as arguments.''' robot_id = "test_bad_direction_18445" robot = Robot(robot_id, "123") world = World() action_manager = ActionManager() database = MemcachedDatabase() world.add_robot(robot, (12, 6)) database.commit() with self.assertRaises(InvalidArgumentsError): action_manager.do_action("123", "move", [robot_id, "U"]) database.rollback() with self.assertRaises(InvalidArgumentsError): action_manager.do_action("123", "move", [robot_id, 988]) database.rollback() with self.assertRaises(InvalidArgumentsError): action_manager.do_action("123", "move", [robot_id, None]) database.rollback() with self.assertRaises(InvalidArgumentsError): action_manager.do_action("123", "move", [robot_id]) database.rollback()
def test_no_plant(self): '''Tests when there's no plant to eat.''' action_manager = ActionManager() database = MemcachedDatabase() with self.assertRaises(NoPlantToEat): action_manager.do_action("123", "eat", [TestEatAction.ROBOT_ID]) database.rollback()
def test_locked(self): '''Tests with a locked square.''' action_manager = ActionManager() database = MemcachedDatabase() database.get_square(TestEatAction.LOCATION, for_update=True) with self.assertRaises(LockAlreadyAquiredError): action_manager.do_action("123", "eat", [TestEatAction.ROBOT_ID]) database.rollback()
def test_bad_argument(self): '''Tests when sending bad arguments to the action.''' action_manager = ActionManager() database = MemcachedDatabase() with self.assertRaises(InvalidArgumentsError): action_manager.do_action("123", "eat", [TestEatAction.ROBOT_ID, None]) database.rollback() with self.assertRaises(InvalidArgumentsError): action_manager.do_action("123", "eat", [TestEatAction.ROBOT_ID, "", 9]) database.rollback()
def test_blocking_object(self): '''Tests moving toward a blocking object.''' robot_id = "test_invalid_location_8765112" robot = Robot(robot_id, "123") world = World() action_manager = ActionManager() database = MemcachedDatabase() world.add_robot(robot, (11, 6)) database.commit() with self.assertRaises(LocationIsBlockedError): action_manager.do_action("123", "move", [robot_id, "W"])
def test_corner(self): '''Tests getting a corner of the map.''' database = MemcachedDatabase() new_robot = Robot("0981kdjieu871", "oie987163") new_robot.set_location((0, 1)) database.add_robot(new_robot, (0, 1)) database.commit() action_manager = ActionManager() info = action_manager.do_action(new_robot.get_password(), "sense", [new_robot.get_id()]) self.assertEqual(len(info), 6)
def test_blind_point(self): '''Gets information of a point, but don't care about the result.''' database = MemcachedDatabase() new_robot = Robot("1873yudhNCbueio", "ueijdnchiop") new_robot.set_location((9, 7)) database.add_robot(new_robot, (9, 7)) database.commit() action_manager = ActionManager() info = action_manager.do_action(new_robot.get_password(), "sense", [new_robot.get_id()]) self.assertEqual(len(info), 9)
def test_moving_outside(self): '''Tests moving a robot to outside of the world.''' robot_id = "test_moving_outside_981165" robot = Robot(robot_id, "123") world = World() action_manager = ActionManager() database = MemcachedDatabase() world.add_robot(robot, (14, 2)) database.commit() with self.assertRaises(InvalidLocationError): action_manager.do_action("123", "move", [robot_id, "E"]) database.rollback()
class Communicator(Singleton): '''Interface between listeners and the application.''' def _initialize(self): self._database = MemcachedDatabase() self._action_manager = ActionManager() self._population_control = PopulationControl() self._admin_handler = AdminHandler() def execute_command(self, password, command, args): '''Execute client's command.''' try: if command in ["born", "give_birth"]: result = self._population_control.execute_command(password, command, args) elif command == "map_data": result = self._admin_handler.execute_command(password, command, args) else: result = self._action_manager.do_action(password, command, args) # Committing or rollbacking all changes after the completion of execution. self._database.commit() return result except Exception: self._database.rollback() raise
def test_lock(self): '''Tests if location is locked.''' robot_id = "test_move_lock_76120" robot = Robot(robot_id, "123") world = World() action_manager = ActionManager() database = MemcachedDatabase() world.add_robot(robot, (13, 6)) database.commit() database.get_square((13, 7), for_update=True) with self.assertRaises(LockAlreadyAquiredError): action_manager.do_action("123", "move", [robot_id, "S"]) database.rollback()
def test_eating_not_matured(self): '''Tests when robot eat a non matured plant.''' world = World() database = MemcachedDatabase() action_manager = ActionManager() plant = Plant() plant.set_age(1) world.plant(plant, TestEatAction.LOCATION) database.commit() robot = database.get_robot(TestEatAction.ROBOT_ID, for_update=True) robot.set_energy(10) database.commit() action_manager.do_action("123", "eat", [TestEatAction.ROBOT_ID]) database.commit() updated_robot = database.get_robot(TestEatAction.ROBOT_ID) self.assertEqual(updated_robot.get_energy(), robot.get_energy() - 1)
def test_plant(self): '''Tests sensing a plant.''' world = World() database = MemcachedDatabase() new_robot = Robot("poeiekfm98871", "123") plant = Plant() plant.set_age(12) plant.set_water_level(60) world.plant(plant, (11, 4)) database.commit() world.add_robot(new_robot, (11, 4)) database.commit() action_manager = ActionManager() info = action_manager.do_action(new_robot.get_password(), "sense", [new_robot.get_id()]) self.assertEqual(info["11,4"], {"surface_type": MapSquareTypes.SOIL, "robot": True, "plant": {"age": 12, "water_level": 60, "matured": True}})
class TestActionManager(unittest.TestCase): def __init__(self, *args, **kwargs): super(TestActionManager, self).__init__(*args, **kwargs) self._action_manager = ActionManager() self._database = MemcachedDatabase() def tearDown(self): # Rolling back any remaining thing. self._database.rollback() def test_not_exist_robot(self): '''Test if ActionManager handles not-existed robot.''' with self.assertRaises(RobotNotFoundError): self._action_manager.do_action("123", "move", ["not_existed_robot_id"]) def test_bad_robot_id(self): '''Test invalid robot IDs.''' # Note that listeners checks if `args' is a list, so action manager won't receive another type. with self.assertRaises(actions.exceptions.InvalidArgumentsError): self._action_manager.do_action("123", "move", []) with self.assertRaises(actions.exceptions.InvalidArgumentsError): self._action_manager.do_action("123", "move", [None]) def test_invalid_password(self): '''Test if ActionManager authenticate passwords correctly.''' robot = Robot("test_invalid_password_95312", "andhue-ifue876-fkdnpw-1") self._database.add_robot(robot, (3, 1)) self._database.commit() with self.assertRaises(AuthenticationFailedError): self._action_manager.do_action("ieukjdf-ioquiwe-751io", "status", ["test_invalid_password_95312"]) def test_dead_robot(self): '''Test if ActionManager checks a dead robot.''' robot = Robot("test_dead_robot_98176", "1234") robot.set_alive(False) self._database.add_robot(robot, (3, 2)) self._database.commit() with self.assertRaises(AuthenticationFailedError): self._action_manager.do_action("1234", "status", ["test_dead_robot_98176"]) def test_bad_actions(self): '''Test wrong action IDs.''' robot = Robot("test_bad_actions_2376", "123") self._database.add_robot(robot, (4, 1)) self._database.commit() with self.assertRaises(actions.exceptions.InvalidActionError): self._action_manager.do_action("123", "not-exist-action", ["test_bad_actions_2376"]) self._database.rollback() with self.assertRaises(actions.exceptions.InvalidActionError): self._action_manager.do_action("123", 5432, ["test_bad_actions_2376"]) self._database.rollback() with self.assertRaises(actions.exceptions.InvalidActionError): self._action_manager.do_action("123", None, ["test_bad_actions_2376"]) self._database.rollback() with self.assertRaises(actions.exceptions.InvalidActionError): self._action_manager.do_action("123", "", ["test_bad_actions_2376"]) def test_ok(self): '''Execute a fine action.''' robot = Robot("test_ok_action_3278", "4467yrt-ddfjh-1u872-oiie") self._database.add_robot(robot, (3, 3)) self._database.commit() initial_energy = robot.get_energy() initial_age = robot.get_life() result = self._action_manager.do_action("4467yrt-ddfjh-1u872-oiie", "status", ["test_ok_action_3278"]) self.assertEqual(result['alive'], True) # Robot should lost energy and age. self._database.commit() robot = self._database.get_robot("test_ok_action_3278") self.assertEqual(robot.get_energy(), initial_energy - 1) self.assertEqual(robot.get_life(), initial_age - 1) def test_losing_energy_on_error(self): '''Tests if ActionManager reduces energy and age after an exception.''' robot = Robot("test_losing_energy_on_error_981", "091oikjdmncj") self._database.add_robot(robot, (5, 3)) self._database.commit() initial_energy = robot.get_energy() initial_age = robot.get_life() with self.assertRaises(actions.exceptions.InvalidActionError): self._action_manager.do_action("091oikjdmncj", "invalid_action", ["test_losing_energy_on_error_981"]) self._database.commit() robot = self._database.get_robot("test_losing_energy_on_error_981") self.assertEqual(robot.get_energy(), initial_energy - 1) self.assertEqual(robot.get_life(), initial_age - 1) # Robot shouldn't lose energy on authentication error. with self.assertRaises(AuthenticationFailedError): self._action_manager.do_action("wrong pass", "invalid_action", ["test_losing_energy_on_error_981"]) self._database.rollback() robot = self._database.get_robot("test_losing_energy_on_error_981") self.assertEqual(robot.get_energy(), initial_energy - 1) self.assertEqual(robot.get_life(), initial_age - 1) def test_delay(self): '''Tests delay between robot actions.''' robot = Robot("test_delay_1223", "09112345") self._database.add_robot(robot, (6, 3)) self._database.commit() self._action_manager.do_action("09112345", "sense", [robot.get_id()]) self._database.commit() start_time = time.time() self._action_manager.do_action("09112345", "sense", [robot.get_id()]) elapsed_time = time.time() - start_time self._database.commit() # one millisecond reduced from delay to cover error. self.assertGreater(elapsed_time, 0.029)
def test_directions(self): '''Tests if moving in different directions works correctly.''' robot_id = "test_directions_154332" robot = Robot(robot_id, "123") world = World() database = MemcachedDatabase() world.add_robot(robot, (10, 2)) database.commit() action_manager = ActionManager() action_manager.do_action("123", "move", [robot_id, "N"]) database.commit() robot = database.get_robot(robot_id) self.assertEqual(robot.get_location(), (10, 1)) action_manager.do_action("123", "move", [robot_id, "NE"]) database.commit() robot = database.get_robot(robot_id) self.assertEqual(robot.get_location(), (11, 0)) action_manager.do_action("123", "move", [robot_id, "E"]) database.commit() robot = database.get_robot(robot_id) self.assertEqual(robot.get_location(), (12, 0)) action_manager.do_action("123", "move", [robot_id, "SE"]) database.commit() robot = database.get_robot(robot_id) self.assertEqual(robot.get_location(), (13, 1)) action_manager.do_action("123", "move", [robot_id, "S"]) database.commit() robot = database.get_robot(robot_id) self.assertEqual(robot.get_location(), (13, 2)) action_manager.do_action("123", "move", [robot_id, "SW"]) database.commit() robot = database.get_robot(robot_id) self.assertEqual(robot.get_location(), (12, 3)) action_manager.do_action("123", "move", [robot_id, "W"]) database.commit() robot = database.get_robot(robot_id) self.assertEqual(robot.get_location(), (11, 3)) action_manager.do_action("123", "move", [robot_id, "NW"]) database.commit() robot = database.get_robot(robot_id) self.assertEqual(robot.get_location(), (10, 2))
def setUp(self): self.manager = ActionManager() super().setUp()
def __init__(self, *args, **kwargs): super(TestActionManager, self).__init__(*args, **kwargs) self._action_manager = ActionManager() self._database = MemcachedDatabase()
class TestActionManager(BaseTest): def setUp(self): self.manager = ActionManager() super().setUp() def test_subscribe(self): self.assertEqual(len(self.manager.state), 0) self.manager.subscribe(WebHookAction) assert len(self.manager.state) == 1 assert len(self.manager.items) == 1 assert len(self.manager.keys) == 1 assert len(self.manager.values) == 1 assert WebHookAction.action_key in self.manager.state assert self.manager.state[WebHookAction.action_key] == WebHookAction # Adding the same event self.manager.subscribe(WebHookAction) assert len(self.manager.state) == 1 assert len(self.manager.items) == 1 assert len(self.manager.items) == 1 assert len(self.manager.keys) == 1 assert len(self.manager.values) == 1 # Adding new event self.manager.subscribe(PagerDutyWebHookAction) assert len(self.manager.state) == 2 assert len(self.manager.items) == 2 assert len(self.manager.items) == 2 assert len(self.manager.keys) == 2 assert len(self.manager.values) == 2 # Adding new event with same event type class DummyEvent(WebHookAction): pass with self.assertRaises(AssertionError): self.manager.subscribe(DummyEvent) def test_knows(self): assert self.manager.knows(action_key=WebHookAction.action_key) is False self.manager.subscribe(WebHookAction) assert self.manager.knows(action_key=WebHookAction.action_key) is True # Adding same event self.manager.subscribe(WebHookAction) assert self.manager.knows(action_key=WebHookAction.action_key) is True # New event assert self.manager.knows(PagerDutyWebHookAction) is False self.manager.subscribe(PagerDutyWebHookAction) assert self.manager.knows( action_key=PagerDutyWebHookAction.action_key) is True def test_get(self): assert self.manager.get(action_key=WebHookAction.action_key) is None self.manager.subscribe(WebHookAction) assert self.manager.get( action_key=WebHookAction.action_key) == WebHookAction def test_action_event(self): assert len(ActionExecutedEvent.attributes) == 2 assert ActionExecutedEvent.attributes[0].name == 'automatic' assert ActionExecutedEvent.attributes[1].name == 'user.id'
def _initialize(self): self._database = MemcachedDatabase() self._action_manager = ActionManager() self._population_control = PopulationControl() self._admin_handler = AdminHandler()
def main(): # Init SMTP smtp_server = None smtp_user = None smtp_password = None smtp_recipients = None smtp_service = None use_smtp = input('Use SMTP? (y/n) ') if use_smtp == 'y': smtp_server = input('\t / SMTP Server: ') smtp_user = input('\t / User: '******'\t / Password: '******'\t / Recipients: ').split(',') ] smtp_service = SMTP_Service(smtp_user, smtp_password, smtp_server) print() # Init projector details IP_class = input('IP class (leave blank if different among projectors): ') default_port = input( 'Default port (leave blank if different among projectors): ') print() if IP_class: IP_class += '.' if default_port: default_port = int(default_port) projectors = {} projector_names = [] while not projectors: number_of_projectors = int(input('Number of projectors: ')) for i in range(1, number_of_projectors + 1): print() name = input('Name of projector {}: '.format(i)) projector_names.append(name) IP = IP_class + input('IP of projector {}: {}'.format(i, IP_class)) if not default_port: PORT = int(input('Port of projector {}: '.format(i))) else: PORT = default_port # Init projector projectors[name] = ChristieProjector(name, IP, PORT) if not projectors[name].connect(): del projectors[name] projector_names.remove(name) continue if not projectors: print() # Init argument parser parser = argparse.ArgumentParser() parser.add_argument('-v', '--videoprojector', nargs='*', help='videoprojector name / identifier') parser.add_argument('-c', '--command', help='serial command to be sent to videoprojector') parser.add_argument( '-p', '--predefined', nargs='*', help= 'predefined command, such as \'temp\', \'conf\', \'sys\', \'lamp\', \'cool\', \'seri\', \'sign\', \'health\', \'vers\', or \'update_loop_email <seconds>\'' ) # Init background action manager action_manager = ActionManager() action_manager.start() # Main loop args = {} destination_projectors = [] while True: # Parse arguments astr = input('\n$: ') if astr == 'exit': break try: args = vars(parser.parse_args(shlex.split(astr))) except SystemExit: # Trap argparse error message continue if args['videoprojector'] is None or args['videoprojector'] == []: destination_projectors = projector_names else: if set(args['videoprojector']).issubset(projector_names): destination_projectors = args['videoprojector'] else: print('\'{}\' not a videoprojector'.format( list(set(args['videoprojector']) - set(projector_names)))) continue for projector_name in destination_projectors: action = None if args['predefined']: command_code = args['predefined'][0] if 'terminate' in args[ 'predefined']: # if the action needs to be terminated for act in action_manager.actions: # parse current actions if act.code == command_code and act.projector.name in destination_projectors: action_manager.remove_action(act) else: if command_code == 'temp': action = TemperatureRequest(projectors[projector_name]) elif command_code == 'conf': action = ConfigurationRequest( projectors[projector_name]) elif command_code == 'sys': action = SystemRequest(projectors[projector_name]) elif command_code == 'vers': action = VersionRequest(projectors[projector_name]) elif command_code == 'sign': action = SignalRequest(projectors[projector_name]) elif command_code == 'cool': action = CoolingRequest(projectors[projector_name]) elif command_code == 'health': action = HealthRequest(projectors[projector_name]) elif command_code == 'serial': action = SerialRequest(projectors[projector_name]) elif command_code == 'lamp': action = LampRequest(projectors[projector_name]) elif command_code == 'update_loop_email': if use_smtp == 'n': use_smtp = input( '\n\t# SMTP was not enabled! Use SMTP? (y/n) ') smtp_server = input('\t\t / SMTP Server: ') smtp_user = input('\t\t / User: '******'\t\t / Password: '******'\t\t / Recipients: ').split(',') ] smtp_service = SMTP_Service( smtp_user, smtp_password, smtp_server) update_interval = float(args['predefined'][1]) action = UpdateLoopEmail( projectors[projector_name], update_interval, smtp_recipients, smtp_service) else: update_interval = float(args['predefined'][1]) action = UpdateLoopEmail( projectors[projector_name], update_interval, smtp_recipients, smtp_service) elif args['command']: is_request = '?' in args['command'] action = Command(projectors[projector_name], args['command'], is_request) # Add action if action != None: action_manager.add_action(action) # Print actions that require printing, such as requests - this blocks I/O if action.needs_printing: while True: if action in action_manager.responses: if not action_manager.responses[action]: print( '\n\t# Projector \'{}\' (IP: {}) did not respond' .format( projector_name, projectors[projector_name]. last_IP_digits)) else: print( '\n\t# Projector \'{}\' (IP: {}) sent the following response:' .format( projector_name, projectors[projector_name]. last_IP_digits)) action.print_response() action_manager.clear_reponse(action) break action_manager.exit()