159 lines
4.5 KiB
Rust
159 lines
4.5 KiB
Rust
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<String>,
|
|
child: Option<Box<Widget>>,
|
|
}
|
|
|
|
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);
|
|
}
|