def test_assign_players_5(self): player_list = [] for i in sorted(range(0, 5)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list) assignments = manager.assign_players(manager.player_pool) self.assertEqual(len(assignments[0]), 3) self.assertEqual(len(assignments[1]), 2)
def setUp(self): self.player1 = Player(1) self.player2 = Player(1) self.player3 = Player(2) self.player4 = Player(1) self.player5 = Player(1) self.player6 = Player(2) self.players = [self.player1, self.player2, self.player3, self.player4, self.player5, self.player6] self.manager = Manager()
def test_is_tournament_over_one_remaining_player(self): player_list = [] for i in sorted(range(0, 8)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list) manager.get_winners_and_cheaters = MagicMock( return_value=([player_list[0]], [])) # manager.get_winners = MagicMock(return_value=[player_list[0]]) manager.run_tournament() # make only one winner self.assertEqual(manager.round, 1)
def test_is_tournament_over_3_remaining_players_with_tie(self): player_list = [] for i in sorted(range(0, 3)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list) manager.get_winners_and_cheaters = MagicMock( return_value=([player_list[0], player_list[1]], [])) manager.run_tournament() #have ties with 4 players left self.assertEqual(manager.round, 2) self.assertEqual(manager.last_round_winners, [player_list[0], player_list[1]])
def test_run_tournament_large(self): """ Purpose: Runs a tournament round given a list of passed players. Checks that the tournament has finished at the end, and checks if the remaining player pool is less than or equal to the starting pool. Signature: Void -> Void """ player_list = [] for i in sorted(range(0, 20)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list) manager.run_tournament() # Checks if minimum amount of rounds has passed self.assertTrue(manager.round >= 2)
def test_assign_players_under_max(self): """ Purpose: Test assigning the players when the player pool is less than than maximum number of players per game Signature: Void -> Void """ player_list = [] for i in sorted(range(0, 2)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list) assignments = manager.assign_players(manager.player_pool, max_players=4) self.assertEqual(len(assignments), 1)
def test_run_tournament(self): """ Purpose: Runs a tournament round given a list of passed players. Checks that the tournament has finished at the end, and checks if the remaining player pool is less than or equal to the starting pool. Signature: Void -> Void """ player_list = [] for i in sorted(range(0, 3)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list) manager.run_tournament() # Checks that the winning player pool is less than or equal to the initial passed pool self.assertTrue(len(player_list) >= len(manager.player_pool)) # Checks if rounds advanced self.assertTrue(manager.round > 0)
def test_assign_players_non_default(self): """ Purpose: Test assigning the players with less than the default (4) players allowed per a single game. Signature: Void -> Void """ player_list = [] for i in sorted(range(0, 4)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list) assignments = manager.assign_players(manager.player_pool, max_players=2) for assignment in assignments: self.assertNotEqual(len(assignment), 1) self.assertNotEqual(len(assignment), 0)
def run_tournament(self): """ Run a tournament with all signed up players. Void -> Void """ winners, cheaters = Manager( board_config=FishServer.BOARD_CONFIG).run_tournament(self.players) print(f"[{len(winners)}, {len(cheaters)}]")
def test_assign_players_max(self): """ Purpose: Test assigning the players with the maximum number of players in a game, 4 Signature: Void -> Void """ player_list = [] for i in sorted(range(0, 14)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list) assignments = manager.assign_players(manager.player_pool) for assignment in assignments: self.assertNotEqual(len(assignment), 1) self.assertNotEqual(len(assignment), 0) self.assertEqual(len(assignments[0]), 4) self.assertEqual(len(assignments[len(assignments) - 1]), 2)
def test_run_tournament(self): server = TCPServer('127.0.0.1', 1234) server.configure_server() player_list = [] for i in sorted(range(0, 3)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list) server.tournament_manager = manager self.assertEqual(server.run_tournament(), [1, 0])
def test_passing_small_pool(self): """ Purpose: Tests passing a pool of players that is less than enough to run a game Signature: Void -> Void """ with self.assertRaises(ValueError): player_list = [] for i in sorted(range(0, 1)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list)
def wait_for_client(self, last_try=False) -> List[int]: """ This TCPServer attempts to initiate a tournament. It listens on self.sock for 30 seconds or until 10 clients connect, creating a PlayerProxy for each client that connects. Then, if at least 5 clients have connected, it initializes self.tournament_manager and initiates a tournament via self.run_tournament() @param last_try: If, after initially waiting 30 seconds, less than 4 clients have connected, the function tries again with last_try set to True. If last_try is True and less than 4 clients connect before timeout, the function exits without trying again. @return: A List of the format [int, int], where the first element is the number of players that won the tournament and the second element is the number of players that failed or cheated during the tournament """ try: self.sock.listen( 10) # 10 clients before server refuses connections while len(self.clients) < 10: client_sock, client_address = self.sock.accept() player_client = PlayerProxy(client_sock) if player_client.name: self.clients.append(player_client) except socket.timeout: if len(self.clients) < 5 and not last_try: self.wait_for_client(True) elif len(self.clients) >= 5: self.tournament_manager = Manager( list( zip(self.clients, [i for i in range(len(self.clients))]))) except KeyboardInterrupt: self.shutdown_server() if len(self.clients) < 5 and not last_try: self.wait_for_client(True) elif len(self.clients) >= 5: self.tournament_manager = Manager( list(zip(self.clients, [i for i in range(len(self.clients))]))) if self.tournament_manager: return self.run_tournament()
def test_is_tournament_over_duplicate_round_winners(self): """ Purpose: Checks to determine if a tournament has reached the end condition. Signature: Void -> Void. """ player_list = [] for i in sorted(range(0, 8)): interface = BasicPlayer() player_list.append((interface, i)) manager = Manager(player_list) manager.get_winners_and_cheaters = MagicMock(return_value=(player_list, [])) manager.last_round_winners = player_list manager.run_tournament() # get last round winners to equal current round winners self.assertEqual(manager.round, 1)
class TCPServer: """ Represents the Fish tournament server that accepts a certain number of client connections and then conducts a Fish tournament by creating PlayerProxy components and handing those to the tournament manager, which interacts with the player proxies as if they were internal players. The PlayerProxy component handles direct communication with the associated client. """ def __init__(self, host, port): """ Initializes a TCPServer instance with the given host and port number for creating a socket via self.configure_server() @param host: The host IP address to connect to @param port: The port number to use for connection """ self.host = host # Host address self.port = port # Host port self.sock = None # Connection socket self.tournament_manager = None self.clients = [] def configure_server(self) -> None: """ Initializes this TCPServer's self.sock, connects it to (self.host, self.port), and sets its timeout to 30 seconds @return: None """ # create TCP socket with IPv4 addressing self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # bind server to the address self.sock.bind((self.host, self.port)) self.sock.settimeout(30) # set listen timeout to 30 def wait_for_client(self, last_try=False) -> List[int]: """ This TCPServer attempts to initiate a tournament. It listens on self.sock for 30 seconds or until 10 clients connect, creating a PlayerProxy for each client that connects. Then, if at least 5 clients have connected, it initializes self.tournament_manager and initiates a tournament via self.run_tournament() @param last_try: If, after initially waiting 30 seconds, less than 4 clients have connected, the function tries again with last_try set to True. If last_try is True and less than 4 clients connect before timeout, the function exits without trying again. @return: A List of the format [int, int], where the first element is the number of players that won the tournament and the second element is the number of players that failed or cheated during the tournament """ try: self.sock.listen( 10) # 10 clients before server refuses connections while len(self.clients) < 10: client_sock, client_address = self.sock.accept() player_client = PlayerProxy(client_sock) if player_client.name: self.clients.append(player_client) except socket.timeout: if len(self.clients) < 5 and not last_try: self.wait_for_client(True) elif len(self.clients) >= 5: self.tournament_manager = Manager( list( zip(self.clients, [i for i in range(len(self.clients))]))) except KeyboardInterrupt: self.shutdown_server() if len(self.clients) < 5 and not last_try: self.wait_for_client(True) elif len(self.clients) >= 5: self.tournament_manager = Manager( list(zip(self.clients, [i for i in range(len(self.clients))]))) if self.tournament_manager: return self.run_tournament() def run_tournament(self) -> List[int]: """ Calls this TCPServer's tournament manager to run a tournament and returns the results. @return: AList of the format [int, int], where the first element is the number of players that won the tournament and the second element is the number of players that failed or cheated during the tournament """ self.tournament_manager.run_tournament() self.shutdown_server() return [ len(self.tournament_manager.player_pool), len(self.tournament_manager.cheaters) ] def shutdown_server(self) -> None: """ Closes this TCPServer's self.sock @return: None """ self.sock.close()
def test_constructor(self): Manager(Referee) Manager(ExtendedReferee) with self.assertRaisesRegex(ValueError, "referee_type must be Referee or a subclass of Referee"): Manager(Move)
class RefereeTestCase(unittest.TestCase): def setUp(self): self.player1 = Player(1) self.player2 = Player(1) self.player3 = Player(2) self.player4 = Player(1) self.player5 = Player(1) self.player6 = Player(2) self.players = [self.player1, self.player2, self.player3, self.player4, self.player5, self.player6] self.manager = Manager() ## TESTING TOURNAMENT CREATION ########################################################### def test_constructor(self): Manager(Referee) Manager(ExtendedReferee) with self.assertRaisesRegex(ValueError, "referee_type must be Referee or a subclass of Referee"): Manager(Move) ## TESTING RUN TOURNAMENT ################################################################ def test_run_tournament(self): winners, cheaters = self.manager.run_tournament(self.players) self.assertEqual(winners, [self.player1, self.player4, self.player5]) self.assertEqual(cheaters, set()) def test_run_tournament_failing_player_start(self): self.player5.tournament_start = MagicMock(return_value=False) winners, cheaters = self.manager.run_tournament(self.players) self.assertEqual(winners, [self.player1, self.player3, self.player4]) self.assertEqual(cheaters, set([self.player5])) def test_run_tournament_failing_player_winner(self): self.player5.tournament_end = MagicMock(return_value=False) winners, cheaters = self.manager.run_tournament(self.players) self.assertEqual(winners, [self.player1, self.player4]) self.assertEqual(cheaters, set([self.player5])) def test_run_tournament_everyone_fails(self): self.player1.choose_next_move = MagicMock(return_value=Move((0, 0), (1, 1))) # illegal move self.player2.choose_placement = MagicMock(return_value=(0, 0)) # penguin already there self.player3.choose_placement = MagicMock(return_value=(-1, 0)) self.player4.choose_next_move = MagicMock( return_value=Move((0, 0), (2, 0))) # no penguin to move self.player5.choose_next_move = MagicMock(return_value=Move((0, 0), (1, 1))) self.player6.choose_next_move = MagicMock(return_value=Move((0, 0), (1, 1))) winners, cheaters = self.manager.run_tournament(self.players) self.assertEqual(winners, []) self.assertEqual(cheaters, set(self.players)) ## TESTING UPDATE BRACKET ################################################################ def test_update_bracket(self): self.manager._Manager__queue = self.players self.manager._Manager__active_players = set(self.players) round_result = { "winners": {self.player1, self.player2}, "losers": {self.player3, self.player4}, "kicked_players": {self.player5, self.player6}, "games_played": 2 } self.assertEqual(self.manager._Manager__queue, self.players) self.assertEqual(self.manager._Manager__active_players, set(self.players)) self.assertEqual(self.manager._Manager__previous_winners, set()) self.assertEqual(self.manager._Manager__kicked_players, set()) self.assertEqual(self.manager._Manager__games_in_previous_round, 0) self.manager._Manager__update_bracket(round_result) self.assertEqual(self.manager._Manager__queue, [self.player1, self.player2]) self.assertEqual(self.manager._Manager__active_players, { self.player1, self.player2, self.player3, self.player4}) self.assertEqual(self.manager._Manager__previous_winners, { self.player1, self.player2, self.player3, self.player4}) self.assertEqual(self.manager._Manager__kicked_players, {self.player5, self.player6}) self.assertEqual(self.manager._Manager__games_in_previous_round, 2) # TESTING KICK PLAYERS ------------------------------------------------------------ def test_kick_players(self): self.manager._Manager__queue = self.players self.manager._Manager__active_players = set(self.players) bad_players = {self.player6, self.player1} self.manager._Manager__kick_players(bad_players) self.assertEqual(self.manager._Manager__queue, self.players[1:5]) self.assertEqual(self.manager._Manager__active_players, set(self.players[1:5])) self.assertEqual(self.manager._Manager__kicked_players, bad_players) def test_kick_players_no_bad_players(self): self.manager._Manager__queue = self.players self.manager._Manager__active_players = set(self.players) bad_players = set() self.manager._Manager__kick_players(bad_players) self.assertEqual(self.manager._Manager__queue, self.players) self.assertEqual(self.manager._Manager__active_players, set(self.players)) self.assertEqual(self.manager._Manager__kicked_players, bad_players) # TESTING RUN ROUNDS ################################################################- def test_run_round(self): match_players = [ self.players[0:4], self.players[4:6] ] expected = { "winners": {self.player1, self.player3, self.player4, self.player5}, "losers": {self.player2, self.player6}, "kicked_players": set(), "games_played": 2 } round_result = self.manager._Manager__run_round(match_players) self.assertEqual(round_result, expected) def test_run_round_failing_player(self): self.player1.choose_next_move = MagicMock( return_value=Move((0, 0), (4, 4))) # runs into another penguin match_players = [ self.players[0:4], self.players[4:6] ] expected = { "winners": {self.player3, self.player5}, "losers": {self.player2, self.player4, self.player6}, "kicked_players": {self.player1}, "games_played": 2 } round_result = self.manager._Manager__run_round(match_players) self.assertEqual(round_result, expected) ## TESTING MAKE ROUNDS ################################################################ def test_make_rounds(self): self.manager._Manager__queue = self.players expected = [ self.players[0:4], self.players[4:6] ] match_players = self.manager._Manager__make_rounds() self.assertEqual(match_players, expected) def test_make_rounds_no_players(self): self.assertRaisesRegex( ValueError, "Not enough players to run another round.", self.manager._Manager__make_rounds) def test_make_rounds_backtracking(self): self.manager._Manager__queue = self.players[0:5] expected = [ self.players[0:3], self.players[3:5] ] match_players = self.manager._Manager__make_rounds() self.assertEqual(match_players, expected) def test_make_rounds_min_players(self): self.manager._Manager__queue = self.players[0:2] expected = [ self.players[0:2] ] match_players = self.manager._Manager__make_rounds() self.assertEqual(match_players, expected) ## TESTING BALANCE GAME ################################################################ def test_balance_games(self): match_players = [ self.players[0:4], self.players[4:5] ] expected = [ self.players[0:3], self.players[3:5] ] balanced = self.manager._Manager__balance_games(match_players) self.assertEqual(balanced, expected) def test_balance_games_already_balanced(self): match_players = [ self.players[0:4], self.players[4:6] ] self.assertEqual(self.manager._Manager__balance_games(match_players), match_players) def test_balance_games_one_game(self): match_players = [ self.players[0:2] ] self.assertEqual(self.manager._Manager__balance_games(match_players), match_players) ## TESTING IS TOURNAMENT OVER ########################################################### def test_is_tournament_over_false(self): self.manager._Manager__queue = self.players self.manager._Manager__previous_winners = set() self.manager._Manager__games_in_previous_round = 2 self.assertFalse(self.manager._Manager__is_tournament_over()) def test_is_tournament_over_same_winners(self): self.manager._Manager__queue = self.players self.manager._Manager__previous_winners = set(self.players) self.assertTrue(self.manager._Manager__is_tournament_over()) def test_is_tournament_over_too_few_players(self): self.manager._Manager__queue = self.players[0:1] self.assertTrue(self.manager._Manager__is_tournament_over()) def test_is_tournament_over_one_game_round(self): self.manager._Manager__queue = self.players[0:3] self.manager._Manager__previous_winners = set(self.players) self.manager._Manager__games_in_previous_round = 1 self.assertTrue(self.manager._Manager__is_tournament_over()) ## TESTING BROADCAST TOURNAMENT START ################################################### def test_broadcast_tournament_start(self): self.manager._Manager__queue = self.players self.manager._Manager__active_players = set(self.players) self.player1.tournament_start = MagicMock(return_value=True) self.manager._Manager__broadcast_tournament_start() self.player1.tournament_start.assert_called() self.assertEqual(self.manager._Manager__queue, self.players) self.assertEqual(self.manager._Manager__active_players, set(self.players)) def test_broadcast_tournament_start_player_bad_response(self): self.player1.tournament_start = MagicMock(return_value=False) self.player2.tournament_start = MagicMock(return_value="True") self.manager._Manager__queue = self.players self.manager._Manager__active_players = set(self.players) self.manager._Manager__broadcast_tournament_start() self.assertEqual(self.manager._Manager__queue, self.players[2:6]) self.assertEqual(self.manager._Manager__active_players, set(self.players[2:6])) ## TESTING BROADCAST TOURNAMENT END ##################################################### def test_broadcast_tournament_end_good_players(self): self.manager._Manager__queue = self.players self.manager._Manager__active_players = set(self.players) round_result = { "winners": {self.player1, self.player4, self.player5}, "losers": {self.player2, self.player6}, "kicked_players": {self.player3}, "games_played": 1 } self.manager._Manager__update_bracket(round_result) self.player1.tournament_end = MagicMock(return_value=True) self.player2.tournament_end = MagicMock(return_value=True) self.manager._Manager__broadcast_tournament_end() self.player1.tournament_end.assert_called_with(True) self.player2.tournament_end.assert_called_with(False) def test_broadcast_tournament_end_bad_winner(self): self.manager._Manager__queue = self.players self.manager._Manager__active_players = set(self.players) round_result = { "winners": {self.player1, self.player4, self.player5}, "losers": {self.player2, self.player6}, "kicked_players": {self.player3}, "games_played": 1 } self.manager._Manager__update_bracket(round_result) self.player4.tournament_end = MagicMock(return_value=False) self.manager._Manager__broadcast_tournament_end() self.player4.tournament_end.assert_called_with(True) self.assertTrue(self.player4 in self.manager._Manager__kicked_players) def test_broadcast_tournament_end_kicked_player_not_called(self): self.manager._Manager__queue = self.players self.manager._Manager__active_players = set(self.players) round_result = { "winners": {self.player1, self.player4, self.player5}, "losers": {self.player2, self.player6}, "kicked_players": {self.player3}, "games_played": 1 } self.manager._Manager__update_bracket(round_result) self.player3.tournament_end = MagicMock(return_value=True) self.manager._Manager__broadcast_tournament_end() self.player3.tournament_end.assert_not_called() ## TESTING GET TOURNAMENT RESULT ######################################################## def test_get_tournament_result(self): self.manager._Manager__queue = self.players self.assertEqual(self.manager._Manager__get_tournament_result(), (self.players, set()))