############################################################################ # Copyright(c) Open Law Library. All rights reserved. # # See ThirdPartyNotices.txt in the project root for additional notices. # # # # Licensed under the Apache License, Version 2.0 (the "License") # # you may not use this file except in compliance with the License. # # You may obtain a copy of the License at # # # # http: // www.apache.org/licenses/LICENSE-2.0 # # # # Unless required by applicable law or agreed to in writing, software # # distributed under the License is distributed on an "AS IS" BASIS, # # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ import asyncio import pathlib import sys from typing import Union import pytest from pygls import IS_PYODIDE from pygls.client import JsonRPCClient from pygls.exceptions import JsonRpcException, PyglsError SERVERS = pathlib.Path(__file__).parent / "servers" @pytest.mark.asyncio @pytest.mark.skipif(IS_PYODIDE, reason="Subprocesses are not available on pyodide.") async def test_client_detect_server_exit(): """Ensure that the client detects when the server process exits.""" class TestClient(JsonRPCClient): server_exit_called = False async def server_exit(self, server: asyncio.subprocess.Process): self.server_exit_called = True assert server.returncode == 0 client = TestClient() await client.start_io(sys.executable, "-c", "print('Hello, World!')") await asyncio.sleep(1) await client.stop() message = "Expected the `server_exit` method to have been called." assert client.server_exit_called, message @pytest.mark.asyncio @pytest.mark.skipif(IS_PYODIDE, reason="Subprocesses are not available on pyodide.") async def test_client_detect_invalid_json(): """Ensure that the client can detect the case where the server returns invalid json.""" class TestClient(JsonRPCClient): report_error_called = False future = None def report_server_error( self, error: Exception, source: Union[PyglsError, JsonRpcException] ): self.report_error_called = True self.future.cancel() self._server.kill() self._stop_event.set() assert "Unterminated string" in str(error) client = TestClient() await client.start_io(sys.executable, str(SERVERS / "invalid_json.py")) future = client.protocol.send_request_async("method/name", {}) client.future = future try: await future except asyncio.CancelledError: pass # Ignore the exception generated by cancelling the future finally: await client.stop() assert_message = "Expected `report_server_error` to have been called" assert client.report_error_called, assert_message @pytest.mark.asyncio @pytest.mark.skipif(IS_PYODIDE, reason="Subprocesses are not available on pyodide.") async def test_client_large_responses(): """Ensure that the client can correctly handle large responses from a server.""" client = JsonRPCClient() await client.start_io(sys.executable, str(SERVERS / "large_response.py")) result = await client.protocol.send_request_async("get/numbers", {}, msg_id=1) assert len(result.numbers) == 100_000 await client.stop()