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
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" } }]
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" } } }]
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" } }]
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())
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()))
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()
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()
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()
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()
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
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()
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)