use serde::{Deserialize, Serialize}; use wson::binary; use wson::graph::Node; use wson::text; use wson::{Config, Graph, Value}; #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Widget { name: String, width: i64, height: i64, enabled: bool, score: f64, tags: Vec, child: Option>, } fn widget() -> Widget { Widget { name: "main_window".to_string(), width: 500, height: 501, enabled: true, score: 36.0, tags: vec!["Ireland".to_string(), "Amazon".to_string()], child: None, } } #[test] fn serde_text_round_trip() { let value = widget(); let text = wson::to_string(&value).unwrap(); let decoded: Widget = wson::from_str(&text).unwrap(); assert_eq!(decoded, value); } #[test] fn serde_binary_round_trip() { let value = widget(); let bytes = wson::to_vec(&value).unwrap(); let decoded: Widget = wson::from_slice(&bytes).unwrap(); assert_eq!(decoded, value); } #[test] fn text_fixture_round_trip() { let cfg = Config::default(); let input = include_str!("fixtures/test.json"); let graph = text::parse_str(input, &cfg).unwrap(); let dumped = text::dump_graph(&graph, &cfg).unwrap(); let reparsed = text::parse_str(&dumped, &cfg).unwrap(); assert_eq!( Value::from_graph(&graph).unwrap(), Value::from_graph(&reparsed).unwrap() ); assert_eq!(dumped, text::dump_graph(&reparsed, &cfg).unwrap()); } #[test] fn wordpress_json_to_jbon_round_trip() { let cfg = Config::default(); let json = include_str!("fixtures/wordpress.json"); let graph = text::parse_str(json, &cfg).unwrap(); let bytes = binary::dump_graph(&graph, &cfg).unwrap(); let reparsed = binary::parse_slice(&bytes, &cfg).unwrap(); assert_eq!( Value::from_graph(&graph).unwrap(), Value::from_graph(&reparsed).unwrap() ); assert_eq!(binary::dump_graph(&reparsed, &cfg).unwrap(), bytes); } #[test] fn wordpress_jbon_byte_identical_round_trip() { let cfg = Config::default(); let expected = include_bytes!("fixtures/wordpress.jbon"); let graph = binary::parse_slice(expected, &cfg).unwrap(); let actual = binary::dump_graph(&graph, &cfg).unwrap(); assert_eq!(actual, expected); } #[test] fn text_references_form_a_cycle() { let cfg = Config { serialize_references: true, ..Config::default() }; let graph = text::parse_str("(0){\"child\":$0,\"id\":25}", &cfg).unwrap(); let root = graph.root(); let child = match graph.node(root) { Node::Object(entries) => *entries.get("child").unwrap(), other => panic!("expected object, got {other:?}"), }; assert_eq!(root, child); assert_eq!( text::dump_graph(&graph, &cfg).unwrap(), "(0){\"child\":$0,\"id\":25}" ); } #[test] fn binary_references_form_a_cycle() { let cfg = Config { serialize_references: true, ..Config::default() }; let graph = text::parse_str("(0){\"child\":$0,\"id\":25}", &cfg).unwrap(); let bytes = binary::dump_graph(&graph, &cfg).unwrap(); let reparsed = binary::parse_slice(&bytes, &cfg).unwrap(); let root = reparsed.root(); let child = match reparsed.node(root) { Node::Object(entries) => *entries.get("child").unwrap(), other => panic!("expected object, got {other:?}"), }; assert_eq!(root, child); assert_eq!(binary::dump_graph(&reparsed, &cfg).unwrap(), bytes); } #[test] fn cyclic_graph_requires_references() { let nodes = vec![Node::Object({ let mut entries = std::collections::BTreeMap::new(); entries.insert("self".to_string(), wson::NodeId(0)); entries })]; let graph = Graph::new(wson::NodeId(0), nodes); assert!(matches!( text::dump_graph(&graph, &Config::default()), Err(wson::Error::Cycle) )); } #[test] fn max_depth_is_enforced() { let cfg = Config { max_depth: 8, serialize_references: false, }; let input = "[[[[[[[[1]]]]]]]]"; assert!(matches!( text::parse_str(input, &cfg), Err(wson::Error::MaxDepthExceeded { max_depth: 8 }) )); } #[test] fn value_implements_serde() { let value = Value::Object({ let mut map = std::collections::BTreeMap::new(); map.insert("answer".to_string(), Value::Integer(42)); map }); let text = wson::to_string(&value).unwrap(); assert_eq!(text, "{\"answer\":42}"); let decoded: Value = wson::from_str(&text).unwrap(); assert_eq!(decoded, value); }