molframe-core 0.6.1

Core types, storage and analysis contracts for molframe
Documentation
use super::*;
use crate::span::Position;

fn at(offset: u32) -> ByteSpan {
    ByteSpan::new(
        Position::new(u64::from(offset), 1, u64::from(offset) + 1),
        u64::from(offset) + 1,
    )
}

#[test]
fn a_finding_with_no_message_reports_its_registered_cause() {
    let finding = Diagnostic::new(Code::W3011);
    assert_eq!(
        finding.message(),
        "residue boundary was inferred from file order by explicit policy"
    );
    assert!(finding.remedy().contains("residue identifiers"));
}

#[test]
fn a_finding_carries_the_severity_its_code_is_registered_with() {
    assert_eq!(Diagnostic::new(Code::E1103).severity(), Severity::Breaking);
    assert_eq!(Diagnostic::new(Code::W2001).severity(), Severity::Info);
}

#[test]
fn a_finding_preserves_rows_beyond_chunk_local_range() {
    let row = u64::from(u32::MAX) + 17;
    assert_eq!(Diagnostic::new(Code::E1103).at_row(row).row(), Some(row));
}

#[test]
fn findings_are_returned_worst_first_then_by_position_then_by_code() {
    let mut sink = Diagnostics::new();
    sink.push(Diagnostic::new(Code::W2001).at(at(50)));
    sink.push(Diagnostic::new(Code::E1103).at(at(90)));
    sink.push(Diagnostic::new(Code::W3011).at(at(10)));
    sink.push(Diagnostic::new(Code::W2002).at(at(50)));

    let ordered: Vec<_> = sink.finish().iter().map(Diagnostic::code).collect();
    assert_eq!(
        ordered,
        [Code::E1103, Code::W3011, Code::W2001, Code::W2002]
    );
}

#[test]
fn findings_without_a_position_sort_after_findings_with_one() {
    let mut sink = Diagnostics::new();
    sink.push(Diagnostic::new(Code::W2001));
    sink.push(Diagnostic::new(Code::W2002).at(at(900)));

    let ordered: Vec<_> = sink.finish().iter().map(Diagnostic::code).collect();
    assert_eq!(ordered, [Code::W2002, Code::W2001]);
}

#[test]
fn strictness_decides_whether_an_accumulated_finding_counts_as_failure() {
    let mut sink = Diagnostics::new();
    sink.push(Diagnostic::new(Code::E2003));
    assert!(sink.has_error(Strictness::Strict));
    assert!(!sink.has_error(Strictness::Medium));
    assert!(!sink.has_error(Strictness::Loose));
}

#[test]
fn the_worst_severity_is_tracked_without_rescanning_the_list() {
    let mut sink = Diagnostics::new();
    assert_eq!(sink.worst(), None);
    sink.push(Diagnostic::new(Code::W2001));
    assert_eq!(sink.worst(), Some(Severity::Info));
    sink.push(Diagnostic::new(Code::E1103));
    sink.push(Diagnostic::new(Code::W2002));
    assert_eq!(sink.worst(), Some(Severity::Breaking));
}

#[test]
fn the_same_input_produces_the_same_list_in_the_same_order() {
    let build = || {
        let mut sink = Diagnostics::new();
        for (code, offset) in [
            (Code::W2002, 30),
            (Code::E1101, 5),
            (Code::W3011, 30),
            (Code::W2001, 1),
        ] {
            sink.push(Diagnostic::new(code).at(at(offset)));
        }
        sink.finish()
            .iter()
            .map(Diagnostic::code)
            .collect::<Vec<_>>()
    };
    assert_eq!(build(), build());
}

#[test]
fn findings_beyond_the_ceiling_are_counted_rather_than_retained() {
    let mut diagnostics = Diagnostics::new().with_ceiling(4);
    for _ in 0..10 {
        diagnostics.push(Diagnostic::new(Code::W1002));
    }
    assert_eq!(diagnostics.len(), 4);
    assert_eq!(diagnostics.suppressed(), 6);
}

#[test]
fn the_worst_severity_ignores_the_ceiling() {
    let mut diagnostics = Diagnostics::new().with_ceiling(1);
    diagnostics.push(Diagnostic::new(Code::W1002));
    diagnostics.push(Diagnostic::new(Code::E1901));

    assert_eq!(diagnostics.len(), 1);
    assert_eq!(diagnostics.worst(), Some(Code::E1901.severity()));
}

#[test]
fn finishing_a_suppressed_list_records_how_many_were_dropped() {
    let mut diagnostics = Diagnostics::new().with_ceiling(2);
    for _ in 0..5 {
        diagnostics.push(Diagnostic::new(Code::W1002));
    }

    let findings = diagnostics.finish();
    assert_eq!(findings.len(), 3);
    let Some(last) = findings.last() else {
        panic!("the suppression notice is missing")
    };
    assert_eq!(last.code(), Code::W1901);
}

#[test]
fn a_list_within_its_ceiling_records_no_suppression_notice() {
    let mut diagnostics = Diagnostics::new();
    diagnostics.push(Diagnostic::new(Code::W1002));

    let findings = diagnostics.finish();
    assert_eq!(findings.len(), 1);
    assert_eq!(diagnostics_codes(&findings), vec![Code::W1002]);
}

fn diagnostics_codes(findings: &[Diagnostic]) -> Vec<Code> {
    findings.iter().map(Diagnostic::code).collect()
}

#[test]
fn a_reserved_capacity_raises_the_ceiling_to_match() {
    let mut diagnostics = Diagnostics::with_capacity(64);
    for _ in 0..64 {
        diagnostics.push(Diagnostic::new(Code::W1002));
    }
    assert_eq!(diagnostics.suppressed(), 0);
}