use adk_core::AdkError;
use proptest::prelude::*;
const POSTGRES_ERROR_PREFIXES: &[&str] = &[
"database connection failed",
"migration failed",
"transaction failed",
"query failed",
"serialize failed",
"insert failed",
"commit failed",
"delete failed",
"update failed",
"session not found",
];
fn make_postgres_error(prefix: &str, detail: &str) -> AdkError {
if detail.is_empty() {
AdkError::session(prefix.to_string())
} else {
AdkError::session(format!("{prefix}: {detail}"))
}
}
fn arb_error_detail() -> impl Strategy<Value = String> {
"[a-zA-Z0-9 _.,:;!?()-]{1,80}"
}
fn arb_error_prefix() -> impl Strategy<Value = &'static str> {
prop::sample::select(POSTGRES_ERROR_PREFIXES)
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(200))]
#[test]
fn prop_postgres_errors_are_session_variant_with_context(
prefix in arb_error_prefix(),
detail in arb_error_detail(),
) {
let err = make_postgres_error(prefix, &detail);
prop_assert!(err.is_session(), "expected session error, got: {:?}", err);
let msg = &err.message;
prop_assert!(!msg.is_empty(), "error message must not be empty");
prop_assert!(
msg.starts_with(prefix),
"error message '{msg}' must start with prefix '{prefix}'"
);
prop_assert!(
msg.contains(&detail),
"error message '{msg}' must contain detail '{detail}'"
);
let display = err.to_string();
prop_assert!(!display.is_empty(), "Display output must not be empty");
prop_assert!(
display.contains(prefix),
"Display '{display}' must contain prefix '{prefix}'"
);
}
#[test]
fn prop_postgres_bare_errors_are_session_variant(
prefix in arb_error_prefix(),
) {
let err = make_postgres_error(prefix, "");
prop_assert!(err.is_session(), "expected session error, got: {:?}", err);
let msg = &err.message;
prop_assert!(!msg.is_empty(), "bare error message must not be empty");
prop_assert_eq!(msg.as_str(), prefix);
}
#[test]
fn prop_postgres_errors_implement_std_error(
prefix in arb_error_prefix(),
detail in arb_error_detail(),
) {
let err = make_postgres_error(prefix, &detail);
let std_err: &dyn std::error::Error = &err;
let display = std_err.to_string();
prop_assert!(!display.is_empty(), "std::error::Error display must not be empty");
prop_assert!(
display.contains(prefix),
"std error display '{display}' must contain prefix '{prefix}'"
);
}
}
#[test]
fn test_all_postgres_error_prefixes_produce_session_variant() {
for prefix in POSTGRES_ERROR_PREFIXES {
let err = AdkError::session(format!("{prefix}: some underlying error"));
assert!(err.is_session(), "expected session error for prefix '{prefix}', got: {err:?}");
let msg = &err.message;
assert!(!msg.is_empty(), "prefix '{prefix}' produced empty message");
assert!(msg.starts_with(prefix), "prefix '{prefix}' not at start of message '{msg}'");
}
}