def testHandleGiStatusWithConnections(self): """Handling of InternalGiStatus""" self.plugin.conns.addConn(self.connWs1) self.plugin.conns.addConn(self.connWs2) # Process InternalGiStatus with two clients connected msg = InternalGiStatus([], "foo:1") self.plugin.processMsg(msg) self.assertGiTxQueueMsgs(self.txq, [ClientTxMsg(["GAME-STATUS", "foo:1"], {self.connWs1, self.connWs2}, initiatorWs=None)]) # Process InternalGiStatus with two clients connected: updating an existing game msg = InternalGiStatus([{"count": 10}], "foo:1") self.plugin.processMsg(msg) self.assertGiTxQueueMsgs(self.txq, [ClientTxMsg(["GAME-STATUS", "foo:1", {"count": 10}], {self.connWs1, self.connWs2}, initiatorWs=None)]) # Processing same InternalGiStatus with two clients connected # should not create messages msg = InternalGiStatus([{"count": 10}], "foo:1") self.plugin.processMsg(msg) self.assertGiTxQueueMsgs(self.txq, [])
def testHandleConnection(self): """InternalGiStatus is sent when websockets connect/disconnect from ChatRoom""" self.testInstantiation() # Connect a websocket msg = InternalConnectWsToGi(self.connWs1) self.plugin.processMsg(msg) self.assertGiTxQueueMsgs( self.txq, [InternalGiStatus([{ "clients": 1 }], "chat:1")]) # Disconnect a websocket msg = InternalDisconnectWsToGi(self.connWs1) self.plugin.processMsg(msg) self.assertGiTxQueueMsgs( self.txq, [InternalGiStatus([{ "clients": 0 }], "chat:1")])
def testNewGame(self): env = self.setUpTabooRoom() self.assertGiTxQueueMsgs(env.txq, [ InternalGiStatus([ {"hostParameters": {"numTeams": 2, "turnDurationSec": 30, "wordSets": ["test"], "numTurns": 1}, "gameState": "WAITING_TO_START", "clientCount": {1: {}, 2: {}}, "winners": []} ], "taboo:1"), ], anyOrder=True) ws1 = 1 env.room.processConnect(ws1) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["TEAM-STATUS", 1, []], {ws1}), ClientTxMsg(["TEAM-STATUS", 2, []], {ws1}), ClientTxMsg(['HOST-PARAMETERS', {'numTeams': 2, 'turnDurationSec': 30, 'wordSets': ['test'], 'numTurns': 1}], {ws1}), ClientTxMsg(["SCORE", {1: 0, 2: 0}], {ws1}), InternalGiStatus([ {"hostParameters": {"numTeams": 2, "turnDurationSec": 30, "wordSets": ["test"], "numTurns": 1}, "gameState": "WAITING_TO_START", "clientCount": {1: {}, 2: {}}, "winners":[] } ], "taboo:1"), ], anyOrder=True)
def testHandleGiStatusNoConnections(self): """Handling of InternalGiStatus""" # Add a game with empty status msg = InternalGiStatus([], "foo:1") self.plugin.processMsg(msg) self.assertGiTxQueueMsgs(self.txq, []) self.assertDictEqual(dict(self.plugin.giStatusByPath), {"foo:1": []}) # Update existing game msg = InternalGiStatus([True], "foo:1") self.plugin.processMsg(msg) self.assertGiTxQueueMsgs(self.txq, []) self.assertDictEqual(dict(self.plugin.giStatusByPath), {"foo:1": [True]}) # Add a different game with non-empty status msg = InternalGiStatus([{"count": 10}], "bar:2") self.plugin.processMsg(msg) self.assertGiTxQueueMsgs(self.txq, []) self.assertDictEqual(dict(self.plugin.giStatusByPath), {"foo:1": [True], "bar:2": [{"count": 10}]})
def publishGiStatus(self): # Publish number of clients connected to this room jmsg = [{ "gameState": self.gameState.toJmsg(), "clientCount": { name: player.playerConns.count() for name, player in self.playerByName.items() }, "spectatorCount": self.spectatorCount() }] jmsg += self.hostParameters.toJmsg() if self.rounds: jmsg += self.currRound.roundParams.toJmsg() self.txQueue.put_nowait(InternalGiStatus(jmsg, self.path))
def publishGiStatus(self): """Invoked to update the lobby of the game instance (room) status ["GAME-STATUS", <path:str>, {"gameState": <str>, "clientCount": { teamId<int>:{plyrName<str>:clientCount<int>} }, "hostParams": <dict>, "winners":[winnerTeam<int>,...]}] """ jmsg = [{"hostParameters": self.hostParameters.toJmsg()[0], "gameState": self.state.name, "clientCount": self._clientInfo(), "winners": self._winnerTeamIds}] self.txQueue.put_nowait(InternalGiStatus(jmsg, self.path))
def testInstantiation(self): """Test attributes of the plugin""" self.assertGiTxQueueMsgs( self.txq, [InternalGiStatus([{ "clients": 0 }], "chat:1")])
def testCompleted(self): env = self.setUpTabooRoom() self.drainGiTxQueue(env.txq) with stubs([(SupportedWordSets["test"], "nextWord", self.mockNextWord), (Taboo.TurnManager, "expiryEpoch", stubExpiryEpochGen())]): env.room.processMsg(ClientRxMsg(["COMPLETED"], 101)) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["COMPLETED-BAD", "Invalid message length"], {101}, 101), ]) env.room.processMsg(ClientRxMsg(["COMPLETED", "foo", 1], 101)) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["COMPLETED-BAD", "Invalid message type"], {101}, 101), ]) env.room.processMsg(ClientRxMsg(["COMPLETED", 1, 1], 101)) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["COMPLETED-BAD", "Game not running"], {101}, 101), ]) self.setUpTeamPlayer(env, 1, "sb1", [101]) self.setUpTeamPlayer(env, 1, "sb2", [102]) self.setUpTeamPlayer(env, 2, "jg1", [201]) self.setUpTeamPlayer(env, 2, "jg2", [202]) def mockFindNextPlayer(remainingPlayers=[ env.room.playerByWs[201], env.room.playerByWs[101], env.room.playerByWs[202], ]): if remainingPlayers: return remainingPlayers.pop(0) return None with stub(env.room.turnMgr, "_findNextPlayer", mockFindNextPlayer): env.room._allPlayersReady() self.drainGiTxQueue(env.txq) env.room.processMsg(ClientRxMsg(["COMPLETED", 1, 1], 101)) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["COMPLETED-BAD", "It is not your turn"], {101}, 101), ]) env.room.processMsg(ClientRxMsg(["COMPLETED", 1, 1], 201)) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["COMPLETED-BAD", "Can't COMPLETED right now"], {201}, 201), #sic ]) # KICKOFF turn env.room.processMsg(ClientRxMsg(["KICKOFF"], 201)) self.drainGiTxQueue(env.txq) env.room.processMsg(ClientRxMsg(["COMPLETED", 0, 1], 201)) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["COMPLETED-BAD", "Invalid turn"], {201}, 201), ]) env.room.processMsg(ClientRxMsg(["COMPLETED", 1, 0], 201)) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["COMPLETED-BAD", "Invalid word"], {201}, 201), ]) env.room.processMsg(ClientRxMsg(["COMPLETED", 1, 1], 201)) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["TURN", 1, 1, {"team": 2, "player": "jg1", "state": "COMPLETED", "secret": "c", "disallowed": ["c1", "c2"], "score": [2]}], {101, 102, 201, 202}), ClientTxMsg(["SCORE", {1: 0, 2: 1}], {101, 102, 201, 202}), ClientTxMsg(["TURN", 1, 2, {"team": 2, "player": "jg1", "state": "IN_PLAY", "utcTimeout": 30}], {101, 102, 201, 202}), ClientTxMsg(["TURN", 1, 2, {"team": 2, "player": "jg1", "state": "IN_PLAY", "utcTimeout": 30, "secret": "a", "disallowed": ["a1", "a2"]}], {201}), ClientTxMsg(["TURN", 1, 2, {"team": 2, "player": "jg1", "state": "IN_PLAY", "utcTimeout": 30, "secret": "a", "disallowed": ["a1", "a2"]}], {101, 102}), ], anyOrder=True) self.assertEqual(env.room.teams[2].members['jg1'].turnsPlayed, 0) env.room.processMsg(ClientRxMsg(["COMPLETED", 1, 2], 201)) self.drainGiTxQueue(env.txq) env.room.processMsg(ClientRxMsg(["COMPLETED", 1, 3], 201)) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["TURN", 1, 3, {"team": 2, "player": "jg1", "state": "COMPLETED", "secret": "b", "disallowed": ["b1", "b2"], "score": [2]}], {101, 102, 201, 202}), ClientTxMsg(["SCORE", {1: 0, 2: 3}], {101, 102, 201, 202}), ClientTxMsg(["GAME-OVER", [2]], {101, 102, 201, 202}), InternalGiStatus([ {"hostParameters": {"numTeams": 2, "turnDurationSec": 30, "wordSets": ["test"], "numTurns": 1}, "gameState": "GAME_OVER", "clientCount": {1: {'sb1': 1, 'sb2': 1}, 2: {'jg1': 1, 'jg2': 1}}, "winners": [2] } ], "taboo:1"), ], anyOrder=True) self.assertEqual(env.room.teams[2].members['jg1'].turnsPlayed, 1) env.room.processMsg(ClientRxMsg(["COMPLETED", 1, 3], 201)) self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["COMPLETED-BAD", "Game not running"], {201}, 201), ])
def testTurnTimeOut(self): env = self.setUpTabooRoom() env.room.state = TabooRoom.GameState.RUNNING self.setUpTeamPlayer(env, 1, "sb1", [101]) self.setUpTeamPlayer(env, 1, "sb2", [102]) self.setUpTeamPlayer(env, 2, "jg1", [201]) self.setUpTeamPlayer(env, 2, "jg2", [202]) self.drainGiTxQueue(env.txq) def mockFindNextPlayer(remainingPlayers=[ env.room.playerByWs[201], env.room.playerByWs[101], env.room.playerByWs[202], ]): if remainingPlayers: return remainingPlayers.pop(0) return None with stubs([(SupportedWordSets["test"], "nextWord", self.mockNextWord), (Taboo.TurnManager, "expiryEpoch", stubExpiryEpochGen()), (env.room.turnMgr, "_findNextPlayer", mockFindNextPlayer)]): env.room.turnMgr.startNewTurn() self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(["WAIT-FOR-KICKOFF", 1, "jg1"], {101, 102, 201, 202}, None), ], anyOrder=True) # Start the timer by issuing a KICKOFF env.room.processMsg(ClientRxMsg(["KICKOFF"], 201)) secretMsg = ['TURN', 1, 1, {'team': 2, 'player': 'jg1', 'state': 'IN_PLAY', 'utcTimeout': 30, 'secret': 'c', 'disallowed': ['c1', 'c2']}] publicMsg = ['TURN', 1, 1, {'team': 2, 'player': 'jg1', 'state': 'IN_PLAY', 'utcTimeout': 30}] self.assertGiTxQueueMsgs(env.txq, [ TimerRequest(30, env.room.turnMgr.timerExpiredCb, { "turnId": 1, }), ClientTxMsg(secretMsg, {201}), ClientTxMsg(secretMsg, {101, 102}), ClientTxMsg(publicMsg, {101, 102, 201, 202}), ], anyOrder=True) self.assertEqual(env.room.teams[2].members['jg1'].turnsPlayed, 0) # Invalid turnId env.room.turnMgr.timerExpiredCb({"turnId": 5}) # Valid timer expiry, starts the next turn env.room.turnMgr.timerExpiredCb({"turnId": 1}) publicMsg = ['TURN', 1, 1, {'team': 2, 'player': 'jg1', 'state': 'TIMED_OUT', 'secret': 'c', 'disallowed': ['c1', 'c2'], 'score': [1]}] self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(publicMsg, {101, 102, 201, 202}), ClientTxMsg(["WAIT-FOR-KICKOFF", 2, "sb1"], {101, 102, 201, 202}, None), ClientTxMsg(["SCORE", {1: 1, 2: 0}], {101, 102, 201, 202}), ], anyOrder=True) self.assertEqual(env.room.teams[2].members['jg1'].turnsPlayed, 1) # KICKOFF new turn, discard 1st word, let timer expire on the last word env.room.processMsg(ClientRxMsg(["KICKOFF"], 101)) secretMsg = ['TURN', 2, 1, {'team': 1, 'player': 'sb1', 'state': 'IN_PLAY', 'utcTimeout': 31, 'secret': 'a', 'disallowed': ['a1', 'a2']}] publicMsg = ['TURN', 2, 1, {'team': 1, 'player': 'sb1', 'state': 'IN_PLAY', 'utcTimeout': 31}] self.assertGiTxQueueMsgs(env.txq, [ TimerRequest(30, env.room.turnMgr.timerExpiredCb, { "turnId": 2, }), ClientTxMsg(secretMsg, {101}), ClientTxMsg(secretMsg, {201, 202}), ClientTxMsg(publicMsg, {101, 102, 201, 202}), ], anyOrder=True) env.room.processMsg(ClientRxMsg(["DISCARD", 2, 1], 101)) self.drainGiTxQueue(env.txq) with stub(env.room.turnMgr._wordSet, "areWordsAvailable", lambda path: False): env.room.turnMgr.timerExpiredCb({"turnId": 2}) publicMsg = ['TURN', 2, 2, {'team': 1, 'player': 'sb1', 'state': 'TIMED_OUT', 'secret': 'b', 'disallowed': ['b1', 'b2'], 'score': [2]}] self.assertGiTxQueueMsgs(env.txq, [ ClientTxMsg(publicMsg, {101, 102, 201, 202}), ClientTxMsg(["SCORE", {1: 1, 2: 2}], {101, 102, 201, 202}), ClientTxMsg(["GAME-OVER", [2]], {101, 102, 201, 202}), InternalGiStatus([ {"hostParameters": {"numTeams": 2, "turnDurationSec": 30, "wordSets": ["test"], "numTurns": 1}, "gameState": "GAME_OVER", "clientCount": {1: {'sb1': 1, 'sb2': 1}, 2: {'jg1': 1, 'jg2': 1}}, "winners": [2] } ], "taboo:1"), ], anyOrder=True) self.assertEqual(env.room.teams[1].members['sb1'].turnsPlayed, 1) # Test timer fire after the game is over env.room.turnMgr.timerExpiredCb({"turnId": 2}) self.assertGiTxQueueMsgs(env.txq, []) self.assertEqual(env.room.teams[1].members['sb1'].turnsPlayed, 1)
def publishGiStatus(self): # Publish number of clients connected to this room self.txQueue.put_nowait( InternalGiStatus([{ "clients": self.conns.count() }], self.path))