Mohammed Naser | 3415a2a | 2025-03-06 21:16:12 -0500 | [diff] [blame] | 1 | use ovsdb_derive::ovsdb_object; |
| 2 | use serde_json::Value; |
| 3 | use std::collections::HashMap; |
| 4 | use uuid::Uuid; |
| 5 | |
| 6 | #[ovsdb_object] |
| 7 | #[derive(Debug, PartialEq)] |
| 8 | pub struct NbGlobal { |
| 9 | pub name: Option<String>, |
| 10 | pub nb_cfg: Option<i64>, |
| 11 | pub nb_cfg_timestamp: Option<i64>, |
| 12 | pub sb_cfg: Option<i64>, |
| 13 | pub sb_cfg_timestamp: Option<i64>, |
| 14 | pub hv_cfg: Option<i64>, |
| 15 | pub hv_cfg_timestamp: Option<i64>, |
| 16 | pub external_ids: Option<HashMap<String, String>>, |
| 17 | pub connections: Option<Vec<Uuid>>, |
| 18 | pub ssl: Option<Vec<Uuid>>, |
| 19 | pub options: Option<HashMap<String, String>>, |
| 20 | pub ipsec: Option<bool>, |
| 21 | |
| 22 | // Required fields |
| 23 | pub _uuid: Option<Uuid>, |
| 24 | pub _version: Option<Uuid>, |
| 25 | } |
| 26 | |
| 27 | #[test] |
| 28 | fn test_nb_global_deserialization() { |
| 29 | // The provided JSON sample |
| 30 | let json_str = r#"{ |
| 31 | "connections": ["uuid", "601c7161-97df-42ae-b377-3baf21830d8f"], |
| 32 | "external_ids": ["map", [["test", "bara"]]], |
| 33 | "hv_cfg": 0, |
| 34 | "hv_cfg_timestamp": 0, |
| 35 | "ipsec": false, |
| 36 | "name": "global", |
| 37 | "nb_cfg": 0, |
| 38 | "nb_cfg_timestamp": 0, |
| 39 | "options": ["map", [["name", "global"], ["northd-backoff-interval-ms", "300"], ["northd_probe_interval", "5000"]]], |
| 40 | "sb_cfg": 0, |
| 41 | "sb_cfg_timestamp": 0, |
| 42 | "ssl": ["set", []] |
| 43 | }"#; |
| 44 | |
| 45 | let json_value: Value = serde_json::from_str(json_str).unwrap(); |
| 46 | |
| 47 | // Parse the JSON to our NbGlobal struct |
| 48 | let nb_global = |
| 49 | NbGlobal::from_map(&serde_json::from_value(json_value.clone()).unwrap()).unwrap(); |
| 50 | |
| 51 | // Test individual fields |
| 52 | assert_eq!(nb_global.name, Some("global".to_string())); |
| 53 | assert_eq!(nb_global.ipsec, Some(false)); |
| 54 | assert_eq!(nb_global.hv_cfg, Some(0)); |
| 55 | assert_eq!(nb_global.hv_cfg_timestamp, Some(0)); |
| 56 | assert_eq!(nb_global.nb_cfg, Some(0)); |
| 57 | assert_eq!(nb_global.nb_cfg_timestamp, Some(0)); |
| 58 | assert_eq!(nb_global.sb_cfg, Some(0)); |
| 59 | assert_eq!(nb_global.sb_cfg_timestamp, Some(0)); |
| 60 | |
| 61 | // Test UUID field |
| 62 | let connection_uuid = Uuid::parse_str("601c7161-97df-42ae-b377-3baf21830d8f").unwrap(); |
| 63 | assert_eq!(nb_global.connections, Some(vec![connection_uuid])); |
| 64 | |
| 65 | // Test empty set |
| 66 | assert_eq!(nb_global.ssl, Some(vec![])); |
| 67 | |
| 68 | // Test maps |
| 69 | let expected_external_ids = { |
| 70 | let mut map = HashMap::new(); |
| 71 | map.insert("test".to_string(), "bara".to_string()); |
| 72 | map |
| 73 | }; |
| 74 | assert_eq!(nb_global.external_ids, Some(expected_external_ids)); |
| 75 | |
| 76 | let expected_options = { |
| 77 | let mut map = HashMap::new(); |
| 78 | map.insert("name".to_string(), "global".to_string()); |
| 79 | map.insert("northd-backoff-interval-ms".to_string(), "300".to_string()); |
| 80 | map.insert("northd_probe_interval".to_string(), "5000".to_string()); |
| 81 | map |
| 82 | }; |
| 83 | assert_eq!(nb_global.options, Some(expected_options)); |
| 84 | } |
| 85 | |
| 86 | #[test] |
| 87 | fn test_nb_global_serialization() { |
| 88 | // Create an NbGlobal object with the same values as the JSON sample |
| 89 | let mut nb_global = NbGlobal::new(); |
| 90 | |
| 91 | // Set scalar values |
| 92 | nb_global.name = Some("global".to_string()); |
| 93 | nb_global.ipsec = Some(false); |
| 94 | nb_global.hv_cfg = Some(0); |
| 95 | nb_global.hv_cfg_timestamp = Some(0); |
| 96 | nb_global.nb_cfg = Some(0); |
| 97 | nb_global.nb_cfg_timestamp = Some(0); |
| 98 | nb_global.sb_cfg = Some(0); |
| 99 | nb_global.sb_cfg_timestamp = Some(0); |
| 100 | |
| 101 | // Set UUID connection |
| 102 | let connection_uuid = Uuid::parse_str("601c7161-97df-42ae-b377-3baf21830d8f").unwrap(); |
| 103 | nb_global.connections = Some(vec![connection_uuid]); |
| 104 | |
| 105 | // Set empty SSL set |
| 106 | nb_global.ssl = Some(vec![]); |
| 107 | |
| 108 | // Set maps |
| 109 | let mut external_ids = HashMap::new(); |
| 110 | external_ids.insert("test".to_string(), "bara".to_string()); |
| 111 | nb_global.external_ids = Some(external_ids); |
| 112 | |
| 113 | let mut options = HashMap::new(); |
| 114 | options.insert("name".to_string(), "global".to_string()); |
| 115 | options.insert("northd-backoff-interval-ms".to_string(), "300".to_string()); |
| 116 | options.insert("northd_probe_interval".to_string(), "5000".to_string()); |
| 117 | nb_global.options = Some(options); |
| 118 | |
| 119 | // Serialize to JSON |
| 120 | let serialized = nb_global.to_map(); |
| 121 | |
| 122 | // Verify each field |
| 123 | assert_eq!(serialized.get("name").unwrap().as_str().unwrap(), "global"); |
| 124 | assert!(!serialized.get("ipsec").unwrap().as_bool().unwrap()); |
| 125 | assert_eq!(serialized.get("hv_cfg").unwrap().as_i64().unwrap(), 0); |
| 126 | |
| 127 | // Test UUID serialization |
| 128 | let connections_json = serialized.get("connections").unwrap(); |
| 129 | assert!(connections_json.is_array()); |
| 130 | let connections_array = connections_json.as_array().unwrap(); |
| 131 | assert_eq!(connections_array[0].as_str().unwrap(), "uuid"); |
| 132 | assert_eq!( |
| 133 | connections_array[1].as_str().unwrap(), |
| 134 | "601c7161-97df-42ae-b377-3baf21830d8f" |
| 135 | ); |
| 136 | |
| 137 | // Test empty set serialization |
| 138 | let ssl_json = serialized.get("ssl").unwrap(); |
| 139 | assert!(ssl_json.is_array()); |
| 140 | assert_eq!(ssl_json.as_array().unwrap().len(), 0); |
| 141 | |
| 142 | // Test map serialization |
| 143 | let external_ids_json = serialized.get("external_ids").unwrap(); |
| 144 | assert!(external_ids_json.is_array()); |
| 145 | assert_eq!( |
| 146 | external_ids_json.as_array().unwrap()[0].as_str().unwrap(), |
| 147 | "map" |
| 148 | ); |
| 149 | |
| 150 | let options_json = serialized.get("options").unwrap(); |
| 151 | assert!(options_json.is_array()); |
| 152 | assert_eq!(options_json.as_array().unwrap()[0].as_str().unwrap(), "map"); |
| 153 | } |
| 154 | |
| 155 | #[test] |
| 156 | fn test_round_trip() { |
| 157 | // JSON string representing an NB_Global object |
| 158 | let json_str = r#"{ |
| 159 | "connections": ["uuid", "601c7161-97df-42ae-b377-3baf21830d8f"], |
| 160 | "external_ids": ["map", [["test", "bara"]]], |
| 161 | "hv_cfg": 0, |
| 162 | "hv_cfg_timestamp": 0, |
| 163 | "ipsec": false, |
| 164 | "name": "global", |
| 165 | "nb_cfg": 0, |
| 166 | "nb_cfg_timestamp": 0, |
| 167 | "options": ["map", [["name", "global"], ["northd-backoff-interval-ms", "300"], ["northd_probe_interval", "5000"]]], |
| 168 | "sb_cfg": 0, |
| 169 | "sb_cfg_timestamp": 0, |
| 170 | "ssl": ["set", []] |
| 171 | }"#; |
| 172 | |
| 173 | // Deserialize from JSON string to NbGlobal object |
| 174 | let json_value: Value = serde_json::from_str(json_str).unwrap(); |
| 175 | let nb_global = NbGlobal::from_map(&serde_json::from_value(json_value).unwrap()).unwrap(); |
| 176 | |
| 177 | // Serialize back to JSON |
| 178 | let serialized = serde_json::to_value(nb_global.to_map()).unwrap(); |
| 179 | |
| 180 | // Deserialize again |
| 181 | let nb_global2 = NbGlobal::from_map(&serde_json::from_value(serialized).unwrap()).unwrap(); |
| 182 | |
| 183 | // The two objects should be equal |
| 184 | assert_eq!(nb_global, nb_global2); |
| 185 | } |
| 186 | |
| 187 | #[test] |
| 188 | fn test_handle_single_element_set() { |
| 189 | // JSON with a single UUID in connections (no ["set", ...] wrapper) |
| 190 | let json_str = r#"{ |
| 191 | "connections": ["uuid", "601c7161-97df-42ae-b377-3baf21830d8f"], |
| 192 | "name": "global" |
| 193 | }"#; |
| 194 | |
| 195 | let json_value: Value = serde_json::from_str(json_str).unwrap(); |
| 196 | let nb_global = NbGlobal::from_map(&serde_json::from_value(json_value).unwrap()).unwrap(); |
| 197 | |
| 198 | // Should be parsed as a Vec with one element |
| 199 | let connection_uuid = Uuid::parse_str("601c7161-97df-42ae-b377-3baf21830d8f").unwrap(); |
| 200 | assert_eq!(nb_global.connections, Some(vec![connection_uuid])); |
| 201 | } |
| 202 | |
| 203 | #[test] |
| 204 | fn test_handle_multiple_element_set() { |
| 205 | // JSON with multiple UUIDs in connections using ["set", [...]] wrapper |
| 206 | let json_str = r#"{ |
| 207 | "connections": ["set", [ |
| 208 | ["uuid", "601c7161-97df-42ae-b377-3baf21830d8f"], |
| 209 | ["uuid", "701c7161-97df-42ae-b377-3baf21830d8f"] |
| 210 | ]], |
| 211 | "name": "global" |
| 212 | }"#; |
| 213 | |
| 214 | let json_value: Value = serde_json::from_str(json_str).unwrap(); |
| 215 | let nb_global = NbGlobal::from_map(&serde_json::from_value(json_value).unwrap()).unwrap(); |
| 216 | |
| 217 | // Should be parsed as a Vec with two elements |
| 218 | let uuid1 = Uuid::parse_str("601c7161-97df-42ae-b377-3baf21830d8f").unwrap(); |
| 219 | let uuid2 = Uuid::parse_str("701c7161-97df-42ae-b377-3baf21830d8f").unwrap(); |
| 220 | assert_eq!(nb_global.connections, Some(vec![uuid1, uuid2])); |
| 221 | } |
| 222 | |
| 223 | #[test] |
| 224 | fn test_empty_set() { |
| 225 | // JSON with empty set |
| 226 | let json_str = r#"{ |
| 227 | "ssl": ["set", []], |
| 228 | "name": "global" |
| 229 | }"#; |
| 230 | |
| 231 | let json_value: Value = serde_json::from_str(json_str).unwrap(); |
| 232 | let nb_global = NbGlobal::from_map(&serde_json::from_value(json_value).unwrap()).unwrap(); |
| 233 | |
| 234 | // Should be parsed as an empty Vec |
| 235 | assert_eq!(nb_global.ssl, Some(vec![])); |
| 236 | } |
| 237 | |
| 238 | #[test] |
| 239 | fn test_serialization_single_element_set() { |
| 240 | let mut nb_global = NbGlobal::new(); |
| 241 | |
| 242 | // Set single UUID connection |
| 243 | let connection_uuid = Uuid::parse_str("601c7161-97df-42ae-b377-3baf21830d8f").unwrap(); |
| 244 | nb_global.connections = Some(vec![connection_uuid]); |
| 245 | |
| 246 | // Serialize to JSON |
| 247 | let serialized = nb_global.to_map(); |
| 248 | let connections_json = serialized.get("connections").unwrap(); |
| 249 | |
| 250 | // Should be serialized as ["uuid", "..."] (not wrapped in ["set", [...]]) |
| 251 | assert!(connections_json.is_array()); |
| 252 | let connections_array = connections_json.as_array().unwrap(); |
| 253 | assert_eq!(connections_array.len(), 2); |
| 254 | assert_eq!(connections_array[0].as_str().unwrap(), "uuid"); |
| 255 | } |
| 256 | |
| 257 | #[test] |
| 258 | fn test_serialization_multiple_element_set() { |
| 259 | let mut nb_global = NbGlobal::new(); |
| 260 | |
| 261 | // Set multiple UUID connections |
| 262 | let uuid1 = Uuid::parse_str("601c7161-97df-42ae-b377-3baf21830d8f").unwrap(); |
| 263 | let uuid2 = Uuid::parse_str("701c7161-97df-42ae-b377-3baf21830d8f").unwrap(); |
| 264 | nb_global.connections = Some(vec![uuid1, uuid2]); |
| 265 | |
| 266 | // Serialize to JSON |
| 267 | let serialized = nb_global.to_map(); |
| 268 | let connections_json = serialized.get("connections").unwrap(); |
| 269 | |
| 270 | // Should be serialized as ["set", [...]] |
| 271 | assert!(connections_json.is_array()); |
| 272 | let connections_array = connections_json.as_array().unwrap(); |
| 273 | assert_eq!(connections_array[0].as_str().unwrap(), "set"); |
| 274 | } |