예제 #1
0
    def test_compile_process(self):
        async def main():
            loop = asyncio.get_running_loop() if sys.version_info >= (3, 7) \
                else asyncio.get_event_loop()
            exec = ExecutionEnvironment(loop)

            diagnostics, rpc_error = await exec.execute(
                exec.process_executor, EBNFServer.compile_EBNF, ('', ))
            json_obj = json.loads(diagnostics)
            assert json_obj[0]['code'] >= ERROR

            diagnostics, rpc_error = await exec.execute(
                exec.process_executor, EBNFServer.compile_EBNF,
                ('document = /.*/', ))
            assert diagnostics == '[]'

            diagnostics, rpc_error = await exec.execute(
                exec.thread_executor, EBNFServer.compile_EBNF, ('', ))
            json_obj = json.loads(diagnostics)
            assert json_obj[0]['code'] >= ERROR

            diagnostics, rpc_error = await exec.execute(
                exec.thread_executor, EBNFServer.compile_EBNF,
                ('document = /.*/', ))
            assert diagnostics == '[]'

            exec.shutdown()

        asyncio_run(main())
예제 #2
0
    def test_initialization_sequence(self):
        self.start_server()

        async def initialization_sequence():
            reader, writer = await asyncio_connect('127.0.0.1', TEST_PORT)
            writer.write(
                json_rpc(
                    'initialize', {
                        'processId': 702,
                        'rootUri': 'file://~/tmp',
                        'capabilities': {}
                    }).encode())
            response = (await reader.read(8192)).decode()
            i = response.find('{')
            res = json.loads(response[i:])
            assert 'result' in res and 'capabilities' in res['result'], str(
                res)

            writer.write(json_rpc('initialized', {}).encode())

            writer.write(json_rpc('custom', {'test': 1}).encode())
            response = (await reader.read(8192)).decode()
            assert response.find('test') >= 0

            writer.close()
            if sys.version_info >= (3, 7): await writer.wait_closed()

        asyncio_run(initialization_sequence())
예제 #3
0
    def test_varying_data_chunk_sizes(self):
        self.start_server()

        async def initialization_sequence():
            reader, writer = await asyncio_connect('127.0.0.1', TEST_PORT)
            writer.write(
                json_rpc(
                    'initialize', {
                        'processId': 702,
                        'rootUri': 'file://~/tmp',
                        'capabilities': {}
                    }).encode())
            response = (await reader.read(8192)).decode()
            i = response.find('{')
            res = json.loads(response[i:])
            assert 'result' in res and 'capabilities' in res['result'], str(
                res)

            # several commands in one chunk
            writer.write(
                json_rpc('initialized', {}).encode() +
                json_rpc('custom', {
                    'test': 1
                }).encode())
            response = (await reader.read(8192)).decode()
            assert response.find('test') >= 0

            data = json_rpc('custom', {'test': 2}).encode()
            i = data.find(b'\n\n')
            assert i > 0, str(data)
            writer.write(data[:i + 2])
            await asyncio.sleep(1)
            writer.write(data[i + 2:])
            response = (await reader.read(8192)).decode()
            assert response.find('test') >= 0

            data = json_rpc('custom', {'test': 3}).encode()
            i = data.find(b'\n\n')
            assert i > 0, str(data)
            writer.write(data[:i + 2])
            await asyncio.sleep(0.1)
            writer.write(data[i + 2:] + json_rpc('custom', {
                'test': 4
            }).encode())
            response = (await reader.read(8192)).decode()
            assert response.find('test') >= 0
            writer.write(b'')
            await writer.drain()
            writer.write_eof()
            await writer.drain()
            writer.close()
            if sys.version_info >= (3, 7): await writer.wait_closed()

        asyncio_run(initialization_sequence())
예제 #4
0
def send_request(request: str, expect_response: bool = True) -> str:
    response = ''

    async def send(request):
        nonlocal response
        reader, writer = await asyncio_connect('127.0.0.1', TEST_PORT)
        writer.write(request.encode())
        if expect_response:
            response = (await reader.read(8192)).decode()
        writer.close()
        if sys.version_info >= (3, 7): await writer.wait_closed()

    asyncio_run(send(request))
    return response
예제 #5
0
    def test_terminate(self):
        """Test different ways of sending a termination message to server:
        http-request, plain-text and json-rpc."""
        async def terminate_server(termination_request, expected_response):
            reader, writer = await asyncio_connect('127.0.0.1', TEST_PORT)
            writer.write(termination_request)
            data = await reader.read(500)
            writer.close()
            if sys.version_info >= (3, 7): await writer.wait_closed()
            assert data.find(expected_response) >= 0, str(data)

        p = None
        try:
            # plain text stop request
            p = spawn_tcp_server('127.0.0.1', TEST_PORT,
                                 (compiler_dummy, set()))
            asyncio_run(
                terminate_server(
                    STOP_SERVER_REQUEST_BYTES,
                    b'DHParser server at 127.0.0.1:%i stopped!' % TEST_PORT))
            assert asyncio_run(has_server_stopped('127.0.0.1', TEST_PORT))

            # http stop request
            p = spawn_tcp_server('127.0.0.1', TEST_PORT,
                                 (compiler_dummy, set()))
            asyncio_run(
                terminate_server(
                    b'GET ' + STOP_SERVER_REQUEST_BYTES + b' HTTP',
                    b'DHParser server at 127.0.0.1:%i stopped!' % TEST_PORT))
            assert asyncio_run(has_server_stopped('127.0.0.1', TEST_PORT))

            # json_rpc stop request
            p = spawn_tcp_server('127.0.0.1', TEST_PORT,
                                 (compiler_dummy, set()))
            jsonrpc = json.dumps({
                "jsonrpc": "2.0",
                "method": STOP_SERVER_REQUEST_BYTES.decode(),
                'id': 1
            })
            asyncio_run(
                terminate_server(
                    jsonrpc.encode(),
                    b'DHParser server at 127.0.0.1:%i stopped!' % TEST_PORT))
            assert asyncio_run(has_server_stopped('127.0.0.1', TEST_PORT))
        finally:
            stop_tcp_server('127.0.0.1', TEST_PORT)
            if p is not None:
                p.join()
예제 #6
0
    def test_server_process(self):
        """Basic Test of server module."""
        async def compile_remote(src):
            reader, writer = await asyncio_connect('127.0.0.1', TEST_PORT)
            writer.write(src.encode())
            data = await reader.read(500)
            writer.close()
            if sys.version_info >= (3, 7): await writer.wait_closed()
            assert data.decode() == "Test", data.decode()

        p = None
        try:
            p = spawn_tcp_server('127.0.0.1', TEST_PORT,
                                 (compiler_dummy, set()))
            asyncio_run(compile_remote('Test'))
        finally:
            stop_tcp_server('127.0.0.1', TEST_PORT)
            if p is not None:
                p.join()
예제 #7
0
    def test_reader_writer_simple(self):
        async def main():
            self.writer.write(b'Hello\n')
            await self.writer.drain()
            data = await self.reader.read()
            self.writer.close()
            return data

        data = asyncio_run(main())
        assert data == b'Hello\n', str(data)
        assert self.pipe.closed
예제 #8
0
    def test_service_call(self):
        async def identify_server():
            main_reader, main_writer = await asyncio_connect(
                '127.0.0.1', TEST_PORT)
            main_writer.write(IDENTIFY_REQUEST.encode())
            data = await main_reader.read(500)
            assert b'already connected' not in data

            service_reader, service_writer = await asyncio_connect(
                '127.0.0.1', TEST_PORT)
            service_writer.write(IDENTIFY_REQUEST.encode())
            data = await service_reader.read(500)
            assert b'already connected' in data
            await asyncio.sleep(0.01)
            assert service_reader.at_eof()
            service_writer.close()
            if sys.version_info >= (3, 7): await service_writer.wait_closed()

            service_reader, service_writer = await asyncio_connect(
                '127.0.0.1', TEST_PORT)
            service_writer.write(json_rpc('identify', {}).encode())
            data = await service_reader.read(500)
            assert b'already connected' in data
            await asyncio.sleep(0.01)
            assert service_reader.at_eof()
            service_writer.close()
            if sys.version_info >= (3, 7): await service_writer.wait_closed()

            main_writer.close()
            if sys.version_info >= (3, 7): await main_writer.wait_closed()

        p = None
        try:
            p = spawn_tcp_server('127.0.0.1', TEST_PORT)
            asyncio_run(identify_server())
        finally:
            stop_tcp_server('127.0.0.1', TEST_PORT)
            if p is not None:
                p.join()
예제 #9
0
    def test_spawn(self):
        spawn_tcp_server('127.0.0.1', TEST_PORT)

        async def identify():
            try:
                reader, writer = await asyncio_connect('127.0.0.1', TEST_PORT)
                writer.write(IDENTIFY_REQUEST.encode())
                data = await reader.read(500)
                await writer.drain()
                writer.close()
                if sys.version_info >= (3, 7): await writer.wait_closed()
                return data.decode()
            except ConnectionRefusedError:
                return ''

        result = asyncio_run(identify())
        assert result.startswith('DHParser'), result
예제 #10
0
    def test_identify(self):
        """Test server's 'identify/'-command."""
        async def send_request(request):
            reader, writer = await asyncio_connect('127.0.0.1', TEST_PORT)
            writer.write(
                request.encode() if isinstance(request, str) else request)
            data = await reader.read(500)
            await writer.drain()
            writer.close()
            if sys.version_info >= (3, 7): await writer.wait_closed()
            return data.decode()

        p = None
        try:
            from timeit import timeit
            p = spawn_tcp_server('127.0.0.1', TEST_PORT, compiler_dummy)
            result = asyncio_run(send_request(IDENTIFY_REQUEST))
            assert isinstance(result,
                              str) and result.startswith('DHParser'), result
        finally:
            stop_tcp_server('127.0.0.1', TEST_PORT)
            if p is not None:
                p.join()
예제 #11
0
    def test_server_process(self):
        """Basic Test of server module."""
        async def compile_remote(src, reader, writer) -> bytes:
            writer.write(add_header(src.encode()))
            await writer.drain()
            data = await read_full_content(reader)
            # writer.close()
            # if sys.version_info >= (3, 7):  await writer.wait_closed()
            header, data, backlog = split_header(data)
            return data.decode()
            # assert data.decode() == "Test", data.decode()

        p = None
        try:
            p = spawn_stream_server(self.readerA, self.writerB,
                                    (mock_compiler, set()), threading.Thread)
            data = asyncio_run(
                compile_remote('Test', self.readerB, self.writerA))
            assert data == "tEST"
        finally:
            if p is not None:
                stop_stream_server(self.readerB, self.writerA)
                p.join()
예제 #12
0
    def test_reader_writer(self):
        async def write(writer):
            writer.write(JSONRPC_HEADER_BYTES % len(IDENTIFY_REQUEST_BYTES) +
                         IDENTIFY_REQUEST_BYTES)
            await writer.drain()

        async def read(reader):
            return await read_full_content(reader)

        async def main():
            if sys.version_info >= (3, 7):
                read_task = asyncio.create_task(read(self.reader))
                write_task = asyncio.create_task(write(self.writer))
            else:
                read_task = asyncio.ensure_future(read(self.reader))
                write_task = asyncio.ensure_future(write(self.writer))
            data = await read_task
            await write_task
            self.writer.close()
            return data

        data = asyncio_run(main())
        assert data == b'Content-Length: 10\r\n\r\nidentify()', str(data)
        assert self.pipe.closed
예제 #13
0
    def test_initialize(self):
        self.start_server()

        async def sequence_test():
            reader, writer = await asyncio_connect('127.0.0.1', TEST_PORT)

            async def send(request: str, expect_response: bool = True) -> str:
                writer.write(request.encode())
                await writer.drain()
                if expect_response:
                    return (await reader.read(8192)).decode()
                return ''

            response = await send(
                json_rpc(
                    'initialize', {
                        'processId': 701,
                        'rootUri': 'file://~/tmp',
                        'capabilities': {}
                    }))
            i = response.find('{') - 1
            res = json.loads(response[i:])
            assert 'result' in res and 'capabilities' in res['result'], str(
                res)

            r2, w2 = await asyncio_connect('127.0.0.1', TEST_PORT)
            w2.write(
                json_rpc(
                    'initialize', {
                        'processId': 701,
                        'rootUri': 'file://~/tmp',
                        'capabilities': {}
                    }).encode())
            fail = await r2.read(8192)
            assert b'error' in fail and b'already connected' in fail
            w2.write_eof()
            w2.close()
            if sys.version_info >= (3, 7): await w2.wait_closed()

            r2, w2 = await asyncio_connect('127.0.0.1', TEST_PORT)
            w2.write(json_rpc('custom', {}).encode())
            fail = await r2.read(8192)
            assert b'result' not in fail
            assert b'not a service function' in fail
            w2.write_eof()
            w2.close()
            if sys.version_info >= (3, 7): await w2.wait_closed()

            response = await send(json_rpc('custom', {}))
            assert response.find('error') >= 0

            response = await send(json_rpc('initialized', {}),
                                  expect_response=False)
            assert response == '', response

            response = await send(json_rpc('custom', {'test': 1}))
            assert response.find('test') >= 0, str(response)

            response = await send(json_rpc('check', {}))
            assert response.find('701') >= 0

            response = await send(json_rpc('non_existant_function', {}))
            assert response.find('-32601') >= 0  # method not found
            response = await send(
                json_rpc('non_existant_function', {
                    'a': 1,
                    'b': 2,
                    'c': 3
                }))
            assert response.find('-32601') >= 0  # method not found

            # test plain-data call
            response = await send('custom(1)')
            assert response.find('1') >= 0

            # test plain-data false call
            response = await send('non_existant_function()')
            assert response.find('No function named "non_extistant_function"')
            response = await send('non_existant_function(1)')
            assert response.find('No function named "non_extistant_function"')

            response = await send(json_rpc('shutdown', {}))
            assert response.find('error') < 0

            # after shutdown, any function call except "exit()" should yield error
            response = await send(json_rpc('custom', {}))
            assert response.find('error') >= 0

            response = await send(json_rpc('exit', {}))
            assert response == '', response

            writer.close()
            if sys.version_info >= (3, 7): await writer.wait_closed()

        asyncio_run(sequence_test())
예제 #14
0
    def test_long_running_task(self):
        """Test, whether delegation of (long-running) tasks to
        processes or threads works."""
        sequence = []
        if self.spawn:
            SLOW, FAST = 0.1, 0.01
        else:
            SLOW, FAST = 0.02, 0.001

        async def run_tasks():
            def extract_result(data: bytes):
                header, data, backlog = split_header(data)
                return json.loads(data.decode())['result']

            reader, writer = await asyncio_connect('127.0.0.1', TEST_PORT)
            sequence.append(SLOW)
            sequence.append(FAST)
            writer.write(json_rpc('long_running', {'duration': SLOW}).encode())
            writer.write(json_rpc('long_running', {'duration': FAST}).encode())
            await writer.drain()
            sequence.append(extract_result(await reader.read(500)))
            sequence.append(extract_result(await reader.read(500)))
            writer.close()
            if sys.version_info >= (3, 7): await writer.wait_closed()

        if sys.version_info >= (3, 6):
            p = None
            try:
                p = spawn_tcp_server(
                    '127.0.0.1', TEST_PORT,
                    (long_running, frozenset(['long_running']), frozenset(),
                     connection_cb_dummy, 'Long-Running-Test', False))
                asyncio_run(run_tasks())
                assert sequence == [SLOW, FAST, FAST, SLOW], str(sequence)
            finally:
                stop_tcp_server('127.0.0.1', TEST_PORT)
                if p is not None:
                    p.join()
                sequence = []
            p = None
            try:
                p = spawn_tcp_server(
                    '127.0.0.1', TEST_PORT,
                    (long_running, frozenset(), frozenset(['long_running']),
                     connection_cb_dummy, 'Long-Running-Test', False))
                asyncio_run(run_tasks())
                assert sequence == [SLOW, FAST, FAST, SLOW], str(sequence)
            finally:
                stop_tcp_server('127.0.0.1', TEST_PORT)
                if p is not None:
                    p.join()
                sequence = []
        p = None
        try:
            p = spawn_tcp_server(
                '127.0.0.1', TEST_PORT,
                (long_running, frozenset(), frozenset(), connection_cb_dummy,
                 'Long-Running-Test', False))
            asyncio_run(run_tasks())
            assert sequence.count(SLOW) == 2 and sequence.count(FAST) == 2
        finally:
            stop_tcp_server('127.0.0.1', TEST_PORT)
            if p is not None:
                p.join()
            sequence = []
예제 #15
0
    def test_server_processes(self):
        # This test takes a few seconds!
        async def test_interaction(reader, writer) -> bool:
            async def send(json_obj: str):
                writer.write(add_header(json.dumps(json_obj).encode()))
                await writer.drain()

            async def receive() -> str:
                package = await read_full_content(reader)
                header, raw_data, backlog = split_header(package)
                return json.loads(raw_data.decode())

            publishDiagnosticsCounter = 0

            await send(initialize_request)
            data = await receive()
            assert "result" in data and data['id'] == initialize_request['id']
            await send(initialized_notification)
            await send(didOpen_notification)
            await asyncio.sleep(EBNFServer.RECOMPILE_DELAY + 2)
            await send(didChange_notifictaion_1)
            await asyncio.sleep(0.1)
            await send(completion_request)
            await asyncio.sleep(EBNFServer.RECOMPILE_DELAY + 0.5)
            await send(didSave_notification_1)
            await asyncio.sleep(0.1)
            await send(didChange_notification_2)
            await asyncio.sleep(EBNFServer.RECOMPILE_DELAY + 0.5)
            await send(didSave_notification_2)
            await asyncio.sleep(0.1)
            data = await receive()
            while 'method' in data:
                assert data['method'] == 'textDocument/publishDiagnostics'
                publishDiagnosticsCounter += 1
                data = await receive()
            assert publishDiagnosticsCounter == 1
            assert 'id' in data and data['id'] == completion_request['id']
            while self.pipeB.data_available():
                data = await receive()
                if 'method' in data:
                    assert data['method'] == 'textDocument/publishDiagnostics'
                    publishDiagnosticsCounter += 1
                await asyncio.sleep(0.1)
            assert publishDiagnosticsCounter == 3
            await send(shutdown_request)
            data = await receive()
            assert 'id' in data and data['id'] == shutdown_request['id']
            await send(exit_notification)
            await asyncio.sleep(0.5)

        p = None
        try:
            p = spawn_stream_server(
                self.readerA, self.writerB, {
                    'rpc_functions': self.lsp_table,
                    'cpu_bound': set(self.EBNF_lsp.cpu_bound.lsp_table.keys()),
                    'blocking': set(self.EBNF_lsp.blocking.lsp_table.keys()),
                    'connection_callback': self.EBNF_lsp.connect,
                    'server_name': 'EBNFServer',
                    'strict_lsp': True
                }, threading.Thread)
            asyncio_run(test_interaction(self.readerB, self.writerA))
        finally:
            if p is not None:
                value_error = stop_stream_server(self.readerB, self.writerA)
                # assert value_error, "server hasn't been shutdown orderly"
                p.join()