Esempio n. 1
0
    def test01_load(self):
        database = 'test.sqlite'
        if os.path.exists(database):
            os.unlink(database)

        service = CardstoriesService({'db': database})
        self.assertFalse(os.path.exists(database))
        service.startService()
        self.assertTrue(os.path.exists(database))
        yield service.stopService()

        game_id = 100
        player_id = 20
        db = sqlite3.connect(database)
        c = db.cursor()
        c.execute("INSERT INTO games (id) VALUES (%d)" % game_id)
        c.execute("INSERT INTO player2game (game_id, player_id) VALUES (%d, %d)" % (game_id, player_id))
        db.commit()
        db.close()

        service = CardstoriesService({'db': database})
        service.startService()
        self.assertEquals(game_id, service.games[game_id].id)
        self.assertEquals([player_id], service.games[game_id].get_players())
        self.assertEquals(len(service.games[game_id].pollers), 1)
        yield service.stopService()
Esempio n. 2
0
    def test01_load_notify(self):
        card = 5
        str_sentence = 'SENTENCE'
        owner_id = 15
        self.loaded = False
        result = yield self.service.create({'owner_id': [owner_id]})

        service2 = CardstoriesService({'db': self.database})

        def accept(event):
            self.assertEquals(event['details']['type'], 'load')
            self.loaded = True
        service2.listen().addCallback(accept)

        service2.startService()
        service2.stopService()
        self.assertTrue(self.loaded, 'load event called')
Esempio n. 3
0
class CardstoriesServiceTestBase(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({'db': self.database})
        self.service.startService()
        self.db = sqlite3.connect(self.database)

    def tearDown(self):
        self.db.close()
        os.unlink(self.database)
        return self.service.stopService()
Esempio n. 4
0
 def test00_startService(self):
     database = 'test.sqlite'
     service = CardstoriesService({'db': database})
     self.assertFalse(os.path.exists(database))
     def start(event):
         self.assertEqual(event['type'], 'start')
         service.notified_start = True
         return event
     service.listen().addCallback(start)
     service.startService()
     self.assertTrue(service.notified_start)
     self.assertTrue(os.path.exists(database))
     def stop(event):
         self.assertEqual(event['type'], 'stop')
         service.notified_stop = True
         return event
     service.listen().addCallback(stop)
     d = service.stopService()
     self.assertTrue(service.notified_stop)
     return d
Esempio n. 5
0
class MailTestAllow(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({'db': self.database,
                                           'plugins-libdir': '../fixture2',
                                           'plugins-confdir': '../fixture2',
                                           'plugins-dir': '../fixture2'})
        self.service.startService()

    def tearDown(self):
        return self.service.stopService()

    def test00_init(self):
        plugin = mail.Plugin(self.service, [ ])
        for allowed in mail.Plugin.ALLOWED:
            has_key = plugin.templates.has_key(allowed)
            if allowed in ('invite', 'vote'):
                self.assertTrue(has_key)
            else:
                self.assertFalse(has_key)
Esempio n. 6
0
class MailTestAllow(unittest.TestCase):
    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({
            'db': self.database,
            'plugins-libdir': '../fixture2',
            'plugins-confdir': '../fixture2',
            'plugins-dir': '../fixture2'
        })
        self.service.startService()

    def tearDown(self):
        return self.service.stopService()

    def test00_init(self):
        plugin = mail.Plugin(self.service, [])
        for allowed in mail.Plugin.ALLOWED:
            has_key = plugin.templates.has_key(allowed)
            if allowed in ('invite', 'vote'):
                self.assertTrue(has_key)
            else:
                self.assertFalse(has_key)
Esempio n. 7
0
class ChatTest(unittest.TestCase):

    # initialise our test with a service that we can use during testing and a testing database
    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)

        # Empty 'chat/' subdir
        self.test_logdir = 'test_logdir.tmp'
        if os.path.exists(self.test_logdir):
            shutil.rmtree(self.test_logdir)

        self.service = CardstoriesService({
            'db': self.database,
            'plugins-confdir': 'CONFDIR',
            'plugins-libdir': 'LIBDIR',
            'plugins-logdir': self.test_logdir,
            'static': 'STATIC'
        })
        self.service.startService()

    def tearDown(self):
        # kill the service we started before the test
        return self.service.stopService()

    @defer.inlineCallbacks
    def complete_game(self):
        self.winner_card = winner_card = 5
        sentence = 'SENTENCE'
        owner_id = 15
        result = yield self.service.create({
            'card': [winner_card],
            'sentence': [sentence],
            'owner_id': [owner_id]
        })
        game_id = result['game_id']

        yield self.service.set_card({
            'action': ['set_card'],
            'card': [winner_card],
            'player_id': [owner_id],
            'game_id': [game_id]
        })

        yield self.service.set_sentence({
            'action': ['set_sentence'],
            'sentence': [sentence],
            'player_id': [owner_id],
            'game_id': [game_id]
        })

        self.player1 = 16
        for player_id in (self.player1, 17):
            yield self.service.participate({
                'action': ['participate'],
                'player_id': [player_id],
                'game_id': [game_id]
            })
            player = yield self.service.player2game({
                'action': ['player2game'],
                'player_id': [player_id],
                'game_id': [game_id]
            })
            card = player['cards'][0]
            yield self.service.pick({
                'action': ['pick'],
                'player_id': [player_id],
                'game_id': [game_id],
                'card': [card]
            })

        yield self.service.voting({
            'action': ['voting'],
            'game_id': [game_id],
            'owner_id': [owner_id]
        })
        winner_id = self.player1
        yield self.service.vote({
            'action': ['vote'],
            'game_id': [game_id],
            'player_id': [winner_id],
            'card': [winner_card]
        })
        loser_id = 17
        yield self.service.vote({
            'action': ['vote'],
            'game_id': [game_id],
            'player_id': [loser_id],
            'card': [120]
        })
        self.assertTrue(self.service.games.has_key(game_id))
        yield self.service.complete({
            'action': ['complete'],
            'game_id': [game_id],
            'owner_id': [owner_id]
        })
        self.assertFalse(self.service.games.has_key(game_id))
        defer.returnValue(True)

    def test00_create_logdir(self):
        chat_instance = Plugin(self.service, [])
        logdir = os.path.join(self.test_logdir, 'chat')
        self.assertTrue(os.path.exists(logdir))

    @defer.inlineCallbacks
    def test00_preprocess_noop(self):
        # create a new instance of the plugin and make sure it's the right type
        chat_instance = Plugin(self.service, [])
        self.assertEquals(chat_instance.name(), 'chat')
        # run a game to get into a realistic situation
        yield self.complete_game()
        # run the preprocess method and make sure it does not affect anything during a normal 'game' event
        result_in = 'RESULT'
        result_out = yield chat_instance.preprocess(result_in,
                                                    Request(action=['game']))
        self.assertEquals(result_in, result_out)

    @defer.inlineCallbacks
    def test01_add_message(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 200
        sentence = "This is my sentence!"
        now = int(runtime.seconds() * 1000)
        request = Request(action=['message'],
                          player_id=[player_id],
                          sentence=[sentence])
        # verify we have no messages yet
        self.assertEquals(len(chat_instance.messages), 0)
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # verify we now have one message
        self.assertEquals(len(chat_instance.messages), 1)
        # verify the event has been removed from the pipeline
        self.assertFalse(request.args.has_key('action'))
        # verify the message we added is in the list
        self.assertEquals(chat_instance.messages[0]["player_id"], player_id)
        self.assertEquals(chat_instance.messages[0]["sentence"], sentence)
        # check that the message has been recorded in log file
        with open(
                os.path.join(self.test_logdir, 'chat',
                             '%s.log' % strftime('%Y-%m-%d'))) as f:
            lines = f.readlines()
            self.assertEquals(len(lines), 1)
            self.assertIn(sentence, lines[0])
            self.assertIn('player_%d' % player_id, lines[0])

    @defer.inlineCallbacks
    def test02_check_added_message_after_now(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 200
        sentence = "This is my sentence!"
        now = int(runtime.seconds() * 1000)
        request = Request(action=['message'],
                          player_id=[player_id],
                          sentence=[sentence])
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # check to make sure no message is returned if we ask for now or later
        state, players_id_list = yield chat_instance.state(
            {"modified": [now + 1]})
        self.assertTrue(state.has_key('messages'))
        self.assertEquals(len(state['messages']), 0)
        self.assertEquals(players_id_list, [])

    @defer.inlineCallbacks
    def test03_check_added_message_before_now(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 200
        sentence = "This is my sentence!"
        now = int(runtime.seconds() * 1000)
        request = Request(action=['message'],
                          player_id=[player_id],
                          sentence=[sentence])
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # check to make sure no message is returned if we ask for now or later
        state, players_id_list = yield chat_instance.state(
            {"modified": [now - 1]})
        self.assertEquals(len(state['messages']), 1)
        self.assertEquals(state['messages'][0]['player_id'], player_id)
        self.assertEquals(state['messages'][0]['sentence'], sentence)
        self.assertEquals(players_id_list, [player_id])

    @defer.inlineCallbacks
    def test04_check_multiple_messages(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_ids = [200, 220, 999]
        sentences = [
            "This is my sentence!", "Yeah another test hello.",
            "Ping ping poing pong."
        ]
        when = []
        for i in range(3):
            when.append(int(runtime.seconds() * 1000))
            request = Request(action=['message'],
                              player_id=[player_ids[i]],
                              sentence=[sentences[i]])
            # run the request
            result = yield chat_instance.preprocess(True, request)
        # check to make sure no message is returned if we ask for now or later
        # we check right back to one second ago to make sure all recently added messages are caught
        state, players_id_list = yield chat_instance.state(
            {"modified": [when[-1] - 1000]})
        self.assertEquals(len(state['messages']), 3)
        for i in range(3):
            self.assertEquals(state['messages'][i]['player_id'], player_ids[i])
            self.assertEquals(state['messages'][i]['sentence'], sentences[i])
        self.assertEquals(players_id_list, player_ids)

    @defer.inlineCallbacks
    def test05_check_half_of_multiple_messages(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_ids = [200, 220, 999]
        sentences = [
            "This is my sentence!", "Yeah another test hello.",
            "Ping ping poing pong."
        ]
        when = []
        for i in range(3):
            sleep(0.1)
            when.append(int(runtime.seconds() * 1000))
            request = Request(action=['message'],
                              player_id=[player_ids[i]],
                              sentence=[sentences[i]])
            # run the request
            result = yield chat_instance.preprocess(True, request)
        # check to make sure no message is returned if we ask for now or later
        # we check right back to one second ago to make sure all recently added messages are caught
        state, players_id_list = yield chat_instance.state(
            {"modified": [when[-1] - 150]})
        # this time because of the 100ms delay between messages, and only checking to 150ms ago
        # we should only get the last two messages
        self.assertEquals(len(state['messages']), 2)
        for i in range(2):
            self.assertEquals(state['messages'][i]['player_id'],
                              player_ids[i + 1])
            self.assertEquals(state['messages'][i]['sentence'],
                              sentences[i + 1])
        self.assertEquals(players_id_list, player_ids[-2:])

    @defer.inlineCallbacks
    def test06_touch_state(self):
        player_id = 200
        sentence = "This is my sentence!"
        # new instance of chat plugin to run the test against
        chat_instance = Plugin(self.service, [])
        # put the chat instance into the service's pollable_plugins
        self.service.pollable_plugins.append(chat_instance)
        # flag to signify whether the callback has run
        self.called = False
        # service to poll instance waiting for chat
        d = self.service.poll({
            'action': ['poll'],
            'player_id': [player_id],
            'type': ['chat'],
            'modified': [chat_instance.get_modified()]
        })

        # callback which runs once the chat plugin calls touch()
        def check(event):
            self.called = True

        d.addCallback(check)
        # make sure our flag is false before we run
        self.assertFalse(self.called)
        # run the test request
        request = Request(action=['message'],
                          player_id=[player_id],
                          sentence=[sentence])
        result = yield chat_instance.preprocess(True, request)
        yield d
        # make sure the flag is now set after we've run the test
        self.assertTrue(self.called)

    @defer.inlineCallbacks
    def test07_notification_messages(self):
        # new instance of chat plugin to run the test against
        chat_instance = Plugin(self.service, [])

        self.count = 0

        def build_message(self, message):
            """
            message == {'type': 'notification',
                        'game_id': GAME_ID,
                        'player_id': 'OWNER_ID',
                        'sentence': 'SENTENCE'}

            """
            self.count += 1
            self.assertEquals(self.count, 1)
            self.assertEquals(message['type'], 'notification')
            self.assertEquals(message['player_id'], '15')
            self.assertEquals(message['sentence'], 'SENTENCE')

        # build_message should only be called once, upon game creation.
        chat_instance.build_message = build_message
        # run a game to get into a realistic situation
        yield self.complete_game()

    @defer.inlineCallbacks
    def test08_nonascii_characters_message(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 200
        # The sentence is a 'str' object. Create it by encoding a unicode string.
        unicode_sentence = u"你好 Matjaž Gregorič"
        sentence_bytes = unicode_sentence.encode('utf-8')
        request = Request(action=['message'],
                          player_id=[player_id],
                          sentence=[sentence_bytes])
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # check that the message has been recorded in log file
        with open(
                os.path.join(self.test_logdir, 'chat',
                             '%s.log' % strftime('%Y-%m-%d'))) as f:
            lines = f.readlines()
            self.assertIn(unicode_sentence, lines[0].decode('utf-8'))

    @defer.inlineCallbacks
    def test09_nonascii_characters_notification(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])

        # create a message event request
        class FakeGame:
            id = 102
            owner_id = 303

        unicode_sentence = u"我不明白 šal čez želodec"
        changes = {
            'type': 'change',
            'details': {
                'type': 'load',
                'sentence': unicode_sentence
            },
            'game': FakeGame()
        }
        result = yield chat_instance.self_notify(changes)
        with open(
                os.path.join(self.test_logdir, 'chat',
                             '%s.log' % strftime('%Y-%m-%d'))) as f:
            lines = f.readlines()
            self.assertIn(unicode_sentence, lines[0].decode('utf-8'))

    @defer.inlineCallbacks
    def test10_escape_html(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 201
        naughty_sentence = '<script>alert("haha!")</script>'
        now = int(runtime.seconds() * 1000)
        request = Request(action=['message'],
                          player_id=[player_id],
                          sentence=[naughty_sentence])
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # check to make sure our naughty message is returned properly escaped
        state, players_id_list = yield chat_instance.state(
            {"modified": [now - 1]})
        self.assertEquals(state['messages'][0]['player_id'], player_id)
        self.assertEquals(state['messages'][0]['sentence'],
                          '&lt;script&gt;alert("haha!")&lt;/script&gt;')

    @defer.inlineCallbacks
    def test11_link_url(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 201
        url_sentence = 'For searching the web I use google.com, it\'s great!'
        now = int(runtime.seconds() * 1000)
        request = Request(action=['message'],
                          player_id=[player_id],
                          sentence=[url_sentence])
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # check to make sure our message is returned with a link for the url
        state, players_id_list = yield chat_instance.state(
            {"modified": [now - 1]})
        self.assertEquals(state['messages'][0]['player_id'], player_id)
        self.assertEquals(
            state['messages'][0]['sentence'],
            'For searching the web I use <a target="_blank" href="http://google.com">google.com</a>, it\'s great!'
        )
Esempio n. 8
0
class TableTest(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)

        self.service = CardstoriesService({'db': self.database,
                                           'plugins-confdir': 'CONFDIR',
                                           'plugins-libdir': 'LIBDIR',
                                           'static': 'STATIC'})
        self.service.auth = Mock()
        self.service.startService()

        # Fake an activity plugin to which the table plugin should listen
        self.mock_activity_instance = Mock()
        self.mock_activity_instance.name.return_value = 'activity'
        # Show all players as online
        self.mock_activity_instance.is_player_online.return_value = True

        self.table_instance = table.Plugin(self.service, [self.mock_activity_instance])

        self.mock_activity_instance.listen.assert_called_once_with()
        self.mock_activity_instance.reset_mock()

    def tearDown(self):
        # kill the service we started before the test
        return self.service.stopService()


    @defer.inlineCallbacks
    def add_players_to_game(self, game_id, player_ids):
        sql = "INSERT INTO tabs (player_id, game_id, created) VALUES (%d, %d, datetime('now'))"
        for player_id in player_ids:
            yield self.service.db.runQuery(sql % (player_id, game_id))

    @defer.inlineCallbacks
    def complete_game(self, game_id, owner, player1, player2):
        # Set card
        yield self.service.handle([], {'action': ['set_card'],
                                       'card': [1],
                                       'game_id': [game_id],
                                       'player_id': [owner]})
        # Set sentence
        yield self.service.handle([], {'action': ['set_sentence'],
                                       'sentence': ['SENTENCE'],
                                       'game_id': [game_id],
                                       'player_id': [owner]})
        # Join
        yield self.service.handle([], {'action': ['participate'],
                                       'game_id': [game_id],
                                       'player_id': [player1]})
        yield self.service.handle([], {'action': ['participate'],
                                       'game_id': [game_id],
                                       'player_id': [player2]})

        # Pick
        game, players_ids = yield self.table_instance.get_game_by_id(game_id, player1)
        yield self.service.handle([], {'action': ['pick'],
                                       'game_id': [game_id],
                                       'player_id': [player1],
                                       'card': [game['self'][2][0]]})
        game, players_ids = yield self.table_instance.get_game_by_id(game_id, player2)
        yield self.service.handle([], {'action': ['pick'],
                                       'game_id': [game_id],
                                       'player_id': [player2],
                                       'card': [game['self'][2][0]]})

        # Vote
        yield self.service.handle([], {'action': ['voting'],
                                       'game_id': [game_id],
                                       'owner_id': [game['owner_id']]})

        @defer.inlineCallbacks
        def player_vote(player_id):
            game, players_ids = yield self.table_instance.get_game_by_id(game_id, player_id)
            my_card = game['self'][0]
            board = [x for x in game['board'] if x != my_card]
            yield self.service.handle([], {'action': ['vote'],
                                           'game_id': [game_id],
                                           'player_id': [player_id],
                                           'card': [board[0]]})
        yield player_vote(player1)
        yield player_vote(player2)

        # Complete
        yield self.service.handle([], {'action': ['complete'],
                                       'game_id': [game_id],
                                       'owner_id': [game['owner_id']]})

    @defer.inlineCallbacks
    def test01_no_table(self):
        player_id = 12
        game_id = 59

        # Request for tables should direct the player to create his own game
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': ['undefined'],
                                                 'player_id': [player_id]})
        self.assertEqual(state, [{'game_id': None,
                                  'next_game_id': None,
                                  'next_owner_id': player_id},
                                 [player_id]])

        # Next games of existing games should also ask to create a new game, since we have no table info
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player_id]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player_id},
                                 [player_id]])

    @defer.inlineCallbacks
    def test02_create_game_next(self):
        player1 = 12
        player2 = 78
        player3 = 98

        # Poll to know when a table gets available
        poll = self.table_instance.poll({'game_id': ['undefined'],
                                         'modified': [0]})
        result = yield poll
        modified = result['modified'][0]
        # Start a new poll immediately.
        poll = self.table_instance.poll({'game_id': ['undefined'],
                                         'modified': [modified]})
        # Make sure it doesn't return at once.
        self.assertFalse(poll.called)

        self.assertEqual(modified, self.table_instance.get_modified({'game_id': ['undefined']}))

        # Create first game
        response = yield self.service.handle([], {'action': ['create'],
                                                  'owner_id': [player1]})
        game_id = response['game_id']

        # Poll must return to inform players waiting for an available table
        result = yield poll
        modified = result['modified'][0]

        # Associate all players with the game in the tabs db table.
        sql = "INSERT INTO tabs (player_id, game_id, created) VALUES (%d, %d, datetime('now'))"
        for player_id in [player1, player2, player3]:
            yield self.service.db.runQuery(sql % (player_id, game_id))

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': ['undefined'],
                                                 'player_id': [player2]})
        self.assertEqual(state, [{'game_id': None,
                                  'next_game_id': game_id,
                                  'next_owner_id': player1},
                                 [player1]])

        # Initial state of the table itself
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': None},
                                 []])

        # Start a poll on this table to know when the next game will be available there
        poll = self.table_instance.poll({'game_id': [game_id],
                                         'modified': [0]})
        result = yield poll
        modified = result['modified'][0]

        poll = self.table_instance.poll({'game_id': [game_id],
                                         'modified': [modified]})
        self.assertFalse(poll.called)
        self.assertEqual(modified, self.table_instance.get_modified({'game_id': [game_id]}))

        # Complete first game
        yield self.complete_game(game_id, player1, player2, player3)
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player2},
                                 [player2]])

        # Poll must return to announce the next owner
        result = yield poll
        modified = result['modified'][0]

        poll = self.table_instance.poll({'game_id': [game_id],
                                         'modified': [modified]})
        self.assertFalse(poll.called)

        # Next owner disconnects before creating the game - should chose another player
        def is_player_online(*args, **kw):
            if args[0] == player2:
                return False
            return True
        self.mock_activity_instance.is_player_online.side_effect = is_player_online
        yield self.table_instance.on_activity_notification({'type': 'player_disconnecting',
                                                            'player_id': player2})

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player3},
                                 [player3]])

        # Poll must return to announce the next owner
        result = yield poll
        modified = result['modified'][0]

        # All players quit - deletes the table
        # Clear the side_effect which otherwise takes precedence over return_value.
        self.mock_activity_instance.is_player_online.side_effect = None
        self.mock_activity_instance.is_player_online.return_value = False
        yield self.table_instance.on_activity_notification({'type': 'player_disconnecting',
                                                            'player_id': player1})
        yield self.table_instance.on_activity_notification({'type': 'player_disconnecting',
                                                            'player_id': player3})

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player1},
                                 [player1]])

    @defer.inlineCallbacks
    def test04_postprocess(self):
        game_id = 55
        tab1_game_id = 17
        tab2_game_id = 18
        player_id = 77

        mock_request = Mock()
        mock_request.args = {'action': ['state'], 'player_id': [player_id], 'game_id': [game_id], 'type': ['tabs']}

        response = [{'type': 'tabs',
                     'games': [{'id': tab1_game_id, 'state': 'complete'}, {'id': tab2_game_id, 'state': 'complete'}]}]

        def mock_state(args):
            game_id = args['game_id'][0]
            if game_id == tab1_game_id:
                next_game_id = 42
                next_owner_id = player_id
            elif game_id == tab2_game_id:
                next_game_id = None
                next_owner_id = 21

            result = [{'game_id': game_id, 'next_game_id': next_game_id, 'next_owner_id': next_owner_id}, [player_id]]
            return result
        self.table_instance.state = mock_state

        result = yield self.table_instance.postprocess(response, mock_request)

        # During postprocessing, next_owner_id and next_game_id should be added to
        # the response.
        self.assertEqual(result[0]['games'][0]['next_owner_id'], player_id)
        self.assertEqual(result[0]['games'][0]['next_game_id'], 42)
        self.assertEqual(result[0]['games'][1]['next_owner_id'], 21)
        self.assertEqual(result[0]['games'][1]['next_game_id'], None)

        # Make sure things don't fail if response is not of the expected shape.
        yield self.table_instance.postprocess({'type': 'chat'}, mock_request)
        yield self.table_instance.postprocess([[1, 2, {'this': 'test'}]], mock_request)

    @defer.inlineCallbacks
    def test06_next_game_timeout(self):
        owner = 98
        player1 = 12
        player2 = 78

        # Create game
        response = yield self.service.handle([], {'action': ['create'],
                                                  'owner_id': [owner]})
        game_id = response['game_id']

        sql = "INSERT INTO tabs (player_id, game_id, created) VALUES (%d, %d, datetime('now'))"
        for player_id in [owner, player1, player2]:
            yield self.service.db.runQuery(sql % (player_id, game_id))

        # Change the next game timeout from the default to 0.2 seconds for the test.
        table = self.table_instance.game2table[game_id]
        table.NEXT_GAME_TIMEOUT = 0.2

        # Complete the game
        yield self.complete_game(game_id, owner, player1, player2)

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player1},
                                 [player1]])

        # Start a poll on this table to know when the next owner will change.
        poll = self.table_instance.poll({'game_id': [game_id],
                                         'modified': [table.get_modified()]})
        result = yield poll

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        # Next owner took too long to create the game,
        # so player2 was chosen as the "new" next owner.
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player2},
                                 [player2]])

        # Cancel the timers, so that the test runner doesn't complain
        # about a "dirty" reactor.
        table.stop_timer(table.next_game_timer)

    @defer.inlineCallbacks
    def test07_next_game_timeout_after_game_created(self):
        owner = 57
        player1 = 123
        player2 = 334

        # Create first game
        response = yield self.service.handle([], {'action': ['create'],
                                                  'owner_id': [owner]})
        game_id = response['game_id']

        self.add_players_to_game(game_id, [owner, player1, player2])

        # Change the next game timeout from the default to 0.2 seconds for the test.
        table = self.table_instance.game2table[game_id]
        table.NEXT_GAME_TIMEOUT = 0.2

        # Complete the game
        yield self.complete_game(game_id, owner, player1, player2)

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player1},
                                 [player1]])

        # player1 is the next owner, let him create the next game.
        # We will let him wait long enough so that the timer kicks in and
        # gives another player a chance to be next owner.
        response = yield self.service.handle([], {'action': ['create'],
                                                  'owner_id': [player1],
                                                  'previous_game_id': [game_id]})
        new_game_id = response['game_id']

        self.add_players_to_game(new_game_id, [owner, player1, player2])

        # Start a poll on this table to know when another player is chosen.
        poll = self.table_instance.poll({'game_id': [new_game_id],
                                         'modified': [table.get_modified()]})
        result = yield poll
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [new_game_id],
                                                 'player_id': [owner]})

        # Next owner took too long to create the game,
        # so player2 was chosen as the "new" next owner.
        # This can be seen when inquiring about table
        # from the new, pending game.
        self.assertEqual(state, [{'game_id': new_game_id,
                                  'next_game_id': None, # player 2 didn't create the next game yet, so it is None
                                  'next_owner_id': player2}, # player2 is now the next owner
                                 [player2]])

        # The same result should be seen when inquiring about the table from the old (previous) game,
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player2]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player2},
                                 [player2]])

        # ----
        # Since player1 already started creating the next game, he should never
        # again be chosen as the next owner for this round, we can see that by
        # checking that next_owner_id only alternates between player2 and the
        # original game's owner.
        # First change:
        yield self.table_instance.poll({'game_id': [new_game_id],
                                        'modified': [table.get_modified()]})
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [new_game_id],
                                                 'player_id': [owner]})
        self.assertEqual(state[0]['next_owner_id'], owner)
        # Second change:
        yield self.table_instance.poll({'game_id': [new_game_id],
                                        'modified': [table.get_modified()]})
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [new_game_id],
                                                 'player_id': [owner]})
        self.assertEqual(state[0]['next_owner_id'], player2)
        # Third change, we're back to the owner:
        yield self.table_instance.poll({'game_id': [new_game_id],
                                        'modified': [table.get_modified()]})
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [new_game_id],
                                                 'player_id': [owner]})
        self.assertEqual(state[0]['next_owner_id'], owner)
        # And fourth change - back to player2:
        yield self.table_instance.poll({'game_id': [new_game_id],
                                        'modified': [table.get_modified()]})
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [new_game_id],
                                                 'player_id': [owner]})
        self.assertEqual(state[0]['next_owner_id'], player2)

        # ----

        # Player 2 creates a new game
        response = yield self.service.handle([], {'action': ['create'],
                                                  'owner_id': [player2],
                                                  'previous_game_id': [new_game_id]})
        newest_game_id = response['game_id']

        # Check the state now.
        # At this point, player1's and player2's games are both pending.
        # Depending on from which game you inquire about it, you should see
        # different results.

        # Looking from the first (and still current) game, the user should be
        # pointed to the newest pending game:
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [owner]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': newest_game_id,
                                  'next_owner_id': player2},
                                 [player2]])

        # Looking from player1's pending game, the table should report the
        # new owner (player2), but not the new game yet, because it's still pending:
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [new_game_id],
                                                 'player_id': [owner]})
        self.assertEqual(state, [{'game_id': new_game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player2},
                                 [player2]])

        # Looking from player2's pending game, we should see the same results:
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [newest_game_id],
                                                 'player_id': [owner]})
        self.assertEqual(state, [{'game_id': newest_game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player2},
                                 [player2]])

        # Let player1 finish creating the game now by setting the card and sentence.
        # player1's game should be promoted as the next game of the table and every
        # of the above requests should now point to it.
        # Set card
        yield self.service.handle([], {'action': ['set_card'],
                                       'card': [1],
                                       'game_id': [new_game_id],
                                       'player_id': [player1]})
        # Set sentence
        yield self.service.handle([], {'action': ['set_sentence'],
                                       'sentence': ['SENTENCE'],
                                       'game_id': [new_game_id],
                                       'player_id': [player1]})

        # Looking from previous game:
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [owner]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': new_game_id,
                                  'next_owner_id': player1},
                                 [player1]])

        # Looking from player1's game, which was promoted:
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [new_game_id],
                                                 'player_id': [owner]})
        self.assertEqual(state, [{'game_id': new_game_id,
                                  'next_game_id': None,
                                  'next_owner_id': None},
                                 []])
        # The game should still be part of the same old table.
        table2 = self.table_instance.game2table[new_game_id]
        self.assertEqual(table2, table)

        # Looking from player2's game, which is still in the pending state,
        # the player should be pointed to the promoted game.
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [newest_game_id],
                                                 'player_id': [owner]})
        self.assertEqual(state, [{'game_id': newest_game_id,
                                  'next_game_id': new_game_id,
                                  'next_owner_id': player1},
                                 [player1]])

        # Now let's move player2's game into 'invitation' state - this should
        # trigger it to be detached from the current table, and put into
        # its own, brand new table.
        # Set card
        yield self.service.handle([], {'action': ['set_card'],
                                       'card': [10],
                                       'game_id': [newest_game_id],
                                       'player_id': [player2]})
        # Set sentence
        yield self.service.handle([], {'action': ['set_sentence'],
                                       'sentence': ['The Real Sentence'],
                                       'game_id': [newest_game_id],
                                       'player_id': [player2]})
        table3 = self.table_instance.game2table[newest_game_id]
        self.assertNotEqual(table3, table)


    @defer.inlineCallbacks
    def test09_next_owner_id_race_condition(self):
        owner = 11
        player1 = 12
        player2 = 13

        # Create the game.
        response = yield self.service.handle([], {'action': ['create'],
                                                  'owner_id': [owner]})
        game_id = response['game_id']
        self.add_players_to_game(game_id, [owner, player1, player2])
        # Complete the game.
        yield self.complete_game(game_id, owner, player1, player2)

        table = self.table_instance.game2table[game_id]

        self.test_done = False

        self.counter = 0

        def listener(args):
            if not self.test_done:
                self.counter += 1
                modified = args['modified'][0]
                table.poll({'modified': [modified]}).addCallback(listener)
            return args

        modified = table.get_modified()
        poll = table.poll({'modified': [modified]}).addCallback(listener)

        d1 = table.update_next_owner_id()
        d2 = table.update_next_owner_id()
        d3 = table.update_next_owner_id()

        d = defer.DeferredList([d1, d2, d3])

        # Wait for all three update operations to finish...
        yield d
        # ...and then wait for the next_owner change to be dispatched by the poll.
        yield poll

        self.assertEquals(self.counter, 1)

        # Break the listen loop so that the test runner doesn't complain
        # about a dirty reactor.
        self.test_done = True
        table.touch({})
        # For the same reason cancel the next_game_timer.
        table.stop_timer(table.next_game_timer)
Esempio n. 9
0
class ActivityTest(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)

        self.service = CardstoriesService({'db': self.database,
                                           'plugins-confdir': 'CONFDIR',
                                           'plugins-libdir': 'LIBDIR',
                                           'static': 'STATIC'
                                           })
        self.service.startService()

        # Don't actually make delayed calls, but allow tests to call them
        self.default_reactor = activity.reactor.callLater
        self.activity_reactor = FakeReactor()
        activity.reactor = self.activity_reactor

        self.activity_instance = activity.Plugin(self.service, [])

    def tearDown(self):
        activity.reactor = self.default_reactor

        # kill the service we started before the test
        return self.service.stopService()

    @defer.inlineCallbacks
    def check_online_players(self, online_players):
        """
        Check that the players currently online are the ones (and only the ones) in the list online_players_ids
        """

        state = yield self.activity_instance.state([])
        self.assertEqual(state[0]['online_players'], online_players)

        for player_id in online_players.keys():
            is_online = self.activity_instance.is_player_online(player_id)
            self.assertTrue(is_online, "Player id %d is not online" % player_id)

    @defer.inlineCallbacks
    def test01_online_offline(self):
        player_id = 12

        # No player initially
        yield self.check_online_players({})

        # Player going online
        on_event_mock = Mock()
        self.activity_instance.listen().addCallback(on_event_mock)
        self.activity_instance.on_service_notification({'type': 'poll_start', 'player_id': player_id})

        on_event_mock.assert_called_once_with({'type': 'player_connecting', 'player_id': player_id})
        on_event_mock.reset_mock()
        self.activity_instance.listen().addCallback(on_event_mock)

        yield self.check_online_players({player_id: {'active_polls': 1} })

        # Player dropping poll
        self.activity_instance.on_service_notification({'type': 'poll_end', 'player_id': player_id})
        self.assertEqual(on_event_mock.call_count, 0)
        yield self.check_online_players({player_id: {'active_polls': 0} })

        # Player starting another poll quickly enough
        self.activity_instance.on_service_notification({'type': 'poll_start', 'player_id': player_id})
        self.assertEqual(on_event_mock.call_count, 0)
        yield self.check_online_players({player_id: {'active_polls': 1} })

        # Player dropping poll again, this time for good (going offline)
        self.activity_instance.on_service_notification({'type': 'poll_end', 'player_id': player_id})
        self.assertEqual(on_event_mock.call_count, 0)
        self.activity_reactor.call_now()
        # Second call should not have any effect (several delayed call can happen concurrently)
        self.activity_reactor.call_now()

        on_event_mock.assert_called_once_with({'type': 'player_disconnecting', 'player_id': player_id})
        yield self.check_online_players({})
Esempio n. 10
0
class CardstoriesEventLogTest(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({'db': self.database})
        self.service.startService()
        self.db = sqlite3.connect(self.database)
        self.game = CardstoriesGame(self.service)

    def tearDown(self):
        self.game.destroy()
        self.db.close()
        os.unlink(self.database)
        return self.service.stopService()

    # Since the logging is all async, the tests would be a nightmare without
    # enforcing events to be logged serially as they happen.
    # In order to do this, we wait by poking at the DB in a loop until the
    # expected number of records exists in the DB.
    def wait_for_logs(self, game_id, expected_nr):
        c = self.db.cursor()
        while True:
            time.sleep(0.005)
            c.execute('SELECT COUNT(*) FROM event_logs WHERE game_id = ?', [game_id])
            if c.fetchone()[0] == expected_nr:
                break

    @defer.inlineCallbacks
    def test01_log_game_events(self):
        owner_id = 42
        player1_id = 84
        player2_id = 86
        sentence = 'The Sentence.'

        # 1 - Should log creation.
        game_id = yield self.game.create(owner_id)
        self.wait_for_logs(game_id, 1)

        # 2 - Should log card set.
        owner = yield self.game.player2game(owner_id)
        winner_card = owner['cards'][0]
        yield self.game.set_card(owner_id, winner_card)
        self.wait_for_logs(game_id, 2)

        # 3 -Should log sentence set.
        yield self.game.set_sentence(owner_id, sentence)
        self.wait_for_logs(game_id, 3)

        # 4 - Should log invitation (player1 only).
        yield self.game.invite([player1_id])
        self.wait_for_logs(game_id, 4)

        # 5 & 6 - Should log joining (both players).
        yield self.game.participate(player1_id)
        self.wait_for_logs(game_id, 5)
        yield self.game.participate(player2_id)
        self.wait_for_logs(game_id, 6)

        # 7 & 8 - Should log players picking cards.
        player1 = yield self.game.player2game(player1_id)
        picked_card1 = player1['cards'][0]
        yield self.game.pick(player1_id, picked_card1)
        self.wait_for_logs(game_id, 7)
        player2 = yield self.game.player2game(player2_id)
        picked_card2 = player1['cards'][0]
        yield self.game.pick(player2_id, picked_card2)
        self.wait_for_logs(game_id, 8)

        # 9 - Should log game moved into voting.
        yield self.game.voting(owner_id)
        self.wait_for_logs(game_id, 9)

        # 10 & 11 - Should log players voting for cards.
        yield self.game.vote(player1_id, winner_card)
        self.wait_for_logs(game_id, 10)
        yield self.game.vote(player2_id, picked_card1)
        self.wait_for_logs(game_id, 11)

        # 12 - Should log game completed.
        yield self.game.complete(owner_id)
        self.wait_for_logs(game_id, 12)

        # Now lets check the logs table.
        c = self.db.cursor()
        # Wait until the logs are written (they're written asynchronously)
        c.execute('SELECT event_type, player_id, data FROM event_logs WHERE game_id = ? ORDER BY timestamp', [game_id])
        # Twelve events should be logged.
        rows = c.fetchall()
        self.assertEqual((event_log.GAME_CREATED, owner_id, None), rows[0])
        self.assertEqual((event_log.OWNER_CHOSE_CARD, owner_id, str(winner_card)), rows[1])
        self.assertEqual((event_log.OWNER_WROTE_STORY, owner_id, sentence), rows[2])
        self.assertEqual((event_log.PLAYER_INVITED, owner_id, str(player1_id)), rows[3])
        self.assertEqual((event_log.PLAYER_JOINED, player1_id, None), rows[4])
        self.assertEqual((event_log.PLAYER_JOINED, player2_id, None), rows[5])
        self.assertEqual((event_log.PLAYER_PICKED_CARD, player1_id, str(picked_card1)), rows[6])
        self.assertEqual((event_log.PLAYER_PICKED_CARD, player2_id, str(picked_card2)), rows[7])
        self.assertEqual((event_log.GAME_MOVED_TO_VOTING, owner_id, None), rows[8])
        self.assertEqual((event_log.PLAYER_VOTED, player1_id, str(winner_card)), rows[9])
        self.assertEqual((event_log.PLAYER_VOTED, player2_id, str(picked_card1)), rows[10])
        self.assertEqual((event_log.GAME_COMPLETED, owner_id, None), rows[11])

        c.close()

    @defer.inlineCallbacks
    def test02_log_canceled_game_events(self):
        owner_id = 4
        player_id = 8
        sentence = 'Some Sentence.'

        # 1 - Should log creation.
        game_id = yield self.game.create(owner_id)
        self.wait_for_logs( game_id, 1)

        # 2 - Should log card set.
        owner = yield self.game.player2game(owner_id)
        winner_card = owner['cards'][0]
        yield self.game.set_card(owner_id, winner_card)
        self.wait_for_logs( game_id, 2)

        # 3 -Should log sentence set.
        yield self.game.set_sentence(owner_id, sentence)
        self.wait_for_logs( game_id, 3)

        # 4 - Should log joining.
        yield self.game.participate(player_id)
        self.wait_for_logs( game_id, 4)

        # 5 - Should log player leaving.
        yield self.game.leave([player_id])
        self.wait_for_logs( game_id, 5)

        # 6 - Should log game cancelation.
        yield self.game.cancel()
        self.wait_for_logs(game_id, 6)

        # Now lets check the logs table.
        c = self.db.cursor()
        c.execute('SELECT event_type, player_id, data FROM event_logs WHERE game_id = ? ORDER BY timestamp', [game_id])
        # Twelve events should be logged.
        rows = c.fetchall()
        self.assertEqual((event_log.GAME_CREATED, owner_id, None), rows[0])
        self.assertEqual((event_log.OWNER_CHOSE_CARD, owner_id, str(winner_card)), rows[1])
        self.assertEqual((event_log.OWNER_WROTE_STORY, owner_id, sentence), rows[2])
        self.assertEqual((event_log.PLAYER_JOINED, player_id, None), rows[3])
        self.assertEqual((event_log.PLAYER_LEFT, player_id, None), rows[4])
        self.assertEqual((event_log.GAME_CANCELED, owner_id, None), rows[5])

        c.close()

    def test03_log_query_functions(self):
        c = self.db.cursor()
        game1 = 99
        game2 = 199
        player1 = 11
        player2 = 12
        invitee = 878

        # Define some datetimes.
        now = datetime.now()
        an_hour_ago = now - timedelta(hours=1)
        six_hours_ago = now - timedelta(hours=6)
        yesterday = now - timedelta(days=1)
        two_days_ago = now - timedelta(days=2)

        # Fill in some log data.
        data = [
            # Game 1
            [game1, two_days_ago, event_log.GAME_CREATED, player1, ''],
            [game1, two_days_ago, event_log.OWNER_CHOSE_CARD, player1, 22],
            [game1, two_days_ago, event_log.OWNER_WROTE_STORY, player1, 'This story'],
            [game1, six_hours_ago, event_log.PLAYER_JOINED, player2, 33],
            [game1, now, event_log.PLAYER_VOTED, player2, 33],
            # Game 2
            [game2, yesterday, event_log.GAME_CREATED, player1, ''],
            [game2, yesterday, event_log.OWNER_CHOSE_CARD, player1, 34],
            [game2, six_hours_ago, event_log.OWNER_WROTE_STORY, player1, 'The Story'],
            [game2, an_hour_ago, event_log.PLAYER_INVITED, player1, invitee],
            [game2, an_hour_ago, event_log.PLAYER_JOINED, invitee, ''],
            [game2, now, event_log.PLAYER_PICKED_CARD, invitee, 23]
        ]
        for d in data:
            c.execute('INSERT INTO event_logs (game_id, timestamp, event_type, player_id, data) VALUES (?, ?, ?, ?, ?)', d)

        # Player's last activity.
        result = event_log.get_players_last_activity(c, player1)
        self.assertEquals(result['timestamp'], str(an_hour_ago))
        self.assertEquals(result['game_id'], game2)
        self.assertEquals(result['event_type'], event_log.PLAYER_INVITED)
        self.assertEquals(result['data'], invitee)

        result = event_log.get_players_last_activity(c, player2)
        self.assertEquals(result['timestamp'], str(now))
        self.assertEquals(result['game_id'], game1)
        self.assertEquals(result['event_type'], event_log.PLAYER_VOTED)
        self.assertEquals(result['data'], 33)

        result = event_log.get_players_last_activity(c, invitee)
        self.assertEquals(result['timestamp'], str(now))
        self.assertEquals(result['game_id'], game2)
        self.assertEquals(result['event_type'], event_log.PLAYER_PICKED_CARD)
        self.assertEquals(result['data'], 23)

        # Game activities.
        result = event_log.get_game_activities(c, game1, since=yesterday)
        self.assertEquals(len(result), 2)
        self.assertEquals(result[0]['event_type'], event_log.PLAYER_JOINED)
        self.assertEquals(result[0]['timestamp'], str(six_hours_ago))
        self.assertEquals(result[1]['event_type'], event_log.PLAYER_VOTED)
        self.assertEquals(result[1]['player_id'], player2)

        result = event_log.get_game_activities(c, game1, since=an_hour_ago)
        self.assertEquals(len(result), 1)
        self.assertEquals(result[0]['event_type'], event_log.PLAYER_VOTED)
        self.assertEquals(result[0]['player_id'], player2)

        result = event_log.get_game_activities(c, game2, since=two_days_ago)
        self.assertEquals(len(result), 6)
        self.assertEquals(result[5]['event_type'], event_log.PLAYER_PICKED_CARD)
        self.assertEquals(result[5]['timestamp'], str(now))
        self.assertEquals(result[5]['player_id'], invitee)
Esempio n. 11
0
class AggregateTest(unittest.TestCase):
    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({'db': self.database})
        self.service.startService()
        self.db = sqlite3.connect(self.database)

    def tearDown(self):
        self.db.close()
        os.unlink(self.database)
        return self.service.stopService()

    def test01_get_player_game_ids(self):
        c = self.db.cursor()
        player_id = 1231
        game_ids = [34, 64, 322, 340]
        # fill in some game_ids for player.
        for game_id in game_ids:
            c.execute(
                'insert into player2game (player_id, game_id) values (?, ?)',
                [player_id, game_id])
        # fill in some bogus ones.
        c.execute('insert into player2game (player_id, game_id) values (?, ?)',
                  [player_id + 3, game_ids[0]])
        c.execute('insert into player2game (player_id, game_id) values (?, ?)',
                  [player_id + 2, game_ids[0]])
        c.execute('insert into player2game (player_id, game_id) values (?, ?)',
                  [player_id + 2, game_ids[0] + 12])

        result = aggregate.get_player_game_ids(c, player_id)
        self.assertEquals(sorted(result), sorted(game_ids))

    def test02_get_game_activities(self):
        c = self.db.cursor()
        game1 = 99
        game2 = 199
        sentence1 = 'This Story'
        sentence2 = 'That Story'
        player1 = 11
        player2 = 12
        invitee = 878

        # Define some datetimes.
        now = datetime.now()
        an_hour_ago = now - timedelta(hours=1)
        six_hours_ago = now - timedelta(hours=6)
        yesterday = now - timedelta(days=1)
        two_days_ago = now - timedelta(days=2)
        three_days_ago = now - timedelta(days=3)

        # Create two games.
        sql = 'INSERT INTO games (id, owner_id, state, sentence, created) VALUES (?, ?, ?, ?, ?)'
        c.execute(sql, [game1, player1, 'voting', sentence1, two_days_ago])
        c.execute(sql, [game2, player1, 'invitation', sentence2, yesterday])

        # Fill in some log data.
        data = [
            # Game 1
            [game1, two_days_ago, event_log.GAME_CREATED, player1, ''],
            [
                game1, two_days_ago + timedelta(seconds=1),
                event_log.OWNER_CHOSE_CARD, player1, 22
            ],
            [
                game1, two_days_ago + timedelta(seconds=2),
                event_log.OWNER_WROTE_STORY, player1, sentence1
            ],
            [game1, six_hours_ago, event_log.PLAYER_JOINED, player2, 33],
            [game1, now, event_log.PLAYER_VOTED, player2, 33],
            # Game 2
            [game2, yesterday, event_log.GAME_CREATED, player1, ''],
            [
                game2, yesterday + timedelta(seconds=1),
                event_log.OWNER_CHOSE_CARD, player1, 34
            ],
            [
                game2, six_hours_ago, event_log.OWNER_WROTE_STORY, player1,
                sentence2
            ],
            [game2, an_hour_ago, event_log.PLAYER_INVITED, player1, invitee],
            [
                game2, an_hour_ago + timedelta(seconds=1),
                event_log.PLAYER_JOINED, invitee, ''
            ],
            [game2, now, event_log.PLAYER_PICKED_CARD, invitee, 23]
        ]
        for d in data:
            c.execute(
                'INSERT INTO event_logs (game_id, timestamp, event_type, player_id, data) VALUES (?, ?, ?, ?, ?)',
                d)

        # Seed the playerid2name data.
        aggregate.seed_playerid2name([
            (player1, '*****@*****.**', 'John Johnson', False),
            (player2, '*****@*****.**', 'Bob Bobbson', False),
            (invitee, '*****@*****.**', 'Mr. Invitee', False)
        ])

        result = aggregate.get_game_activities(c, [game1],
                                               player1,
                                               happened_since=three_days_ago)
        self.assertEquals(len(result), 1)
        self.assertEquals(result[0]['game_id'], game1)
        self.assertEquals(result[0]['state'], 'voting')
        self.assertEquals(result[0]['owner_name'], 'You')
        events = result[0]['events']
        self.assertEquals(len(events), 5)
        self.assertEquals(events[0], 'You created the game')
        self.assertEquals(events[1], 'You chose the card')
        self.assertEquals(events[2], 'You wrote the story')
        self.assertEquals(events[3], 'Bob Bobbson joined the game')
        self.assertEquals(events[4], 'Bob Bobbson voted')

        since = six_hours_ago - timedelta(seconds=1)
        result = aggregate.get_game_activities(c, [game1, game2],
                                               invitee,
                                               happened_since=since)
        self.assertEquals(len(result), 2)
        self.assertEquals(result[0]['game_id'], game1)
        self.assertEquals(result[0]['state'], 'voting')
        self.assertEquals(result[0]['owner_name'], 'John Johnson')
        events1 = result[0]['events']
        self.assertEquals(len(events1), 2)
        self.assertEquals(events1[0], 'Bob Bobbson joined the game')
        self.assertEquals(events1[1], 'Bob Bobbson voted')
        events2 = result[1]['events']
        self.assertEquals(len(events2), 4)
        self.assertEquals(events2[0], 'John Johnson wrote the story')
        self.assertEquals(events2[1],
                          'John Johnson invited You to join the game')
        self.assertEquals(events2[2], 'You joined the game')
        self.assertEquals(events2[3], 'You picked a fake card')

    def test03_get_available_games(self):
        c = self.db.cursor()
        owner_id = 42

        # Define some datetimes.
        now = datetime.now()
        an_hour_ago = now - timedelta(hours=1)
        yesterday = now - timedelta(days=1)
        two_days_ago = now - timedelta(days=2)
        three_days_ago = now - timedelta(days=3)
        sec = timedelta(seconds=1)

        # Create some games.
        sql = 'INSERT INTO games (id, owner_id, state, sentence, created) VALUES (?, ?, ?, ?, ?)'
        games = [
            [1, 'invitation', 'Story 1', three_days_ago],
            [2, 'invitation', 'Story 2', two_days_ago],
            [3, 'create', '', yesterday],
            [4, 'voting', 'Story 4', yesterday],
            [5, 'canceled', 'Story 5', an_hour_ago],
            [6, 'complete', 'Story 6', an_hour_ago],
            [7, 'invitation', 'Story 7', now],
        ]
        for game in games:
            c.execute(sql, [game[0], owner_id, game[1], game[2], game[3]])

        # Seed the playerid2name data.
        aggregate.seed_playerid2name([(owner_id, '*****@*****.**',
                                       'John Johnson', False)])

        # Fetching all available games since two days ago should yeild two results.
        result = aggregate.get_available_games(c, two_days_ago - sec)
        self.assertEquals(len(result), 2)
        self.assertEquals(result[0]['game_id'], 2)
        self.assertEquals(result[0]['owner_name'], 'John Johnson')
        self.assertEquals(result[0]['sentence'], 'Story 2')
        self.assertEquals(result[1]['game_id'], 7)
        self.assertEquals(result[1]['owner_name'], 'John Johnson')
        self.assertEquals(result[1]['sentence'], 'Story 7')

        # Fetching all available games since three days ago should yeild three results,
        # but we are excluding three of them with the third optional parameter,
        # so there should be only one game in the result.
        result = aggregate.get_available_games(c, three_days_ago - sec,
                                               [2, 7, 888])
        self.assertEquals(len(result), 1)
        self.assertEquals(result[0]['game_id'], 1)
        self.assertEquals(result[0]['owner_name'], 'John Johnson')
        self.assertEquals(result[0]['sentence'], 'Story 1')

    def test04_get_completed_games(self):
        c = self.db.cursor()
        owner_id = 42

        # Define some datetimes.
        now = datetime.now()
        an_hour_ago = now - timedelta(hours=1)
        yesterday = now - timedelta(days=1)
        two_days_ago = now - timedelta(days=2)
        three_days_ago = now - timedelta(days=3)

        # Seed the playerid2name data.
        aggregate.seed_playerid2name([(owner_id, '*****@*****.**',
                                       'John Johnson', False)])

        # Create some games.
        sql = 'INSERT INTO games (id, owner_id, state, sentence, created) VALUES (?, ?, ?, ?, ?)'
        games = [
            [1, 'invitation', 'Story 1', three_days_ago],
            [2, 'create', '', two_days_ago],
            [3, 'complete', 'Story 3', yesterday],
            [4, 'voting', 'Story 4', yesterday],
            [5, 'canceled', 'Story 5', an_hour_ago],
            [6, 'complete', 'Story 6', an_hour_ago],
            [7, 'invitation', 'Story 7', now],
        ]
        for game in games:
            c.execute(sql, [game[0], owner_id, game[1], game[2], game[3]])

        # Fetching completed games since two days ago should yeild two results.
        result = aggregate.get_completed_games(c, two_days_ago)
        self.assertEquals(len(result), 2)
        self.assertEquals(result[0]['game_id'], 3)
        self.assertEquals(result[0]['owner_name'], 'John Johnson')
        self.assertEquals(result[0]['sentence'], 'Story 3')
        self.assertEquals(result[1]['game_id'], 6)
        self.assertEquals(result[1]['owner_name'], 'John Johnson')
        self.assertEquals(result[1]['sentence'], 'Story 6')

        # Fetching completed games since three days ago should again yeild two results,
        # but we are excluding one of them with the third optional parameter,
        # so there should be only one game in the result.
        result = aggregate.get_available_games(c, three_days_ago, [1, 4, 888])
        self.assertEquals(len(result), 1)
        self.assertEquals(result[0]['game_id'], 7)
        self.assertEquals(result[0]['owner_name'], 'John Johnson')
        self.assertEquals(result[0]['sentence'], 'Story 7')

    def test05_get_all_players(self):
        # Fake out the django table in our test db.
        c = self.db.cursor()
        c.execute("CREATE TABLE auth_user ( "
                  "  id INTEGER PRIMARY KEY, "
                  "  username VARCHAR(255), "
                  "  first_name VARCHAR(255) "
                  "); ")
        c.execute(
            "CREATE TABLE cardstories_userprofile ( "
            "  user_id INTEGER, "
            "  activity_notifications_disabled BOOL NOT NULL DEFAULT False "
            "); ")

        players = [(1, '*****@*****.**', 'John Johnson', False),
                   (2, '*****@*****.**', 'Bill Billson', True),
                   (88, '*****@*****.**', None, False)]

        for player in players:
            c.execute(
                'INSERT INTO auth_user (id, username, first_name) VALUES (?, ?, ?)',
                (player[0], player[1], player[2]))
            c.execute(
                'INSERT INTO cardstories_userprofile (user_id, activity_notifications_disabled) VALUES (?, ?)',
                (player[0], player[3]))

        result = aggregate.get_all_players(c)
        self.assertEquals(len(result), 3)
        self.assertEquals(result[0], players[0])
        self.assertEquals(result[1], players[1])
        # For players without first name present in the database, it shouold return
        # the part of the email before the '@' character in place of the name.
        self.assertEquals(result[2],
                          (88, '*****@*****.**', 'bigjoe99', False))
        c.close()

    def test06_get_player_name(self):
        players = [(1, '*****@*****.**', 'John Johnson', False),
                   (2, '*****@*****.**', 'Bob Bobbson', False),
                   (42, '*****@*****.**', 'bigjoe99', False)]

        aggregate.seed_playerid2name(players)

        self.assertEquals(aggregate.get_player_name(1, 42), 'John Johnson')
        self.assertEquals(aggregate.get_player_name(2, 1), 'Bob Bobbson')
        self.assertEquals(aggregate.get_player_name(42, 2), 'bigjoe99')
        # Should return 'You' when current_player_id equals the requested player.
        self.assertEquals(aggregate.get_player_name(1, 1), 'You')
        self.assertEquals(aggregate.get_player_name(2, 2), 'You')
        self.assertEquals(aggregate.get_player_name(42, 42), 'You')
Esempio n. 12
0
class LoopTest(unittest.TestCase):
    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({'db': self.database})
        self.service.startService()
        self.db = sqlite3.connect(self.database)
        # Fake out the django table in our test db.
        c = self.db.cursor()
        c.execute("CREATE TABLE auth_user ( "
                  "  id INTEGER PRIMARY KEY, "
                  "  username VARCHAR(255), "
                  "  first_name VARCHAR(255) "
                  "); ")
        c.execute(
            "CREATE TABLE cardstories_userprofile ( "
            "  user_id INTEGER UNIQUE, "
            "  activity_notifications_disabled BOOL NOT NULL DEFAULT False "
            "); ")
        c.close()

        # Mock out send.smtp_open() and
        # smtp.close() calls.
        class FakeSmtp(object):
            def close(self):
                pass

        def fake_smtp_open():
            return FakeSmtp()

        send.smtp_open = fake_smtp_open

    def tearDown(self):
        self.db.close()
        os.unlink(self.database)
        return self.service.stopService()

    def test01_loop(self):
        player1 = 1
        player2 = 2
        player3 = 88
        player4 = 122
        game1 = 111
        game2 = 122
        game3 = 133

        # Mock out should_send_email to always return True,
        # we'll test that function separately.
        original_should_send_email = loop.should_send_email

        def always_true(last_active, game_activities_24h):
            return True

        loop.should_send_email = always_true

        now = datetime.now()
        yesterday = now - timedelta(days=1)
        two_days_ago = now - timedelta(days=2)
        three_days_ago = now - timedelta(days=3)
        sec = timedelta(seconds=1)

        c = self.db.cursor()

        # Prepopulate the tables with fixture data.
        # ------------------------------------------------------------
        # 1. auth_user
        auth_user_fixtures = [
            (player1, '*****@*****.**', 'John Johnson', False),
            (player2, '*****@*****.**', 'Bill Billson', False),
            (player3, '*****@*****.**', None, False),
            (player4, '*****@*****.**', None, True)
        ]
        for player in auth_user_fixtures:
            c.execute(
                'INSERT INTO auth_user (id, username, first_name) VALUES (?, ?, ?)',
                player[:3])
            c.execute(
                'INSERT INTO cardstories_userprofile (user_id, activity_notifications_disabled) VALUES (?, ?)',
                (player[0], player[3]))

        # 2. games
        games_fixtures = [
            (game1, player1, 'Sentence 1', 'invitation', three_days_ago),
            (game2, player1, 'Sentence 2', 'complete', three_days_ago),
            (game3, player2, 'Sentence 3', 'invitation', now)
        ]
        for game in games_fixtures:
            c.execute(
                'INSERT INTO games (id, owner_id, sentence, state, created) VALUES (?, ?, ?, ?, ?)',
                game)

        # 3. player2game
        player2game_fixtures = [(player1, game1), (player1, game2),
                                (player2, game1), (player2, game2),
                                (player2, game3), (player3, game2)]
        for player_id, game_id in player2game_fixtures:
            c.execute(
                'insert into player2game (player_id, game_id) values (?, ?)',
                [player_id, game_id])

        # 4. event_logs
        event_logs_fixtures = [
            # Game 1
            [game1, two_days_ago, event_log.GAME_CREATED, player1, ''],
            [game1, two_days_ago, event_log.OWNER_CHOSE_CARD, player1, 22],
            [
                game1, two_days_ago, event_log.OWNER_WROTE_STORY, player1,
                'Sentence 1'
            ],
            [game1, yesterday, event_log.PLAYER_JOINED, player2, ''],
            [game1, yesterday, event_log.PLAYER_VOTED, player2, 33],
            # Game 2
            [game2, two_days_ago, event_log.GAME_CREATED, player1, ''],
            [game2, two_days_ago, event_log.OWNER_CHOSE_CARD, player1, 34],
            [
                game2, two_days_ago, event_log.OWNER_WROTE_STORY, player1,
                'Sentence 2'
            ],
            [game2, two_days_ago, event_log.PLAYER_INVITED, player1, player3],
            [game2, two_days_ago, event_log.PLAYER_JOINED, player3, ''],
            [game2, two_days_ago, event_log.PLAYER_PICKED_CARD, player3, 23],
            [game2, two_days_ago, event_log.PLAYER_JOINED, player2, ''],
            [game2, two_days_ago, event_log.PLAYER_PICKED_CARD, player2, 24],
            [game2, two_days_ago, event_log.PLAYER_JOINED, player4, ''],
            [game2, two_days_ago, event_log.GAME_MOVED_TO_VOTING, player1, ''],
            [game2, two_days_ago, event_log.PLAYER_VOTED, player2, 44],
            [game2, two_days_ago, event_log.PLAYER_VOTED, player3, 45],
            [game2, two_days_ago, event_log.GAME_COMPLETED, player1, ''],
            # Game 3
            [game3, now, event_log.GAME_CREATED, player2, ''],
            [game3, now, event_log.OWNER_CHOSE_CARD, player2, 34],
            [game3, now, event_log.OWNER_WROTE_STORY, player2, 'Sentence 3']
        ]
        for event in event_logs_fixtures:
            c.execute(
                'INSERT INTO event_logs (game_id, timestamp, event_type, player_id, data) VALUES (?, ?, ?, ?, ?)',
                event)

        # ------------------------------------------------------------
        self.db.commit()
        c.close()

        # Mock out send.send_mail to collect arguments it's been called with.
        calls = []

        def mock_send_mail(email, name, context):
            calls.append([email, name, context])

        send.send_mail = mock_send_mail

        count = loop.loop(self.database, self.database)
        # Should send out two emails (for player1 and player 3).
        # The email shouldn't be sent to player2 because he was last active 'now',
        # and nothing has happened since now (a blank email such as that shouldn't be sent).
        # The email shouldn't be sent to player4 because he has unsubscribed from the emails.
        self.assertEquals(count, 2)

        # Let's see what send_mail has been called with.
        self.assertEquals(len(calls), 2)

        # For player1:
        self.assertEquals(calls[0][1], '*****@*****.**')
        # No completed games:
        self.assertEquals(len(calls[0][2]['completed_games']), 0)
        # One available game (game3 by player2):
        self.assertEquals(len(calls[0][2]['available_games']), 1)
        game = calls[0][2]['available_games'][0]
        self.assertEquals(game['game_id'], game3)
        self.assertEquals(game['owner_name'], 'Bill Billson')
        self.assertEquals(game['sentence'], 'Sentence 3')
        # Player1 was last active two_days ago.
        # Since then (yesterday), two events happened on one of his games (game1).
        self.assertEquals(len(calls[0][2]['game_activities']), 1)
        activity = calls[0][2]['game_activities'][0]
        self.assertEquals(activity['game_id'], game1)
        self.assertEquals(activity['state'], 'invitation')
        self.assertEquals(activity['owner_name'], 'You')
        self.assertEquals(activity['sentence'], 'Sentence 1')
        self.assertEquals(len(activity['events']), 2)
        self.assertEquals(activity['events'][0],
                          'Bill Billson joined the game')
        self.assertEquals(activity['events'][1], 'Bill Billson voted')

        # For player3:
        self.assertEquals(calls[1][1], '*****@*****.**')
        # No completed games:
        self.assertEquals(len(calls[1][2]['completed_games']), 0)
        # One available game (game3 by player2):
        self.assertEquals(len(calls[1][2]['available_games']), 1)
        self.assertEquals(game['game_id'], game3)
        self.assertEquals(game['owner_name'], 'Bill Billson')
        self.assertEquals(game['sentence'], 'Sentence 3')
        # No game activities - player3 has less been active two days ago, but he has only
        # participated in game2 which hasn't seen any activity since then:
        self.assertEquals(len(calls[1][2]['game_activities']), 0)

        loop.should_send_email = original_should_send_email

    def test02_should_send_email(self):
        def to_iso_string(datetime):
            return datetime.strftime('%Y-%m-%d %H:%M:%S')

        now = datetime.now()

        # Should always send if player's last activity was less than 24 hours ago.
        self.assertTrue(loop.should_send_email(to_iso_string(now), []))
        self.assertTrue(
            loop.should_send_email(to_iso_string(now - timedelta(hours=12)),
                                   []))
        self.assertTrue(
            loop.should_send_email(to_iso_string(now - timedelta(hours=22)),
                                   []))
        # Should always send if player's last activity was 7 days ago.
        self.assertTrue(
            loop.should_send_email(to_iso_string(now - timedelta(days=7)), []))
        self.assertTrue(
            loop.should_send_email(
                to_iso_string(now - timedelta(days=7, hours=5)), []))
        self.assertTrue(
            loop.should_send_email(
                to_iso_string(now - timedelta(days=7, hours=23)), []))
        # Should always send if player's last activity was 30, 60, 90, ... days ago.
        self.assertTrue(
            loop.should_send_email(to_iso_string(now - timedelta(days=30)),
                                   []))
        self.assertTrue(
            loop.should_send_email(
                to_iso_string(now - timedelta(days=60, hours=5)), []))
        self.assertTrue(
            loop.should_send_email(
                to_iso_string(now - timedelta(days=90, hours=23)), []))
        # Should NOT send otherwise, if there's no recent activities on player's games.
        self.assertFalse(
            loop.should_send_email(to_iso_string(now - timedelta(days=2)), []))
        self.assertFalse(
            loop.should_send_email(
                to_iso_string(now - timedelta(days=26, hours=5)), []))
        self.assertFalse(
            loop.should_send_email(
                to_iso_string(now - timedelta(days=6, hours=23)), []))
        # Should still send, if there were recent activities on player's games.
        fake_activity = [{'game_id': 42, 'state': 'vote', 'events': []}]
        self.assertTrue(
            loop.should_send_email(to_iso_string(now - timedelta(days=2)),
                                   [fake_activity]))
        self.assertTrue(
            loop.should_send_email(
                to_iso_string(now - timedelta(days=26, hours=5)),
                [fake_activity]))
        self.assertTrue(
            loop.should_send_email(
                to_iso_string(now - timedelta(days=6, hours=23)),
                [fake_activity]))
Esempio n. 13
0
class LoopTest(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({'db': self.database})
        self.service.startService()
        self.db = sqlite3.connect(self.database)
        # Fake out the django table in our test db.
        c = self.db.cursor()
        c.execute(
            "CREATE TABLE auth_user ( "
            "  id INTEGER PRIMARY KEY, "
            "  username VARCHAR(255), "
            "  first_name VARCHAR(255) "
            "); ")
        c.execute(
            "CREATE TABLE cardstories_userprofile ( "
            "  user_id INTEGER UNIQUE, "
            "  activity_notifications_disabled BOOL NOT NULL DEFAULT False "
            "); ")
        c.close()
        # Mock out send.smtp_open() and
        # smtp.close() calls.
        class FakeSmtp(object):
            def close(self):
                pass
        def fake_smtp_open():
            return FakeSmtp()
        send.smtp_open = fake_smtp_open

    def tearDown(self):
        self.db.close()
        os.unlink(self.database)
        return self.service.stopService()

    def test01_loop(self):
        player1 = 1
        player2 = 2
        player3 = 88
        player4 = 122
        game1 = 111
        game2 = 122
        game3 = 133

        # Mock out should_send_email to always return True,
        # we'll test that function separately.
        original_should_send_email = loop.should_send_email
        def always_true(last_active, game_activities_24h):
            return True
        loop.should_send_email = always_true

        now = datetime.now()
        yesterday = now - timedelta(days=1)
        two_days_ago = now - timedelta(days=2)
        three_days_ago = now - timedelta(days=3)
        sec = timedelta(seconds=1)

        c = self.db.cursor()

        # Prepopulate the tables with fixture data.
        # ------------------------------------------------------------
        # 1. auth_user
        auth_user_fixtures = [
            (player1, '*****@*****.**', 'John Johnson', False),
            (player2, '*****@*****.**', 'Bill Billson', False),
            (player3, '*****@*****.**', None, False),
            (player4, '*****@*****.**', None, True)
        ]
        for player in auth_user_fixtures:
            c.execute('INSERT INTO auth_user (id, username, first_name) VALUES (?, ?, ?)', player[:3])
            c.execute('INSERT INTO cardstories_userprofile (user_id, activity_notifications_disabled) VALUES (?, ?)', (player[0], player[3]))


        # 2. games
        games_fixtures = [
            (game1, player1, 'Sentence 1', 'invitation', three_days_ago),
            (game2, player1, 'Sentence 2', 'complete', three_days_ago),
            (game3, player2, 'Sentence 3', 'invitation', now)
        ]
        for game in games_fixtures:
            c.execute('INSERT INTO games (id, owner_id, sentence, state, created) VALUES (?, ?, ?, ?, ?)', game)

        # 3. player2game
        player2game_fixtures =[
            (player1, game1),
            (player1, game2),
            (player2, game1),
            (player2, game2),
            (player2, game3),
            (player3, game2)
        ]
        for player_id, game_id in player2game_fixtures:
            c.execute('insert into player2game (player_id, game_id) values (?, ?)', [player_id, game_id])

        # 4. event_logs
        event_logs_fixtures = [
            # Game 1
            [game1, two_days_ago, event_log.GAME_CREATED,         player1, ''],
            [game1, two_days_ago, event_log.OWNER_CHOSE_CARD,     player1, 22],
            [game1, two_days_ago, event_log.OWNER_WROTE_STORY,    player1, 'Sentence 1'],
            [game1, yesterday,    event_log.PLAYER_JOINED,        player2, ''],
            [game1, yesterday,    event_log.PLAYER_VOTED,         player2, 33],
            # Game 2
            [game2, two_days_ago, event_log.GAME_CREATED,         player1, ''],
            [game2, two_days_ago, event_log.OWNER_CHOSE_CARD,     player1, 34],
            [game2, two_days_ago, event_log.OWNER_WROTE_STORY,    player1, 'Sentence 2'],
            [game2, two_days_ago, event_log.PLAYER_INVITED,       player1, player3],
            [game2, two_days_ago, event_log.PLAYER_JOINED,        player3, ''],
            [game2, two_days_ago, event_log.PLAYER_PICKED_CARD,   player3, 23],
            [game2, two_days_ago, event_log.PLAYER_JOINED,        player2, ''],
            [game2, two_days_ago, event_log.PLAYER_PICKED_CARD,   player2, 24],
            [game2, two_days_ago, event_log.PLAYER_JOINED,        player4, ''],
            [game2, two_days_ago, event_log.GAME_MOVED_TO_VOTING, player1, ''],
            [game2, two_days_ago, event_log.PLAYER_VOTED,         player2, 44],
            [game2, two_days_ago, event_log.PLAYER_VOTED,         player3, 45],
            [game2, two_days_ago, event_log.GAME_COMPLETED,       player1, ''],
            # Game 3
            [game3, now,          event_log.GAME_CREATED,         player2, ''],
            [game3, now,          event_log.OWNER_CHOSE_CARD,     player2, 34],
            [game3, now,          event_log.OWNER_WROTE_STORY,    player2, 'Sentence 3']
        ]
        for event in event_logs_fixtures:
            c.execute('INSERT INTO event_logs (game_id, timestamp, event_type, player_id, data) VALUES (?, ?, ?, ?, ?)', event)

        # ------------------------------------------------------------
        self.db.commit()
        c.close()

        # Mock out send.send_mail to collect arguments it's been called with.
        calls = []
        def mock_send_mail(email, name, context):
            calls.append([email, name, context])
        send.send_mail = mock_send_mail

        count = loop.loop(self.database, self.database)
        # Should send out two emails (for player1 and player 3).
        # The email shouldn't be sent to player2 because he was last active 'now',
        # and nothing has happened since now (a blank email such as that shouldn't be sent).
        # The email shouldn't be sent to player4 because he has unsubscribed from the emails.
        self.assertEquals(count, 2)

        # Let's see what send_mail has been called with.
        self.assertEquals(len(calls), 2)

        # For player1:
        self.assertEquals(calls[0][1], '*****@*****.**')
        # No completed games:
        self.assertEquals(len(calls[0][2]['completed_games']), 0)
        # One available game (game3 by player2):
        self.assertEquals(len(calls[0][2]['available_games']), 1)
        game = calls[0][2]['available_games'][0]
        self.assertEquals(game['game_id'], game3)
        self.assertEquals(game['owner_name'], 'Bill Billson')
        self.assertEquals(game['sentence'], 'Sentence 3')
        # Player1 was last active two_days ago.
        # Since then (yesterday), two events happened on one of his games (game1).
        self.assertEquals(len(calls[0][2]['game_activities']), 1)
        activity = calls[0][2]['game_activities'][0]
        self.assertEquals(activity['game_id'], game1)
        self.assertEquals(activity['state'], 'invitation')
        self.assertEquals(activity['owner_name'], 'You')
        self.assertEquals(activity['sentence'], 'Sentence 1')
        self.assertEquals(len(activity['events']), 2)
        self.assertEquals(activity['events'][0], 'Bill Billson joined the game')
        self.assertEquals(activity['events'][1], 'Bill Billson voted')

        # For player3:
        self.assertEquals(calls[1][1], '*****@*****.**')
        # No completed games:
        self.assertEquals(len(calls[1][2]['completed_games']), 0)
        # One available game (game3 by player2):
        self.assertEquals(len(calls[1][2]['available_games']), 1)
        self.assertEquals(game['game_id'], game3)
        self.assertEquals(game['owner_name'], 'Bill Billson')
        self.assertEquals(game['sentence'], 'Sentence 3')
        # No game activities - player3 has less been active two days ago, but he has only
        # participated in game2 which hasn't seen any activity since then:
        self.assertEquals(len(calls[1][2]['game_activities']), 0)

        loop.should_send_email = original_should_send_email

    def test02_should_send_email(self):
        def to_iso_string(datetime):
            return datetime.strftime('%Y-%m-%d %H:%M:%S')

        now = datetime.now()

        # Should always send if player's last activity was less than 24 hours ago.
        self.assertTrue(loop.should_send_email(to_iso_string(now), []))
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(hours=12)), []))
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(hours=22)), []))
        # Should always send if player's last activity was 7 days ago.
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(days=7)), []))
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(days=7, hours=5)), []))
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(days=7, hours=23)), []))
        # Should always send if player's last activity was 30, 60, 90, ... days ago.
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(days=30)), []))
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(days=60, hours=5)), []))
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(days=90, hours=23)), []))
        # Should NOT send otherwise, if there's no recent activities on player's games.
        self.assertFalse(loop.should_send_email(to_iso_string(now - timedelta(days=2)), []))
        self.assertFalse(loop.should_send_email(to_iso_string(now - timedelta(days=26, hours=5)), []))
        self.assertFalse(loop.should_send_email(to_iso_string(now - timedelta(days=6, hours=23)), []))
        # Should still send, if there were recent activities on player's games.
        fake_activity = [{'game_id': 42, 'state': 'vote', 'events': []}]
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(days=2)), [fake_activity]))
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(days=26, hours=5)), [fake_activity]))
        self.assertTrue(loop.should_send_email(to_iso_string(now - timedelta(days=6, hours=23)), [fake_activity]))
Esempio n. 14
0
class MailTest(unittest.TestCase):
    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({
            'db': self.database,
            'plugins-libdir': '../fixture',
            'plugins-confdir': '../fixture',
            'plugins-dir': '../fixture'
        })
        self.service.startService()

    def tearDown(self):
        return self.service.stopService()

    @defer.inlineCallbacks
    def complete_game(self):
        self.owner_id = 1
        self.player1 = 2
        self.player2 = 3
        self.owner_email = '*****@*****.**'
        self.player1_email = '*****@*****.**'
        self.player2_email = '*****@*****.**'
        self.winner_card = winner_card = 5
        sentence = 'SENTENCE'
        game = yield self.service.create({'owner_id': [self.owner_id]})
        self.game_id = game['game_id']
        yield self.service.set_card({
            'action': ['set_card'],
            'card': [winner_card],
            'game_id': [self.game_id],
            'player_id': [self.owner_id]
        })
        yield self.service.set_sentence({
            'action': ['set_sentence'],
            'sentence': [sentence],
            'game_id': [self.game_id],
            'player_id': [self.owner_id]
        })
        yield self.service.invite({
            'action': ['invite'],
            'game_id': [self.game_id],
            'invited_email': [self.player1_email],
            'owner_id': [self.owner_id]
        })
        for player_id in (self.player1, self.player2):
            yield self.service.participate({
                'action': ['participate'],
                'player_id': [player_id],
                'game_id': [self.game_id]
            })
            player = yield self.service.player2game({
                'action': ['player2game'],
                'player_id': [player_id],
                'game_id': [self.game_id]
            })
            card = player['cards'][0]
            yield self.service.pick({
                'action': ['pick'],
                'player_id': [player_id],
                'game_id': [self.game_id],
                'card': [card]
            })

        yield self.service.voting({
            'action': ['voting'],
            'game_id': [self.game_id],
            'owner_id': [self.owner_id]
        })
        winner_id = self.player1
        yield self.service.vote({
            'action': ['vote'],
            'game_id': [self.game_id],
            'player_id': [winner_id],
            'card': [winner_card]
        })
        loser_id = self.player2
        yield self.service.vote({
            'action': ['vote'],
            'game_id': [self.game_id],
            'player_id': [loser_id],
            'card': [120]
        })
        self.assertTrue(self.service.games.has_key(self.game_id))
        yield self.service.complete({
            'action': ['complete'],
            'game_id': [self.game_id],
            'owner_id': [self.owner_id]
        })
        self.assertFalse(self.service.games.has_key(self.game_id))
        defer.returnValue(True)

    def test00_init(self):
        plugin = mail.Plugin(self.service, [])
        self.assertEquals(plugin.name(), 'mail')
        self.assertEquals(plugin.host, 'localhost')
        for allowed in mail.Plugin.ALLOWED:
            self.assertTrue(plugin.templates.has_key(allowed))

    @defer.inlineCallbacks
    def test01_invite(self):
        plugin = mail.Plugin(self.service, [])

        def get_player_email(player_id):
            if player_id == self.player1:
                email = self.player1_email
            elif player_id == self.player2:
                email = self.player2_email
            elif player_id == self.owner_id:
                email = self.owner_email
            return defer.succeed(email)

        self.service.auth.get_player_email = get_player_email

        def get_player_id(email, create=False):
            return defer.succeed(self.player1)

        self.service.auth.get_player_id = get_player_id

        self.count = 0

        def sendmail(host, sender, recipients, email):
            self.count += 1
            self.assertSubstring('game_id=%d' % self.game_id, email)
            self.assertSubstring('url=URL', email)
            self.assertSubstring('static_url=STATIC_URL', email)
            if self.count == 1:
                self.assertSubstring('_INVITE_', email)
                self.assertSubstring('owner_email=%s' % self.owner_name, email)
            elif self.count in (2, 3):
                self.assertSubstring('_PICK_', email)
                if self.count == 2:
                    self.assertSubstring('player_email=%s' % self.player1_name,
                                         email)
                elif self.count == 3:
                    self.assertSubstring('player_email=%s' % self.player2_name,
                                         email)
            elif self.count in (4, 5):
                self.assertSubstring('_VOTE_', email)
                if self.count == 4:
                    self.assertSubstring('player_email=%s' % self.player1_name,
                                         email)
                elif self.count == 5:
                    self.assertSubstring('player_email=%s' % self.player2_name,
                                         email)
            elif self.count == 6:
                self.assertSubstring('_VOTING_', email)
            elif self.count == 7:
                self.assertSubstring('_COMPLETE_', email)
                self.assertSubstring('owner_email=%s' % self.owner_name, email)
            return defer.succeed(True)

        plugin.sendmail = sendmail

        yield self.complete_game()
        self.assertEqual(self.count, 7)

    @defer.inlineCallbacks
    def test02_send_nothing(self):
        self.service.auth.get_players_emails = Mock(
            return_value=['not_an_email'])
        plugin = mail.Plugin(self.service, [])
        d = plugin.send('SUBJECT', [1], 'TEMPLATE', {})

        def check(result):
            self.assertFalse(result)

        d.addCallback(check)
        yield d
Esempio n. 15
0
class TableTest(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)

        self.service = CardstoriesService({'db': self.database,
                                           'plugins-confdir': 'CONFDIR',
                                           'plugins-libdir': 'LIBDIR',
                                           'static': 'STATIC'})
        self.service.auth = Mock()
        self.service.startService()

        # Fake an activity plugin to which the table plugin should listen
        self.mock_activity_instance = Mock()
        self.mock_activity_instance.name.return_value = 'activity'
        self.table_instance = table.Plugin(self.service, [self.mock_activity_instance])

        self.mock_activity_instance.listen.assert_called_once_with()
        self.mock_activity_instance.reset_mock()

    def tearDown(self):
        # kill the service we started before the test
        return self.service.stopService()

    @defer.inlineCallbacks
    def test01_no_table(self):
        player_id = 12
        game_id = 59

        # Request for tables should direct the player to create his own game
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': ['undefined'],
                                                 'player_id': [player_id]})
        self.assertEqual(state, [{'game_id': None,
                                  'next_game_id': None,
                                  'next_owner_id': player_id},
                                 [player_id]])

        # Next games of existing games should also ask to create a new game, since we have no table info
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player_id]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player_id},
                                 [player_id]])

    @defer.inlineCallbacks
    def test02_create_game_next(self):
        player1 = 12
        player2 = 78
        player3 = 98

        # Show all players as online
        self.mock_activity_instance.is_player_online.return_value = True

        # Poll to know when a table gets available
        poll = self.table_instance.poll({'game_id': ['undefined'],
                                         'modified': [0]})
        result = yield poll
        modified = result['modified'][0]
        # Start a new poll immediately.
        poll = self.table_instance.poll({'game_id': ['undefined'],
                                         'modified': [modified]})
        # Make sure it doesn't return at once.
        self.assertFalse(poll.called)

        self.assertEqual(modified, self.table_instance.get_modified({'game_id': ['undefined']}))

        # Create first game
        response = yield self.service.handle([], {'action': ['create'],
                                                  'owner_id': [player1]})
        game_id = response['game_id']

        # Poll must return to inform players waiting for an available table
        result = yield poll
        modified = result['modified'][0]

        # Associate all players with the game in the tabs db table.
        sql = "INSERT INTO tabs (player_id, game_id, created) VALUES (%d, %d, datetime('now'))"
        for player_id in [player1, player2, player3]:
            yield self.service.db.runQuery(sql % (player_id, game_id))

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': ['undefined'],
                                                 'player_id': [player2]})
        self.assertEqual(state, [{'game_id': None,
                                  'next_game_id': game_id,
                                  'next_owner_id': player1},
                                 [player1]])

        # Initial state of the table itself
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': None},
                                 []])

        # Start a poll on this table to know when the next game will be available there
        poll = self.table_instance.poll({'game_id': [game_id],
                                         'modified': [0]})
        result = yield poll
        modified = result['modified'][0]

        poll = self.table_instance.poll({'game_id': [game_id],
                                         'modified': [modified]})
        self.assertFalse(poll.called)
        self.assertEqual(modified, self.table_instance.get_modified({'game_id': [game_id]}))

        # Complete first game
        yield self.complete_game(game_id, player1, player2, player3)
        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player2},
                                 [player2]])

        # Poll must return to announce the next owner
        result = yield poll
        modified = result['modified'][0]

        poll = self.table_instance.poll({'game_id': [game_id],
                                         'modified': [modified]})
        self.assertFalse(poll.called)

        # Next owner disconnects before creating the game - should chose another player
        def is_player_online(*args, **kw):
            if args[0] == player2:
                return False
            return True
        self.mock_activity_instance.is_player_online.side_effect = is_player_online
        yield self.table_instance.on_activity_notification({'type': 'player_disconnecting',
                                                            'player_id': player2})

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player3},
                                 [player3]])

        # Poll must return to announce the next owner
        result = yield poll
        modified = result['modified'][0]

        poll = self.table_instance.poll({'game_id': [game_id],
                                         'modified': [modified]})
        self.assertFalse(poll.called)


        # Next owner closes the tab before creating the game - should chose another player
        yield self.service.remove_tab({'action': ['remove_tab'],
                                       'player_id': [player3],
                                       'game_id': [game_id]})

        # Poll must return to announce the next owner
        result = yield poll
        modified = result['modified'][0]

        poll = self.table_instance.poll({'game_id': [game_id],
                                         'modified': [modified]})
        self.assertFalse(poll.called)

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player1},
                                 [player1]])

        # Create second game
        response = yield self.service.handle([], {'action': ['create'],
                                                  'owner_id': [player2],
                                                  'card': [1],
                                                  'previous_game_id': [game_id],
                                                  'sentence': ['sentence']})
        game2_id = response['game_id']

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': game2_id,
                                  'next_owner_id': player2},
                                 [player2]])

        # Poll must return to announce the new game
        result = yield poll
        modified = result['modified'][0]

        # All players quit - deletes the table
        self.mock_activity_instance.is_player_online.return_value = False
        yield self.table_instance.on_activity_notification({'type': 'player_disconnecting',
                                                            'player_id': player1})
        yield self.table_instance.on_activity_notification({'type': 'player_disconnecting',
                                                            'player_id': player3})

        state = yield self.table_instance.state({'type': ['table'],
                                                 'game_id': [game_id],
                                                 'player_id': [player1]})
        self.assertEqual(state, [{'game_id': game_id,
                                  'next_game_id': None,
                                  'next_owner_id': player1},
                                 [player1]])

    @defer.inlineCallbacks
    def complete_game(self, game_id, owner, player1, player2):
        # Set card
        yield self.service.handle([], {'action': ['set_card'],
                                       'card': [1],
                                       'game_id': [game_id],
                                       'player_id': [owner]})
        # Set sentence
        yield self.service.handle([], {'action': ['set_sentence'],
                                       'sentence': ['SENTENCE'],
                                       'game_id': [game_id],
                                       'player_id': [owner]})
        # Join
        yield self.service.handle([], {'action': ['participate'],
                                       'game_id': [game_id],
                                       'player_id': [player1]})
        yield self.service.handle([], {'action': ['participate'],
                                       'game_id': [game_id],
                                       'player_id': [player2]})

        # Pick
        game, players_ids = yield self.table_instance.get_game_by_id(game_id, player1)
        yield self.service.handle([], {'action': ['pick'],
                                       'game_id': [game_id],
                                       'player_id': [player1],
                                       'card': [game['self'][2][0]]})
        game, players_ids = yield self.table_instance.get_game_by_id(game_id, player2)
        yield self.service.handle([], {'action': ['pick'],
                                       'game_id': [game_id],
                                       'player_id': [player2],
                                       'card': [game['self'][2][0]]})

        # Vote
        yield self.service.handle([], {'action': ['voting'],
                                       'game_id': [game_id],
                                       'owner_id': [game['owner_id']]})

        @defer.inlineCallbacks
        def player_vote(player_id):
            game, players_ids = yield self.table_instance.get_game_by_id(game_id, player_id)
            my_card = game['self'][0]
            board = [x for x in game['board'] if x != my_card]
            yield self.service.handle([], {'action': ['vote'],
                                           'game_id': [game_id],
                                           'player_id': [player_id],
                                           'card': [board[0]]})
        yield player_vote(player1)
        yield player_vote(player2)

        # Complete
        yield self.service.handle([], {'action': ['complete'],
                                       'game_id': [game_id],
                                       'owner_id': [game['owner_id']]})

    @defer.inlineCallbacks
    def test03_disconnect_with_two_tables(self):
        """
        Bug #797 - ValueError: list.remove(x): x not in list (table.py, delete_table)
        """

        player_id = 12
        self.mock_activity_instance.is_player_online.return_value = True

        # Create two tables
        self.assertEqual(len(self.table_instance.tables), 0)

        response = yield self.service.handle([], {'action': ['create'],
                                                  'owner_id': [player_id],})
        game1_id = response['game_id']
        yield self.service.handle([], {'action': ['set_card'],
                                       'card': [1],
                                       'player_id': [player_id],
                                       'game_id': [game1_id]})
        yield self.service.handle([], {'action': ['set_sentence'],
                                       'sentence': ['sentence'],
                                       'player_id': [player_id],
                                       'game_id': [game1_id]})

        response = yield self.service.handle([], {'action': ['create'],
                                       'owner_id': [player_id],})
        game2_id = response['game_id']
        yield self.service.handle([], {'action': ['set_card'],
                                       'card': [1],
                                       'player_id': [player_id],
                                       'game_id': [game2_id]})
        yield self.service.handle([], {'action': ['set_sentence'],
                                       'sentence': ['sentence'],
                                       'player_id': [player_id],
                                       'game_id': [game2_id]})

        self.assertEqual(len(self.table_instance.tables), 2)

        # Players quits - deletes the two tables simulteanously
        self.mock_activity_instance.is_player_online.return_value = False
        yield self.table_instance.on_activity_notification({'type': 'player_disconnecting',
                                                            'player_id': player_id})
        self.assertEqual(len(self.table_instance.tables), 0)

    @defer.inlineCallbacks
    def test04_postprocess(self):
        game_id = 55
        tab1_game_id = 17
        tab2_game_id = 18
        player_id = 77

        mock_request = Mock()
        mock_request.args = {'action': ['state'], 'player_id': [player_id], 'game_id': [game_id], 'type': ['tabs']}

        response = [{'type': 'tabs',
                     'games': [{'id': tab1_game_id, 'state': 'complete'}, {'id': tab2_game_id, 'state': 'complete'}]}]

        def mock_state(args):
            game_id = args['game_id'][0]
            if game_id == tab1_game_id:
                next_game_id = 42
                next_owner_id = player_id
            elif game_id == tab2_game_id:
                next_game_id = None
                next_owner_id = 21

            result = [{'game_id': game_id, 'next_game_id': next_game_id, 'next_owner_id': next_owner_id}, [player_id]]
            return result
        self.table_instance.state = mock_state

        result = yield self.table_instance.postprocess(response, mock_request)

        # During postprocessing, next_owner_id and next_game_id should be added to
        # the response.
        self.assertEqual(result[0]['games'][0]['next_owner_id'], player_id)
        self.assertEqual(result[0]['games'][0]['next_game_id'], 42)
        self.assertEqual(result[0]['games'][1]['next_owner_id'], 21)
        self.assertEqual(result[0]['games'][1]['next_game_id'], None)

        # Make sure things don't fail if response is not of the expected shape.
        yield self.table_instance.postprocess({'type': 'chat'}, mock_request)
        yield self.table_instance.postprocess([[1, 2, {'this': 'test'}]], mock_request)

    @defer.inlineCallbacks
    def test05_close_tab_with_nonexisting_table(self):
        player_id = 43
        game_id = 1123321
        self.assertEqual(len(self.table_instance.tables), 0)
        result = yield self.table_instance.on_tab_closed(player_id, game_id)
        self.assertEqual(result, True)
Esempio n. 16
0
class AggregateTest(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({'db': self.database})
        self.service.startService()
        self.db = sqlite3.connect(self.database)

    def tearDown(self):
        self.db.close()
        os.unlink(self.database)
        return self.service.stopService()

    def test01_get_player_game_ids(self):
        c = self.db.cursor()
        player_id = 1231
        game_ids = [34, 64, 322, 340]
        # fill in some game_ids for player.
        for game_id in game_ids:
            c.execute('insert into player2game (player_id, game_id) values (?, ?)', [player_id, game_id])
        # fill in some bogus ones.
        c.execute('insert into player2game (player_id, game_id) values (?, ?)', [player_id + 3, game_ids[0]])
        c.execute('insert into player2game (player_id, game_id) values (?, ?)', [player_id + 2, game_ids[0]])
        c.execute('insert into player2game (player_id, game_id) values (?, ?)', [player_id + 2, game_ids[0] + 12])

        result = aggregate.get_player_game_ids(c, player_id)
        self.assertEquals(sorted(result), sorted(game_ids))

    def test02_get_game_activities(self):
        c = self.db.cursor()
        game1 = 99
        game2 = 199
        sentence1 = 'This Story'
        sentence2 = 'That Story'
        player1 = 11
        player2 = 12
        invitee = 878

        # Define some datetimes.
        now = datetime.now()
        an_hour_ago = now - timedelta(hours=1)
        six_hours_ago = now - timedelta(hours=6)
        yesterday = now - timedelta(days=1)
        two_days_ago = now - timedelta(days=2)
        three_days_ago = now - timedelta(days=3)

        # Create two games.
        sql = 'INSERT INTO games (id, owner_id, state, sentence, created) VALUES (?, ?, ?, ?, ?)'
        c.execute(sql, [game1, player1, 'voting', sentence1, two_days_ago])
        c.execute(sql, [game2, player1, 'invitation', sentence2, yesterday])

        # Fill in some log data.
        data = [
            # Game 1
            [game1, two_days_ago, event_log.GAME_CREATED, player1, ''],
            [game1, two_days_ago + timedelta(seconds=1), event_log.OWNER_CHOSE_CARD, player1, 22],
            [game1, two_days_ago + timedelta(seconds=2), event_log.OWNER_WROTE_STORY, player1, sentence1],
            [game1, six_hours_ago, event_log.PLAYER_JOINED, player2, 33],
            [game1, now, event_log.PLAYER_VOTED, player2, 33],
            # Game 2
            [game2, yesterday, event_log.GAME_CREATED, player1, ''],
            [game2, yesterday + timedelta(seconds=1), event_log.OWNER_CHOSE_CARD, player1, 34],
            [game2, six_hours_ago, event_log.OWNER_WROTE_STORY, player1, sentence2],
            [game2, an_hour_ago, event_log.PLAYER_INVITED, player1, invitee],
            [game2, an_hour_ago + timedelta(seconds=1), event_log.PLAYER_JOINED, invitee, ''],
            [game2, now, event_log.PLAYER_PICKED_CARD, invitee, 23]
        ]
        for d in data:
            c.execute('INSERT INTO event_logs (game_id, timestamp, event_type, player_id, data) VALUES (?, ?, ?, ?, ?)', d)

        # Seed the playerid2name data.
        aggregate.seed_playerid2name([
            (player1, '*****@*****.**', 'John Johnson'),
            (player2, '*****@*****.**', 'Bob Bobbson'),
            (invitee, '*****@*****.**', 'Mr. Invitee')
        ])


        result = aggregate.get_game_activities(c, [game1], player1, happened_since=three_days_ago)
        self.assertEquals(len(result), 1)
        self.assertEquals(result[0]['game_id'], game1)
        self.assertEquals(result[0]['state'], 'voting')
        self.assertEquals(result[0]['owner_name'], 'You')
        events = result[0]['events']
        self.assertEquals(len(events), 5)
        self.assertEquals(events[0], 'You created the game')
        self.assertEquals(events[1], 'You chose the card')
        self.assertEquals(events[2], 'You wrote the story')
        self.assertEquals(events[3], 'Bob Bobbson joined the game')
        self.assertEquals(events[4], 'Bob Bobbson voted')

        since = six_hours_ago - timedelta(seconds=1)
        result = aggregate.get_game_activities(c, [game1, game2], invitee, happened_since=since)
        self.assertEquals(len(result), 2)
        self.assertEquals(result[0]['game_id'], game1)
        self.assertEquals(result[0]['state'], 'voting')
        self.assertEquals(result[0]['owner_name'], 'John Johnson')
        events1 = result[0]['events']
        self.assertEquals(len(events1), 2)
        self.assertEquals(events1[0], 'Bob Bobbson joined the game')
        self.assertEquals(events1[1], 'Bob Bobbson voted')
        events2 = result[1]['events']
        self.assertEquals(len(events2), 4)
        self.assertEquals(events2[0], 'John Johnson wrote the story')
        self.assertEquals(events2[1], 'John Johnson invited You to join the game')
        self.assertEquals(events2[2], 'You joined the game')
        self.assertEquals(events2[3], 'You picked a fake card')

    def test03_get_available_games(self):
        c = self.db.cursor()
        owner_id = 42

        # Define some datetimes.
        now = datetime.now()
        an_hour_ago = now - timedelta(hours=1)
        yesterday = now - timedelta(days=1)
        two_days_ago = now - timedelta(days=2)
        three_days_ago = now - timedelta(days=3)
        sec = timedelta(seconds=1)

        # Create some games.
        sql = 'INSERT INTO games (id, owner_id, state, sentence, created) VALUES (?, ?, ?, ?, ?)'
        games = [
            [1, 'invitation', 'Story 1', three_days_ago],
            [2, 'invitation', 'Story 2', two_days_ago],
            [3, 'create', '', yesterday],
            [4, 'voting', 'Story 4', yesterday],
            [5, 'canceled', 'Story 5', an_hour_ago],
            [6, 'complete', 'Story 6', an_hour_ago],
            [7, 'invitation', 'Story 7', now],
        ]
        for game in games:
            c.execute(sql, [game[0], owner_id, game[1], game[2], game[3]])

        # Seed the playerid2name data.
        aggregate.seed_playerid2name([(owner_id, '*****@*****.**', 'John Johnson')])

        # Fetching all available games since two days ago should yeild two results.
        result = aggregate.get_available_games(c, two_days_ago - sec)
        self.assertEquals(len(result), 2)
        self.assertEquals(result[0]['game_id'], 2)
        self.assertEquals(result[0]['owner_name'], 'John Johnson')
        self.assertEquals(result[0]['sentence'], 'Story 2')
        self.assertEquals(result[1]['game_id'], 7)
        self.assertEquals(result[1]['owner_name'], 'John Johnson')
        self.assertEquals(result[1]['sentence'], 'Story 7')

        # Fetching all available games since three days ago should yeild three results,
        # but we are excluding three of them with the third optional parameter,
        # so there should be only one game in the result.
        result = aggregate.get_available_games(c, three_days_ago - sec, [2, 7, 888])
        self.assertEquals(len(result), 1)
        self.assertEquals(result[0]['game_id'], 1)
        self.assertEquals(result[0]['owner_name'], 'John Johnson')
        self.assertEquals(result[0]['sentence'], 'Story 1')


    def test04_get_completed_games(self):
        c = self.db.cursor()
        owner_id = 42

        # Define some datetimes.
        now = datetime.now()
        an_hour_ago = now - timedelta(hours=1)
        yesterday = now - timedelta(days=1)
        two_days_ago = now - timedelta(days=2)
        three_days_ago = now - timedelta(days=3)

        # Seed the playerid2name data.
        aggregate.seed_playerid2name([(owner_id, '*****@*****.**', 'John Johnson')])

        # Create some games.
        sql = 'INSERT INTO games (id, owner_id, state, sentence, created) VALUES (?, ?, ?, ?, ?)'
        games = [
            [1, 'invitation', 'Story 1', three_days_ago],
            [2, 'create', '', two_days_ago],
            [3, 'complete', 'Story 3', yesterday],
            [4, 'voting', 'Story 4', yesterday],
            [5, 'canceled', 'Story 5', an_hour_ago],
            [6, 'complete', 'Story 6', an_hour_ago],
            [7, 'invitation', 'Story 7', now],
        ]
        for game in games:
            c.execute(sql, [game[0], owner_id, game[1], game[2], game[3]])

        # Fetching completed games since two days ago should yeild two results.
        result = aggregate.get_completed_games(c, two_days_ago)
        self.assertEquals(len(result), 2)
        self.assertEquals(result[0]['game_id'], 3)
        self.assertEquals(result[0]['owner_name'], 'John Johnson')
        self.assertEquals(result[0]['sentence'], 'Story 3')
        self.assertEquals(result[1]['game_id'], 6)
        self.assertEquals(result[1]['owner_name'], 'John Johnson')
        self.assertEquals(result[1]['sentence'], 'Story 6')

        # Fetching completed games since three days ago should again yeild two results,
        # but we are excluding one of them with the third optional parameter,
        # so there should be only one game in the result.
        result = aggregate.get_available_games(c, three_days_ago, [1, 4, 888])
        self.assertEquals(len(result), 1)
        self.assertEquals(result[0]['game_id'], 7)
        self.assertEquals(result[0]['owner_name'], 'John Johnson')
        self.assertEquals(result[0]['sentence'], 'Story 7')


    def test05_get_all_players(self):
        # Fake out the django table in our test db.
        c = self.db.cursor()
        c.execute(
            "CREATE TABLE auth_user ( "
            "  id INTEGER PRIMARY KEY, "
            "  username VARCHAR(255), "
            "  first_name VARCHAR(255) "
            "); ")

        players = [
            (1, '*****@*****.**', 'John Johnson'),
            (2, '*****@*****.**', 'Bill Billson'),
            (88, '*****@*****.**', None)
        ]

        for player in players:
            c.execute('INSERT INTO auth_user (id, username, first_name) VALUES (?, ?, ?)', player)

        result = aggregate.get_all_players(c)
        self.assertEquals(len(result), 3)
        self.assertEquals(result[0], players[0])
        self.assertEquals(result[1], players[1])
        # For players without first name present in the database, it shouold return
        # the part of the email before the '@' character in place of the name.
        self.assertEquals(result[2], (88, '*****@*****.**', 'bigjoe99'))
        c.close()


    def test06_get_player_name(self):
        players = [
            (1, '*****@*****.**', 'John Johnson'),
            (2, '*****@*****.**', 'Bob Bobbson'),
            (42, '*****@*****.**', 'bigjoe99')
        ]

        aggregate.seed_playerid2name(players)

        self.assertEquals(aggregate.get_player_name(1, 42), 'John Johnson')
        self.assertEquals(aggregate.get_player_name(2, 1), 'Bob Bobbson')
        self.assertEquals(aggregate.get_player_name(42, 2), 'bigjoe99')
        # Should return 'You' when current_player_id equals the requested player.
        self.assertEquals(aggregate.get_player_name(1, 1), 'You')
        self.assertEquals(aggregate.get_player_name(2, 2), 'You')
        self.assertEquals(aggregate.get_player_name(42, 42), 'You')
Esempio n. 17
0
class ChatTest(unittest.TestCase):

    # initialise our test with a service that we can use during testing and a testing database
    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)

        # Empty 'chat/' subdir
        self.test_logdir = 'test_logdir.tmp'
        if os.path.exists(self.test_logdir):
            shutil.rmtree(self.test_logdir)

        self.service = CardstoriesService({'db': self.database,
                                           'plugins-confdir': 'CONFDIR',
                                           'plugins-libdir': 'LIBDIR',
                                           'plugins-logdir': self.test_logdir,
                                           'static': 'STATIC'
                                           })
        self.service.startService()

    def tearDown(self):
        # kill the service we started before the test
        return self.service.stopService()

    @defer.inlineCallbacks
    def complete_game(self):
        self.winner_card = winner_card = 5
        sentence = 'SENTENCE'
        owner_id = 15
        result = yield self.service.create({'card': [winner_card],
                                            'sentence': [sentence],
                                            'owner_id': [owner_id]})
        game_id = result['game_id']

        yield self.service.set_card({'action': ['set_card'],
                                     'card': [winner_card],
                                     'player_id': [owner_id],
                                     'game_id': [game_id]})

        yield self.service.set_sentence({'action': ['set_sentence'],
                                         'sentence': [sentence],
                                         'player_id': [owner_id],
                                         'game_id': [game_id]})

        self.player1 = 16
        for player_id in (self.player1, 17):
            yield self.service.participate({ 'action': ['participate'],
                                             'player_id': [player_id],
                                             'game_id': [game_id] })
            player = yield self.service.player2game({ 'action': ['player2game'],
                                                      'player_id': [player_id],
                                                      'game_id': [game_id] })
            card = player['cards'][0]
            yield self.service.pick({ 'action': ['pick'],
                                      'player_id': [player_id],
                                      'game_id': [game_id],
                                      'card': [card] })

        yield self.service.voting({ 'action': ['voting'],
                                    'game_id': [game_id],
                                    'owner_id': [owner_id] })
        winner_id = self.player1
        yield self.service.vote({ 'action': ['vote'],
                                  'game_id': [game_id],
                                  'player_id': [winner_id],
                                  'card': [winner_card] })
        loser_id = 17
        yield self.service.vote({ 'action': ['vote'],
                                  'game_id': [game_id],
                                  'player_id': [loser_id],
                                  'card': [120] })
        self.assertTrue(self.service.games.has_key(game_id))
        yield self.service.complete({ 'action': ['complete'],
                                      'game_id': [game_id],
                                      'owner_id': [owner_id] })
        self.assertFalse(self.service.games.has_key(game_id))
        defer.returnValue(True)

    def test00_create_logdir(self):
        chat_instance = Plugin(self.service, [])
        logdir = os.path.join(self.test_logdir, 'chat')
        self.assertTrue(os.path.exists(logdir))

    @defer.inlineCallbacks
    def test00_preprocess_noop(self):
        # create a new instance of the plugin and make sure it's the right type
        chat_instance = Plugin(self.service, [])
        self.assertEquals(chat_instance.name(), 'chat')
        # run a game to get into a realistic situation
        yield self.complete_game()
        # run the preprocess method and make sure it does not affect anything during a normal 'game' event
        result_in = 'RESULT'
        result_out = yield chat_instance.preprocess(result_in, Request(action=['game']))
        self.assertEquals(result_in, result_out)

    @defer.inlineCallbacks
    def test01_add_message(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 200
        sentence = "This is my sentence!"
        now = int(runtime.seconds() * 1000)
        request = Request(action=['message'], player_id=[player_id], sentence=[sentence])
        # verify we have no messages yet
        self.assertEquals(len(chat_instance.messages), 0)
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # verify we now have one message
        self.assertEquals(len(chat_instance.messages), 1)
        # verify the event has been removed from the pipeline
        self.assertFalse(request.args.has_key('action'))
        # verify the message we added is in the list
        self.assertEquals(chat_instance.messages[0]["player_id"], player_id)
        self.assertEquals(chat_instance.messages[0]["sentence"], sentence)
        # check that the message has been recorded in log file
        with open(os.path.join(self.test_logdir, 'chat', '%s.log' % strftime('%Y-%m-%d'))) as f:
            lines = f.readlines()
            self.assertEquals(len(lines), 1)
            self.assertIn(sentence, lines[0])
            self.assertIn('player_%d' % player_id, lines[0])


    @defer.inlineCallbacks
    def test02_check_added_message_after_now(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 200
        sentence = "This is my sentence!"
        now = int(runtime.seconds() * 1000)
        request = Request(action=['message'], player_id=[player_id], sentence=[sentence])
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # check to make sure no message is returned if we ask for now or later
        state, players_id_list = yield chat_instance.state({"modified": [now + 1]})
        self.assertTrue(state.has_key('messages'))
        self.assertEquals(len(state['messages']), 0)
        self.assertEquals(players_id_list, [])

    @defer.inlineCallbacks
    def test03_check_added_message_before_now(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 200
        sentence = "This is my sentence!"
        now = int(runtime.seconds() * 1000)
        request = Request(action=['message'], player_id=[player_id], sentence=[sentence])
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # check to make sure no message is returned if we ask for now or later
        state, players_id_list = yield chat_instance.state({"modified": [now - 1]})
        self.assertEquals(len(state['messages']), 1)
        self.assertEquals(state['messages'][0]['player_id'], player_id)
        self.assertEquals(state['messages'][0]['sentence'], sentence)
        self.assertEquals(players_id_list, [player_id])

    @defer.inlineCallbacks
    def test04_check_multiple_messages(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_ids = [200, 220, 999]
        sentences = ["This is my sentence!", "Yeah another test hello.", "Ping ping poing pong."]
        when = []
        for i in range(3):
            when.append(int(runtime.seconds() * 1000))
            request = Request(action=['message'], player_id=[player_ids[i]], sentence=[sentences[i]])
            # run the request
            result = yield chat_instance.preprocess(True, request)
        # check to make sure no message is returned if we ask for now or later
        # we check right back to one second ago to make sure all recently added messages are caught
        state, players_id_list = yield chat_instance.state({"modified": [when[-1] - 1000]})
        self.assertEquals(len(state['messages']), 3)
        for i in range(3):
            self.assertEquals(state['messages'][i]['player_id'], player_ids[i])
            self.assertEquals(state['messages'][i]['sentence'], sentences[i])
        self.assertEquals(players_id_list, player_ids)

    @defer.inlineCallbacks
    def test05_check_half_of_multiple_messages(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_ids = [200, 220, 999]
        sentences = ["This is my sentence!", "Yeah another test hello.", "Ping ping poing pong."]
        when = []
        for i in range(3):
            sleep(0.1)
            when.append(int(runtime.seconds() * 1000))
            request = Request(action=['message'], player_id=[player_ids[i]], sentence=[sentences[i]])
            # run the request
            result = yield chat_instance.preprocess(True, request)
        # check to make sure no message is returned if we ask for now or later
        # we check right back to one second ago to make sure all recently added messages are caught
        state, players_id_list = yield chat_instance.state({"modified": [when[-1] - 150]})
        # this time because of the 100ms delay between messages, and only checking to 150ms ago
        # we should only get the last two messages
        self.assertEquals(len(state['messages']), 2)
        for i in range(2):
            self.assertEquals(state['messages'][i]['player_id'], player_ids[i + 1])
            self.assertEquals(state['messages'][i]['sentence'], sentences[i + 1])
        self.assertEquals(players_id_list, player_ids[-2:])

    @defer.inlineCallbacks
    def test06_touch_state(self):
        player_id = 200
        sentence = "This is my sentence!"
        # new instance of chat plugin to run the test against
        chat_instance = Plugin(self.service, [])
        # put the chat instance into the service's pollable_plugins
        self.service.pollable_plugins.append(chat_instance)
        # flag to signify whether the callback has run
        self.called = False
        # service to poll instance waiting for chat
        d = self.service.poll({'action': ['poll'],
                               'player_id': [player_id],
                               'type': ['chat'],
                               'modified': [chat_instance.get_modified()]})
        # callback which runs once the chat plugin calls touch()
        def check(event):
            self.called = True
        d.addCallback(check)
        # make sure our flag is false before we run
        self.assertFalse(self.called)
        # run the test request
        request = Request(action=['message'], player_id=[player_id], sentence=[sentence])
        result = yield chat_instance.preprocess(True, request)
        yield d
        # make sure the flag is now set after we've run the test
        self.assertTrue(self.called)

    @defer.inlineCallbacks
    def test07_notification_messages(self):
        # new instance of chat plugin to run the test against
        chat_instance = Plugin(self.service, [])

        self.count = 0
        def build_message(self, message):
            """
            message == {'type': 'notification',
                        'game_id': GAME_ID,
                        'player_id': 'OWNER_ID',
                        'sentence': 'SENTENCE'}

            """
            self.count += 1
            self.assertEquals(self.count, 1)
            self.assertEquals(message['type'], 'notification')
            self.assertEquals(message['player_id'], '15')
            self.assertEquals(message['sentence'], 'SENTENCE')

        # build_message should only be called once, upon game creation.
        chat_instance.build_message = build_message
        # run a game to get into a realistic situation
        yield self.complete_game()

    @defer.inlineCallbacks
    def test08_nonascii_characters_message(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 200
        # The sentence is a 'str' object. Create it by encoding a unicode string.
        unicode_sentence = u"你好 Matjaž Gregorič"
        sentence_bytes = unicode_sentence.encode('utf-8')
        request = Request(action=['message'], player_id=[player_id], sentence=[sentence_bytes])
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # check that the message has been recorded in log file
        with open(os.path.join(self.test_logdir, 'chat', '%s.log' % strftime('%Y-%m-%d'))) as f:
            lines = f.readlines()
            self.assertIn(unicode_sentence, lines[0].decode('utf-8'))

    @defer.inlineCallbacks
    def test09_nonascii_characters_notification(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        class FakeGame:
            id = 102
            owner_id = 303
        unicode_sentence = u"我不明白 šal čez želodec"
        changes = {'type': 'change',
                   'details': {'type': 'load',
                               'sentence': unicode_sentence},
                   'game': FakeGame()}
        result = yield chat_instance.self_notify(changes)
        with open(os.path.join(self.test_logdir, 'chat', '%s.log' % strftime('%Y-%m-%d'))) as f:
            lines = f.readlines()
            self.assertIn(unicode_sentence, lines[0].decode('utf-8'))

    @defer.inlineCallbacks
    def test10_escape_html(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 201
        naughty_sentence = '<script>alert("haha!")</script>'
        now = int(runtime.seconds() * 1000)
        request = Request(action=['message'], player_id=[player_id], sentence=[naughty_sentence])
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # check to make sure our naughty message is returned properly escaped
        state, players_id_list = yield chat_instance.state({"modified": [now - 1]})
        self.assertEquals(state['messages'][0]['player_id'], player_id)
        self.assertEquals(state['messages'][0]['sentence'], '&lt;script&gt;alert("haha!")&lt;/script&gt;')

    @defer.inlineCallbacks
    def test11_link_url(self):
        # new instance of the chat plugin to test
        chat_instance = Plugin(self.service, [])
        # create a message event request
        player_id = 201
        url_sentence = 'For searching the web I use google.com, it\'s great!'
        now = int(runtime.seconds() * 1000)
        request = Request(action=['message'], player_id=[player_id], sentence=[url_sentence])
        # run the request
        result = yield chat_instance.preprocess(True, request)
        # check to make sure our message is returned with a link for the url
        state, players_id_list = yield chat_instance.state({"modified": [now - 1]})
        self.assertEquals(state['messages'][0]['player_id'], player_id)
        self.assertEquals(state['messages'][0]['sentence'], 'For searching the web I use <a target="_blank" href="http://google.com">google.com</a>, it\'s great!')
Esempio n. 18
0
class MailTest(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({'db': self.database,
                                           'plugins-libdir': '../fixture',
                                           'plugins-confdir': '../fixture',
                                           'plugins-dir': '../fixture'})
        self.service.startService()

    def tearDown(self):
        return self.service.stopService()

    @defer.inlineCallbacks
    def complete_game(self):
        self.owner_id = 1
        self.player1 = 2
        self.player2 = 3
        self.owner_email = '*****@*****.**'
        self.player1_email = '*****@*****.**'
        self.player2_email = '*****@*****.**'
        self.winner_card = winner_card = 5
        sentence = 'SENTENCE'
        game = yield self.service.create({'owner_id': [self.owner_id]})
        self.game_id = game['game_id']
        yield self.service.set_card({ 'action': ['set_card'],
                                      'card': [winner_card],
                                      'game_id': [self.game_id],
                                      'player_id': [self.owner_id] })
        yield self.service.set_sentence({ 'action': ['set_sentence'],
                                          'sentence': [sentence],
                                          'game_id': [self.game_id],
                                          'player_id': [self.owner_id] })
        yield self.service.invite({ 'action': ['invite'],
                                    'game_id': [self.game_id],
                                    'invited_email': [self.player1_email],
                                    'owner_id': [self.owner_id] })
        for player_id in (self.player1, self.player2):
            yield self.service.participate({ 'action': ['participate'],
                                             'player_id': [player_id],
                                             'game_id': [self.game_id] })
            player = yield self.service.player2game({ 'action': ['player2game'],
                                                      'player_id': [player_id],
                                                      'game_id': [self.game_id] })
            card = player['cards'][0]
            yield self.service.pick({ 'action': ['pick'],
                                      'player_id': [player_id],
                                      'game_id': [self.game_id],
                                      'card': [card] })

        yield self.service.voting({ 'action': ['voting'],
                                    'game_id': [self.game_id],
                                    'owner_id': [self.owner_id] })
        winner_id = self.player1
        yield self.service.vote({ 'action': ['vote'],
                                  'game_id': [self.game_id],
                                  'player_id': [winner_id],
                                  'card': [winner_card] })
        loser_id = self.player2
        yield self.service.vote({ 'action': ['vote'],
                                  'game_id': [self.game_id],
                                  'player_id': [loser_id],
                                  'card': [120] })
        self.assertTrue(self.service.games.has_key(self.game_id))
        yield self.service.complete({ 'action': ['complete'],
                                      'game_id': [self.game_id],
                                      'owner_id': [self.owner_id] })
        self.assertFalse(self.service.games.has_key(self.game_id))
        defer.returnValue(True)

    def test00_init(self):
        plugin = mail.Plugin(self.service, [ ])
        self.assertEquals(plugin.name(), 'mail')
        self.assertEquals(plugin.host, 'localhost')
        for allowed in mail.Plugin.ALLOWED:
            self.assertTrue(plugin.templates.has_key(allowed))

    @defer.inlineCallbacks
    def test01_invite(self):
        plugin = mail.Plugin(self.service, [ ])

        def get_player_email(player_id):
            if player_id == self.player1:
                email = self.player1_email
            elif player_id == self.player2:
                email = self.player2_email
            elif player_id == self.owner_id:
                email = self.owner_email
            return defer.succeed(email)
        self.service.auth.get_player_email = get_player_email

        def get_player_id(email, create=False):
            return defer.succeed(self.player1)
        self.service.auth.get_player_id = get_player_id

        self.count = 0

        def sendmail(host, sender, recipients, email):
            self.count += 1
            self.assertSubstring('game_id=%d' % self.game_id, email)
            self.assertSubstring('url=URL', email)
            self.assertSubstring('static_url=STATIC_URL', email)
            if self.count == 1:
                self.assertSubstring('_INVITE_', email)
                self.assertSubstring('owner_email=%s' % self.owner_name, email)
            elif self.count in (2, 3) :
                self.assertSubstring('_PICK_', email)
                if self.count == 2:
                    self.assertSubstring('player_email=%s' % self.player1_name, email)
                elif self.count == 3:
                    self.assertSubstring('player_email=%s' % self.player2_name, email)
            elif self.count in (4, 5) :
                self.assertSubstring('_VOTE_', email)
                if self.count == 4:
                    self.assertSubstring('player_email=%s' % self.player1_name, email)
                elif self.count == 5:
                    self.assertSubstring('player_email=%s' % self.player2_name, email)
            elif self.count == 6:
                self.assertSubstring('_VOTING_', email)
            elif self.count == 7:
                self.assertSubstring('_COMPLETE_', email)
                self.assertSubstring('owner_email=%s' % self.owner_name, email)
            return defer.succeed(True)
        plugin.sendmail = sendmail

        yield self.complete_game()
        self.assertEqual(self.count, 7)

    @defer.inlineCallbacks
    def test02_send_nothing(self):
        self.service.auth.get_players_emails = Mock(return_value=['not_an_email'])
        plugin = mail.Plugin(self.service, [ ])
        d = plugin.send('SUBJECT', [ 1 ], 'TEMPLATE', {})
        def check(result):
            self.assertFalse(result)
        d.addCallback(check)
        yield d
Esempio n. 19
0
class LoopTest(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({'db': self.database})
        self.service.startService()
        self.db = sqlite3.connect(self.database)
        # Fake out the django table in our test db.
        c = self.db.cursor()
        c.execute(
            "CREATE TABLE auth_user ( "
            "  id INTEGER PRIMARY KEY, "
            "  username VARCHAR(255), "
            "  first_name VARCHAR(255) "
            "); ")
        c.close()

    def tearDown(self):
        self.db.close()
        os.unlink(self.database)
        return self.service.stopService()

    def test01_loop(self):
        player1 = 1
        player2 = 2
        player3 = 88
        game1 = 111
        game2 = 122
        game3 = 133

        now = datetime.now()
        yesterday = now - timedelta(days=1)
        two_days_ago = now - timedelta(days=2)
        three_days_ago = now - timedelta(days=3)
        sec = timedelta(seconds=1)

        c = self.db.cursor()

        # Prepopulate the tables with fixture data.
        # ------------------------------------------------------------
        # 1. auth_user
        auth_user_fixtures = [
            (player1, '*****@*****.**', 'John Johnson'),
            (player2, '*****@*****.**', 'Bill Billson'),
            (player3, '*****@*****.**', None)
        ]
        for player in auth_user_fixtures:
            c.execute('INSERT INTO auth_user (id, username, first_name) VALUES (?, ?, ?)', player)

        # 2. games
        games_fixtures = [
            (game1, player1, 'Sentence 1', 'invitation', three_days_ago),
            (game2, player1, 'Sentence 2', 'complete', three_days_ago),
            (game3, player2, 'Sentence 3', 'invitation', now)
        ]
        for game in games_fixtures:
            c.execute('INSERT INTO games (id, owner_id, sentence, state, created) VALUES (?, ?, ?, ?, ?)', game)

        # 3. player2game
        player2game_fixtures =[
            (player1, game1),
            (player1, game2),
            (player2, game1),
            (player2, game2),
            (player2, game3),
            (player3, game2)
        ]
        for player_id, game_id in player2game_fixtures:
            c.execute('insert into player2game (player_id, game_id) values (?, ?)', [player_id, game_id])

        # 4. event_logs
        event_logs_fixtures = [
            # Game 1
            [game1, two_days_ago, event_log.GAME_CREATED,         player1, ''],
            [game1, two_days_ago, event_log.OWNER_CHOSE_CARD,     player1, 22],
            [game1, two_days_ago, event_log.OWNER_WROTE_STORY,    player1, 'Sentence 1'],
            [game1, yesterday,    event_log.PLAYER_JOINED,        player2, ''],
            [game1, yesterday,    event_log.PLAYER_VOTED,         player2, 33],
            # Game 2
            [game2, two_days_ago, event_log.GAME_CREATED,         player1, ''],
            [game2, two_days_ago, event_log.OWNER_CHOSE_CARD,     player1, 34],
            [game2, two_days_ago, event_log.OWNER_WROTE_STORY,    player1, 'Sentence 2'],
            [game2, two_days_ago, event_log.PLAYER_INVITED,       player1, player3],
            [game2, two_days_ago, event_log.PLAYER_JOINED,        player3, ''],
            [game2, two_days_ago, event_log.PLAYER_PICKED_CARD,   player3, 23],
            [game2, two_days_ago, event_log.PLAYER_JOINED,        player2, ''],
            [game2, two_days_ago, event_log.PLAYER_PICKED_CARD,   player2, 24],
            [game2, two_days_ago, event_log.GAME_MOVED_TO_VOTING, player1, ''],
            [game2, two_days_ago, event_log.PLAYER_VOTED,         player2, 44],
            [game2, two_days_ago, event_log.PLAYER_VOTED,         player3, 45],
            [game2, two_days_ago, event_log.GAME_COMPLETED,       player1, ''],
            # Game 3
            [game3, now,          event_log.GAME_CREATED,         player2, ''],
            [game3, now,          event_log.OWNER_CHOSE_CARD,     player2, 34],
            [game3, now,          event_log.OWNER_WROTE_STORY,    player2, 'Sentence 3']
        ]
        for event in event_logs_fixtures:
            c.execute('INSERT INTO event_logs (game_id, timestamp, event_type, player_id, data) VALUES (?, ?, ?, ?, ?)', event)

        # ------------------------------------------------------------
        self.db.commit()
        c.close()

        # Mock out send.send_mail to collect arguments it's been called with.
        calls = []
        def mock_send_mail(email, name, context):
            calls.append([email, name, context])
        send.send_mail = mock_send_mail

        count = loop.loop(self.database, self.database)
        # Should send out three emails (for each of the three players in the db).
        self.assertEquals(count, 3)

        # Let's see what send_mail has been called with.
        self.assertEquals(len(calls), 3)

        # For player1:
        self.assertEquals(calls[0][0], '*****@*****.**')
        self.assertEquals(calls[0][1], 'John Johnson')
        # No completed games:
        self.assertEquals(len(calls[0][2]['completed_games']), 0)
        # One available game (game3 by player2):
        self.assertEquals(len(calls[0][2]['available_games']), 1)
        game = calls[0][2]['available_games'][0]
        self.assertEquals(game['game_id'], game3)
        self.assertEquals(game['owner_name'], 'Bill Billson')
        self.assertEquals(game['sentence'], 'Sentence 3')
        # Player1 was last active two_days ago.
        # Since then (yesterday), two events happened on one of his games (game1).
        self.assertEquals(len(calls[0][2]['game_activities']), 1)
        activity = calls[0][2]['game_activities'][0]
        self.assertEquals(activity['game_id'], game1)
        self.assertEquals(activity['state'], 'invitation')
        self.assertEquals(activity['owner_name'], 'You')
        self.assertEquals(activity['sentence'], 'Sentence 1')
        self.assertEquals(len(activity['events']), 2)
        self.assertEquals(activity['events'][0], 'Bill Billson joined the game')
        self.assertEquals(activity['events'][1], 'Bill Billson voted')

        # For player2:
        self.assertEquals(calls[1][0], '*****@*****.**')
        self.assertEquals(calls[1][1], 'Bill Billson')
        # Player2 has last been active 'now', not much has happened since 'now', obviously.
        # No completed games:
        self.assertEquals(len(calls[1][2]['completed_games']), 0)
        # No available games:
        self.assertEquals(len(calls[1][2]['available_games']), 0)
        # No game acitvities:
        self.assertEquals(len(calls[1][2]['game_activities']), 0)

        # For player3:
        self.assertEquals(calls[2][0], '*****@*****.**')
        self.assertEquals(calls[2][1], 'bigjoe99')
        # No completed games:
        self.assertEquals(len(calls[2][2]['completed_games']), 0)
        # One available game (game3 by player2):
        self.assertEquals(len(calls[2][2]['available_games']), 1)
        self.assertEquals(game['game_id'], game3)
        self.assertEquals(game['owner_name'], 'Bill Billson')
        self.assertEquals(game['sentence'], 'Sentence 3')
        # No game acitvities - player3 has less been active two days ago, but he has only
        # participated in game2 which hasn't seen any activity since then:
        self.assertEquals(len(calls[2][2]['game_activities']), 0)
Esempio n. 20
0
class BotTest(unittest.TestCase):

    # initialise our test with a service that we can use during testing and a testing database
    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)

        self.service = CardstoriesService({
            'db': self.database,
            'plugins-confdir': '../fixture',
            'plugins-libdir': 'LIBDIR',
            'static': 'STATIC'
        })
        self.service.auth = Mock()
        self.service.startService()

    def tearDown(self):
        # kill the service we started before the test
        return self.service.stopService()

    @defer.inlineCallbacks
    def game_create(self):
        """Creates the game, sets the card, and sets the sentence in one step."""
        self.winner_card = winner_card = 5
        sentence = 'SENTENCE'
        self.owner_id = 15
        result = yield self.service.create({'owner_id': [self.owner_id]})
        game_id = result['game_id']
        yield self.service.set_card({
            'action': ['set_card'],
            'card': [winner_card],
            'player_id': [self.owner_id],
            'game_id': [game_id]
        })
        yield self.service.set_sentence({
            'action': ['set_sentence'],
            'sentence': [sentence],
            'player_id': [self.owner_id],
            'game_id': [game_id]
        })

        defer.returnValue(result)

    @defer.inlineCallbacks
    def game_to_vote(self, game_id):
        yield self.service.voting({
            'action': ['voting'],
            'game_id': [game_id],
            'owner_id': [self.owner_id]
        })
        self.assertTrue(self.service.games.has_key(game_id))
        defer.returnValue(True)

    @defer.inlineCallbacks
    def game_to_complete(self, game_id):
        yield self.service.complete({
            'action': ['complete'],
            'game_id': [game_id],
            'owner_id': [self.owner_id]
        })
        self.assertFalse(self.service.games.has_key(game_id))
        defer.returnValue(True)

    @defer.inlineCallbacks
    def test01_play_game(self):
        mock_reactor = bot.reactor = Mock()  # Don't delay calls

        bot_plugin = bot.Plugin(self.service, [])
        self.assertEquals(bot_plugin.name(), 'bot')
        bots = [bot_plugin.bots[0], bot_plugin.bots[1], bot_plugin.bots[2]]
        self.assertEqual(bots[0].player_id, 2)
        self.assertEqual(bots[1].player_id, 3)
        self.assertEqual(bots[2].player_id, 4)

        # New game
        game = yield self.game_create()
        game_id = game['game_id']
        mock_reactor.callLater.assert_called_once_with(
            1, bot_plugin.check_need_player, game_id)
        mock_reactor.reset_mock()

        # Only the author in the game
        game, players_ids = yield bots[0].get_game_by_id(game_id)
        self.assertEqual(len(game['players']), 1)

        # Bots don't join by default
        yield bot_plugin.check_need_player(game_id)
        self.assertEqual(len(mock_reactor.callLater.call_args_list), 0)

        # Enable joining
        request = Request(action=['bot'],
                          enable_join=['true'],
                          game_id=[str(game_id)])
        result = yield bot_plugin.preprocess(True, request)
        self.assertFalse(request.args.has_key('action'))
        self.assertTrue(bot_plugin.enable_join[game_id])
        mock_reactor.reset_mock()

        # Bots join after enabling it
        for i in xrange(2):
            yield bot_plugin.check_need_player(game_id)
            self.assertEqual(len(mock_reactor.callLater.call_args_list), 2)
            mock_reactor.reset_mock()

            game, player_ids = yield bots[i].get_game_by_id(game_id)
            self.assertEqual(game['players'][i + 1]['id'], bots[i].player_id)
            self.assertEqual(game['players'][i + 1]['picked'], None)

        # Bots pick a card
        for i in xrange(2):
            yield bots[i].pick(game_id)
            self.assertFalse(mock_reactor.called)

            game, player_ids = yield bots[i].get_game_by_id(
                game_id, player_id=bots[i].player_id)
            self.assertIsInstance(game['players'][i + 1]['picked'], int)
            self.assertEqual(game['players'][i + 1]['vote'], None)

        # Go to vote phase
        yield self.game_to_vote(game_id)
        self.assertEqual(mock_reactor.callLater.call_args_list,
                         [((3, bots[0].vote, game_id), {}),
                          ((3, bots[1].vote, game_id), {})])
        mock_reactor.reset_mock()

        # A bot should never join or pick at this stage
        joined = yield bots[2].join(game_id)
        self.assertFalse(joined)
        picked = yield bots[2].pick(game_id)
        self.assertFalse(picked)

        # Bots vote
        for i in xrange(2):
            yield bots[i].vote(game_id)
            self.assertFalse(mock_reactor.called)

            game, player_ids = yield bots[i].get_game_by_id(
                game_id, player_id=bots[i].player_id)
            self.assertIsInstance(game['players'][i + 1]['picked'], int)
            self.assertEqual(game['players'][i + 1]['vote'], '')

        # A bot should never vote at this stage
        joined = yield bots[2].vote(game_id)
        self.assertFalse(joined)

    def test02_brain_not_implemented(self):
        brain = bot.Brain(None)
        self.assertRaises(NotImplementedError,
                          brain.get_all_cards_scores_for_sentence, "Test")

    def test03_brain_weighted_card_choice(self):
        brain = bot.Brain(None)
        ranked_cards = [(1, 1), (2, 10000), (3, 0), (4, 0), (5, 0), (6, 0),
                        (7, 0), (8, 0), (9, 0)]
        chosen_card = brain.weighted_card_choice(ranked_cards)
        self.assertTrue(chosen_card == 1 or chosen_card == 2)

    @defer.inlineCallbacks
    def test04_nlwordmatcherbrain(self):
        bot_plugin = bot.Plugin(self.service, [])
        brain = bot.NLWordMatcherBrain(bot_plugin)

        # Make sure we can record scores for cards that are earned (card # > NCARDS)
        max_cards = 42
        assert CardstoriesGame.NCARDS < max_cards <= CardstoriesGame.NCARDS_EARNED

        ranked_cards = yield brain.sort_cards_by_ranking_for_sentence(
            "word", [1, 2, 3, 42])
        self.assertEquals(ranked_cards, [(3, 4), (2, 3), (1, 2),
                                         (max_cards, 1)])
Esempio n. 21
0
class ExampleTest(unittest.TestCase):

    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)
        self.service = CardstoriesService({'db': self.database,
                                           'plugins-confdir': 'CONFDIR',
                                           'plugins-libdir': 'LIBDIR',
                                           'static': 'STATIC'
                                           })

    @defer.inlineCallbacks
    def complete_game(self, send):
        self.winner_card = winner_card = 5
        self.player1 = 1001
        self.player2 = 1002
        self.owner_id = 1003
        self.sentence = sentence = 'SENTENCE'
        game = yield send('create', {'owner_id': [self.owner_id]})
        self.game_id = game['game_id']
        yield send('set_card', { 'action': ['set_card'],
                                 'card': [winner_card],
                                 'player_id': [self.owner_id],
                                 'game_id': [self.game_id] })
        yield send('set_sentence', { 'action': ['set_sentence'],
                                     'sentence': [sentence],
                                     'player_id': [self.owner_id],
                                     'game_id': [self.game_id] })
        yield send('invite', { 'action': ['invite'],
                                    'game_id': [self.game_id],
                                    'player_id': [self.player1],
                                    'owner_id': [self.owner_id] })
        for player_id in (self.player1, self.player2):
            yield send('participate', { 'action': ['participate'],
                                             'player_id': [player_id],
                                             'game_id': [self.game_id] })
            player = yield self.service.player2game({ 'action': ['player2game'],
                                                      'player_id': [player_id],
                                                      'game_id': [self.game_id] })
            card = player['cards'][0]
            yield send('pick', { 'action': ['pick'],
                                      'player_id': [player_id],
                                      'game_id': [self.game_id],
                                      'card': [card] })

        yield send('voting', { 'action': ['voting'],
                                    'game_id': [self.game_id],
                                    'owner_id': [self.owner_id] })
        winner_id = self.player1
        yield send('vote', { 'action': ['vote'],
                                  'game_id': [self.game_id],
                                  'player_id': [winner_id],
                                  'card': [winner_card] })
        loser_id = self.player2
        yield send('vote', { 'action': ['vote'],
                                  'game_id': [self.game_id],
                                  'player_id': [loser_id],
                                  'card': [120] })
        self.assertTrue(self.service.games.has_key(self.game_id))
        yield send('complete', { 'action': ['complete'],
                                      'game_id': [self.game_id],
                                      'owner_id': [self.owner_id] })
        self.assertFalse(self.service.games.has_key(self.game_id))
        defer.returnValue(True)

    def test00_init(self):
        plugin = example.Plugin(self.service, [ AnotherPlugin() ])
        self.assertEqual(plugin.service, self.service)
        self.assertSubstring('example', plugin.confdir)
        self.assertSubstring('example', plugin.libdir)

    @defer.inlineCallbacks
    def test01_accept(self):
        plugin = example.Plugin(self.service, [ AnotherPlugin() ])
        self.events = []
        def accept(event):
            self.service.listen().addCallback(accept)
            self.events.append(plugin.event)
            return defer.succeed(True)
        self.service.listen().addCallback(accept)
        self.service.startService()
        yield self.complete_game(lambda action, args: getattr(self.service, action)(args))
        yield self.service.stopService()
        self.assertEqual(self.events, ['START',
                                       'CHANGE create',
                                       'CHANGE set_card',
                                       'CHANGE set_sentence',
                                       'CHANGE invite',
                                       'CHANGE participate',
                                       'CHANGE pick',
                                       'CHANGE participate',
                                       'CHANGE pick',
                                       'CHANGE voting',
                                       'CHANGE vote',
                                       'CHANGE vote',
                                       'CHANGE complete',
                                       'DELETE',
                                       'STOP'])

        # Test for the load event.
        self.service.startService()
        yield self.service.create({'owner_id': [2]})
        yield self.service.stopService()

        self.events = []
        self.service.startService()
        yield self.service.stopService()
        self.assertTrue('CHANGE load' in self.events)

    def test02_transparent_transform(self):
        self.site = CardstoriesSite(CardstoriesTree(self.service),
                                    { 'plugins-pre-process': 'example',
                                      'plugins-post-process': 'example' },
                                    [ example.Plugin(self.service, [ AnotherPlugin() ]) ])
        r = server.Request(Channel(self.site), True)
        r.site = r.channel.site
        input = ''
        r.gotLength(len(input))
        r.handleContentChunk(input)
        r.queued = 0
        d = r.notifyFinish()
        def finish(result):
            self.assertSubstring('\r\n\r\n{"arg1": ["val10X", "val11X"], "arg2": ["val20X"], "MORE": "YES", "echo": ["yesX"]}', r.transport.getvalue())
        d.addCallback(finish)
        r.requestReceived('GET', '/resource?action=echo&echo=yes&arg1=val10&arg1=val11&arg2=val20', '')
        return d

    @defer.inlineCallbacks
    def test03_pipeline(self):
        plugin = example.Plugin(self.service, [ AnotherPlugin() ])
        resource = CardstoriesResource(self.service)
        self.site = CardstoriesSite(CardstoriesTree(self.service),
                                    { 'plugins-pre-process': 'example',
                                      'plugins-post-process': 'example' },
                                    [ plugin ])
        self.collected = []
        def collect(result):
            self.collected.append([ plugin.preprocessed, plugin.postprocessed ])
            return result
        def send(action, args):
            args['action'] = [action];
            request = server.Request(Channel(self.site), True)
            request.site = self.site
            request.args = args
            request.method = 'GET'
            d = resource.wrap_http(request)
            d.addCallback(collect)
            return d
        self.service.startService()
        yield self.complete_game(send)
        yield self.service.stopService()
        count = 0
        self.assertEquals(self.collected[count],
                          [{'action': ['create'],
                            'owner_id': [self.owner_id]},
                           {'game_id': self.game_id}]);
        count += 1
        del self.collected[count][1]['modified']
        self.assertEquals(self.collected[count],
                          [{'action': ['set_card'],
                            'card': [self.winner_card],
                            'player_id': [self.owner_id],
                            'game_id': [self.game_id]},
                           {'type': 'set_card',
                            'card': self.winner_card,
                            'player_id': self.owner_id,
                            'game_id': [self.game_id]}]);
        count += 1
        del self.collected[count][1]['modified']
        self.assertEquals(self.collected[count],
                          [{'action': ['set_sentence'],
                            'sentence': [self.sentence],
                            'player_id': [self.owner_id],
                            'game_id': [self.game_id]},
                           {'type': 'set_sentence',
                            'sentence': self.sentence,
                            'game_id': [self.game_id]}]);
        count += 1
        del self.collected[count][1]['modified']
        self.assertEquals(self.collected[count],
                          [{'action': ['invite'],
                            'game_id': [self.game_id],
                            'owner_id': [self.owner_id],
                            'player_id': [self.player1]},
                           {'game_id': [self.game_id],
                            'invited': [self.player1],
                            'type': 'invite'}]);
        count += 1
        del self.collected[count][1]['modified']
        self.assertEquals(self.collected[count],
                          [{'action': ['participate'],
                            'game_id': [self.game_id],
                            'player_id': [self.player1]},
                           {'game_id': [self.game_id],
                            'player_id': self.player1,
                            'type': 'participate'}]);
        count += 1
        del self.collected[count][1]['modified']
        player1_card = self.collected[count][0]['card'][0]
        self.assertEquals(self.collected[count],
                          [{'action': ['pick'],
                            'card': [player1_card],
                            'game_id': [self.game_id],
                            'player_id': [self.player1]},
                           {'card': player1_card,
                            'game_id': [self.game_id],
                            'player_id': self.player1,
                            'type': 'pick'}]);
        count += 1
        del self.collected[count][1]['modified']
        self.assertEquals(self.collected[count],
                          [{'action': ['participate'],
                            'game_id': [self.game_id],
                            'player_id': [self.player2]},
                           {'game_id': [self.game_id],
                            'player_id': self.player2,
                            'type': 'participate'}]);
        count += 1
        del self.collected[count][1]['modified']
        player2_card = self.collected[count][0]['card'][0]
        self.assertEquals(self.collected[count],
                          [{'action': ['pick'],
                            'card': [player2_card],
                            'game_id': [self.game_id],
                            'player_id': [self.player2]},
                           {'card': player2_card,
                            'game_id': [self.game_id],
                            'player_id': self.player2,
                            'type': 'pick'}]);
        count += 1
        del self.collected[count][1]['modified']
        self.assertEquals(self.collected[count],
                          [{'action': ['voting'],
                            'game_id': [self.game_id],
                            'owner_id': [self.owner_id]},
                           {'game_id': [self.game_id], 'type': 'voting'}]);
        count += 1
        del self.collected[count][1]['modified']
        self.assertEquals(self.collected[count],
                          [{'action': ['vote'],
                            'card': [self.winner_card],
                            'game_id': [self.game_id],
                            'player_id': [self.player1]},
                           {'game_id': [self.game_id],
                            'player_id': self.player1,
                            'type': 'vote',
                            'vote': self.winner_card}]);
        count += 1
        del self.collected[count][1]['modified']
        looser_card = self.collected[count][0]['card'][0]
        self.assertEquals(self.collected[count],
                          [{'action': ['vote'],
                            'card': [looser_card],
                            'game_id': [self.game_id],
                            'player_id': [self.player2]},
                           {'game_id': [self.game_id],
                            'player_id': self.player2,
                            'type': 'vote',
                            'vote': looser_card}]);
        count += 1
        del self.collected[count][1]['modified']
        self.assertEquals(self.collected[count],
                          [{'action': ['complete'],
                            'game_id': [self.game_id],
                            'owner_id': [self.owner_id]},
                           {'game_id': [self.game_id],
                            'type': 'complete'}]);
        count += 1
        self.assertEqual(len(self.collected), count)

    def test04_poll(self):
        plugin = example.Plugin(self.service, [ AnotherPlugin() ])
        d = plugin.poll({'modified': [plugin.get_modified()]})
        @defer.inlineCallbacks
        def check(result):
            plugin.ok = True
            self.assertEquals(plugin.counter, 1)
            self.assertTrue(result['info'])
            state, players_list = yield plugin.state({'modified': [0]})
            self.assertEquals(plugin.counter, state['counter'])
            defer.returnValue(result)
        d.addCallback(check)
        plugin.count()
        self.assertEquals(plugin.counter, 0)
        return d
Esempio n. 22
0
class BotTest(unittest.TestCase):

    # initialise our test with a service that we can use during testing and a testing database
    def setUp(self):
        self.database = 'test.sqlite'
        if os.path.exists(self.database):
            os.unlink(self.database)

        self.service = CardstoriesService({'db': self.database,
                                           'plugins-confdir': '../fixture',
                                           'plugins-libdir': 'LIBDIR',
                                           'static': 'STATIC'
                                           })
        self.service.auth = Mock()
        self.service.startService()

    def tearDown(self):
        # kill the service we started before the test
        return self.service.stopService()

    @defer.inlineCallbacks
    def game_create(self):
        """Creates the game, sets the card, and sets the sentence in one step."""
        self.winner_card = winner_card = 5
        sentence = 'SENTENCE'
        self.owner_id = 15
        result = yield self.service.create({'owner_id': [self.owner_id]})
        game_id = result['game_id']
        yield self.service.set_card({'action': ['set_card'],
                                     'card': [winner_card],
                                     'player_id': [self.owner_id],
                                     'game_id': [game_id]})
        yield self.service.set_sentence({'action': ['set_sentence'],
                                         'sentence': [sentence],
                                         'player_id': [self.owner_id],
                                         'game_id': [game_id]})

        defer.returnValue(result)

    @defer.inlineCallbacks
    def game_to_vote(self, game_id):
        yield self.service.voting({ 'action': ['voting'],
                                    'game_id': [game_id],
                                    'owner_id': [self.owner_id] })
        self.assertTrue(self.service.games.has_key(game_id))
        defer.returnValue(True)

    @defer.inlineCallbacks
    def game_to_complete(self, game_id):
        yield self.service.complete({ 'action': ['complete'],
                                      'game_id': [game_id],
                                      'owner_id': [self.owner_id] })
        self.assertFalse(self.service.games.has_key(game_id))
        defer.returnValue(True)

    @defer.inlineCallbacks
    def test01_play_game(self):
        mock_reactor = bot.reactor = Mock() # Don't delay calls

        bot_plugin = bot.Plugin(self.service, [])
        self.assertEquals(bot_plugin.name(), 'bot')
        bots = [bot_plugin.bots[0], bot_plugin.bots[1], bot_plugin.bots[2]]
        self.assertEqual(bots[0].player_id, 2)
        self.assertEqual(bots[1].player_id, 3)
        self.assertEqual(bots[2].player_id, 4)

        # New game
        game = yield self.game_create()
        game_id = game['game_id']
        mock_reactor.callLater.assert_called_once_with(1, bot_plugin.check_need_player, game_id)
        mock_reactor.reset_mock()

        # Only the author in the game
        game, players_ids = yield bots[0].get_game_by_id(game_id)
        self.assertEqual(len(game['players']), 1)

        # Bots don't join by default
        yield bot_plugin.check_need_player(game_id)
        self.assertEqual(len(mock_reactor.callLater.call_args_list), 0)

        # Enable joining
        request = Request(action=['bot'], enable_join=['true'], game_id=[str(game_id)])
        result = yield bot_plugin.preprocess(True, request)
        self.assertFalse(request.args.has_key('action'))
        self.assertTrue(bot_plugin.enable_join[game_id])
        mock_reactor.reset_mock()

        # Bots join after enabling it
        for i in xrange(2):
            yield bot_plugin.check_need_player(game_id)
            self.assertEqual(len(mock_reactor.callLater.call_args_list), 2)
            mock_reactor.reset_mock()

            game, player_ids = yield bots[i].get_game_by_id(game_id)
            self.assertEqual(game['players'][i + 1]['id'], bots[i].player_id)
            self.assertEqual(game['players'][i + 1]['picked'], None)

        # Bots pick a card
        for i in xrange(2):
            yield bots[i].pick(game_id)
            self.assertFalse(mock_reactor.called)

            game, player_ids = yield bots[i].get_game_by_id(game_id, player_id=bots[i].player_id)
            self.assertIsInstance(game['players'][i + 1]['picked'], int)
            self.assertEqual(game['players'][i + 1]['vote'], None)

        # Go to vote phase
        yield self.game_to_vote(game_id)
        self.assertEqual(mock_reactor.callLater.call_args_list,
                         [((3, bots[0].vote, game_id), {}),
                          ((3, bots[1].vote, game_id), {})])
        mock_reactor.reset_mock()

        # A bot should never join or pick at this stage
        joined = yield bots[2].join(game_id)
        self.assertFalse(joined)
        picked = yield bots[2].pick(game_id)
        self.assertFalse(picked)

        # Bots vote
        for i in xrange(2):
            yield bots[i].vote(game_id)
            self.assertFalse(mock_reactor.called)

            game, player_ids = yield bots[i].get_game_by_id(game_id, player_id=bots[i].player_id)
            self.assertIsInstance(game['players'][i + 1]['picked'], int)
            self.assertEqual(game['players'][i + 1]['vote'], '')

        # A bot should never vote at this stage
        joined = yield bots[2].vote(game_id)
        self.assertFalse(joined)

    def test02_brain_not_implemented(self):
        brain = bot.Brain(None)
        self.assertRaises(NotImplementedError, brain.get_all_cards_scores_for_sentence, "Test")

    def test03_brain_weighted_card_choice(self):
        brain = bot.Brain(None)
        ranked_cards = [(1, 1), (2, 10000), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0), (8, 0), (9, 0)]
        chosen_card = brain.weighted_card_choice(ranked_cards)
        self.assertTrue(chosen_card == 1 or chosen_card == 2)

    @defer.inlineCallbacks
    def test04_nlwordmatcherbrain(self):
        bot_plugin = bot.Plugin(self.service, [])
        brain = bot.NLWordMatcherBrain(bot_plugin)

        # Make sure we can record scores for cards that are earned (card # > NCARDS)
        max_cards = 42
        assert CardstoriesGame.NCARDS < max_cards <= CardstoriesGame.NCARDS_EARNED

        ranked_cards = yield brain.sort_cards_by_ranking_for_sentence("word", [1, 2, 3, 42])
        self.assertEquals(ranked_cards, [(3, 4), (2, 3), (1, 2), (max_cards, 1)])