Example #1
0
class MockFrontend(Frontend):
    def __init__(self):
        self._gamedb = None

    def start_game(self, tiktok: Text, phone_number: Text, game_hashtag: Text):
        game_id = FirestoreDB.add_game(
            json_config_path=_TEST_FIRESTORE_INSTANCE_JSON_PATH,
            hashtag=game_hashtag)
        self._gamedb = FirestoreDB(
            json_config_path=_TEST_FIRESTORE_INSTANCE_JSON_PATH,
            game_id=game_id)
        self.join_game(tiktok=tiktok,
                       phone_number=phone_number,
                       game_id=game_id)

    def _verify_game_started(self):
        if not self._gamedb:
            raise TestError('Must call start_game to create a game_id.')

    def join_game(self, tiktok: Text, phone_number: Text,
                  game_id: Text) -> None:
        name = tiktok
        self._verify_game_started()
        self._gamedb.player(name=name,
                            tiktok=tiktok,
                            phone_number=phone_number)

    def submit_entry(self, likes: int, views: int, player_id: Text,
                     tribe_id: Text, challenge_id: Text, team_id: Text,
                     url: Text) -> None:
        self._verify_game_started()
        self._gamedb.add_challenge_entry(
            database.Entry(likes=likes,
                           views=views,
                           player_id=player_id,
                           tribe_id=tribe_id,
                           challenge_id=challenge_id,
                           team_id=team_id,
                           url=url))

    def submit_challenge(self, from_player_id: Text, challenge_name: Text,
                         challenge_message: Text) -> None:
        self._verify_game_started()
Example #2
0
    def test_integration(self):
        test_id = str(uuid.uuid4())
        # Inject a game ID (test uuid) into the gamedb. use a globally unique country code to ensure
        # that only this game gets scheduled.
        game_id = FirestoreDB.add_game(
            json_config_path=_TEST_FIRESTORE_INSTANCE_JSON_PATH,
            hashtag=_TEST_GAME_HASHTAG,
            country_code=f'US-{test_id}')
        gamedb = FirestoreDB(
            json_config_path=_TEST_FIRESTORE_INSTANCE_JSON_PATH,
            game_id=game_id)
        log_message(f'Running integration test for game {game_id}')

        # create an integration test subsystem log stream that specifically captures
        # game inputs and outputs at the SMS boundary.
        test_log_stream = GameIntegrationTestLogStream(game_id=game_id,
                                                       test_id=test_id)

        # add test challenges
        for challenge in _TEST_CHALLENGES:
            gamedb.add_challenge(challenge=challenge)

        # if non-existent, create users associated with players. NOTE: critical for FE code
        # to create users when players sign up.
        for player_info in [*_EMULATED_PLAYERS, *_REAL_PLAYERS]:
            FirestoreDB.add_user(
                json_config_path=_TEST_FIRESTORE_INSTANCE_JSON_PATH,
                name=player_info[0],
                tiktok=player_info[1],
                phone_number=player_info[2])

        # Inject players into gamedb. set the phone number of the players to a known, or emulated device.
        emulated_players = []
        for player_info in _EMULATED_PLAYERS:
            player = gamedb.player(name=player_info[0],
                                   tiktok=player_info[1],
                                   phone_number=player_info[2])
            emulated_players.append(
                EmulatedPlayer(id=player.id,
                               name=player.name,
                               tiktok=player.tiktok,
                               phone_number=player.phone_number,
                               test_stream=test_log_stream,
                               gamedb=gamedb))
        for player_info in _REAL_PLAYERS:
            player = gamedb.player(name=player_info[0],
                                   tiktok=player_info[1],
                                   phone_number=player_info[2])

        # mock the scheduling method in MM service so that we can force schedule
        # after initialization.
        save_check_start_time_fn = MatchmakerService._check_start_time
        check_start_time_fn = mock.MagicMock()
        check_start_time_fn.return_value = False
        MatchmakerService._check_start_time = check_start_time_fn

        # create device emulator for Twilio SMS events. patch this
        # into the game engine class for the test.
        notification_emulator = FakeTwilioSMSNotifier(
            json_config_path=_TEST_TWILIO_SMS_CONFIG_PATH,
            game_id=game_id,
            emulated_devices=emulated_players)
        build_notifier_fn = mock.MagicMock()
        build_notifier_fn.return_value = notification_emulator
        Engine._get_sms_notifier = build_notifier_fn

        # Instantiate a local matchmaker service. make sure all services have the right configs,
        # e.g. twilio should be using the prod service phone number so that it can actually send messages.
        # set the clock mode on (2) to async so that game events happen immediately during testing.
        service = MatchmakerService(
            matchmaker=MatchMakerRoundRobin(),
            region=f'US-{test_id}',
            gamedb=gamedb,
            game_options=GameOptions(
                game_clock_mode=GameClockMode.ASYNC,
                game_wait_sleep_interval_sec=_TEST_SLEEP_INTERVAL,
                multi_tribe_min_tribe_size=2,
                engine_worker_thread_count=5,
                tribe_council_time_sec=_TEST_SLEEP_INTERVAL))
        # mock the MM Twilio client
        service._get_sms_notifier = mock.MagicMock(
            return_value=notification_emulator)
        try:
            service.start_matchmaker_daemon(sleep_seconds=1)
            # force schedule the game in MM (1).
            check_start_time_fn.return_value = True
            MatchmakerService._check_start_time = check_start_time_fn
            while gamedb.game_from_id(game_id).count_players > 1:
                time.sleep(_TEST_SLEEP_INTERVAL)
        finally:
            MatchmakerService._check_start_time = save_check_start_time_fn
            service.set_stop()
            test_dict = test_log_stream.to_dict()
            if _SAVE_TEST_LOGS:
                persisted_test_logs = test_log_stream.persist()
                log_message(persisted_test_logs)
                with open(f'game_logs/stream.{test_id}.json', 'w+') as f:
                    f.write(persisted_test_logs)
            active_players = list()
            for player in gamedb.stream_players(
                    active_player_predicate_value=True):
                active_players.append(player)
            winner = active_players[0]
            found_winner_message = False
            for output in test_dict['outputs']:
                if 'You are the last survivor and WINNER' in output[
                        'message'] and output['name'] == winner.name:
                    found_winner_message = True
            self.assertTrue(found_winner_message)