use std::collections::HashMap;
use epics_base_rs::server::ioc_builder::IocBuilder;
async fn load(db: &str) -> Result<(), String> {
let builder = IocBuilder::new()
.db_string(db, &HashMap::new())
.expect("parse is fine — the refusal happens at field application");
match builder.build().await {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
}
fn failed_to_load() -> String {
format!(
"Failed to load '{}'",
epics_base_rs::server::db_loader::DB_STRING_SOURCE
)
}
fn reason(db: &str) -> String {
let defs = epics_base_rs::server::db_loader::parse_db(db, &HashMap::new())
.expect("parse is fine — the refusal happens at field application");
for def in defs {
let mut record = epics_base_rs::server::db_loader::create_record_with_factories(
&def.record_type,
&HashMap::new(),
)
.unwrap_or_else(|e| panic!("{}: create_record failed: {e}", def.record_type));
let mut common = Vec::new();
if let Err(e) =
epics_base_rs::server::db_loader::apply_fields(&mut record, &def.fields, &mut common)
{
return e.to_string();
}
}
panic!("no field was refused in: {db}");
}
#[epics_macros_rs::epics_test]
async fn lso_val_in_db_is_refused_with_the_real_reason() {
let db = r#"record(lso, "L") { field(VAL, "hello") }"#;
let status = load(db)
.await
.expect_err("C refuses lso VAL from a .db (measured on softIoc)");
assert_eq!(status, failed_to_load());
let msg = reason(db);
assert!(
msg.contains("before iocInit"),
"diagnostic must name the real constraint, got: {msg}"
);
assert!(
!msg.contains("cannot parse"),
"must not blame the value's syntax, got: {msg}"
);
}
#[epics_macros_rs::epics_test]
async fn printf_val_in_db_is_refused_and_other_lso_fields_still_load() {
let db = r#"record(printf, "P") { field(VAL, "x") }"#;
let status = load(db)
.await
.expect_err("printf VAL is the same DBF_NOACCESS refusal family");
assert_eq!(status, failed_to_load());
let msg = reason(db);
assert!(msg.contains("before iocInit"), "got: {msg}");
load(r#"record(lso, "L2") { field(SIZV, "80") }"#)
.await
.expect("non-long-string lso fields must still load");
}