use serde_json::Value;
fn known_methods() -> Vec<&'static str> {
let mut methods = vec![
"create",
"load",
"load_with_info",
"ephemeral",
"create_with_params",
"from_agent",
"get_agent_id",
"key_id",
"is_strict",
"config_path",
"export_agent",
"get_public_key_pem",
"get_public_key_base64",
"diagnostics",
"inner_ref",
"verify_self",
"verify_json",
"verify_with_key_json",
"verify_by_id_json",
"sign_message_json",
"sign_raw_bytes_base64",
"sign_file_json",
"to_yaml",
"from_yaml",
"to_html",
"from_html",
"rotate_keys",
"export_w3c_did",
"export_w3c_did_document_json",
"export_w3c_agent_description_json",
"generate_w3c_well_known_json",
"sign_w3c_request_json",
"verify_w3c_request_json",
"sign_text_file_json",
"verify_text_file_json",
"sign_image_json",
"verify_image_json",
"extract_media_signature_json",
];
methods.sort();
methods
}
#[cfg(feature = "agreements")]
fn known_agreement_v2_methods() -> Vec<&'static str> {
let mut methods = vec![
"create_agreement_v2_json",
"apply_agreement_v2_json",
"sign_agreement_v2_json",
"verify_agreement_v2_json",
"detect_agreement_v2_branch_conflict_json",
"merge_agreement_v2_transcript_branches_json",
"resolve_agreement_v2_branch_conflict_json",
];
methods.sort();
methods
}
fn load_method_parity_fixture() -> Value {
let fixture_bytes = include_bytes!("fixtures/method_parity.json");
serde_json::from_slice(fixture_bytes).expect("method_parity.json should be valid JSON")
}
#[test]
fn test_method_parity_fixture_matches_impl() {
let fixture = load_method_parity_fixture();
let fixture_methods: Vec<String> = fixture["all_methods_flat"]
.as_array()
.expect("all_methods_flat should be an array")
.iter()
.map(|v| {
v.as_str()
.expect("each method should be a string")
.to_string()
})
.collect();
let known = known_methods();
let known_strings: Vec<String> = known.iter().map(|s| s.to_string()).collect();
assert_eq!(
fixture_methods,
known_strings,
"\nFixture method list does not match known SimpleAgentWrapper methods.\n\
\nFixture has {} methods, known list has {} methods.\n\
\nIn fixture but not in known list: {:?}\n\
In known list but not in fixture: {:?}\n\
\nIf you added a method to SimpleAgentWrapper, update BOTH:\n\
1. binding-core/tests/fixtures/method_parity.json\n\
2. The known_methods() list in binding-core/tests/method_parity.rs",
fixture_methods.len(),
known_strings.len(),
fixture_methods
.iter()
.filter(|m| !known_strings.contains(m))
.collect::<Vec<_>>(),
known_strings
.iter()
.filter(|m| !fixture_methods.contains(m))
.collect::<Vec<_>>(),
);
}
#[test]
fn test_method_parity_fixture_categories_cover_all() {
let fixture = load_method_parity_fixture();
let categories = fixture["simple_agent_wrapper_methods"]
.as_object()
.expect("simple_agent_wrapper_methods should be an object");
let mut category_methods: Vec<String> = Vec::new();
for (_category_name, methods) in categories {
for method in methods.as_array().expect("category should be an array") {
category_methods.push(
method
.as_str()
.expect("method should be a string")
.to_string(),
);
}
}
category_methods.sort();
let flat_methods: Vec<String> = fixture["all_methods_flat"]
.as_array()
.expect("all_methods_flat should be an array")
.iter()
.map(|v| {
v.as_str()
.expect("each method should be a string")
.to_string()
})
.collect();
assert_eq!(
category_methods,
flat_methods,
"\nCategorized methods do not match all_methods_flat.\n\
This means the fixture is internally inconsistent.\n\
\nIn categories but not in flat: {:?}\n\
In flat but not in categories: {:?}",
category_methods
.iter()
.filter(|m| !flat_methods.contains(m))
.collect::<Vec<_>>(),
flat_methods
.iter()
.filter(|m| !category_methods.contains(m))
.collect::<Vec<_>>(),
);
}
#[test]
fn test_method_parity_fixture_count() {
let fixture = load_method_parity_fixture();
let flat_methods = fixture["all_methods_flat"]
.as_array()
.expect("all_methods_flat should be an array");
assert_eq!(
flat_methods.len(),
38,
"SimpleAgentWrapper should have exactly 38 public methods. \
Found {}. If you added or removed a method, update the fixture.",
flat_methods.len()
);
}
#[cfg(feature = "agreements")]
#[test]
fn test_agreement_v2_feature_gated_methods_match_impl() {
let fixture = load_method_parity_fixture();
let mut fixture_methods: Vec<String> = fixture["feature_gated_methods"]["agreements"]
.as_array()
.expect("feature_gated_methods.agreements should be an array")
.iter()
.map(|v| {
v.as_str()
.expect("each agreement v2 method should be a string")
.to_string()
})
.collect();
fixture_methods.sort();
let known = known_agreement_v2_methods();
let known_strings: Vec<String> = known.iter().map(|s| s.to_string()).collect();
assert_eq!(
fixture_methods, known_strings,
"\nAgreement v2 feature-gated methods do not match SimpleAgentWrapper.\n\
If you added an agreement v2 binding-core method, update \
binding-core/tests/fixtures/method_parity.json feature_gated_methods.agreements."
);
}
#[cfg(feature = "agreements")]
#[test]
fn wrapper_exposes_create_agreement_v2_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::create_agreement_v2_json;
}
#[cfg(feature = "agreements")]
#[test]
fn wrapper_exposes_apply_agreement_v2_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::apply_agreement_v2_json;
}
#[cfg(feature = "agreements")]
#[test]
fn wrapper_exposes_sign_agreement_v2_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::sign_agreement_v2_json;
}
#[cfg(feature = "agreements")]
#[test]
fn wrapper_exposes_verify_agreement_v2_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::verify_agreement_v2_json;
}
#[cfg(feature = "agreements")]
#[test]
fn wrapper_exposes_detect_agreement_v2_branch_conflict_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
&str,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::detect_agreement_v2_branch_conflict_json;
}
#[cfg(feature = "agreements")]
#[test]
fn wrapper_exposes_merge_agreement_v2_transcript_branches_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
&str,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::merge_agreement_v2_transcript_branches_json;
}
#[cfg(feature = "agreements")]
#[test]
fn wrapper_exposes_resolve_agreement_v2_branch_conflict_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
&str,
&str,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::resolve_agreement_v2_branch_conflict_json;
}
#[test]
fn wrapper_exposes_sign_text_file_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::sign_text_file_json;
}
#[test]
fn wrapper_exposes_verify_text_file_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::verify_text_file_json;
}
#[test]
fn wrapper_exposes_sign_image_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
&str,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::sign_image_json;
}
#[test]
fn wrapper_exposes_verify_image_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::verify_image_json;
}
#[test]
fn wrapper_exposes_extract_media_signature_json() {
let _: fn(
&jacs_binding_core::SimpleAgentWrapper,
&str,
&str,
) -> jacs_binding_core::BindingResult<String> =
jacs_binding_core::SimpleAgentWrapper::extract_media_signature_json;
}