use sml::parse_file;
use std::path::Path;
#[test]
fn showcase_contract_parses_and_applies() {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/../showcase_contract.sml");
if !Path::new(path).exists() {
eprintln!("跳过:未找到 {path}(crate 中未包含仓库根的示例文件)");
return;
}
let v = match parse_file(path) {
Ok(v) => v,
Err(e) => panic!("showcase_contract.sml 解析失败: {e}"),
};
assert_eq!(
v.get("database.primary.host").unwrap().as_str(),
Some("db1.internal")
);
assert_eq!(
v.get("database.primary.port"),
Some(&sml::Value::Int(5432)),
"primary 省略 port,应填 default 5432"
);
assert_eq!(
v.get("database.primary.tls"),
Some(&sml::Value::Bool(false)),
"primary 省略 tls,应填 default false"
);
assert_eq!(
v.get("database.primary.status").unwrap().as_str(),
Some("active")
);
assert_eq!(
v.get("database.replica.port"),
Some(&sml::Value::Int(5433)),
"显式值不应被 default 覆盖"
);
assert_eq!(
v.get("database.replica.tls"),
Some(&sml::Value::Bool(true))
);
assert_eq!(
v.get("database.replica.status").unwrap().as_str(),
Some("standby")
);
assert_eq!(
v.get("database.primary.address.city").unwrap().as_str(),
Some("Beijing")
);
assert_eq!(
v.get("database.primary.address.country").unwrap().as_str(),
Some("CN"),
"子块缺失字段应填被引用契约的 default"
);
assert_eq!(
v.get("database.replica.address.zip").unwrap().as_str(),
Some("200120")
);
assert_eq!(
v.get("metrics.latency"),
Some(&sml::Value::Float(12.5))
);
assert!(
v.get("metrics.customCounter").is_some(),
"loose 契约应保留未声明字段"
);
assert_eq!(
v.get("database.primary.prot"),
None,
"严格契约下的拼错字段不应被静默接受"
);
assert_eq!(v.get("contract"), None);
assert_eq!(v.get("Server"), None);
assert_eq!(v.get("Address"), None);
assert_eq!(v.get("Metrics"), None);
}