use super::{ConformanceLevel, CoverageMetrics, OpOutcome, OpResult, TrackReport};
use crate::pipeline::CertificateTrack;
use crate::spec::types::OpSpec;
pub(super) fn optional_track(
routed_ops: &[(CertificateTrack, &OpSpec, OpResult)],
target: CertificateTrack,
parity_level: ConformanceLevel,
algebraic_level: ConformanceLevel,
) -> Option<TrackReport> {
let track = build_track(routed_ops, target, parity_level, algebraic_level);
(!track.ops.is_empty()).then_some(track)
}
pub(super) fn build_track(
routed_ops: &[(CertificateTrack, &OpSpec, OpResult)],
target: CertificateTrack,
parity_level: ConformanceLevel,
algebraic_level: ConformanceLevel,
) -> TrackReport {
let specs: Vec<_> = routed_ops
.iter()
.filter_map(|(track, spec, _)| (*track == target).then_some(*spec))
.collect();
let ops: Vec<_> = routed_ops
.iter()
.filter_map(|(track, _, op_result)| (*track == target).then_some(op_result.clone()))
.collect();
let supported: Vec<_> = ops
.iter()
.zip(specs.iter())
.filter(|(op, _)| !matches!(op.outcome, OpOutcome::Unsupported | OpOutcome::Pending))
.collect();
let all_parity = !supported.is_empty() && supported.iter().all(|(op, _)| op.parity_passed);
let all_laws = supported
.iter()
.all(|(op, spec)| op.laws_failed.is_empty() && op.laws_verified.len() == spec.laws.len());
let level = if supported.is_empty() {
None
} else if all_parity && all_laws {
Some(algebraic_level)
} else if all_parity {
Some(parity_level)
} else {
None
};
TrackReport {
level,
coverage: coverage_for_refs(&specs, &ops),
unsupported_ops: unsupported_ops(&ops),
ops,
}
}
pub(super) fn coverage_for(specs: &[OpSpec], ops: &[OpResult]) -> CoverageMetrics {
let spec_refs: Vec<_> = specs.iter().collect();
coverage_for_refs(&spec_refs, ops)
}
pub(super) fn coverage_for_refs(specs: &[&OpSpec], ops: &[OpResult]) -> CoverageMetrics {
let laws_total = specs
.iter()
.zip(ops)
.filter(|(_, op)| !matches!(op.outcome, OpOutcome::Unsupported | OpOutcome::Pending))
.map(|(spec, _)| spec.laws.len() as u64)
.sum();
CoverageMetrics {
ops_total: ops.len() as u64,
ops_parity_passed: ops
.iter()
.filter(|op| op.outcome == OpOutcome::Passed)
.count() as u64,
ops_unsupported: ops
.iter()
.filter(|op| op.outcome == OpOutcome::Unsupported)
.count() as u64,
ops_laws_passed: ops
.iter()
.filter(|op| {
!matches!(op.outcome, OpOutcome::Unsupported | OpOutcome::Pending)
&& op.laws_failed.is_empty()
})
.count() as u64,
laws_total,
laws_passed: ops.iter().map(|op| op.laws_verified.len() as u64).sum(),
equivalence_classes_total: specs
.iter()
.map(|spec| spec.equivalence_classes.len() as u64)
.sum(),
boundary_values_total: specs
.iter()
.map(|spec| spec.boundary_values.len() as u64)
.sum(),
cases_tested: ops.iter().map(|op| op.cases_tested).sum(),
}
}
pub(super) fn unsupported_ops(ops: &[OpResult]) -> Vec<String> {
ops.iter()
.filter(|op| op.outcome == OpOutcome::Unsupported)
.map(|op| op.id.clone())
.collect()
}
pub(super) fn build_certificate_hash(
backend_id: &str,
specs: &[OpSpec],
registry_hash: &[u8; 32],
) -> [u8; 32] {
let mut hasher = blake3::Hasher::new();
hasher.update(b"vyre-conform-certificate-v1");
hasher.update(backend_id.as_bytes());
hasher.update(registry_hash);
for spec in specs {
hasher.update(spec.id.as_bytes());
hasher.update(&spec.version.to_le_bytes());
hasher.update(&spec.signature.min_input_bytes().to_le_bytes());
}
*hasher.finalize().as_bytes()
}