#![cfg(feature = "serialization")]
mod common;
use common::strategies::*;
use libdictenstein::double_array_trie::DoubleArrayTrie;
use libdictenstein::dynamic_dawg::DynamicDawg;
use libdictenstein::serialization::{BincodeSerializer, DictionarySerializer, JsonSerializer};
use libdictenstein::Dictionary;
use proptest::prelude::*;
use std::collections::HashSet;
proptest! {
#![proptest_config(ProptestConfig::with_cases(50))]
#[test]
fn dawg_serialization_roundtrip(
terms in prop::collection::vec(ascii_term(1, 15), 1..=50)
) {
let unique_terms: HashSet<_> = terms.into_iter().collect();
let dict: DynamicDawg<()> = DynamicDawg::from_terms(unique_terms.iter());
let mut buffer = Vec::new();
BincodeSerializer::serialize(&dict, &mut buffer).expect("serialization should succeed");
let restored: DynamicDawg<()> = BincodeSerializer::deserialize(&buffer[..])
.expect("deserialization should succeed");
for term in &unique_terms {
prop_assert!(
restored.contains(term),
"Term '{}' should be present after roundtrip",
term
);
}
prop_assert_eq!(
dict.len(),
restored.len(),
"Length should match after roundtrip"
);
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(50))]
#[test]
fn dat_serialization_roundtrip(
terms in prop::collection::vec(ascii_term(1, 15), 1..=50)
) {
let unique_terms: HashSet<_> = terms.into_iter().collect();
let dict = DoubleArrayTrie::from_terms(unique_terms.iter());
let mut buffer = Vec::new();
BincodeSerializer::serialize(&dict, &mut buffer).expect("serialization should succeed");
let restored: DoubleArrayTrie = BincodeSerializer::deserialize(&buffer[..])
.expect("deserialization should succeed");
for term in &unique_terms {
prop_assert!(
restored.contains(term),
"Term '{}' should be present after roundtrip",
term
);
}
prop_assert_eq!(
dict.len(),
restored.len(),
"Length should match after roundtrip"
);
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(30))]
#[test]
fn json_serialization_roundtrip(
terms in prop::collection::vec(ascii_term(1, 15), 1..=30)
) {
let unique_terms: HashSet<_> = terms.into_iter().collect();
let dict = DoubleArrayTrie::from_terms(unique_terms.iter());
let mut buffer = Vec::new();
JsonSerializer::serialize(&dict, &mut buffer).expect("JSON serialization should succeed");
let restored: DoubleArrayTrie = JsonSerializer::deserialize(&buffer[..])
.expect("JSON deserialization should succeed");
for term in &unique_terms {
prop_assert!(
restored.contains(term),
"Term '{}' should be present after JSON roundtrip",
term
);
}
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(10))]
#[test]
fn large_dict_serialization(
terms in prop::collection::vec(ascii_term(1, 20), 500..=1000)
) {
let unique_terms: HashSet<_> = terms.into_iter().collect();
let dict: DynamicDawg<()> = DynamicDawg::from_terms(unique_terms.iter());
let mut buffer = Vec::new();
BincodeSerializer::serialize(&dict, &mut buffer).expect("serialization should succeed");
prop_assert!(!buffer.is_empty(), "Serialized buffer should not be empty");
let restored: DynamicDawg<()> = BincodeSerializer::deserialize(&buffer[..])
.expect("deserialization should succeed");
prop_assert_eq!(
dict.len(),
restored.len(),
"Length should match after roundtrip"
);
for term in unique_terms.iter().take(100) {
prop_assert!(
restored.contains(term),
"Sampled term '{}' should be present",
term
);
}
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(20))]
#[test]
fn cross_backend_serialization_consistency(
terms in prop::collection::vec(ascii_term(1, 15), 5..=30)
) {
let unique_terms: HashSet<_> = terms.into_iter().collect();
let dawg: DynamicDawg<()> = DynamicDawg::from_terms(unique_terms.iter());
let dat = DoubleArrayTrie::from_terms(unique_terms.iter());
let mut dawg_buffer = Vec::new();
BincodeSerializer::serialize(&dawg, &mut dawg_buffer).expect("dawg serialize");
let dawg_restored: DynamicDawg<()> = BincodeSerializer::deserialize(&dawg_buffer[..]).expect("dawg deserialize");
let mut dat_buffer = Vec::new();
BincodeSerializer::serialize(&dat, &mut dat_buffer).expect("dat serialize");
let dat_restored: DoubleArrayTrie = BincodeSerializer::deserialize(&dat_buffer[..]).expect("dat deserialize");
for term in &unique_terms {
prop_assert!(
dawg_restored.contains(term),
"DynamicDawg should contain '{}'",
term
);
prop_assert!(
dat_restored.contains(term),
"DoubleArrayTrie should contain '{}'",
term
);
}
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(20))]
#[test]
fn empty_dict_serialization(_dummy in 0..1i32) {
let dict: DynamicDawg<()> = DynamicDawg::new();
let mut buffer = Vec::new();
BincodeSerializer::serialize(&dict, &mut buffer).expect("serialization should succeed");
let restored: DynamicDawg<()> = BincodeSerializer::deserialize(&buffer[..])
.expect("deserialization should succeed");
prop_assert_eq!(restored.len(), Some(0), "Empty dict should remain empty");
}
#[test]
fn single_term_serialization(term in ascii_term(1, 15)) {
let dict: DynamicDawg<()> = DynamicDawg::from_terms(std::iter::once(&term));
let mut buffer = Vec::new();
BincodeSerializer::serialize(&dict, &mut buffer).expect("serialization should succeed");
let restored: DynamicDawg<()> = BincodeSerializer::deserialize(&buffer[..])
.expect("deserialization should succeed");
prop_assert!(restored.contains(&term), "Single term should survive roundtrip");
prop_assert_eq!(restored.len(), Some(1), "Length should be 1");
}
#[test]
fn prefix_sharing_serialization(
terms in prefix_clustered_terms(20)
) {
let unique_terms: HashSet<_> = terms.into_iter().filter(|t| !t.is_empty()).collect();
let dict: DynamicDawg<()> = DynamicDawg::from_terms(unique_terms.iter());
let mut buffer = Vec::new();
BincodeSerializer::serialize(&dict, &mut buffer).expect("serialization should succeed");
let restored: DynamicDawg<()> = BincodeSerializer::deserialize(&buffer[..])
.expect("deserialization should succeed");
for term in &unique_terms {
prop_assert!(
restored.contains(term),
"Prefix-clustered term '{}' should survive roundtrip",
term
);
}
}
}