mqtt5_protocol/packet/
pubcomp.rs

1use super::ack_common::{define_ack_packet, is_valid_pubrel_reason_code};
2use crate::packet::PacketType;
3use crate::prelude::{format, String, ToString};
4
5define_ack_packet! {
6    /// MQTT PUBCOMP packet (`QoS` 2 publish complete, part 3)
7    pub struct PubCompPacket;
8    packet_type = PacketType::PubComp;
9    validator = is_valid_pubrel_reason_code;
10    error_prefix = "PUBCOMP";
11}
12
13#[cfg(test)]
14mod tests {
15    use super::*;
16    use crate::packet::{FixedHeader, MqttPacket};
17    use crate::protocol::v5::properties::PropertyId;
18    use crate::types::ReasonCode;
19    use bytes::{BufMut, BytesMut};
20
21    #[test]
22    fn test_pubcomp_basic() {
23        let packet = PubCompPacket::new(123);
24
25        assert_eq!(packet.packet_id, 123);
26        assert_eq!(packet.reason_code, ReasonCode::Success);
27        assert!(packet.properties.is_empty());
28    }
29
30    #[test]
31    fn test_pubcomp_with_reason() {
32        let packet = PubCompPacket::new_with_reason(456, ReasonCode::PacketIdentifierNotFound)
33            .with_reason_string("Packet ID not found".to_string());
34
35        assert_eq!(packet.packet_id, 456);
36        assert_eq!(packet.reason_code, ReasonCode::PacketIdentifierNotFound);
37        assert!(packet.properties.contains(PropertyId::ReasonString));
38    }
39
40    #[test]
41    fn test_pubcomp_encode_decode() {
42        let packet = PubCompPacket::new(789);
43
44        let mut buf = BytesMut::new();
45        packet.encode(&mut buf).unwrap();
46
47        let fixed_header = FixedHeader::decode(&mut buf).unwrap();
48        assert_eq!(fixed_header.packet_type, PacketType::PubComp);
49
50        let decoded = PubCompPacket::decode_body(&mut buf, &fixed_header).unwrap();
51        assert_eq!(decoded.packet_id, 789);
52        assert_eq!(decoded.reason_code, ReasonCode::Success);
53    }
54
55    #[test]
56    fn test_pubcomp_encode_decode_with_properties() {
57        let packet = PubCompPacket::new(999)
58            .with_user_property("status".to_string(), "completed".to_string());
59
60        let mut buf = BytesMut::new();
61        packet.encode(&mut buf).unwrap();
62
63        let fixed_header = FixedHeader::decode(&mut buf).unwrap();
64        let decoded = PubCompPacket::decode_body(&mut buf, &fixed_header).unwrap();
65
66        assert_eq!(decoded.packet_id, 999);
67        assert!(decoded.properties.contains(PropertyId::UserProperty));
68    }
69
70    #[test]
71    fn test_pubcomp_v311_style() {
72        let mut buf = BytesMut::new();
73        buf.put_u16(1234);
74
75        let fixed_header = FixedHeader::new(PacketType::PubComp, 0, 2);
76        let decoded = PubCompPacket::decode_body(&mut buf, &fixed_header).unwrap();
77
78        assert_eq!(decoded.packet_id, 1234);
79        assert_eq!(decoded.reason_code, ReasonCode::Success);
80    }
81
82    #[test]
83    fn test_pubcomp_invalid_reason_code() {
84        let mut buf = BytesMut::new();
85        buf.put_u16(123);
86        buf.put_u8(0xFF);
87
88        let fixed_header = FixedHeader::new(PacketType::PubComp, 0, 3);
89        let result = PubCompPacket::decode_body(&mut buf, &fixed_header);
90        assert!(result.is_err());
91    }
92
93    #[test]
94    fn test_pubcomp_missing_packet_id() {
95        let mut buf = BytesMut::new();
96        buf.put_u8(0);
97
98        let fixed_header = FixedHeader::new(PacketType::PubComp, 0, 1);
99        let result = PubCompPacket::decode_body(&mut buf, &fixed_header);
100        assert!(result.is_err());
101    }
102}