use super::*;
fn derived_config_type(siblings: Vec<FieldDef>) -> TypeDef {
let target = FieldDef {
default: Some("serde(default = \"mylib::default_count\")".to_string()),
typed_default: Some(DefaultValue::FunctionCall("mylib::default_count".to_string())),
..make_field("count", TypeRef::Primitive(PrimitiveType::U32))
};
let mut fields = siblings;
fields.push(target);
TypeDef {
name: "DerivedConfig".to_string(),
rust_path: "mylib::DerivedConfig".to_string(),
has_default: true,
has_serde: true,
fields,
..Default::default()
}
}
fn target_field(typ: &TypeDef) -> &FieldDef {
typ.fields.iter().find(|f| f.name == "count").unwrap()
}
#[test]
fn derive_default_seeded_empty_is_not_treated_as_a_serde_default() {
let label = FieldDef {
typed_default: Some(DefaultValue::Empty),
..make_field("label", TypeRef::String)
};
let typ = derived_config_type(vec![label]);
let rendered = default_value_for_field_in_type(target_field(&typ), "rust", &typ);
assert_eq!(
rendered,
"serde_json::from_str::<mylib::DerivedConfig>(r#\"{\"label\":\"\"}\"#)\
.expect(\"alef-generated default JSON for `DerivedConfig` failed to deserialize\").count",
"a required sibling seeded `Empty` only by `#[derive(Default)]` must still get a \
placeholder, not be dropped from the probe: {rendered}"
);
}
#[test]
fn container_level_serde_default_omits_an_unmarked_sibling() {
let label = make_field("label", TypeRef::String);
let mut typ = derived_config_type(vec![label]);
typ.serde_container_default = true;
let rendered = default_value_for_field_in_type(target_field(&typ), "rust", &typ);
assert_eq!(
rendered,
"serde_json::from_str::<mylib::DerivedConfig>(r#\"{}\"#)\
.expect(\"alef-generated default JSON for `DerivedConfig` failed to deserialize\").count",
"a container-level `#[serde(default)]` must omit every sibling, including one with no \
attribute of its own: {rendered}"
);
}
#[test]
fn field_level_named_serde_default_omits_its_own_sibling() {
let user_agent = FieldDef {
default: Some("serde(default = \"mylib::default_user_agent\")".to_string()),
typed_default: Some(DefaultValue::FunctionCall("mylib::default_user_agent".to_string())),
..make_field("user_agent", TypeRef::String)
};
let typ = derived_config_type(vec![user_agent]);
let rendered = default_value_for_field_in_type(target_field(&typ), "rust", &typ);
assert_eq!(
rendered,
"serde_json::from_str::<mylib::DerivedConfig>(r#\"{}\"#)\
.expect(\"alef-generated default JSON for `DerivedConfig` failed to deserialize\").count",
"a field carrying its own named serde default must be omitted from the probe: {rendered}"
);
}
#[test]
fn optional_sibling_is_omitted_regardless_of_default() {
let nickname = FieldDef {
optional: true,
..make_field("nickname", TypeRef::Optional(Box::new(TypeRef::String)))
};
let typ = derived_config_type(vec![nickname]);
let rendered = default_value_for_field_in_type(target_field(&typ), "rust", &typ);
assert_eq!(
rendered,
"serde_json::from_str::<mylib::DerivedConfig>(r#\"{}\"#)\
.expect(\"alef-generated default JSON for `DerivedConfig` failed to deserialize\").count",
"an Option<T> sibling must be omitted from the probe: {rendered}"
);
}
#[test]
fn required_nested_named_sibling_fails_generation_instead_of_probing_empty() {
let owner = FieldDef {
typed_default: Some(DefaultValue::Empty),
..make_field("owner", TypeRef::Named("Author".to_string()))
};
let typ = derived_config_type(vec![owner]);
let message = default_value_for_field_in_type(target_field(&typ), "rust", &typ);
assert!(
message.starts_with("compile_error!"),
"a required sibling with no safe placeholder must fail generation, not probe `{{}}`: {message}"
);
for needle in ["mylib", "DerivedConfig", "count", "mylib::default_count"] {
assert!(
message.contains(needle),
"the failure must name `{needle}` so the author can act on it: {message}"
);
}
}