mqtt5_protocol/packet/
pubcomp.rs

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