Example #1
0
 def setup(self):
     self.pipeA = MockStream('pipeA')
     self.pipeB = MockStream('pipeB')
     self.readerA = StreamReaderProxy(self.pipeA)
     self.writerA = StreamWriterProxy(self.pipeA)
     self.readerB = StreamReaderProxy(self.pipeB)
     self.writerB = StreamWriterProxy(self.pipeB)
Example #2
0
 def setup(self):
     self.EBNF_lsp = EBNFServer.EBNFLanguageServerProtocol()
     self.lsp_table = self.EBNF_lsp.lsp_fulltable.copy()
     self.lsp_table.setdefault('default', EBNFParser.compile_src)
     self.pipeA = MockStream('pipeA')
     self.pipeB = MockStream('pipeB')
     self.readerA = StreamReaderProxy(self.pipeA)
     self.writerA = StreamWriterProxy(self.pipeA)
     self.readerB = StreamReaderProxy(self.pipeB)
     self.writerB = StreamWriterProxy(self.pipeB)
Example #3
0
class TestServer:
    def setup(self):
        self.pipeA = MockStream('pipeA')
        self.pipeB = MockStream('pipeB')
        self.readerA = StreamReaderProxy(self.pipeA)
        self.writerA = StreamWriterProxy(self.pipeA)
        self.readerB = StreamReaderProxy(self.pipeB)
        self.writerB = StreamWriterProxy(self.pipeB)

    def teardown(self):
        self.writerA.close()
        self.writerB.close()

    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()
Example #4
0
def run_server(host, port, log_path=None):
    """
    Starts a new atfServer. If `port` is already occupied, different
    ports will be tried.
    """
    global KNOWN_HOST, KNOWN_PORT
    global scriptpath, servername

    from multiprocessing import set_start_method
    # 'forkserver' or 'spawn' required to avoid broken process pools
    if sys.platform.lower().startswith('linux'): set_start_method('forkserver')
    else: set_start_method('spawn')

    grammar_src = os.path.abspath(__file__).replace('Server.py', '.ebnf')
    dhparserdir = os.path.abspath(os.path.join(scriptpath, '../..'))
    if scriptpath not in sys.path:
        sys.path.append(scriptpath)
    if dhparserdir not in sys.path:
        sys.path.append(dhparserdir)
    # from tst_atf_grammar import recompile_grammar
    # recompile_grammar(os.path.join(scriptpath, 'atf.ebnf'), force=False)
    from DHParser.dsl import recompile_grammar
    if not recompile_grammar(
            grammar_src,
            force=False,
            notify=lambda: print('recompiling ' + grammar_src)):
        print('\nErrors while recompiling "%s":' % grammar_src +
              '\n--------------------------------------\n\n')
        with open('atf_ebnf_ERRORS.txt', encoding='utf-8') as f:
            print(f.read())
        sys.exit(1)
    from atfParser import compile_src
    from DHParser.server import Server, probe_tcp_server, StreamReaderProxy, StreamWriterProxy
    from DHParser.lsp import gen_lsp_table

    atf_lsp = atfLanguageServerProtocol()
    lsp_table = atf_lsp.lsp_fulltable.copy()
    lsp_table.setdefault('default', compile_src)
    atf_server = Server(rpc_functions=lsp_table,
                        cpu_bound=atf_lsp.cpu_bound.lsp_table.keys(),
                        blocking=atf_lsp.blocking.lsp_table.keys(),
                        connection_callback=atf_lsp.connect,
                        server_name="atfServer",
                        strict_lsp=True)
    if log_path is not None:
        # echoing does not work with stream connections!
        atf_server.echo_log = True if port >= 0 and host else False
        msg = atf_server.start_logging(log_path.strip('" \''))
        if atf_server.echo_log: echo(msg)

    if port < 0 or not host:
        # communication via streams instead of tcp server
        reader = StreamReaderProxy(sys.stdin)
        writer = StreamWriterProxy(sys.stdout)
        atf_server.run_stream_server(reader, writer)
        return

    cfg_filename = get_config_filename()
    overwrite = not os.path.exists(cfg_filename)
    ports = ALTERNATIVE_PORTS.copy() if port == DEFAULT_PORT else []
    if port in ports:
        ports.remove(port)
    ports.append(port)

    while ports:
        port = ports.pop()
        if (host, port) == (KNOWN_HOST, KNOWN_PORT):
            ident = asyncio_run(
                probe_tcp_server(host, port, SERVER_REPLY_TIMEOUT))
            if ident:
                if ident.endswith(servername):
                    echo(
                        'A server of type "%s" already exists on %s:%i.' %
                        (servername, host, port) +
                        ' Use --port option to start a secondary server on a different port.'
                    )
                    sys.exit(1)
                if ports:
                    echo('"%s" already occupies %s:%i. Trying port %i' %
                         (ident, host, port, ports[-1]))
                    continue
                else:
                    echo('"%s" already occupies %s:%i. No more ports to try.' %
                         (ident, host, port))
                    sys.exit(1)
        if overwrite:
            try:
                with open(cfg_filename, 'w') as f:
                    debug('Storing host and port value %s:%i in file "%s".' %
                          (host, port, cfg_filename))
                    f.write(host + ' ' + str(port))
            except (PermissionError, IOError) as e:
                echo('%s: Could not write temporary config file: "%s"' %
                     (str(e), cfg_filename))
                ports = []
        else:
            echo(
                'Configuration file "%s" already existed and was not overwritten. '
                'Use option "--port %i" to stop this server!' %
                (cfg_filename, port))
        try:
            debug('Starting server on %s:%i' % (host, port))
            atf_server.run_tcp_server(
                host, port)  # returns only after server has stopped!
            ports = []
        except OSError as e:
            if not (ports and e.errno == 98):
                echo(e)
                echo('Could not start server. Shutting down!')
                sys.exit(1)
            elif ports:
                echo('Could not start server on %s:%i. Trying port %s' %
                     (host, port, ports[-1]))
            else:
                echo('Could not start server on %s:%i. No more ports to try.' %
                     (host, port))
        finally:
            if not ports:
                echo('Server on %s:%i stopped' % (host, port))
                if overwrite:
                    try:
                        os.remove(cfg_filename)
                        debug('removing temporary config file: ' +
                              cfg_filename)
                    except FileNotFoundError:
                        pass
Example #5
0
 def setup(self):
     self.pipe = MockStream()
     self.reader = StreamReaderProxy(self.pipe)
     self.writer = StreamWriterProxy(self.pipe)
Example #6
0
class TestStreamProxies:
    def setup(self):
        self.pipe = MockStream()
        self.reader = StreamReaderProxy(self.pipe)
        self.writer = StreamWriterProxy(self.pipe)

    def teardown(self):
        self.writer.close()

    def test_pipe(self):
        message = b"alpha\nbeta\ngamma\n"

        def writer(pipe: MockStream):
            nonlocal message
            for i in range(0, len(message), 2):
                pipe.write(message[i:i + 2])
                pipe.flush()

        def reader(pipe: MockStream):
            nonlocal message
            received = []
            for i in range(3):
                received.append(pipe.readline())
            return b''.join(received)

        with ThreadPoolExecutor() as executor:
            future = executor.submit(reader, self.pipe)
            executor.submit(writer, self.pipe)
            assert future.result() == message

    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

    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