rocketmq_remoting/protocol/header/
query_message_request_header.rs1use cheetah_string::CheetahString;
18use rocketmq_macros::RequestHeaderCodecV2;
19use serde::Deserialize;
20use serde::Serialize;
21
22use crate::rpc::topic_request_header::TopicRequestHeader;
23
24#[derive(Debug, Clone, Serialize, Deserialize, Default, RequestHeaderCodecV2)]
25#[serde(rename_all = "camelCase")]
26pub struct QueryMessageRequestHeader {
27 #[required]
28 pub topic: CheetahString,
29
30 #[required]
31 pub key: CheetahString,
32
33 #[required]
34 pub max_num: i32,
35
36 #[required]
37 pub begin_timestamp: i64,
38
39 #[required]
40 pub end_timestamp: i64,
41
42 #[serde(flatten)]
43 pub topic_request_header: Option<TopicRequestHeader>,
44}
45
46#[cfg(test)]
47mod query_message_request_header_tests {
48 use std::collections::HashMap;
49
50 use super::*;
51 use crate::protocol::command_custom_header::CommandCustomHeader;
52 use crate::protocol::command_custom_header::FromMap;
53
54 #[test]
55 fn creating_from_map_with_all_fields_populates_struct_correctly() {
56 let mut map = HashMap::new();
57 map.insert("topic".into(), "test_topic".into());
58 map.insert("key".into(), "test_key".into());
59 map.insert("maxNum".into(), "10".into());
60 map.insert("beginTimestamp".into(), "1000".into());
61 map.insert("endTimestamp".into(), "2000".into());
62
63 let header: QueryMessageRequestHeader =
64 <QueryMessageRequestHeader as FromMap>::from(&map).unwrap();
65
66 assert_eq!(header.topic, "test_topic");
67 assert_eq!(header.key, "test_key");
68 assert_eq!(header.max_num, 10);
69 assert_eq!(header.begin_timestamp, 1000);
70 assert_eq!(header.end_timestamp, 2000);
71 }
72
73 #[test]
74 fn creating_from_map_missing_optional_fields_still_succeeds() {
75 let mut map = HashMap::new();
76 map.insert("topic".into(), "test_topic".into());
77 map.insert("key".into(), "test_key".into());
78 map.insert("maxNum".into(), "10".into());
79 map.insert("beginTimestamp".into(), "1000".into());
80 map.insert("endTimestamp".into(), "2000".into());
81
82 let header: QueryMessageRequestHeader =
83 <QueryMessageRequestHeader as FromMap>::from(&map).unwrap();
84
85 assert_eq!(header.topic, "test_topic");
86 assert_eq!(header.key, "test_key");
87 assert_eq!(header.max_num, 10);
88 }
89
90 #[test]
91 fn creating_from_map_with_invalid_number_fields_returns_none() {
92 let mut map = HashMap::new();
93 map.insert("topic".into(), "test_topic".into());
94 map.insert("key".into(), "test_key".into());
95 map.insert("maxNum".into(), "invalid".into());
96
97 let header: Result<QueryMessageRequestHeader, rocketmq_error::RocketMQError> =
98 <QueryMessageRequestHeader as FromMap>::from(&map);
99
100 assert!(header.is_err());
101 }
102
103 #[test]
104 fn to_map_includes_all_fields() {
105 let header = QueryMessageRequestHeader {
106 topic: "test_topic".into(),
107 key: "test_key".into(),
108 max_num: 10,
109 begin_timestamp: 1000,
110 end_timestamp: 2000,
111 topic_request_header: None,
112 };
113
114 let map: HashMap<CheetahString, CheetahString> = header.to_map().unwrap();
115
116 assert_eq!(map.get("topic").unwrap(), "test_topic");
117 assert_eq!(map.get("key").unwrap(), "test_key");
118 assert_eq!(map.get("maxNum").unwrap(), "10");
119 assert_eq!(map.get("beginTimestamp").unwrap(), "1000");
120 assert_eq!(map.get("endTimestamp").unwrap(), "2000");
121 }
122
123 #[test]
124 fn to_map_with_topic_request_header_includes_nested_fields() {
125 let topic_request_header = TopicRequestHeader::default();
126 let header = QueryMessageRequestHeader {
127 topic: "test_topic".into(),
128 key: "test_key".into(),
129 max_num: 10,
130 begin_timestamp: 1000,
131 end_timestamp: 2000,
132 topic_request_header: Some(topic_request_header),
133 };
134
135 let map = header.to_map().unwrap();
136
137 assert!(!map.contains_key("nestedField"));
141 }
142}