#![allow(dead_code)]
use comparable::{Changed, Comparable};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt::Debug;
fn assert_serialize<T: Serialize>() {}
fn assert_deserialize<T: serde::de::DeserializeOwned>() {}
fn assert_change_is_serde<T: Comparable>() {
assert_serialize::<T::Desc>();
assert_serialize::<T::Change>();
assert_deserialize::<T::Desc>();
assert_deserialize::<T::Change>();
}
#[test]
fn builtin_desc_and_change_are_serde() {
assert_change_is_serde::<i32>();
assert_change_is_serde::<bool>();
assert_change_is_serde::<char>();
assert_change_is_serde::<f64>();
assert_change_is_serde::<String>();
assert_change_is_serde::<Option<u32>>();
assert_change_is_serde::<Vec<u32>>();
assert_change_is_serde::<std::collections::BTreeSet<u32>>();
assert_change_is_serde::<std::collections::HashSet<u32>>();
assert_change_is_serde::<std::collections::BTreeMap<String, u32>>();
assert_change_is_serde::<std::collections::HashMap<String, u32>>();
assert_change_is_serde::<[u32; 4]>();
assert_change_is_serde::<(u32, String)>();
assert_change_is_serde::<(u8, u16, u32)>();
assert_change_is_serde::<Box<u32>>();
assert_change_is_serde::<std::path::PathBuf>();
assert_serialize::<<Vec<i32> as Comparable>::Change>();
}
#[derive(Serialize)]
struct DiffReport<T: Comparable> {
added: Vec<String>,
removed: Vec<String>,
modified: HashMap<String, <T as Comparable>::Change>,
}
#[test]
fn diff_report_with_change_field_serializes() {
let mut modified = HashMap::new();
if let Changed::Changed(change) = 100i32.comparison(&200) {
modified.insert("answer".to_string(), change);
}
let report = DiffReport::<i32> { added: vec!["a".to_string()], removed: vec!["b".to_string()], modified };
let json = serde_json::to_value(&report).expect("DiffReport should serialize");
assert_eq!(json["added"], serde_json::json!(["a"]));
assert_eq!(json["removed"], serde_json::json!(["b"]));
assert_eq!(json["modified"]["answer"], serde_json::json!([100, 200]));
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Comparable)]
pub enum IdOrObject<T: Clone + PartialEq + Debug + Comparable> {
Id(#[comparable_ignore] u64),
Object(T),
}
#[test]
fn generic_enum_change_round_trips() {
let a = IdOrObject::<i32>::Object(1);
let b = IdOrObject::<i32>::Object(2);
let change = match a.comparison(&b) {
Changed::Changed(c) => c,
Changed::Unchanged => panic!("expected a change"),
};
let json = serde_json::to_string(&change).expect("Change should serialize");
let back: <IdOrObject<i32> as Comparable>::Change = serde_json::from_str(&json).expect("Change should deserialize");
assert_eq!(change, back);
}
#[test]
fn generic_enum_desc_round_trips() {
let value = IdOrObject::<i32>::Object(7);
let desc = value.describe();
let json = serde_json::to_string(&desc).expect("Desc should serialize");
let back: <IdOrObject<i32> as Comparable>::Desc = serde_json::from_str(&json).expect("Desc should deserialize");
assert_eq!(desc, back);
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Comparable)]
pub struct Wrapper<T: Clone + PartialEq + Debug + Comparable> {
name: String,
payload: T,
}
#[test]
fn generic_struct_change_round_trips() {
let a = Wrapper { name: "x".to_string(), payload: 1u32 };
let b = Wrapper { name: "y".to_string(), payload: 2u32 };
let change = match a.comparison(&b) {
Changed::Changed(c) => c,
Changed::Unchanged => panic!("expected a change"),
};
let json = serde_json::to_string(&change).expect("Change should serialize");
let back: <Wrapper<u32> as Comparable>::Change = serde_json::from_str(&json).expect("Change should deserialize");
assert_eq!(change, back);
}