def setUpClass(cls): # Creating a robot that all the tests will use. database = MemcachedDatabase() world = World() robot = Robot(TestGiveBirth.ROBOT_ID, "123") world.add_robot(robot, (0, 14)) database.commit()
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_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 setUpClass(cls): # Addin a robot to the world. All the tests would use this robot. robot = Robot(cls.ROBOT_ID, "123") world = World() world.add_robot(robot, cls.LOCATION) database = MemcachedDatabase() database.commit()
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_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 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()
def test_locked(self): '''Tests with a locked square.''' database = MemcachedDatabase() world = World() robot = Robot("test_locked_robot_190083", "123") # Setting the energy to zero, so the updater tries to update the square too. robot.set_energy(0) world.add_robot(robot, (5, 9)) database.commit() world.get_square((5, 9), for_update=True) with self.assertRaises(LockAlreadyAquiredError): database.get_robot(robot.get_id(), for_update=True)
def test_out_of_energy_robot(self): '''Tests when a robot ran out of energy.''' database = MemcachedDatabase() world = World() robot = Robot("test_out_of_energy_robot_18773", "123") robot.set_energy(0) world.add_robot(robot, (1, 9)) database.commit() got_robot = database.get_robot("test_out_of_energy_robot_18773", for_update=False) self.assertFalse(got_robot.get_alive()) square = world.get_square((1, 9)) self.assertIsNone(square.get_robot_id())
def test_out_of_life_robot(self): '''Tests when a robot ran out of life.''' database = MemcachedDatabase() world = World() robot = Robot("test_out_of_life_robot_9022", "123") robot.set_life(0) world.add_robot(robot, (0, 9)) database.commit() received_robot = database.get_robot("test_out_of_life_robot_9022", for_update=False) self.assertFalse(received_robot.get_alive()) square = world.get_square((0, 9)) self.assertIsNone(square.get_robot_id())
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_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 AddRobotTest(unittest.TestCase): def __init__(self, *args, **kwargs): super(AddRobotTest, self).__init__(*args, **kwargs) self._world = World() def test_duplicate(self): '''Tests adding duplicate robot.''' database = MemcachedDatabase() robot = Robot("world_duplicate_robot_8722", "123") self._world.add_robot(robot, (5, 1)) database.commit() robot_2 = Robot("world_duplicate_robot_8722", "1236") with self.assertRaises(CannotAddObjectError): self._world.add_robot(robot_2, (5, 2)) database.commit() def test_ok(self): '''Adds a good robot object to the world.''' database = MemcachedDatabase() robot = Robot("world_ok_robot_38364", "123") self._world.add_robot(robot, (5, 0)) database.commit() gotted_robot = database.get_robot(robot.get_id()) self.assertEqual(gotted_robot.get_alive(), robot.get_alive()) all_robots = database.get_all_robot_ids() self.assertIn(robot.get_id(), all_robots) def test_invalid_location(self): '''Tests adding a robot to an invalid location.''' database = MemcachedDatabase() robot = Robot("invalid_location_robot_1863", "123") with self.assertRaises(InvalidLocationError): self._world.add_robot(robot, (19872, 1190)) database.commit() def test_blocked_location(self): '''Tests adding the robot to a blocked square.''' database = MemcachedDatabase() robot = Robot("test_blocked_location_91882", "123") # There's a rock here. self._world.add_robot(robot, (6, 1)) database.commit() received_robot = database.get_robot(robot.get_id()) self.assertNotEqual(received_robot.get_location(), (6, 1)) def test_locked_location(self): '''Tests adding a robot to a locked location.''' database = MemcachedDatabase() robot = Robot("test_locked_location_0023", "123") # Locking 8,1 database.get_square((8, 1), for_update=True) self._world.add_robot(robot, (8, 1)) database.commit() received_robot = database.get_robot(robot.get_id()) self.assertNotEqual(received_robot.get_location(), (8, 1))
class PopulationControl: '''Controls the population of the world. i.e. controlling if a robot can have a child, or gives birth to new robots. ''' def __init__(self): self._authenticator = Authenticator() self._database = MemcachedDatabase() self._world = World() self._id_generator = IDGenerator() self._configs = Configs() def execute_command(self, password, command, args): '''Executes the specified command.''' if not isinstance(password, str): raise InvalidArgumentsError( "Expected {0} as password, found {1}.".format( type(str), type(password))) if command == "born": return self._born(password, args) elif command == "give_birth": return self._give_birth(password, args) def _born(self, password, args): '''Gives birth to a robot for the first time. @param args: List of arguments. The first argument can be a parent robot. If provided, the new robot will be born software near its parent. If not, it will be born on a random place. ''' parent_robot_id = None if len(args) > 0: parent_robot_id = args[0] if parent_robot_id is not None: if not isinstance(parent_robot_id, str): raise InvalidArgumentsError( "`parent_robot_id' must be `str', not {0}".format( type(parent_robot_id))) parent_robot = self._database.get_robot(parent_robot_id) born_location = parent_robot.get_location() else: world_size = self._world.get_size() born_location = (random.randint(0, world_size[0] - 1), random.randint(0, world_size[1] - 1)) robot_name = "" if len(args) == 2: robot_name = args[1] self._authenticator.authenticate_new_robot(password) new_robot = Robot(self._id_generator.get_robot_id(), self._id_generator.get_password(), name=robot_name) self._world.add_robot(new_robot, (born_location[0], born_location[1])) return { 'robot_id': new_robot.get_id(), 'password': new_robot.get_password() } def _give_birth(self, password, args): '''Checks if robot has the permission to give birth to a child. If so, it generates and returns a new password. ''' if len(args) != 1: raise InvalidArgumentsError( "`give_birth' takes exactly one argument.") robot_id = args[0] if not isinstance(robot_id, str): raise InvalidArgumentsError( "Expected {0} as robot_id, found {1}".format( type(str), type(args[0]))) robot = self._database.get_robot(robot_id, for_update=True) required_honor = self._configs.get_robots_birth_required_honor() if robot.get_honor() < required_honor: raise NotEnoughHonorError( "Robot needs {0} honor to give birth, but has {1}.".format( required_honor, robot.get_honor())) robot.set_honor(robot.get_honor() - required_honor) # This while is exists, to prevent generating duplicated passwords. while True: try: new_password = self._id_generator.get_password() self._database.add_password(new_password) break except DuplicatedPasswordError: # pragma: no cover continue return new_password
def test_robot_simulation(self): '''This test simulates a full game scenario.''' database = MemcachedDatabase() world = World() configs = Configs() print() print("Simulating a robot playing the game. This may take a while.") # Creating a world for the robot to live in. # The world map is: # # 000000 # 000222 # 000144 # 000144 row01 = [ MapSquare(MapSquareTypes.SOIL, (0, 30)), MapSquare(MapSquareTypes.SOIL, (1, 30)), MapSquare(MapSquareTypes.SOIL, (2, 30)), MapSquare(MapSquareTypes.SOIL, (3, 30)), MapSquare(MapSquareTypes.SOIL, (4, 30)), MapSquare(MapSquareTypes.SOIL, (5, 30)) ] row02 = [ MapSquare(MapSquareTypes.SOIL, (0, 31)), MapSquare(MapSquareTypes.SOIL, (1, 31)), MapSquare(MapSquareTypes.SOIL, (2, 31)), MapSquare(MapSquareTypes.ROCK, (3, 31)), MapSquare(MapSquareTypes.ROCK, (4, 31)), MapSquare(MapSquareTypes.ROCK, (5, 31)) ] row03 = [ MapSquare(MapSquareTypes.SOIL, (0, 32)), MapSquare(MapSquareTypes.SOIL, (1, 32)), MapSquare(MapSquareTypes.SOIL, (2, 32)), MapSquare(MapSquareTypes.SAND, (3, 32)), MapSquare(MapSquareTypes.WATER, (4, 32)), MapSquare(MapSquareTypes.WATER, (5, 32)) ] row04 = [ MapSquare(MapSquareTypes.SOIL, (0, 33)), MapSquare(MapSquareTypes.SOIL, (1, 33)), MapSquare(MapSquareTypes.SOIL, (2, 33)), MapSquare(MapSquareTypes.SAND, (3, 33)), MapSquare(MapSquareTypes.WATER, (4, 33)), MapSquare(MapSquareTypes.WATER, (5, 33)) ] database.add_square_row(row01) database.add_square_row(row02) database.add_square_row(row03) database.add_square_row(row04) # Creating parent of our robot. parent_robot = Robot("parent_robot_1982.345", "123", name="Parent") parent_robot.set_honor(configs.get_robots_birth_required_honor() + 1) world.add_robot(parent_robot, (2, 31)) database.commit() # Giving birth to our hero. result = self.post_request({ 'command': 'give_birth', 'password': '******', 'args': ["parent_robot_1982.345"] }) self.assertEqual(result['status'], 200, result) born_password = result['result'] # Robot requests a born. result = self.post_request({ 'command': 'born', 'password': born_password, 'args': [parent_robot.get_id()] }) self.assertEqual(result['status'], 200) robot_id = result['result']['robot_id'] password = result['result']['password'] # Getting status. result = self.post_request({ 'command': 'status', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) self.assertTrue(result['result']['alive']) self.assertFalse(result['result']['has_water']) self.assertEqual(result['result']['location'], "2,30") # Moving somewhere to plan a corp. # Note that parent robot is on the south. So, we have to turn around it. result = self.post_request({ 'command': 'move', 'password': password, 'args': [robot_id, 'W'] }) self.assertEqual(result['status'], 200, result) result = self.post_request({ 'command': 'move', 'password': password, 'args': [robot_id, 'S'] }) self.assertEqual(result['status'], 200, result) result = self.post_request({ 'command': 'move', 'password': password, 'args': [robot_id, 'S'] }) self.assertEqual(result['status'], 200, result) result = self.post_request({ 'command': 'move', 'password': password, 'args': [robot_id, 'E'] }) self.assertEqual(result['status'], 200, result) # We are at the location. Checking if its correct. result = self.post_request({ 'command': 'status', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) self.assertEqual(result['result']['location'], "2,32") # Planting a corp here. result = self.post_request({ 'command': 'plant', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) # Checking if it is planted. result = self.post_request({ 'command': 'sense', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) self.assertEqual(result['result']['2,32']['surface_type'], MapSquareTypes.SOIL) self.assertIsNotNone(result['result']['2,32']['plant']) # Going to pick water. result = self.post_request({ 'command': 'move', 'password': password, 'args': [robot_id, 'E'] }) self.assertEqual(result['status'], 200, result) result = self.post_request({ 'command': 'move', 'password': password, 'args': [robot_id, 'E'] }) self.assertEqual(result['status'], 200, result) result = self.post_request({ 'command': 'pick_water', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) result = self.post_request({ 'command': 'status', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) self.assertTrue(result['result']['has_water']) # Getting back to the plant location. result = self.post_request({ 'command': 'move', 'password': password, 'args': [robot_id, 'W'] }) self.assertEqual(result['status'], 200, result) result = self.post_request({ 'command': 'move', 'password': password, 'args': [robot_id, 'W'] }) self.assertEqual(result['status'], 200, result) # Watering result = self.post_request({ 'command': 'water', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) # Checking result = self.post_request({ 'command': 'sense', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) # It lost some water already. self.assertGreater(result['result']['2,32']['plant']['water_level'], 70) # Plant should be matured by now. Eating! result = self.post_request({ 'command': 'status', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) previous_energy = result['result']['energy'] result = self.post_request({ 'command': 'eat', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) result = self.post_request({ 'command': 'status', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 200, result) self.assertGreater(result['result']['energy'], previous_energy) # Now, trying some bad moves! # Trying to plant on a sand. result = self.post_request({ 'command': 'move', 'password': password, 'args': [robot_id, 'E'] }) self.assertEqual(result['status'], 200, result) result = self.post_request({ 'command': 'plant', 'password': password, 'args': [robot_id] }) self.assertEqual(result['status'], 500, result) self.assertEqual(result['error_code'], 'CannotPlantHereError') # Trying to move to a rock. result = self.post_request({ 'command': 'move', 'password': password, 'args': [robot_id, 'N'] }) self.assertEqual(result['status'], 500, result) self.assertEqual(result['error_code'], 'LocationIsBlockedError')
def test_robot_simulation(self): '''This test simulates a full game scenario.''' database = MemcachedDatabase() world = World() configs = Configs() print() print("Simulating a robot playing the game. This may take a while.") # Creating a world for the robot to live in. # The world map is: # # 000000 # 000222 # 000144 # 000144 row01 = [MapSquare(MapSquareTypes.SOIL, (0, 30)), MapSquare(MapSquareTypes.SOIL, (1, 30)), MapSquare(MapSquareTypes.SOIL, (2, 30)), MapSquare(MapSquareTypes.SOIL, (3, 30)), MapSquare(MapSquareTypes.SOIL, (4, 30)), MapSquare(MapSquareTypes.SOIL, (5, 30))] row02 = [MapSquare(MapSquareTypes.SOIL, (0, 31)), MapSquare(MapSquareTypes.SOIL, (1, 31)), MapSquare(MapSquareTypes.SOIL, (2, 31)), MapSquare(MapSquareTypes.ROCK, (3, 31)), MapSquare(MapSquareTypes.ROCK, (4, 31)), MapSquare(MapSquareTypes.ROCK, (5, 31))] row03 = [MapSquare(MapSquareTypes.SOIL, (0, 32)), MapSquare(MapSquareTypes.SOIL, (1, 32)), MapSquare(MapSquareTypes.SOIL, (2, 32)), MapSquare(MapSquareTypes.SAND, (3, 32)), MapSquare(MapSquareTypes.WATER, (4, 32)), MapSquare(MapSquareTypes.WATER, (5, 32))] row04 = [MapSquare(MapSquareTypes.SOIL, (0, 33)), MapSquare(MapSquareTypes.SOIL, (1, 33)), MapSquare(MapSquareTypes.SOIL, (2, 33)), MapSquare(MapSquareTypes.SAND, (3, 33)), MapSquare(MapSquareTypes.WATER, (4, 33)), MapSquare(MapSquareTypes.WATER, (5, 33))] database.add_square_row(row01) database.add_square_row(row02) database.add_square_row(row03) database.add_square_row(row04) # Creating parent of our robot. parent_robot = Robot("parent_robot_1982.345", "123", name="Parent") parent_robot.set_honor(configs.get_robots_birth_required_honor() + 1) world.add_robot(parent_robot, (2, 31)) database.commit() # Giving birth to our hero. result = self.post_request({'command': 'give_birth', 'password': '******', 'args': ["parent_robot_1982.345"]}) self.assertEqual(result['status'], 200, result) born_password = result['result'] # Robot requests a born. result = self.post_request({'command': 'born', 'password': born_password, 'args': [parent_robot.get_id()]}) self.assertEqual(result['status'], 200) robot_id = result['result']['robot_id'] password = result['result']['password'] # Getting status. result = self.post_request({'command': 'status', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) self.assertTrue(result['result']['alive']) self.assertFalse(result['result']['has_water']) self.assertEqual(result['result']['location'], "2,30") # Moving somewhere to plan a corp. # Note that parent robot is on the south. So, we have to turn around it. result = self.post_request({'command': 'move', 'password': password, 'args': [robot_id, 'W']}) self.assertEqual(result['status'], 200, result) result = self.post_request({'command': 'move', 'password': password, 'args': [robot_id, 'S']}) self.assertEqual(result['status'], 200, result) result = self.post_request({'command': 'move', 'password': password, 'args': [robot_id, 'S']}) self.assertEqual(result['status'], 200, result) result = self.post_request({'command': 'move', 'password': password, 'args': [robot_id, 'E']}) self.assertEqual(result['status'], 200, result) # We are at the location. Checking if its correct. result = self.post_request({'command': 'status', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) self.assertEqual(result['result']['location'], "2,32") # Planting a corp here. result = self.post_request({'command': 'plant', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) # Checking if it is planted. result = self.post_request({'command': 'sense', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) self.assertEqual(result['result']['2,32']['surface_type'], MapSquareTypes.SOIL) self.assertIsNotNone(result['result']['2,32']['plant']) # Going to pick water. result = self.post_request({'command': 'move', 'password': password, 'args': [robot_id, 'E']}) self.assertEqual(result['status'], 200, result) result = self.post_request({'command': 'move', 'password': password, 'args': [robot_id, 'E']}) self.assertEqual(result['status'], 200, result) result = self.post_request({'command': 'pick_water', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) result = self.post_request({'command': 'status', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) self.assertTrue(result['result']['has_water']) # Getting back to the plant location. result = self.post_request({'command': 'move', 'password': password, 'args': [robot_id, 'W']}) self.assertEqual(result['status'], 200, result) result = self.post_request({'command': 'move', 'password': password, 'args': [robot_id, 'W']}) self.assertEqual(result['status'], 200, result) # Watering result = self.post_request({'command': 'water', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) # Checking result = self.post_request({'command': 'sense', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) # It lost some water already. self.assertGreater(result['result']['2,32']['plant']['water_level'], 70) # Plant should be matured by now. Eating! result = self.post_request({'command': 'status', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) previous_energy = result['result']['energy'] result = self.post_request({'command': 'eat', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) result = self.post_request({'command': 'status', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 200, result) self.assertGreater(result['result']['energy'], previous_energy) # Now, trying some bad moves! # Trying to plant on a sand. result = self.post_request({'command': 'move', 'password': password, 'args': [robot_id, 'E']}) self.assertEqual(result['status'], 200, result) result = self.post_request({'command': 'plant', 'password': password, 'args': [robot_id]}) self.assertEqual(result['status'], 500, result) self.assertEqual(result['error_code'], 'CannotPlantHereError') # Trying to move to a rock. result = self.post_request({'command': 'move', 'password': password, 'args': [robot_id, 'N']}) self.assertEqual(result['status'], 500, result) self.assertEqual(result['error_code'], 'LocationIsBlockedError')