#![deny(clippy::all)]
use http::{HeaderMap, Method};
use parlov_core::OracleVerdict;
use parlov_elicit::{generate_plan, ProbePair, ProbeSpec, RiskLevel, ScanContext};
use parlov_probe::http::HttpProbe;
use parlov_probe::Probe;
use parlov_analysis::{Analyzer, SampleDecision};
use parlov_analysis::existence::ExistenceAnalyzer;
use parlov_core::{OracleResult, ProbeSet};
mod fixtures {
pub mod scan_server;
}
async fn collect_pair(pair: &ProbePair) -> OracleResult {
let client = HttpProbe::new();
let analyzer = ExistenceAnalyzer;
let mut probe_set = ProbeSet { baseline: Vec::new(), probe: Vec::new() };
loop {
let b = client
.execute(&pair.baseline)
.await
.expect("baseline request failed");
let p = client
.execute(&pair.probe)
.await
.expect("probe request failed");
probe_set.baseline.push(b);
probe_set.probe.push(p);
if let SampleDecision::Complete(result) = analyzer.evaluate(&probe_set) {
return result;
}
}
}
fn make_ctx(base_url: &str) -> ScanContext {
ScanContext {
target: format!("{base_url}/oracle/{{id}}"),
baseline_id: "1001".to_owned(),
probe_id: "9999".to_owned(),
headers: HeaderMap::new(),
max_risk: RiskLevel::Safe,
known_duplicate: None,
state_field: None,
alt_credential: None,
body_template: None,
}
}
#[tokio::test]
async fn accept_strategy_produces_confirmed_finding() {
let addr = fixtures::scan_server::spawn().await;
let base_url = format!("http://{addr}");
let ctx = make_ctx(&base_url);
let plan = generate_plan(&ctx);
let accept_pair = plan.iter().find_map(|spec| {
if let ProbeSpec::Pair(p) = spec {
if p.metadata.strategy_id == "accept-elicit" && p.baseline.method == Method::GET {
return Some(p.clone());
}
}
None
});
let pair = accept_pair.expect("accept-elicit GET spec must be in safe plan");
let result = collect_pair(&pair).await;
assert_eq!(
result.verdict,
OracleVerdict::Confirmed,
"accept-elicit should produce Confirmed; evidence: {:?}",
result.evidence
);
}
#[tokio::test]
async fn if_none_match_strategy_produces_confirmed_finding() {
let addr = fixtures::scan_server::spawn().await;
let base_url = format!("http://{addr}");
let ctx = make_ctx(&base_url);
let plan = generate_plan(&ctx);
let inmatch_pair = plan.iter().find_map(|spec| {
if let ProbeSpec::Pair(p) = spec {
if p.metadata.strategy_id == "if-none-match-elicit"
&& p.baseline.method == Method::GET
{
return Some(p.clone());
}
}
None
});
let pair = inmatch_pair.expect("if-none-match-elicit GET spec must be in safe plan");
let result = collect_pair(&pair).await;
assert_eq!(
result.verdict,
OracleVerdict::Confirmed,
"if-none-match-elicit should produce Confirmed; evidence: {:?}",
result.evidence
);
}
#[tokio::test]
async fn safe_plan_generates_specs_for_minimal_ctx() {
let addr = fixtures::scan_server::spawn().await;
let base_url = format!("http://{addr}");
let ctx = make_ctx(&base_url);
let plan = generate_plan(&ctx);
assert!(!plan.is_empty(), "safe plan must contain at least one spec");
}