use proptest::prelude::*;
use serializer::IndexMap;
use serializer::llm::{DxDocument, DxLlmValue, LlmSerializer, SerializerConfig};
fn arb_simple_object() -> impl Strategy<Value = IndexMap<String, DxLlmValue>> {
prop::collection::vec(
(
"[a-z]{3,8}",
prop_oneof![
any::<bool>().prop_map(DxLlmValue::Bool),
(0.0..1000.0).prop_map(DxLlmValue::Num),
"[a-zA-Z0-9]{1,10}".prop_map(DxLlmValue::Str),
],
),
1..5,
)
.prop_map(|entries| entries.into_iter().collect())
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn compact_syntax_uses_at_equals_format(obj in arb_simple_object()) {
let mut config = SerializerConfig::default();
config.compact_syntax = true;
let serializer = LlmSerializer::with_config(config);
let mut doc = DxDocument::new();
doc.context.insert("config".to_string(), DxLlmValue::Obj(obj.clone()));
let output = serializer.serialize(&doc);
prop_assert!(output.contains("@="), "Compact syntax should use @= marker: {}", output);
prop_assert!(output.contains(&format!("config:{}@=[", obj.len())),
"Should have count prefix with @=: {}", output);
}
#[test]
fn compact_syntax_space_separated_no_equals(obj in arb_simple_object()) {
let mut config = SerializerConfig::default();
config.compact_syntax = true;
let serializer = LlmSerializer::with_config(config);
let mut doc = DxDocument::new();
doc.context.insert("data".to_string(), DxLlmValue::Obj(obj.clone()));
let output = serializer.serialize(&doc);
if let Some(start) = output.find("@=[") {
let content_start = start + 3;
if let Some(end) = output[content_start..].find(']') {
let content = &output[content_start..content_start + end];
let tokens: Vec<&str> = content.split_whitespace().collect();
prop_assert_eq!(tokens.len() % 2, 0,
"Compact syntax should have even number of tokens: {}", content);
prop_assert!(!content.contains('='),
"Compact syntax content should not contain = signs: {}", content);
}
}
}
#[test]
fn without_compact_syntax_uses_inline_format(obj in arb_simple_object()) {
let config = SerializerConfig::default(); let serializer = LlmSerializer::with_config(config);
let mut doc = DxDocument::new();
doc.context.insert("config".to_string(), DxLlmValue::Obj(obj.clone()));
let output = serializer.serialize(&doc);
prop_assert!(!output.contains("@="),
"Without compact_syntax, should not use @= marker: {}", output);
prop_assert!(output.contains("config:"), "Should have name prefix: {}", output);
prop_assert!(output.contains('['), "Should use brackets: {}", output);
let bracket_content = output.split('[').nth(1).unwrap_or("");
if !obj.is_empty() {
prop_assert!(bracket_content.contains('='),
"Inline format should contain = signs: {}", output);
}
}
#[test]
fn compact_syntax_preserves_all_fields(obj in arb_simple_object()) {
let mut config = SerializerConfig::default();
config.compact_syntax = true;
let serializer = LlmSerializer::with_config(config);
let mut doc = DxDocument::new();
doc.context.insert("data".to_string(), DxLlmValue::Obj(obj.clone()));
let output = serializer.serialize(&doc);
for key in obj.keys() {
prop_assert!(output.contains(key),
"Key '{}' should appear in output: {}", key, output);
}
}
}