Skip to main content

rocketmq_remoting/protocol/body/topic_info_wrapper/
topic_config_wrapper.rs

1// Copyright 2023 The RocketMQ Rust Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::HashMap;
16
17use cheetah_string::CheetahString;
18use dashmap::DashMap;
19use rocketmq_common::common::config::TopicConfig;
20use rocketmq_rust::ArcMut;
21use serde::Deserialize;
22use serde::Serialize;
23
24use crate::protocol::static_topic::topic_queue_mapping_detail::TopicQueueMappingDetail;
25use crate::protocol::static_topic::topic_queue_mapping_info::TopicQueueMappingInfo;
26use crate::protocol::DataVersion;
27
28#[derive(Debug, Clone, Serialize, Deserialize, Default)]
29pub struct TopicConfigAndMappingSerializeWrapper {
30    #[serde(rename = "topicQueueMappingInfoMap")]
31    pub topic_queue_mapping_info_map: DashMap<CheetahString /* topic */, ArcMut<TopicQueueMappingInfo>>,
32
33    #[serde(rename = "topicQueueMappingDetailMap")]
34    pub topic_queue_mapping_detail_map: DashMap<CheetahString /* topic */, ArcMut<TopicQueueMappingDetail>>,
35
36    #[serde(rename = "mappingDataVersion")]
37    pub mapping_data_version: DataVersion,
38
39    #[serde(flatten)]
40    pub topic_config_serialize_wrapper: TopicConfigSerializeWrapper,
41}
42
43impl TopicConfigAndMappingSerializeWrapper {
44    pub fn topic_queue_mapping_info_map(&self) -> &DashMap<CheetahString, ArcMut<TopicQueueMappingInfo>> {
45        &self.topic_queue_mapping_info_map
46    }
47
48    pub fn topic_queue_mapping_detail_map(
49        &self,
50    ) -> &DashMap<CheetahString /* topic */, ArcMut<TopicQueueMappingDetail>> {
51        &self.topic_queue_mapping_detail_map
52    }
53
54    pub fn mapping_data_version(&self) -> &DataVersion {
55        &self.mapping_data_version
56    }
57    pub fn topic_config_serialize_wrapper(&self) -> &TopicConfigSerializeWrapper {
58        &self.topic_config_serialize_wrapper
59    }
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
63pub struct TopicConfigSerializeWrapper {
64    #[serde(rename = "topicConfigTable")]
65    pub topic_config_table: HashMap<CheetahString, TopicConfig>,
66    #[serde(rename = "dataVersion")]
67    pub data_version: DataVersion,
68}
69
70impl TopicConfigSerializeWrapper {
71    pub fn topic_config_table(&self) -> &HashMap<CheetahString, TopicConfig> {
72        &self.topic_config_table
73    }
74
75    pub fn data_version(&self) -> &DataVersion {
76        &self.data_version
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn topic_config_and_mapping_serialize_wrapper_default() {
86        let wrapper = TopicConfigAndMappingSerializeWrapper::default();
87        assert!(wrapper.topic_queue_mapping_info_map.is_empty());
88        assert!(wrapper.topic_queue_mapping_detail_map.is_empty());
89        assert_eq!(wrapper.mapping_data_version, DataVersion::new());
90        assert!(wrapper.topic_config_serialize_wrapper().topic_config_table().is_empty());
91        assert_eq!(
92            wrapper.topic_config_serialize_wrapper().data_version(),
93            &DataVersion::new()
94        );
95    }
96
97    #[test]
98    fn topic_config_and_mapping_serialize_wrapper_getters() {
99        let mut wrapper = TopicConfigAndMappingSerializeWrapper::default();
100        let _topic_config = TopicConfig::default();
101        let topic_queue_mapping_info = ArcMut::new(TopicQueueMappingInfo::default());
102        let topic_queue_mapping_detail = ArcMut::<TopicQueueMappingDetail>::default();
103        let data_version = DataVersion::default();
104
105        let topic_config_serialize_wrapper = TopicConfigSerializeWrapper::default();
106        wrapper.topic_config_serialize_wrapper = topic_config_serialize_wrapper.clone();
107        wrapper
108            .topic_queue_mapping_info_map
109            .insert("test".into(), topic_queue_mapping_info.clone());
110        wrapper
111            .topic_queue_mapping_detail_map
112            .insert("test".into(), topic_queue_mapping_detail.clone());
113
114        assert_eq!(wrapper.mapping_data_version(), &data_version);
115        assert_eq!(
116            wrapper.topic_config_serialize_wrapper(),
117            &topic_config_serialize_wrapper
118        );
119    }
120
121    #[test]
122    fn topic_config_serialize_wrapper_methods() {
123        let mut wrapper = TopicConfigSerializeWrapper::default();
124        let topic_config = TopicConfig::default();
125        wrapper
126            .topic_config_table
127            .insert("test_topic".into(), topic_config.clone());
128        let data_version = DataVersion::default();
129        wrapper.data_version = data_version.clone();
130
131        assert_eq!(
132            wrapper
133                .topic_config_table()
134                .get(&CheetahString::from_static_str("test_topic")),
135            Some(&topic_config)
136        );
137        assert_eq!(wrapper.data_version(), &data_version);
138    }
139
140    fn create_topic_config(name: &str) -> (CheetahString, TopicConfig) {
141        (CheetahString::from(name), TopicConfig::default())
142    }
143
144    #[test]
145    fn test_default_initialization() {
146        let wrapper = TopicConfigSerializeWrapper::default();
147        assert!(wrapper.topic_config_table.is_empty());
148        assert_eq!(wrapper.data_version, DataVersion::default());
149    }
150
151    #[test]
152    fn test_clone_trait() {
153        let mut wrapper = TopicConfigSerializeWrapper::default();
154        let (k, v) = create_topic_config("topic_a");
155        wrapper.topic_config_table.insert(k.clone(), v.clone());
156
157        let cloned = wrapper.clone();
158
159        assert_eq!(wrapper, cloned);
160        assert_eq!(cloned.topic_config_table.get(&k), Some(&v));
161    }
162
163    #[test]
164    fn test_partial_eq_identical() {
165        let mut w1 = TopicConfigSerializeWrapper::default();
166        let mut w2 = TopicConfigSerializeWrapper::default();
167
168        let (k, v) = create_topic_config("topic_eq");
169
170        w1.topic_config_table.insert(k.clone(), v.clone());
171        w2.topic_config_table.insert(k, v);
172
173        assert_eq!(w1, w2);
174    }
175
176    #[test]
177    fn test_partial_eq_different() {
178        let mut w1 = TopicConfigSerializeWrapper::default();
179        let mut w2 = TopicConfigSerializeWrapper::default();
180
181        let (k1, v1) = create_topic_config("topic1");
182        let (k2, v2) = create_topic_config("topic2");
183
184        w1.topic_config_table.insert(k1, v1);
185        w2.topic_config_table.insert(k2, v2);
186
187        assert_ne!(w1, w2);
188    }
189
190    #[test]
191    fn test_getters() {
192        let mut wrapper = TopicConfigSerializeWrapper::default();
193
194        let (k, v) = create_topic_config("topic_getter");
195        wrapper.topic_config_table.insert(k.clone(), v.clone());
196
197        let dv = DataVersion::default();
198        wrapper.data_version = dv.clone();
199
200        assert_eq!(wrapper.topic_config_table().get(&k), Some(&v));
201        assert_eq!(wrapper.data_version(), &dv);
202    }
203
204    #[test]
205    fn test_empty_topic_config_table() {
206        let wrapper = TopicConfigSerializeWrapper::default();
207        assert!(wrapper.topic_config_table().is_empty());
208    }
209
210    #[test]
211    fn test_single_topic_config() {
212        let mut wrapper = TopicConfigSerializeWrapper::default();
213        let (k, v) = create_topic_config("single_topic");
214
215        wrapper.topic_config_table.insert(k.clone(), v.clone());
216
217        assert_eq!(wrapper.topic_config_table().len(), 1);
218        assert_eq!(wrapper.topic_config_table().get(&k), Some(&v));
219    }
220
221    #[test]
222    fn test_multiple_topic_configs() {
223        let mut wrapper = TopicConfigSerializeWrapper::default();
224
225        for i in 0..5 {
226            let name = format!("topic_{i}");
227            let (k, v) = create_topic_config(&name);
228            wrapper.topic_config_table.insert(k, v);
229        }
230
231        assert_eq!(wrapper.topic_config_table().len(), 5);
232    }
233
234    #[test]
235    fn test_data_version_behavior() {
236        let mut wrapper = TopicConfigSerializeWrapper::default();
237        let dv = DataVersion::default();
238
239        wrapper.data_version = dv.clone();
240
241        assert_eq!(wrapper.data_version(), &dv);
242    }
243
244    #[test]
245    fn test_json_serialization_field_names() {
246        let mut wrapper = TopicConfigSerializeWrapper::default();
247        let (k, v) = create_topic_config("serde_topic");
248
249        wrapper.topic_config_table.insert(k, v);
250
251        let json = serde_json::to_string(&wrapper).unwrap();
252
253        assert!(json.contains("topicConfigTable"));
254        assert!(json.contains("dataVersion"));
255    }
256
257    #[test]
258    fn test_json_deserialization_field_names() {
259        let json = r#"
260    {
261        "topicConfigTable": {},
262        "dataVersion": {
263            "stateVersion": 0,
264            "timestamp": 0,
265            "counter": 0
266        }
267    }
268    "#;
269
270        let wrapper: TopicConfigSerializeWrapper = serde_json::from_str(json).unwrap();
271
272        assert!(wrapper.topic_config_table.is_empty());
273    }
274
275    #[test]
276    fn test_serde_roundtrip() {
277        let mut wrapper = TopicConfigSerializeWrapper::default();
278
279        let (k1, v1) = create_topic_config("topic_round_1");
280        let (k2, v2) = create_topic_config("topic_round_2");
281
282        wrapper.topic_config_table.insert(k1, v1);
283        wrapper.topic_config_table.insert(k2, v2);
284
285        let json = serde_json::to_string(&wrapper).unwrap();
286        let decoded: TopicConfigSerializeWrapper = serde_json::from_str(&json).unwrap();
287
288        assert_eq!(wrapper, decoded);
289    }
290
291    #[test]
292    fn test_debug_trait_output() {
293        let wrapper = TopicConfigSerializeWrapper::default();
294        let debug_str = format!("{:?}", wrapper);
295
296        assert!(debug_str.contains("TopicConfigSerializeWrapper"));
297    }
298
299    #[test]
300    fn test_create_with_populated_fields() {
301        let mut table = HashMap::new();
302        let (k, v) = create_topic_config("populated_topic");
303
304        table.insert(k.clone(), v.clone());
305
306        let dv = DataVersion::default();
307
308        let wrapper = TopicConfigSerializeWrapper {
309            topic_config_table: table,
310            data_version: dv.clone(),
311        };
312
313        assert_eq!(wrapper.topic_config_table().get(&k), Some(&v));
314        assert_eq!(wrapper.data_version(), &dv);
315    }
316}