def test_01_unsolicited_response(self):
        """
        Create a server that sends an immediate Request Timeout response
        without first waiting for a request to arrive.
        """
        class UnsolicitedResponse(FakeHttpServerBase):
            def __init__(self, host, port):
                self.request_sent = False
                super(UnsolicitedResponse, self).__init__(host, port)

            def do_connect(self):
                self.conn.sendall(b'HTTP/1.1 408 Request Timeout\r\n' +
                                  b'Content-Length: 10\r\n' + b'\r\n' +
                                  b'Bad Server')
                self.request_sent = True

        count, error = http1_ping(self.http_server_port,
                                  self.http_listener_port)
        self.assertIsNone(error)
        self.assertEqual(1, count)
        server = UnsolicitedResponse('127.0.0.1', self.http_server_port)
        self.assertTrue(server.request_sent)
        count, error = http1_ping(self.http_server_port,
                                  self.http_listener_port)
        self.assertIsNone(error)
        self.assertEqual(1, count)
    def test_01_mgmt(self):
        """
        Create and delete HTTP1 connectors and listeners
        """
        LISTENER_TYPE = 'org.apache.qpid.dispatch.httpListener'
        CONNECTOR_TYPE = 'org.apache.qpid.dispatch.httpConnector'
        CONNECTION_TYPE = 'org.apache.qpid.dispatch.connection'

        mgmt = self.router.management
        self.assertEqual(0, len(mgmt.query(type=LISTENER_TYPE).results))
        self.assertEqual(0, len(mgmt.query(type=CONNECTOR_TYPE).results))

        mgmt.create(type=CONNECTOR_TYPE,
                    name="ServerConnector",
                    attributes={
                        'address': 'http1',
                        'port': self.http_server_port,
                        'protocolVersion': 'HTTP1'
                    })

        mgmt.create(type=LISTENER_TYPE,
                    name="ClientListener",
                    attributes={
                        'address': 'http1',
                        'port': self.http_listener_port,
                        'protocolVersion': 'HTTP1'
                    })

        # verify the entities have been created and http traffic works

        self.assertEqual(1, len(mgmt.query(type=LISTENER_TYPE).results))
        self.assertEqual(1, len(mgmt.query(type=CONNECTOR_TYPE).results))

        count, error = http1_ping(sport=self.http_server_port,
                                  cport=self.http_listener_port)
        self.assertIsNone(error)
        self.assertEqual(1, count)

        #
        # delete the connector and wait for the associated connection to be
        # removed
        #

        mgmt.delete(type=CONNECTOR_TYPE, name="ServerConnector")
        self.assertEqual(0, len(mgmt.query(type=CONNECTOR_TYPE).results))

        retry = 20  # 20 * 0.25 = 5 sec
        hconns = 0
        while retry:
            obj = mgmt.query(type=CONNECTION_TYPE,
                             attribute_names=["protocol"])
            for item in obj.get_dicts():
                if "http/1.x" in item["protocol"]:
                    hconns += 1
            if hconns == 0:
                break
            sleep(0.25)
            retry -= 1
            hconns = 0

        self.assertEqual(0, hconns, msg="HTTP connection not deleted")

        # When a connector is configured the router will periodically attempt
        # to connect to the server address. To prove that the connector has
        # been completely removed listen for connection attempts on the server
        # port.
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(("", self.http_server_port))
        s.setblocking(True)
        s.settimeout(3)  # reconnect attempts every 2.5 seconds
        s.listen(1)
        with self.assertRaises(socket.timeout):
            conn, addr = s.accept()
        s.close()

        #
        # re-create the connector and verify it works
        #
        mgmt.create(type=CONNECTOR_TYPE,
                    name="ServerConnector",
                    attributes={
                        'address': 'http1',
                        'port': self.http_server_port,
                        'protocolVersion': 'HTTP1'
                    })

        self.assertEqual(1, len(mgmt.query(type=CONNECTOR_TYPE).results))

        count, error = http1_ping(sport=self.http_server_port,
                                  cport=self.http_listener_port)
        self.assertIsNone(error)
        self.assertEqual(1, count)
    def test_03_bad_response_message(self):
        """
        Test various improperly constructed response messages
        """
        DUMMY_TESTS = {
            "GET": [
                (
                    RequestMsg("GET",
                               "/GET/test_03_bad_response_message",
                               headers={"Content-Length": "000"}),
                    None,
                    None,
                ),
            ]
        }

        body_filler = "?" * 1024 * 300  # Q2

        # fake server - just to create a sink for the "fakeServer" address so
        # credit will be granted.
        rx = AsyncTestReceiver(self.INT_A.listener, source="fakeServer")

        # no correlation id:
        client = ThreadedTestClient(DUMMY_TESTS, self.http_fake_port)
        req = rx.queue.get(timeout=TIMEOUT)
        resp = Message(body="NO CORRELATION ID " + body_filler)
        resp.to = req.reply_to
        ts = AsyncTestSender(address=self.INT_A.listener,
                             target=req.reply_to,
                             message=resp)
        ts.wait()
        self.assertEqual(1, ts.rejected)
        client.wait()
        self.assertIsNotNone(client.error)

        # missing application properties
        client = ThreadedTestClient(DUMMY_TESTS, self.http_fake_port)
        req = rx.queue.get(timeout=TIMEOUT)

        resp = Message(body="NO APPLICATION PROPS " + body_filler)
        resp.to = req.reply_to
        resp.correlation_id = req.id
        ts = AsyncTestSender(address=self.INT_A.listener,
                             target=req.reply_to,
                             message=resp)
        ts.wait()
        self.assertEqual(1, ts.rejected)
        client.wait()
        self.assertIsNotNone(client.error)

        # no status application property
        client = ThreadedTestClient(DUMMY_TESTS, self.http_fake_port)
        req = rx.queue.get(timeout=TIMEOUT)
        resp = Message(body="MISSING STATUS HEADER " + body_filler)
        resp.to = req.reply_to
        resp.correlation_id = req.id
        resp.properties = {"stuff": "value"}
        ts = AsyncTestSender(address=self.INT_A.listener,
                             target=req.reply_to,
                             message=resp)
        ts.wait()
        self.assertEqual(1, ts.rejected)
        client.wait()
        self.assertIsNotNone(client.error)

        # TODO: fix body parsing (returns NEED_MORE)
        # # invalid body format
        # client = ThreadedTestClient(DUMMY_TESTS,
        #                             self.http_fake_port)
        # req = rx.queue.get(timeout=TIMEOUT)
        # resp = Message(body="INVALID BODY FORMAT " + body_filler)
        # resp.to = req.reply_to
        # resp.correlation_id = req.id
        # resp.properties = {"http:status": 200}
        # ts = AsyncTestSender(address=self.INT_A.listener,
        #                      target=req.reply_to,
        #                      message=resp)
        # ts.wait()
        # self.assertEqual(1, ts.rejected);
        # client.wait()
        # self.assertIsNotNone(client.error)

        rx.stop()
        sleep(0.5)  # fudge factor allow socket close to complete

        # verify router is still sane:
        count, error = http1_ping(self.http_server_port,
                                  self.http_listener_port)
        self.assertIsNone(error)
        self.assertEqual(1, count)
    def test_02_bad_request_message(self):
        """
        Test various improperly constructed request messages
        """
        server = TestServer(server_port=self.http_server_port,
                            client_port=self.http_listener_port,
                            tests={})

        body_filler = "?" * 1024 * 300  # Q2

        msg = Message(body="NOMSGID " + body_filler)
        ts = AsyncTestSender(address=self.INT_A.listener,
                             target="testServer",
                             message=msg)
        ts.wait()
        self.assertEqual(1, ts.rejected)

        msg = Message(body="NO REPLY TO " + body_filler)
        msg.id = 1
        ts = AsyncTestSender(address=self.INT_A.listener,
                             target="testServer",
                             message=msg)
        ts.wait()
        self.assertEqual(1, ts.rejected)

        msg = Message(body="NO SUBJECT " + body_filler)
        msg.id = 1
        msg.reply_to = "amqp://fake/reply_to"
        ts = AsyncTestSender(address=self.INT_A.listener,
                             target="testServer",
                             message=msg)
        ts.wait()
        self.assertEqual(1, ts.rejected)

        msg = Message(body="NO APP PROPERTIES " + body_filler)
        msg.id = 1
        msg.reply_to = "amqp://fake/reply_to"
        msg.subject = "GET"
        ts = AsyncTestSender(address=self.INT_A.listener,
                             target="testServer",
                             message=msg)
        ts.wait()
        self.assertEqual(1, ts.rejected)

        # TODO: fix body parsing (returns NEED_MORE)
        # msg = Message(body="INVALID BODY " + body_filler)
        # msg.id = 1
        # msg.reply_to = "amqp://fake/reply_to"
        # msg.subject = "GET"
        # msg.properties = {"http:target": "/Some/target"}
        # ts = AsyncTestSender(address=self.INT_A.listener,
        #                      target="testServer",
        #                      message=msg)
        # ts.wait()
        # self.assertEqual(1, ts.rejected);

        server.wait()

        # verify router is still sane:
        count, error = http1_ping(self.http_server_port,
                                  self.http_listener_port)
        self.assertIsNone(error)
        self.assertEqual(1, count)
예제 #5
0
    def test_01_create_delete(self):
        """ Create and delete HTTP1 connectors and listeners.  The
        connectors/listeners are created on the edge router.  Verify that the
        adaptor properly notifies the interior of the subscribers/producers.
        """
        e_mgmt = self.e_router.management
        self.assertEqual(0, len(e_mgmt.query(type=self.LISTENER_TYPE).results))
        self.assertEqual(0,
                         len(e_mgmt.query(type=self.CONNECTOR_TYPE).results))

        e_mgmt.create(type=self.CONNECTOR_TYPE,
                      name="ServerConnector",
                      attributes={
                          'address': 'closest/http1Service',
                          'port': self.http_server_port,
                          'protocolVersion': 'HTTP1'
                      })

        e_mgmt.create(type=self.LISTENER_TYPE,
                      name="ClientListener",
                      attributes={
                          'address': 'closest/http1Service',
                          'port': self.http_listener_port,
                          'protocolVersion': 'HTTP1'
                      })

        # verify the entities have been created and http traffic works

        self.assertEqual(1, len(e_mgmt.query(type=self.LISTENER_TYPE).results))
        self.assertEqual(1,
                         len(e_mgmt.query(type=self.CONNECTOR_TYPE).results))

        count, error = http1_ping(sport=self.http_server_port,
                                  cport=self.http_listener_port)
        self.assertIsNone(error)
        self.assertEqual(1, count)

        # now check the interior router for the closest/http1Service address
        self.i_router.wait_address("closest/http1Service", subscribers=1)

        #
        # delete the connector and listener; wait for the associated connection
        # to be removed
        #
        e_mgmt.delete(type=self.CONNECTOR_TYPE, name="ServerConnector")
        self.assertEqual(0,
                         len(e_mgmt.query(type=self.CONNECTOR_TYPE).results))
        e_mgmt.delete(type=self.LISTENER_TYPE, name="ClientListener")
        self.assertEqual(0, len(e_mgmt.query(type=self.LISTENER_TYPE).results))

        # will hit test timeout on failure:
        while True:
            hconns = 0
            obj = e_mgmt.query(type=self.CONNECTION_TYPE,
                               attribute_names=["protocol"])
            for item in obj.get_dicts():
                if "http/1.x" in item["protocol"]:
                    hconns += 1
            if hconns == 0:
                break
            sleep(0.25)

        # When a connector is configured the router will periodically attempt
        # to connect to the server address. To prove that the connector has
        # been completely removed listen for connection attempts on the server
        # port.
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(("", self.http_server_port))
        s.setblocking(True)
        s.settimeout(3)  # reconnect attempts every 2.5 seconds
        s.listen(1)
        with self.assertRaises(socket.timeout):
            conn, addr = s.accept()
        s.close()

        # Verify that the address is no longer bound on the interior
        self.i_router.wait_address_unsubscribed("closest/http1Service")

        #
        # re-create the connector and listener; verify it works
        #
        e_mgmt.create(type=self.CONNECTOR_TYPE,
                      name="ServerConnector",
                      attributes={
                          'address': 'closest/http1Service',
                          'port': self.http_server_port,
                          'protocolVersion': 'HTTP1'
                      })

        e_mgmt.create(type=self.LISTENER_TYPE,
                      name="ClientListener",
                      attributes={
                          'address': 'closest/http1Service',
                          'port': self.http_listener_port,
                          'protocolVersion': 'HTTP1'
                      })

        self.assertEqual(1, len(e_mgmt.query(type=self.LISTENER_TYPE).results))
        self.assertEqual(1,
                         len(e_mgmt.query(type=self.CONNECTOR_TYPE).results))

        count, error = http1_ping(sport=self.http_server_port,
                                  cport=self.http_listener_port)
        self.assertIsNone(error)
        self.assertEqual(1, count)

        self.i_router.wait_address("closest/http1Service", subscribers=1)

        e_mgmt.delete(type=self.CONNECTOR_TYPE, name="ServerConnector")
        self.assertEqual(0,
                         len(e_mgmt.query(type=self.CONNECTOR_TYPE).results))
        e_mgmt.delete(type=self.LISTENER_TYPE, name="ClientListener")
        self.assertEqual(0, len(e_mgmt.query(type=self.LISTENER_TYPE).results))