mod common;
use common::{build_client, cleanup, fresh_tenant, require_backend};
use reasoninglayer::{
psi, AddFactRequest, BackwardChainRequest, CreateSortRequest, CreateTermRequest,
FeatureInputValueDto, FindBySortRequest, Value,
};
use std::collections::BTreeMap;
#[tokio::test]
#[ignore = "requires a running backend"]
async fn diag_health_check_returns_status() {
let tenant = fresh_tenant();
let client = build_client(&tenant);
let resp = client
.health()
.check(None)
.await
.expect("health check round-trips");
assert_eq!(resp.status, "healthy", "backend should report healthy");
assert!(
!resp.components.is_empty(),
"expected at least one component reported"
);
}
#[tokio::test]
#[ignore = "requires a running backend"]
async fn diag_sorts_create_and_list_round_trips() {
let tenant = fresh_tenant();
let client = build_client(&tenant);
require_backend(&client).await;
let sort = client
.sorts()
.create_sort(CreateSortRequest::with_name("diag_sort"), None)
.await
.expect("create_sort succeeds");
assert_eq!(sort.name, "diag_sort");
assert_eq!(sort.tenant_id.to_string(), tenant);
let listed = client
.sorts()
.list_sorts(None)
.await
.expect("list_sorts succeeds");
assert!(
listed.iter().any(|s| s.id == sort.id),
"list_sorts should include just-created sort {}",
sort.id
);
cleanup(&client, &tenant).await;
}
#[tokio::test]
#[ignore = "requires a running backend"]
async fn diag_terms_create_round_trips() {
let tenant = fresh_tenant();
let client = build_client(&tenant);
require_backend(&client).await;
let sort = client
.sorts()
.create_sort(CreateSortRequest::with_name("diag_term_sort"), None)
.await
.expect("create_sort succeeds");
let mut features = BTreeMap::new();
features.insert("label".into(), Value::string("hello"));
let resp = client
.terms()
.create_term(
CreateTermRequest {
sort_id: sort.id.to_string(),
owner_id: tenant.clone(),
features,
},
None,
)
.await
.expect("create_term succeeds");
assert_eq!(resp.term.sort_id, sort.id.to_string());
assert_eq!(resp.term.owner_id, tenant);
cleanup(&client, &tenant).await;
}
#[tokio::test]
#[ignore = "requires a running backend"]
async fn diag_inference_add_fact_then_get_facts() {
let tenant = fresh_tenant();
let client = build_client(&tenant);
require_backend(&client).await;
client
.sorts()
.create_sort(CreateSortRequest::with_name("diag_fact_sort"), None)
.await
.expect("create_sort succeeds");
let fact = psi(
"diag_fact_sort",
[("name", FeatureInputValueDto::string("alpha"))],
);
client
.inference()
.add_fact(
AddFactRequest { term: fact },
None,
)
.await
.expect("add_fact succeeds");
let facts = client
.inference()
.get_facts(None)
.await
.expect("get_facts succeeds");
assert!(
facts.facts.iter().any(|t| t.sort_name == "diag_fact_sort"),
"expected the just-added fact to appear in get_facts"
);
cleanup(&client, &tenant).await;
}
#[tokio::test]
#[ignore = "requires a running backend"]
async fn diag_query_find_by_sort_returns_terms() {
let tenant = fresh_tenant();
let client = build_client(&tenant);
require_backend(&client).await;
let sort_name = "diag_query_sort";
let sort = client
.sorts()
.create_sort(CreateSortRequest::with_name(sort_name), None)
.await
.expect("create_sort succeeds");
let mut features = BTreeMap::new();
features.insert("name".into(), Value::string("alpha"));
client
.terms()
.create_term(
CreateTermRequest {
sort_id: sort.id.to_string(),
owner_id: tenant.clone(),
features,
},
None,
)
.await
.expect("create_term succeeds");
let terms = client
.query()
.find_by_sort(
FindBySortRequest {
sort_name: Some(sort_name.into()),
..Default::default()
},
None,
)
.await
.expect("find_by_sort succeeds");
assert!(
!terms.is_empty(),
"expected at least one term for sort {sort_name}, got 0"
);
cleanup(&client, &tenant).await;
}
#[tokio::test]
#[ignore = "requires a running backend"]
async fn diag_admin_list_tenants_returns_us() {
let tenant = fresh_tenant();
let client = build_client(&tenant);
require_backend(&client).await;
let listed = client
.admin()
.list_tenants(None)
.await
.expect("list_tenants succeeds");
for t in &listed.tenants {
assert!(
uuid::Uuid::parse_str(&t.tenant_id).is_ok(),
"list_tenants returned non-UUID tenant_id: {:?}",
t.tenant_id
);
}
cleanup(&client, &tenant).await;
}
#[tokio::test]
#[ignore = "requires a running backend"]
async fn diag_backward_chain_round_trips_empty_solution() {
let tenant = fresh_tenant();
let client = build_client(&tenant);
require_backend(&client).await;
client
.sorts()
.create_sort(CreateSortRequest::with_name("diag_chain_sort"), None)
.await
.expect("create_sort succeeds");
let resp = client
.inference()
.backward_chain(
BackwardChainRequest {
goal: Some(psi(
"diag_chain_sort",
[("name", FeatureInputValueDto::string("missing"))],
)),
max_solutions: Some(1),
..Default::default()
},
None,
)
.await
.expect("backward_chain round-trips even on empty result");
assert!(
resp.solutions.is_empty(),
"expected empty solutions but got {}",
resp.solutions.len()
);
cleanup(&client, &tenant).await;
}