use super::*;
use parlov_core::{OracleClass, OracleResult, OracleVerdict, Signal, SignalKind};
use crate::context::test_helpers::{exchange_ctx, probe_ctx};
fn confirmed_with_metadata() -> OracleResult {
OracleResult {
class: OracleClass::Existence,
verdict: OracleVerdict::Confirmed,
severity: Some(Severity::High),
confidence: 0,
impact_class: None,
reasons: vec![],
signals: vec![Signal {
kind: SignalKind::StatusCodeDiff,
evidence: "403 (baseline) vs 404 (probe)".into(),
rfc_basis: None,
}],
technique_id: None,
vector: None,
normative_strength: None,
label: Some("Authorization-based differential".into()),
leaks: Some("Resource existence confirmed".into()),
rfc_basis: Some("RFC 9110 \u{00a7}15.5.4".into()),
}
}
fn not_present_no_metadata() -> OracleResult {
OracleResult {
class: OracleClass::Existence,
verdict: OracleVerdict::NotPresent,
severity: None,
confidence: 0,
impact_class: None,
reasons: vec![],
signals: vec![Signal {
kind: SignalKind::StatusCodeDiff,
evidence: "404 (baseline) vs 404 (probe)".into(),
rfc_basis: None,
}],
technique_id: None,
vector: None,
normative_strength: None,
label: None,
leaks: None,
rfc_basis: None,
}
}
#[test]
fn table_includes_label_when_present() {
let table = render_table(&confirmed_with_metadata());
assert!(table.contains("Authorization-based differential"));
}
#[test]
fn table_includes_leaks_when_present() {
let table = render_table(&confirmed_with_metadata());
assert!(table.contains("Resource existence confirmed"));
}
#[test]
fn table_includes_rfc_basis_when_present() {
let table = render_table(&confirmed_with_metadata());
assert!(table.contains("RFC 9110 \u{00a7}15.5.4"));
}
#[test]
fn table_omits_label_row_when_none() {
let table = render_table(¬_present_no_metadata());
assert!(!table.contains("Label"));
}
#[test]
fn table_omits_leaks_row_when_none() {
let table = render_table(¬_present_no_metadata());
assert!(!table.contains("Leaks"));
}
#[test]
fn table_omits_rfc_basis_row_when_none() {
let table = render_table(¬_present_no_metadata());
assert!(!table.contains("RFC Basis"));
}
#[test]
fn table_shows_primary_evidence_from_signals() {
let table = render_table(&confirmed_with_metadata());
assert!(table.contains("403 (baseline) vs 404 (probe)"));
}
#[test]
fn scan_table_contains_strategy_name_and_method() {
let findings = vec![crate::ScanFinding {
target_url: "https://api.example.com/users/1".to_owned(),
strategy_id: "accept-elicit".to_owned(),
strategy_name: "Accept header elicitation".to_owned(),
method: "GET".to_owned(),
result: not_present_no_metadata(),
repro: None,
probe: probe_ctx(
"GET",
"https://api.example.com/users/1",
"https://api.example.com/users/9999",
),
exchange: exchange_ctx(404, 404),
chain_provenance: None,
}];
let table = render_scan_table(&findings);
assert!(table.contains("Accept header elicitation"));
assert!(table.contains("GET"));
}
#[test]
fn scan_table_confirmed_verdict_appears() {
let findings = vec![crate::ScanFinding {
target_url: "https://api.example.com/users/1".to_owned(),
strategy_id: "s1".to_owned(),
strategy_name: "test".to_owned(),
method: "GET".to_owned(),
result: confirmed_with_metadata(),
repro: None,
probe: probe_ctx(
"GET",
"https://api.example.com/users/1",
"https://api.example.com/users/9999",
),
exchange: exchange_ctx(403, 404),
chain_provenance: None,
}];
let table = render_scan_table(&findings);
assert!(table.contains("Confirmed"));
}
#[test]
fn scan_table_empty_findings_no_panic() {
let table = render_scan_table(&[]);
assert!(!table.is_empty());
}
fn confirmed_endpoint_verdict() -> parlov_core::EndpointVerdict {
use parlov_core::{
EndpointStopReason, EndpointVerdict, ObservabilityStatus, OracleClass, OracleVerdict,
Severity,
};
EndpointVerdict {
oracle_class: OracleClass::Existence,
posterior_probability: 0.87,
verdict: OracleVerdict::Confirmed,
severity: Some(Severity::High),
strategies_run: 8,
strategies_total: 20,
stop_reason: Some(EndpointStopReason::EarlyAccept),
first_threshold_crossed_by: None,
final_confirming_strategy: None,
contributing_findings: vec![],
observability_status: ObservabilityStatus::EvidenceObserved,
block_summary: None,
}
}
fn inconclusive_endpoint_verdict() -> parlov_core::EndpointVerdict {
use parlov_core::{EndpointVerdict, ObservabilityStatus, OracleClass, OracleVerdict};
EndpointVerdict {
oracle_class: OracleClass::Existence,
posterior_probability: 0.50,
verdict: OracleVerdict::Inconclusive,
severity: None,
strategies_run: 5,
strategies_total: 5,
stop_reason: None,
first_threshold_crossed_by: None,
final_confirming_strategy: None,
contributing_findings: vec![],
observability_status: ObservabilityStatus::Underpowered,
block_summary: None,
}
}
#[test]
fn endpoint_table_contains_posterior_percentage() {
let table = render_endpoint_verdict_table(&confirmed_endpoint_verdict(), &[]);
assert!(
table.contains("87%"),
"expected posterior percentage in output, got:\n{table}"
);
}
#[test]
fn endpoint_table_contains_verdict_string() {
let table = render_endpoint_verdict_table(&confirmed_endpoint_verdict(), &[]);
assert!(
table.contains("Confirmed"),
"expected verdict string in output, got:\n{table}"
);
}
#[test]
fn endpoint_table_contains_stop_reason_when_set() {
let table = render_endpoint_verdict_table(&confirmed_endpoint_verdict(), &[]);
assert!(
table.contains("EarlyAccept"),
"expected stop_reason in output, got:\n{table}"
);
}
#[test]
fn endpoint_table_no_stop_reason_shows_dash() {
let table = render_endpoint_verdict_table(&inconclusive_endpoint_verdict(), &[]);
assert!(table.contains('\u{2014}') || table.contains("—"));
}
#[test]
fn endpoint_table_first_column_header_is_oracle_slash_strategy() {
let table = render_endpoint_verdict_table(&confirmed_endpoint_verdict(), &[]);
assert!(
table.contains("Oracle / Strategy"),
"expected 'Oracle / Strategy' column header, got:\n{table}"
);
}
fn blocked_endpoint_verdict() -> parlov_core::EndpointVerdict {
use parlov_core::{
BlockFamily, BlockSummary, EndpointVerdict, ObservabilityStatus, OracleClass, OracleVerdict,
};
EndpointVerdict {
oracle_class: OracleClass::Existence,
posterior_probability: 0.50,
verdict: OracleVerdict::Inconclusive,
severity: None,
strategies_run: 8,
strategies_total: 8,
stop_reason: None,
first_threshold_crossed_by: None,
final_confirming_strategy: None,
contributing_findings: vec![],
observability_status: ObservabilityStatus::BlockedBeforeOracleLayer,
block_summary: Some(BlockSummary {
expected_observation_opportunities: 8,
blocked_before_oracle_layer: 8,
blocked_fraction: 1.0,
dominant_block_family: BlockFamily::Authorization,
dominant_block_reasons: vec![
"auth gate fired before technique (no credential provided)".to_owned(),
],
operator_action: Some(
r#"Retry with --header "Authorization: Bearer <token>""#.to_owned(),
),
}),
}
}
#[test]
fn blocked_endpoint_table_contains_observability_label() {
let table = render_endpoint_verdict_table(&blocked_endpoint_verdict(), &[]);
assert!(
table.contains("Observability"),
"expected 'Observability' label in blocked verdict table, got:\n{table}"
);
}
#[test]
fn blocked_endpoint_table_contains_blocked_before_oracle_layer() {
let table = render_endpoint_verdict_table(&blocked_endpoint_verdict(), &[]);
assert!(
table.contains("blocked before oracle layer") || table.contains("BlockedBeforeOracleLayer"),
"expected blocked-before-oracle-layer status in table, got:\n{table}"
);
}
#[test]
fn blocked_endpoint_table_contains_blocked_fraction() {
let table = render_endpoint_verdict_table(&blocked_endpoint_verdict(), &[]);
assert!(
table.contains("8/8"),
"expected blocked fraction '8/8' in table, got:\n{table}"
);
}
#[test]
fn blocked_endpoint_table_contains_action_row() {
let table = render_endpoint_verdict_table(&blocked_endpoint_verdict(), &[]);
assert!(
table.contains("Action"),
"expected 'Action' row in blocked verdict table, got:\n{table}"
);
}