Exemple #1
0
    def testTcpServerCloseActiveConnection(self):
        ''' Test server_close() while there are active TCP connections '''
        data = b"\x01\x00\x00\x00\x00\x06\x01\x01\x00\x00\x00\x01"
        server = yield from StartTcpServer(context=self.context,address=("127.0.0.1", 0),loop=self.loop)
        if PYTHON_VERSION >= (3, 7):
            server_task = asyncio.create_task(server.serve_forever())
        else:
            server_task = asyncio.ensure_future(server.serve_forever())
        yield from server.serving

        random_port = server.server.sockets[0].getsockname()[1] # get the random server port

        step1 = self.loop.create_future()
        done = self.loop.create_future()
        received_value = None

        class BasicClient(asyncio.BaseProtocol):
            def connection_made(self, transport):
                self.transport = transport
                step1.set_result(True)

        transport, protocol = yield from self.loop.create_connection(BasicClient, host='127.0.0.1',port=random_port)
        yield from step1

        # On Windows we seem to need to give this an extra chance to finish,
        # otherwise there ends up being an active connection at the assert.
        yield from asyncio.sleep(0.0)
        server.server_close()

        # close isn't synchronous and there's no notification that it's done
        # so we have to wait a bit
        yield from asyncio.sleep(0.0)
        self.assertTrue( len(server.active_connections) == 0 )
Exemple #2
0
    def testTcpServerNoSlave(self):
        ''' Test unknown slave unit exception '''
        context = ModbusServerContext(slaves={0x01: self.store, 0x02: self.store  }, single=False)
        data = b"\x01\x00\x00\x00\x00\x06\x05\x03\x00\x00\x00\x01" # get slave 5 function 3 (holding register)
        server = yield from StartTcpServer(context=context,address=("127.0.0.1", 0),loop=self.loop)
        if PYTHON_VERSION >= (3, 7):
            server_task = asyncio.create_task(server.serve_forever())
        else:
            server_task = asyncio.ensure_future(server.serve_forever())
        yield from server.serving
        connect, receive, eof = self.loop.create_future(),self.loop.create_future(),self.loop.create_future()
        received_data = None
        random_port = server.server.sockets[0].getsockname()[1] # get the random server port

        class BasicClient(asyncio.BaseProtocol):
            def connection_made(self, transport):
                _logger.debug("Client connected")
                self.transport = transport
                transport.write(data)
                connect.set_result(True)

            def data_received(self, data):
                _logger.debug("Client received data")
                receive.set_result(True)
                received_data = data

            def eof_received(self):
                _logger.debug("Client stream eof")
                eof.set_result(True)

        transport, protocol = yield from self.loop.create_connection(BasicClient, host='127.0.0.1',port=random_port)
        yield from asyncio.wait_for(connect, timeout=0.1)
        self.assertFalse(eof.done())
        server.server_close()
Exemple #3
0
    def testTcpServerReceiveData(self):
        ''' Test data sent on socket is received by internals - doesn't not process data '''
        data = b'\x01\x00\x00\x00\x00\x06\x01\x03\x00\x00\x00\x19'
        server = yield from StartTcpServer(context=self.context,address=("127.0.0.1", 0),loop=self.loop)
        if PYTHON_VERSION >= (3, 7):
            server_task = asyncio.create_task(server.serve_forever())
        else:
            server_task = asyncio.ensure_future(server.serve_forever())
        yield from server.serving
        with patch('pymodbus.transaction.ModbusSocketFramer.processIncomingPacket', new_callable=Mock) as process:
        # process = server.framer.processIncomingPacket = Mock()
            connected = self.loop.create_future()
            random_port = server.server.sockets[0].getsockname()[1] # get the random server port

            class BasicClient(asyncio.BaseProtocol):
                def connection_made(self, transport):
                    self.transport = transport
                    self.transport.write(data)
                    connected.set_result(True)

                def eof_received(self):
                    pass

            transport, protocol = yield from self.loop.create_connection(BasicClient, host='127.0.0.1',port=random_port)
            yield from asyncio.sleep(0.1) # this may be better done by making an internal hook in the actual implementation
            # if this unit test fails on a machine, see if increasing the sleep time makes a difference, if it does
            # blame author for a fix

            if PYTHON_VERSION >= (3, 6):
                process.assert_called_once()
            self.assertTrue( process.call_args[1]["data"] == data )
            server.server_close()
Exemple #4
0
 def testStartTcpServer(self):
     ''' Test that the modbus tcp asyncio server starts correctly '''
     identity = ModbusDeviceIdentification(info={0x00: 'VendorName'})
     self.loop = asynctest.Mock(self.loop)
     server = yield from StartTcpServer(context=self.context,loop=self.loop,identity=identity)
     self.assertEqual(server.control.Identity.VendorName, 'VendorName')
     if PYTHON_VERSION >= (3, 6):
         self.loop.create_server.assert_called_once()
 def testTcpServerServeNoDefer(self):
     ''' Test StartTcpServer without deferred start (immediate execution of server) '''
     with patch('asyncio.base_events.Server.serve_forever',
                new_callable=asynctest.CoroutineMock) as serve:
         server = yield from StartTcpServer(context=self.context,
                                            address=("127.0.0.1", 0),
                                            loop=self.loop,
                                            defer_start=False)
         serve.assert_awaited()
 def testUdpServerServeForeverStart(self):
     ''' Test StartUdpServer serve_forever() method '''
     with patch('asyncio.base_events.Server.serve_forever',
                new_callable=asynctest.CoroutineMock) as serve:
         server = yield from StartTcpServer(context=self.context,
                                            address=("127.0.0.1", 0),
                                            loop=self.loop)
         yield from server.serve_forever()
         serve.assert_awaited()
Exemple #7
0
 def testTcpServerServeForeverTwice(self):
     ''' Call on serve_forever() twice should result in a runtime error '''
     server = yield from StartTcpServer(context=self.context,address=("127.0.0.1", 0), loop=self.loop)
     if PYTHON_VERSION >= (3, 7):
         server_task = asyncio.create_task(server.serve_forever())
     else:
         server_task = asyncio.ensure_future(server.serve_forever())
     yield from server.serving
     with self.assertRaises(RuntimeError):
         yield from server.serve_forever()
     server.server_close()
Exemple #8
0
    def testTcpServerConnectionLost(self):
        ''' Test tcp stream interruption '''
        data = b"\x01\x00\x00\x00\x00\x06\x01\x01\x00\x00\x00\x01"
        server = yield from StartTcpServer(context=self.context, address=("127.0.0.1", 0), loop=self.loop)

        if PYTHON_VERSION >= (3, 7):
            server_task = asyncio.create_task(server.serve_forever())
        else:
            server_task = asyncio.ensure_future(server.serve_forever())
        yield from server.serving

        random_port = server.server.sockets[0].getsockname()[1]     # get the random server port

        step1 = self.loop.create_future()
        # done = self.loop.create_future()
        # received_value = None
        time.sleep(1)

        class BasicClient(asyncio.BaseProtocol):
            def connection_made(self, transport):
                self.transport = transport
                step1.set_result(True)

        transport, protocol = yield from self.loop.create_connection(BasicClient, host='127.0.0.1', port=random_port)
        yield from step1
        # On Windows we seem to need to give this an extra chance to finish,
        # otherwise there ends up being an active connection at the assert.
        yield from asyncio.sleep(0.0)
        self.assertTrue(len(server.active_connections) == 1)

        protocol.transport.close()  # close isn't synchronous and there's no notification that it's done
        # so we have to wait a bit
        allowed_delay = 1
        deadline = time.monotonic() + allowed_delay
        while time.monotonic() <= deadline:
            yield from asyncio.sleep(0.1)
            if len(server.active_connections) == 0:
                break
        else:
            self.assertTrue(
                len(server.active_connections) == 0,
                msg="connections not closed within {} seconds".format(allowed_delay),
            )

        server.server_close()
    def testTcpServerInternalException(self):
        ''' Test sending garbage data on a TCP socket should drop the connection '''
        data = b"\x01\x00\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01"  # get slave 5 function 3 (holding register)
        server = yield from StartTcpServer(context=self.context,
                                           address=("127.0.0.1", 0),
                                           loop=self.loop)
        if PYTHON_VERSION >= (3, 7):
            server_task = asyncio.create_task(server.serve_forever())
        else:
            server_task = asyncio.ensure_future(server.serve_forever())
        yield from server.serving
        with patch(
                "pymodbus.register_read_message.ReadHoldingRegistersRequest.execute",
                side_effect=Exception):
            connect, receive, eof = self.loop.create_future(
            ), self.loop.create_future(), self.loop.create_future()
            received_data = None
            random_port = server.server.sockets[0].getsockname()[
                1]  # get the random server port

            class BasicClient(asyncio.BaseProtocol):
                def connection_made(self, transport):
                    _logger.debug("Client connected")
                    self.transport = transport
                    transport.write(data)
                    connect.set_result(True)

                def data_received(self, data):
                    _logger.debug("Client received data")
                    receive.set_result(True)
                    received_data = data

                def eof_received(self):
                    _logger.debug("Client stream eof")
                    eof.set_result(True)

            transport, protocol = yield from self.loop.create_connection(
                BasicClient, host='127.0.0.1', port=random_port)
            yield from asyncio.wait_for(connect, timeout=0.1)
            yield from asyncio.wait_for(receive, timeout=0.1)
            self.assertFalse(eof.done())

            transport.close()
            server.server_close()
    def testTcpServerException(self):
        ''' Sending garbage data on a TCP socket should drop the connection '''
        garbage = b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF'
        server = yield from StartTcpServer(context=self.context,
                                           address=("127.0.0.1", 0),
                                           loop=self.loop)
        if PYTHON_VERSION >= (3, 7):
            server_task = asyncio.create_task(server.serve_forever())
        else:
            server_task = asyncio.ensure_future(server.serve_forever())
        yield from server.serving
        with patch(
                'pymodbus.transaction.ModbusSocketFramer.processIncomingPacket',
                new_callable=lambda: Mock(side_effect=Exception)) as process:
            connect, receive, eof = self.loop.create_future(
            ), self.loop.create_future(), self.loop.create_future()
            received_data = None
            random_port = server.server.sockets[0].getsockname()[
                1]  # get the random server port

            class BasicClient(asyncio.BaseProtocol):
                def connection_made(self, transport):
                    _logger.debug("Client connected")
                    self.transport = transport
                    transport.write(garbage)
                    connect.set_result(True)

                def data_received(self, data):
                    _logger.debug("Client received data")
                    receive.set_result(True)
                    received_data = data

                def eof_received(self):
                    _logger.debug("Client stream eof")
                    eof.set_result(True)

            transport, protocol = yield from self.loop.create_connection(
                BasicClient, host='127.0.0.1', port=random_port)
            yield from asyncio.wait_for(connect, timeout=0.1)
            yield from asyncio.wait_for(eof, timeout=0.1)
            # neither of these should timeout if the test is successful
            server.server_close()
    def testTcpServerRoundtrip(self):
        ''' Test sending and receiving data on tcp socket '''
        data = b"\x01\x00\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01"  # unit 1, read register
        expected_response = b'\x01\x00\x00\x00\x00\x05\x01\x03\x02\x00\x11'  # value of 17 as per context
        server = yield from StartTcpServer(context=self.context,
                                           address=("127.0.0.1", 0),
                                           loop=self.loop)
        if PYTHON_VERSION >= (3, 7):
            server_task = asyncio.create_task(server.serve_forever())
        else:
            server_task = asyncio.ensure_future(server.serve_forever())
        yield from server.serving

        random_port = server.server.sockets[0].getsockname()[
            1]  # get the random server port

        connected, done = self.loop.create_future(), self.loop.create_future()
        received_value = None

        class BasicClient(asyncio.BaseProtocol):
            def connection_made(self, transport):
                self.transport = transport
                self.transport.write(data)
                connected.set_result(True)

            def data_received(self, data):
                nonlocal received_value, done
                received_value = data
                done.set_result(True)

            def eof_received(self):
                pass

        transport, protocol = yield from self.loop.create_connection(
            BasicClient, host='127.0.0.1', port=random_port)
        yield from asyncio.wait_for(done, timeout=0.1)

        self.assertEqual(received_value, expected_response)

        transport.close()
        yield from asyncio.sleep(0)
        server.server_close()
Exemple #12
0
    def testTcpServerConnectionLost(self):
        ''' Test tcp stream interruption '''
        data = b"\x01\x00\x00\x00\x00\x06\x01\x01\x00\x00\x00\x01"
        server = yield from StartTcpServer(context=self.context,
                                           address=("127.0.0.1", 0),
                                           loop=self.loop)

        if PYTHON_VERSION >= (3, 7):
            server_task = asyncio.create_task(server.serve_forever())
        else:
            server_task = asyncio.ensure_future(server.serve_forever())
        yield from server.serving

        random_port = server.server.sockets[0].getsockname()[
            1]  # get the random server port

        step1 = self.loop.create_future()
        # done = self.loop.create_future()
        # received_value = None
        time.sleep(1)

        class BasicClient(asyncio.BaseProtocol):
            def connection_made(self, transport):
                self.transport = transport
                step1.set_result(True)

        transport, protocol = yield from self.loop.create_connection(
            BasicClient, host='127.0.0.1', port=random_port)
        yield from step1
        # await asyncio.sleep(1)
        self.assertTrue(len(server.active_connections) == 1)

        protocol.transport.close(
        )  # close isn't synchronous and there's no notification that it's done
        # so we have to wait a bit
        yield from asyncio.sleep(0.1)
        self.assertTrue(len(server.active_connections) == 0)

        server.server_close()