axiolid-reference 0.3.14

Portable scalar reference implementation and certified predicates
Documentation
//! Mutation probe: does the section conformance suite actually bite?
use axiolid_mesh_section_contract::conformance::{ConformanceSuite, RegionConformanceSuite};
use axiolid_mesh_section_contract::MeshPlaneSection;
use axiolid_reference::section::ScalarSection;

#[test]
fn scalar_section_satisfies_the_geometry_conformance_suite() {
    let report = ConformanceSuite::run(&ScalarSection);
    assert!(report.is_success(), "conformance failures: {report}");
}

#[test]
fn scalar_section_satisfies_the_region_conformance_suite() {
    let report = RegionConformanceSuite::run(&ScalarSection);
    assert!(
        report.claimed,
        "the reference provider implements section_request"
    );
    assert!(report.is_success(), "region conformance failures: {report}");
}

/// The reference provider, but refusing sheets as a solids-only provider would.
#[derive(Debug)]
struct SolidsOnly;

impl axiolid_contracts::Backend for SolidsOnly {
    fn descriptor(&self) -> axiolid_contracts::BackendDescriptor {
        ScalarSection.descriptor()
    }
}

impl MeshPlaneSection for SolidsOnly {
    fn section(
        &self,
        mesh: &axiolid_mesh::TriMesh,
        frame: axiolid_core::Frame3,
        limits: axiolid_mesh_section_contract::SectionLimits,
        options: &axiolid_contracts::ExecutionOptions,
    ) -> axiolid_contracts::GeomResult<axiolid_mesh_section_contract::SectionOutcome> {
        ScalarSection.section(mesh, frame, limits, options)
    }

    fn section_request(
        &self,
        mesh: &axiolid_mesh::TriMesh,
        request: &axiolid_mesh_section_contract::SectionRequest,
        options: &axiolid_contracts::ExecutionOptions,
    ) -> axiolid_contracts::GeomResult<axiolid_mesh_section_contract::PlaneSection> {
        if request.role == axiolid_mesh_section_contract::SectionRole::Sheet {
            return Err(axiolid_contracts::GeomError::Unsupported {
                backend: ScalarSection::ID,
                operation: axiolid_contracts::Operation::MeshPlaneSection,
            });
        }
        ScalarSection.section_request(mesh, request, options)
    }
}

#[test]
fn a_provider_without_sheets_passes_and_reports_it() {
    let report = RegionConformanceSuite::run(&SolidsOnly);
    assert!(report.claimed && report.is_success(), "{report}");
    assert!(!report.sheets_claimed);
    let full = RegionConformanceSuite::run(&ScalarSection);
    assert!(full.sheets_claimed);
}

/// The reference provider with a hook on the answer to a cut-region request.
#[derive(Debug)]
struct CutHook {
    hook: fn(
        axiolid_contracts::GeomResult<axiolid_mesh_section_contract::PlaneSection>,
    ) -> axiolid_contracts::GeomResult<axiolid_mesh_section_contract::PlaneSection>,
}

impl axiolid_contracts::Backend for CutHook {
    fn descriptor(&self) -> axiolid_contracts::BackendDescriptor {
        ScalarSection.descriptor()
    }
}

impl MeshPlaneSection for CutHook {
    fn section(
        &self,
        mesh: &axiolid_mesh::TriMesh,
        frame: axiolid_core::Frame3,
        limits: axiolid_mesh_section_contract::SectionLimits,
        options: &axiolid_contracts::ExecutionOptions,
    ) -> axiolid_contracts::GeomResult<axiolid_mesh_section_contract::SectionOutcome> {
        ScalarSection.section(mesh, frame, limits, options)
    }

    fn section_request(
        &self,
        mesh: &axiolid_mesh::TriMesh,
        request: &axiolid_mesh_section_contract::SectionRequest,
        options: &axiolid_contracts::ExecutionOptions,
    ) -> axiolid_contracts::GeomResult<axiolid_mesh_section_contract::PlaneSection> {
        let answer = ScalarSection.section_request(mesh, request, options);
        if request.cut_regions.is_some() {
            (self.hook)(answer)
        } else {
            answer
        }
    }
}

#[test]
fn the_reference_provider_claims_cut_regions() {
    let report = RegionConformanceSuite::run(&ScalarSection);
    assert!(
        report.cut_regions_claimed && report.is_success(),
        "{report}"
    );
}

#[test]
fn a_provider_that_refuses_cut_regions_passes_and_reports_it() {
    let report = RegionConformanceSuite::run(&CutHook {
        hook: |_| {
            Err(axiolid_contracts::GeomError::Unsupported {
                backend: ScalarSection::ID,
                operation: axiolid_contracts::Operation::MeshPlaneSection,
            })
        },
    });
    assert!(report.claimed && report.is_success(), "{report}");
    assert!(!report.cut_regions_claimed);
}

#[test]
fn a_provider_that_ignores_cut_regions_does_not_claim_them() {
    let report = RegionConformanceSuite::run(&CutHook {
        hook: |answer| {
            answer.map(|mut section| {
                section.cut_regions = None;
                section.evidence = section.evidence.with_cut_pairs(0).with_cut_output(&[]);
                section
            })
        },
    });
    assert!(report.claimed && report.is_success(), "{report}");
    assert!(!report.cut_regions_claimed);
}

#[test]
fn a_provider_that_claims_cut_regions_and_then_drops_them_fails() {
    let report = RegionConformanceSuite::run(&CutHook {
        hook: |answer| {
            answer.map(|mut section| {
                // The first case has none; a later one loses its regions.
                if section
                    .cut_regions
                    .as_ref()
                    .is_some_and(|cut| !cut.is_empty())
                {
                    section.cut_regions = None;
                }
                section
            })
        },
    });
    assert!(report.cut_regions_claimed && !report.is_success());
}

#[test]
fn a_provider_whose_rings_differ_from_the_chains_in_the_last_bit_fails() {
    // Within the fixtures' comparison tolerance, but not bit for bit.
    let report = RegionConformanceSuite::run(&CutHook {
        hook: |answer| {
            answer.map(|mut section| {
                if let Some(region) = section.cut_regions.as_mut().and_then(|cut| cut.first_mut()) {
                    region.outer[0].x += 1.0e-12;
                }
                section
            })
        },
    });
    assert!(!report.is_success());
}

#[test]
fn a_provider_that_reverses_a_cut_ring_fails() {
    let report = RegionConformanceSuite::run(&CutHook {
        hook: |answer| {
            answer.map(|mut section| {
                if let Some(region) = section.cut_regions.as_mut().and_then(|cut| cut.first_mut()) {
                    region.outer.reverse();
                }
                section
            })
        },
    });
    assert!(!report.is_success());
}