drasi_bootstrap_scriptfile/
script_types.rs1use chrono::{DateTime, FixedOffset};
22use serde::{Deserialize, Serialize};
23
24#[derive(Clone, Debug, Serialize, Deserialize)]
29#[serde(tag = "kind")]
30pub enum BootstrapScriptRecord {
31 Comment(CommentRecord),
33 Header(BootstrapHeaderRecord),
35 Label(LabelRecord),
37 Node(NodeRecord),
39 Relation(RelationRecord),
41 Finish(BootstrapFinishRecord),
43}
44
45#[derive(Clone, Debug, Serialize, Deserialize, Default)]
49pub struct BootstrapHeaderRecord {
50 pub start_time: DateTime<FixedOffset>,
52 #[serde(default)]
54 pub description: String,
55}
56
57#[derive(Clone, Debug, Serialize, Deserialize)]
61pub struct NodeRecord {
62 pub id: String,
64 pub labels: Vec<String>,
66 #[serde(default)]
68 pub properties: serde_json::Value,
69}
70
71#[derive(Clone, Debug, Serialize, Deserialize)]
75pub struct RelationRecord {
76 pub id: String,
78 pub labels: Vec<String>,
80 pub start_id: String,
82 pub start_label: Option<String>,
84 pub end_id: String,
86 pub end_label: Option<String>,
88 #[serde(default)]
90 pub properties: serde_json::Value,
91}
92
93#[derive(Clone, Debug, Serialize, Deserialize)]
97pub struct LabelRecord {
98 #[serde(default)]
100 pub offset_ns: u64,
101 pub label: String,
103 #[serde(default)]
105 pub description: String,
106}
107
108#[derive(Clone, Debug, Serialize, Deserialize)]
113pub struct CommentRecord {
114 pub comment: String,
116}
117
118#[derive(Clone, Debug, Serialize, Deserialize)]
122pub struct BootstrapFinishRecord {
123 #[serde(default)]
125 pub description: String,
126}
127
128#[derive(Clone, Debug, Serialize)]
133pub struct SequencedBootstrapScriptRecord {
134 pub seq: u64,
136 pub record: BootstrapScriptRecord,
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143 use serde_json::json;
144
145 #[test]
146 fn test_header_record_serialization() {
147 let header = BootstrapHeaderRecord {
148 start_time: DateTime::parse_from_rfc3339("2024-01-01T00:00:00Z").unwrap(),
149 description: "Test Script".to_string(),
150 };
151 let record = BootstrapScriptRecord::Header(header);
152
153 let json = serde_json::to_string(&record).unwrap();
154 assert!(json.contains(r#""kind":"Header"#));
155 assert!(json.contains(r#""description":"Test Script"#));
156
157 let deserialized: BootstrapScriptRecord = serde_json::from_str(&json).unwrap();
159 if let BootstrapScriptRecord::Header(h) = deserialized {
160 assert_eq!(h.description, "Test Script");
161 } else {
162 panic!("Expected Header record");
163 }
164 }
165
166 #[test]
167 fn test_node_record_serialization() {
168 let node = NodeRecord {
169 id: "n1".to_string(),
170 labels: vec!["Person".to_string()],
171 properties: json!({"name": "Alice", "age": 30}),
172 };
173 let record = BootstrapScriptRecord::Node(node);
174
175 let json = serde_json::to_string(&record).unwrap();
176 assert!(json.contains(r#""kind":"Node"#));
177 assert!(json.contains(r#""id":"n1"#));
178
179 let deserialized: BootstrapScriptRecord = serde_json::from_str(&json).unwrap();
181 if let BootstrapScriptRecord::Node(n) = deserialized {
182 assert_eq!(n.id, "n1");
183 assert_eq!(n.labels, vec!["Person"]);
184 } else {
185 panic!("Expected Node record");
186 }
187 }
188
189 #[test]
190 fn test_relation_record_serialization() {
191 let relation = RelationRecord {
192 id: "r1".to_string(),
193 labels: vec!["KNOWS".to_string()],
194 start_id: "n1".to_string(),
195 start_label: Some("Person".to_string()),
196 end_id: "n2".to_string(),
197 end_label: Some("Person".to_string()),
198 properties: json!({"since": 2020}),
199 };
200 let record = BootstrapScriptRecord::Relation(relation);
201
202 let json = serde_json::to_string(&record).unwrap();
203 assert!(json.contains(r#""kind":"Relation"#));
204 assert!(json.contains(r#""start_id":"n1"#));
205
206 let deserialized: BootstrapScriptRecord = serde_json::from_str(&json).unwrap();
208 if let BootstrapScriptRecord::Relation(r) = deserialized {
209 assert_eq!(r.id, "r1");
210 assert_eq!(r.start_id, "n1");
211 assert_eq!(r.end_id, "n2");
212 } else {
213 panic!("Expected Relation record");
214 }
215 }
216
217 #[test]
218 fn test_comment_record_serialization() {
219 let comment = CommentRecord {
220 comment: "This is a comment".to_string(),
221 };
222 let record = BootstrapScriptRecord::Comment(comment);
223
224 let json = serde_json::to_string(&record).unwrap();
225 assert!(json.contains(r#""kind":"Comment"#));
226
227 let deserialized: BootstrapScriptRecord = serde_json::from_str(&json).unwrap();
229 if let BootstrapScriptRecord::Comment(c) = deserialized {
230 assert_eq!(c.comment, "This is a comment");
231 } else {
232 panic!("Expected Comment record");
233 }
234 }
235
236 #[test]
237 fn test_label_record_serialization() {
238 let label = LabelRecord {
239 offset_ns: 1000,
240 label: "checkpoint_1".to_string(),
241 description: "First checkpoint".to_string(),
242 };
243 let record = BootstrapScriptRecord::Label(label);
244
245 let json = serde_json::to_string(&record).unwrap();
246 assert!(json.contains(r#""kind":"Label"#));
247
248 let deserialized: BootstrapScriptRecord = serde_json::from_str(&json).unwrap();
250 if let BootstrapScriptRecord::Label(l) = deserialized {
251 assert_eq!(l.label, "checkpoint_1");
252 assert_eq!(l.offset_ns, 1000);
253 } else {
254 panic!("Expected Label record");
255 }
256 }
257
258 #[test]
259 fn test_finish_record_serialization() {
260 let finish = BootstrapFinishRecord {
261 description: "End of script".to_string(),
262 };
263 let record = BootstrapScriptRecord::Finish(finish);
264
265 let json = serde_json::to_string(&record).unwrap();
266 assert!(json.contains(r#""kind":"Finish"#));
267
268 let deserialized: BootstrapScriptRecord = serde_json::from_str(&json).unwrap();
270 if let BootstrapScriptRecord::Finish(f) = deserialized {
271 assert_eq!(f.description, "End of script");
272 } else {
273 panic!("Expected Finish record");
274 }
275 }
276
277 #[test]
278 fn test_default_header_record() {
279 let header = BootstrapHeaderRecord::default();
280 assert!(header.description.is_empty());
281 }
282
283 #[test]
284 fn test_node_with_empty_properties() {
285 let json = r#"{"kind":"Node","id":"n1","labels":["Test"]}"#;
286 let record: BootstrapScriptRecord = serde_json::from_str(json).unwrap();
287
288 if let BootstrapScriptRecord::Node(n) = record {
289 assert_eq!(n.id, "n1");
290 assert_eq!(n.properties, serde_json::Value::Null);
291 } else {
292 panic!("Expected Node record");
293 }
294 }
295
296 #[test]
297 fn test_relation_without_optional_labels() {
298 let json =
299 r#"{"kind":"Relation","id":"r1","labels":["REL"],"start_id":"n1","end_id":"n2"}"#;
300 let record: BootstrapScriptRecord = serde_json::from_str(json).unwrap();
301
302 if let BootstrapScriptRecord::Relation(r) = record {
303 assert_eq!(r.start_label, None);
304 assert_eq!(r.end_label, None);
305 } else {
306 panic!("Expected Relation record");
307 }
308 }
309}