Files

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);
}