async def test_prepare_get_subscription_games_context_error(
        plugin, read, write):
    request_id = "31415"
    error_details = "Unexpected backend error"
    error_message, error_code = BackendError().message, BackendError().code
    plugin.prepare_subscription_games_context.side_effect = BackendError(
        error_details)
    request = {
        "jsonrpc": "2.0",
        "id": request_id,
        "method": "start_subscription_games_import",
        "params": {
            "subscription_names": ["sub_a", "sub_b"]
        }
    }
    read.side_effect = [
        async_return_value(create_message(request)),
        async_return_value(b"", 10)
    ]
    await plugin.run()

    assert get_messages(write) == [{
        "jsonrpc": "2.0",
        "id": request_id,
        "error": {
            "code": error_code,
            "message": error_message,
            "data": error_details
        }
    }]
    async def authenticate(self, stored_credentials=None):
        #check stored credentials
        if stored_credentials:
            auth_result = await self._gw2_api.do_auth_apikey(stored_credentials['api_key'])
            if auth_result != gw2.gw2_api.GW2AuthorizationResult.FINISHED:
                self.__logger.warning('authenticate: stored credentials are invalid')
                raise InvalidCredentials()

            return Authentication(self._gw2_api.get_account_id(), self._gw2_api.get_account_name())

        #new auth
        self.__authserver = gw2.gw2_authserver.Gw2AuthServer(self._gw2_api)
        self.__logger.info('authenticate: no stored credentials')

        AUTH_PARAMS = {
            "window_title": "Login to Guild Wars 2",
            "window_width": 640,
            "window_height": 460,
            "start_uri": self.__authserver.get_uri(),
            "end_uri_regex": '.*finished'
        }
        if not await self.__authserver.start():
            self.__logger.error('authenticate: failed to start auth server', exc_info=True)
            raise BackendError()
        return NextStep("web_session", AUTH_PARAMS)
async def test_subscription_games_error(authenticated_plugin, backend_client):
    backend_client.get_games_in_subscription.side_effect = BackendError()

    context = await authenticated_plugin.prepare_subscription_games_context([SUBSCRIPTION_OWNED_ID])
    with pytest.raises(BackendError):
        async for _ in authenticated_plugin.get_subscription_games(SUBSCRIPTION_OWNED_ID, context):
            pass
    async def request(self, method, url, *args, **kwargs):
        try:
            response = await self._session.request(method, url, *args,
                                                   **kwargs)
        except asyncio.TimeoutError:
            raise BackendTimeout()
        except aiohttp.ServerDisconnectedError:
            raise BackendNotAvailable()
        except aiohttp.ClientConnectionError:
            raise NetworkError()
        except aiohttp.ContentTypeError:
            raise UnknownBackendResponse()
        except aiohttp.ClientError:
            logging.exception(
                "Caught exception while running {} request for {}".format(
                    method, url))
            raise UnknownError()
        if response.status == HTTPStatus.UNAUTHORIZED:
            raise AuthenticationRequired()
        if response.status == HTTPStatus.FORBIDDEN:
            raise AccessDenied()
        if response.status == HTTPStatus.SERVICE_UNAVAILABLE:
            raise BackendNotAvailable()
        if response.status == HTTPStatus.TOO_MANY_REQUESTS:
            raise TooManyRequests()
        if response.status >= 500:
            raise BackendError()
        if response.status >= 400:
            logging.warning(
                "Got status {} while running {} request for {}".format(
                    response.status, method, url))
            raise UnknownError()

        return response
Beispiel #5
0
async def test_prepare_get_unlocked_achievements_context_error(
        plugin, read, write):
    plugin.prepare_achievements_context.side_effect = BackendError()
    request = {
        "jsonrpc": "2.0",
        "id": "3",
        "method": "start_achievements_import",
        "params": {
            "game_ids": ["14"]
        }
    }
    read.side_effect = [
        async_return_value(create_message(request)),
        async_return_value(b"", 10)
    ]

    await plugin.run()

    assert get_messages(write) == [{
        "jsonrpc": "2.0",
        "id": "3",
        "error": {
            "code": 4,
            "message": "Backend error"
        }
    }]
Beispiel #6
0
async def test_prepare_get_user_presence_context_error(plugin, read, write):
    request_id = "31415"
    plugin.prepare_user_presence_context.side_effect = BackendError()
    request = {
        "jsonrpc": "2.0",
        "id": request_id,
        "method": "start_user_presence_import",
        "params": {
            "user_id_list": ["6"]
        }
    }
    read.side_effect = [
        async_return_value(create_message(request)),
        async_return_value(b"", 10)
    ]
    await plugin.run()

    assert get_messages(write) == [{
        "jsonrpc": "2.0",
        "id": request_id,
        "error": {
            "code": 4,
            "message": "Backend error",
            "data": {
                "internal_type": "BackendError"
            }
        }
    }]
Beispiel #7
0
def handle_exception():
    """
    Context manager translating network related exceptions
    to custom :mod:`~galaxy.api.errors`.
    """
    try:
        yield
    except asyncio.TimeoutError:
        raise BackendTimeout()
    except aiohttp.ServerDisconnectedError:
        raise BackendNotAvailable()
    except aiohttp.ClientConnectionError:
        raise NetworkError()
    except aiohttp.ContentTypeError as error:
        raise UnknownBackendResponse(error.message)
    except aiohttp.ClientResponseError as error:
        if error.status == HTTPStatus.UNAUTHORIZED:
            raise AuthenticationRequired(error.message)
        if error.status == HTTPStatus.FORBIDDEN:
            raise AccessDenied(error.message)
        if error.status == HTTPStatus.SERVICE_UNAVAILABLE:
            raise BackendNotAvailable(error.message)
        if error.status == HTTPStatus.TOO_MANY_REQUESTS:
            raise TooManyRequests(error.message)
        if error.status >= 500:
            raise BackendError(error.message)
        if error.status >= 400:
            logger.warning("Got status %d while performing %s request for %s",
                           error.status, error.request_info.method,
                           str(error.request_info.url))
            raise UnknownError(error.message)
    except aiohttp.ClientError as e:
        logger.exception("Caught exception while performing request")
        raise UnknownError(repr(e))
async def test_prepare_get_os_compatibility_context_error(plugin, read, write):
    request_id = "31415"
    plugin.prepare_os_compatibility_context.side_effect = BackendError()
    request = {
        "jsonrpc": "2.0",
        "id": request_id,
        "method": "start_os_compatibility_import",
        "params": {
            "game_ids": ["6"]
        }
    }
    read.side_effect = [
        async_return_value(create_message(request)),
        async_return_value(b"", 10)
    ]
    await plugin.run()

    assert get_messages(write) == [{
        "jsonrpc": "2.0",
        "id": request_id,
        "error": {
            "code": 4,
            "message": "Backend error"
        }
    }]
Beispiel #9
0
    async def authenticate(self, stored_credentials=None):
        if not stored_credentials:
            logging.info('No stored credentials')

            AUTH_PARAMS = {
                "window_title": "Login to Guild Wars 2",
                "window_width": 640,
                "window_height": 460,
                "start_uri": self._gw2_api.auth_server_uri(),
                "end_uri_regex": '.*finished'
            }

            if not self._gw2_api.auth_server_start():
                raise BackendError()

            return NextStep("web_session", AUTH_PARAMS)

        else:
            auth_passed = self._gw2_api.do_auth_apikey(
                stored_credentials['api_key'])
            if not auth_passed:
                logging.warning(
                    'plugin/authenticate: stored credentials are invalid')
                raise InvalidCredentials()

            return Authentication(self._gw2_api.get_account_id(),
                                  self._gw2_api.get_account_name())
Beispiel #10
0
async def test_start_achievements_import(plugin, write, mocker):
    game_achievements_import_success = mocker.patch.object(
        plugin, "game_achievements_import_success")
    game_achievements_import_failure = mocker.patch.object(
        plugin, "game_achievements_import_failure")
    achievements_import_finished = mocker.patch.object(
        plugin, "achievements_import_finished")

    game_ids = ["1", "5", "9"]
    error = BackendError()
    achievements = [
        Achievement(achievement_id="lvl10", unlock_time=1548421241),
        Achievement(achievement_name="Got level 20", unlock_time=1548422395)
    ]
    plugin.get_unlocked_achievements.coro.side_effect = [
        achievements, [], error
    ]
    await plugin.start_achievements_import(game_ids)

    with pytest.raises(ImportInProgress):
        await plugin.start_achievements_import(["4", "8"])

    # wait until all tasks are finished
    for _ in range(4):
        await asyncio.sleep(0)

    plugin.get_unlocked_achievements.coro.assert_has_calls(
        [call("1"), call("5"), call("9")])
    game_achievements_import_success.assert_has_calls(
        [call("1", achievements), call("5", [])])
    game_achievements_import_failure.assert_called_once_with("9", error)
    achievements_import_finished.assert_called_once_with()
    async def authenticate(self, stored_credentials=None):
        if not stored_credentials:
            logging.info('No stored credentials')

            AUTH_PARAMS = {
                "window_title": "Login to Wargaming",
                "window_width": 640,
                "window_height": 460,
                "start_uri": self._wgc.auth_server_uri(),
                "end_uri_regex": '.*finished'
            }
            if not self._wgc.auth_server_start():
                raise BackendError()

            return NextStep("web_session", AUTH_PARAMS)

        else:
            auth_passed = self._wgc.login_info_set(stored_credentials)
            if not auth_passed:
                logging.warning('Stored credentials are invalid')
                raise InvalidCredentials()

            return Authentication(
                self._wgc.account_id(), '%s_%s' %
                (self._wgc.account_realm(), self._wgc.account_nickname()))
    async def authenticate(self, stored_credentials=None):
        authserver = self._wgc.get_auth_server()
        wgni = self._wgc.get_wgni_client()

        if not stored_credentials:
            self._logger.info('plugin/authenticate: no stored credentials')

            AUTH_PARAMS = {
                "window_title": "Login to Wargaming",
                "window_width": 640,
                "window_height": 460,
                "start_uri": authserver.get_uri(),
                "end_uri_regex": '.*finished'
            }
            if not await authserver.start():
                raise BackendError()

            return NextStep("web_session", AUTH_PARAMS)

        else:
            auth_passed = await wgni.login_info_set(stored_credentials)
            if not auth_passed:
                self._logger.warning(
                    'plugin/authenticate: stored credentials are invalid')
                raise InvalidCredentials()

            return Authentication(
                wgni.get_account_id(), '%s_%s' %
                (wgni.get_account_realm(), wgni.get_account_nickname()))
Beispiel #13
0
async def test_get_achievements_error(authenticated_plugin, backend_client):
    context = {
        "236850": GameTime(game_id="236850", time_played=86820, last_played_time=1549385500),
        "281990": GameTime(game_id="281990", time_played=78, last_played_time=1549385500)
    }
    backend_client.get_achievements.side_effect = BackendError()
    with pytest.raises(BackendError):
        await authenticated_plugin.get_unlocked_achievements("281990", context)
    async def install_game(self, game_id):
        instances = self._wgc.get_owned_applications()

        if game_id not in instances:
            logging.warning(
                'plugin/install_games: failed to find the application with id %s'
                % game_id)
            raise BackendError()

        instances[game_id].install_application()
Beispiel #15
0
 def handle_status_code(status_code):
     if status_code == HTTPStatus.UNAUTHORIZED:
         raise AuthenticationRequired()
     if status_code == HTTPStatus.FORBIDDEN:
         raise AccessDenied()
     if status_code == HTTPStatus.SERVICE_UNAVAILABLE:
         raise BackendNotAvailable()
     if status_code >= 500:
         raise BackendError()
     if status_code >= 400:
         raise UnknownError()
Beispiel #16
0
    async def do_request(self,
                         method,
                         url,
                         data=None,
                         json=True,
                         headers=None,
                         ignore_failure=False):
        loop = asyncio.get_event_loop()
        if not headers:
            headers = self._authentication_client.session.headers
        try:
            if data is None:
                data = {}
            params = {
                "method": method,
                "url": url,
                "data": data,
                "timeout": self._authentication_client.timeout,
                "headers": headers
            }
            try:
                response = await loop.run_in_executor(
                    None,
                    functools.partial(
                        self._authentication_client.session.request, **params))
            except requests.Timeout:
                raise BackendTimeout()

            if not ignore_failure:
                if response.status_code == HTTPStatus.UNAUTHORIZED:
                    raise AuthenticationRequired()
                if response.status_code == HTTPStatus.FORBIDDEN:
                    raise AccessDenied()
                if response.status_code == HTTPStatus.SERVICE_UNAVAILABLE:
                    raise BackendNotAvailable()
                if response.status_code >= 500:
                    raise BackendError()
                if response.status_code >= 400:
                    raise UnknownError()

            if json:
                return response.json()
            else:
                return response

        except Exception as e:
            log.exception(
                f"Request exception: {str(e)}; url: {url}, method: {method}, data: {data}, headers: {headers}"
            )
            raise
    async def install_game(self, game_id: str) -> None:
        if not self._wgc.is_wgc_installed():
            webbrowser.open(self._wgc.get_wgc_install_url())
            return

        wgni = self._wgc.get_wgni_client()
        instances = await self._wgc.get_owned_applications(
            wgni.get_account_realm())
        if game_id not in instances:
            self._logger.warning(
                'plugin/install_games: failed to find the application with id %s'
                % game_id)
            raise BackendError()

        await instances[game_id].install_application()
Beispiel #18
0
    async def _do_request(self, method, url, *args, **kwargs):
        loop = asyncio.get_running_loop()
        r = await loop.run_in_executor(None, functools.partial(self.session.request, method, url, *args, **kwargs))
        log.info(f"{r.status_code}: response from endpoint {url}")

        if r.status_code in (HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN):
            raise AccessDenied()
        if r.status_code == HTTPStatus.SERVICE_UNAVAILABLE:
            raise BackendNotAvailable()
        if r.status_code >= 500:
            raise BackendError()
        if r.status_code >= 400:
            raise UnknownError()
        
        j = r.json()  # all ubi endpoints return jsons
        return j
async def test_start_game_times_import_failure(plugin, write, mocker):
    game_time_import_failure = mocker.patch.object(plugin, "game_time_import_failure")
    game_times_import_finished = mocker.patch.object(plugin, "game_times_import_finished")

    game_ids = ["1", "5"]
    error = BackendError()
    plugin.get_game_times.coro.side_effect = error

    await plugin.start_game_times_import(game_ids)

    # wait until all tasks are finished
    for _ in range(4):
        await asyncio.sleep(0)

    plugin.get_game_times.coro.assert_called_once_with()

    assert game_time_import_failure.mock_calls == [call("1", error), call("5", error)]
    game_times_import_finished.assert_called_once_with()
Beispiel #20
0
    async def _request(self, method, *args, **kwargs):
        try:
            response = await self._session.request(method, *args, **kwargs)
        except asyncio.TimeoutError:
            raise BackendTimeout()
        except aiohttp.ClientConnectionError:
            raise NetworkError()
        logging.debug(f"Request response status: {response.status}")
        if response.status == HTTPStatus.UNAUTHORIZED:
            raise AuthenticationRequired()
        if response.status == HTTPStatus.FORBIDDEN:
            raise AccessDenied()
        if response.status == HTTPStatus.SERVICE_UNAVAILABLE:
            raise BackendNotAvailable()
        if response.status >= 500:
            raise BackendError()
        if response.status >= 400:
            raise UnknownError()

        return response
Beispiel #21
0
async def test_prepare_get_game_library_settings_context_error(plugin, read, write):
    plugin.prepare_game_library_settings_context.side_effect = BackendError()
    request = {
        "jsonrpc": "2.0",
        "id": "3",
        "method": "start_game_library_settings_import",
        "params": {
            "game_ids": ["6"]
        }
    }
    read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)]
    await plugin.run()

    assert get_messages(write) == [
        {
            "jsonrpc": "2.0",
            "id": "3",
            "error": {
                "code": 4,
                "message": "Backend error",
                "data": {"internal_type": "BackendError"}
            }
        }
    ]
async def test_subscription_games_context_error(authenticated_plugin):
    authenticated_plugin.client.get_subscription = AsyncMock()
    authenticated_plugin.client.get_subscription.side_effect = BackendError()

    with pytest.raises(BackendError):
        await authenticated_plugin.prepare_subscription_games_context(['Uplay+'])
    protocol_client.close.return_value = async_return_value(None)
    protocol_client.wait_closed.return_value = async_return_value(None)
    websocket.close.return_value = async_return_value(None)
    websocket.wait_closed.return_value = async_return_value(None)
    await client.run()
    assert servers_cache.get.call_count == 2
    assert protocol_client.authenticate.call_count == 2
    assert protocol_client.run.call_count == 2


@pytest.mark.asyncio
@pytest.mark.parametrize(
    "exception",
    [BackendNotAvailable(),
     BackendTimeout(),
     BackendError(),
     NetworkError()])
async def test_servers_cache_retry(client, protocol_client, backend_client,
                                   servers_cache, websocket, mocker,
                                   exception):
    servers_cache.get.side_effect = [
        async_raise(exception),
        async_return_value(["wss://abc.com/websocket"])
    ]
    sleep = mocker.patch("protocol.websocket_client.asyncio.sleep",
                         side_effect=lambda x: async_return_value(None))
    backend_client.get_authentication_data.return_value = STEAM_ID, ACCOUNT_NAME, TOKEN
    protocol_client.authenticate.return_value = async_return_value(None)
    protocol_client.run.return_value = async_raise(
        websockets.ConnectionClosedOK(1000, ""), 10)
    await client.run()
Beispiel #24
0
        async_raise(websockets.ConnectionClosedError(1002, ""), 10),
        async_raise(websockets.ConnectionClosedOK(1000, ""), 10)
    ]
    protocol_client.close.return_value = async_return_value(None)
    protocol_client.wait_closed.return_value = async_return_value(None)
    websocket.close.return_value = async_return_value(None)
    websocket.wait_closed.return_value = async_return_value(None)
    await client.run()
    assert servers_cache.get.call_count == 2
    assert protocol_client.authenticate.call_count == 2
    assert protocol_client.run.call_count == 2


@pytest.mark.asyncio
@pytest.mark.parametrize("exception", [
    BackendNotAvailable(), BackendTimeout(), BackendError(), NetworkError()
])
async def test_servers_cache_retry(
    client, protocol_client, backend_client, servers_cache, websocket, mocker, exception
):
    servers_cache.get.side_effect = [
        async_raise(exception),
        async_return_value(["wss://abc.com/websocket"])
    ]
    sleep = mocker.patch("protocol.websocket_client.asyncio.sleep", side_effect=lambda x: async_return_value(None))
    backend_client.get_authentication_data.return_value = STEAM_ID, ACCOUNT_NAME, TOKEN
    protocol_client.authenticate.return_value = async_return_value(None)
    protocol_client.run.return_value = async_raise(websockets.ConnectionClosedOK(1000, ""), 10)
    await client.run()
    sleep.assert_any_call(RECONNECT_INTERVAL_SECONDS)