rocketmq_remoting/protocol/header/
query_message_request_header.rs

1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17use 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        // Verify that nested fields are included, assuming specific fields in TopicRequestHeader
138        // This is a placeholder assertion; actual fields and checks depend on TopicRequestHeader's
139        // structure
140        assert!(!map.contains_key("nestedField"));
141    }
142}