Exemple #1
0
    def test_qos_2_queues_message(self):
        """
        The WAMP layer calling send_publish will queue a message up for
        sending, and send it next time it has a chance.
        """
        h = BasicHandler()
        r, t, p, cp = make_test_items(h)

        data = (Connect(client_id=u"test123",
                        flags=ConnectFlags(clean_session=True)).serialise())

        for x in iterbytes(data):
            p.dataReceived(x)

        # Connect has happened
        events = cp.data_received(t.value())
        t.clear()
        self.assertFalse(t.disconnecting)
        self.assertIsInstance(events[0], ConnACK)

        # WAMP layer calls send_publish, with QoS 2
        p.send_publish(u"hello", 2, b'some bytes', False)

        # Nothing should have been sent yet, it is queued
        self.assertEqual(t.value(), b'')

        # Advance the clock
        r.advance(0.1)

        # We should now get the sent Publish
        expected_publish = Publish(duplicate=False,
                                   qos_level=2,
                                   retain=False,
                                   packet_identifier=1,
                                   topic_name=u"hello",
                                   payload=b"some bytes")
        events = cp.data_received(t.value())
        t.clear()
        self.assertEqual(len(events), 1)
        self.assertEqual(events[0], expected_publish)

        # We send the PubREC, which we should get a PubREL back with
        pubrec = PubREC(packet_identifier=1)

        for x in iterbytes(pubrec.serialise()):
            p.dataReceived(x)

        events = cp.data_received(t.value())
        t.clear()
        self.assertEqual(len(events), 1)
        self.assertEqual(events[0], PubREL(packet_identifier=1))

        # We send the PubCOMP, which has no response
        pubcomp = PubCOMP(packet_identifier=1)

        for x in iterbytes(pubcomp.serialise()):
            p.dataReceived(x)

        self.assertFalse(t.disconnecting)
Exemple #2
0
    def test_qos_2_sends_ack(self):
        """
        When a QoS 2 Publish packet is recieved, we send a PubREC with the same
        packet identifier as the original Publish, wait for a PubREL, and then
        send a PubCOMP.

        Compliance statement MQTT-4.3.3-2
        Spec part 3.4, 4.3.3
        """
        got_packets = []

        class PubHandler(BasicHandler):
            def process_publish_qos_2(self, event):
                got_packets.append(event)
                return succeed(None)

        h = PubHandler()
        r, t, p, cp = make_test_items(h)

        pub = Publish(duplicate=False,
                      qos_level=2,
                      retain=False,
                      topic_name=u"foo",
                      packet_identifier=1,
                      payload=b"bar").serialise()

        data = (Connect(client_id=u"test123",
                        flags=ConnectFlags(clean_session=True)).serialise() +
                pub)

        with LogCapturer("trace") as logs:
            for x in iterbytes(data):
                p.dataReceived(x)

        events = cp.data_received(t.value())
        self.assertFalse(t.disconnecting)

        # ConnACK + PubREC with the same packet ID
        self.assertEqual(len(events), 2)
        self.assertEqual(events[1], PubREC(packet_identifier=1))

        # The publish handler should have been called
        self.assertEqual(len(got_packets), 1)
        self.assertEqual(got_packets[0].serialise(), pub)

        # We should get a debug message saying we got the publish
        messages = logs.get_category("MQ203")
        self.assertEqual(len(messages), 1)
        self.assertEqual(messages[0]["publish"].serialise(), pub)

        # Clear the client transport
        t.clear()

        # Now we send the PubREL
        pubrel = PubREL(packet_identifier=1)
        for x in iterbytes(pubrel.serialise()):
            p.dataReceived(x)

        events = cp.data_received(t.value())
        self.assertFalse(t.disconnecting)

        # We should get a PubCOMP in response
        self.assertEqual(len(events), 1)
        self.assertEqual(events[0], PubCOMP(packet_identifier=1))
Exemple #3
0
    def test_qos_2_resent_on_disconnect_pubcomp(self):
        """
        If we send a QoS2 Publish and we did not get a PubCOMP from the client
        before it disconnected, we will resend the PubREL packet if it
        connects with a non-clean session.

        Compliance statements: MQTT-4.4.0-1, MQTT-3.3.1-1
        """
        h = BasicHandler()
        r, t, p, cp = make_test_items(h)

        data = (Connect(client_id=u"test123",
                        flags=ConnectFlags(clean_session=False)).serialise())

        for x in iterbytes(data):
            p.dataReceived(x)

        # WAMP layer calls send_publish, with QoS 2
        p.send_publish(u"hello", 2, b'some bytes', False)

        # Advance the clock
        r.advance(0.1)

        # We should now get the sent Publish
        expected_publish = Publish(duplicate=False,
                                   qos_level=2,
                                   retain=False,
                                   packet_identifier=1,
                                   topic_name=u"hello",
                                   payload=b"some bytes")
        events = cp.data_received(t.value())
        t.clear()
        self.assertEqual(len(events), 2)
        self.assertEqual(events[1], expected_publish)

        # We send the PubREC to this Publish
        pubrec = PubREC(packet_identifier=1)

        for x in iterbytes(pubrec.serialise()):
            p.dataReceived(x)

        # Should get a PubREL back
        events = cp.data_received(t.value())
        t.clear()
        self.assertEqual(len(events), 1)
        self.assertEqual(events[0], PubREL(packet_identifier=1))

        # Disconnect the client
        t.connected = False
        t.loseConnection()
        p.connectionLost(None)

        r2, t2, p2, cp2 = make_test_items(h)

        # We must NOT have a clean session
        data = (Connect(client_id=u"test123",
                        flags=ConnectFlags(clean_session=False)).serialise())

        for x in iterbytes(data):
            p2.dataReceived(x)

        # The flushing is queued, so we'll have to spin the reactor
        r2.advance(0.1)

        # Should get a resent PubREL back
        events = cp2.data_received(t2.value())
        t2.clear()
        self.assertEqual(len(events), 2)
        self.assertIsInstance(events[0], ConnACK)
        self.assertEqual(events[1], PubREL(packet_identifier=1))

        self.assertFalse(t2.disconnecting)

        # We send the PubCOMP to this PubREL
        pubcomp = PubCOMP(packet_identifier=1)

        for x in iterbytes(pubcomp.serialise()):
            p2.dataReceived(x)

        # No more packets sent to us
        events = cp2.data_received(t2.value())
        self.assertEqual(len(events), 0)

        self.assertFalse(t2.disconnecting)