master
Colby Knox Fix #133 (outline box from arcs and circles; ring courtyards: 2-degree sampling, interior probes), #130 (KICAD10_3RD_PA… f7d1e2b 15d ago
//! Wiki #131: pin connection points, checked against KiCad's own demo sheets: every no-connect flag
//! KiCad placed sits on a pin the bridge computes (rotated and mirrored symbols included).
use kicad_core::schematic::Schematic;
use std::path::PathBuf;

#[test]
fn every_demo_no_connect_flag_lands_on_a_computed_pin() {
    let dir = PathBuf::from(std::env::var("KICAD_DEMO_SCH").unwrap_or_else(|_| format!("{}/../../../../fixtures/sch", env!("CARGO_MANIFEST_DIR"))));
    let Ok(rd) = std::fs::read_dir(&dir) else { eprintln!("no demo sheets at {}; skipped", dir.display()); return };
    let (mut flags, mut hit) = (0, 0);
    let mut misses = Vec::new();
    for e in rd.flatten().filter(|e| e.path().extension().map_or(false, |x| x == "kicad_sch")) {
        let text = std::fs::read_to_string(e.path()).unwrap();
        let sch = Schematic::parse(&text).unwrap();
        let refs: std::collections::BTreeSet<String> = sch.symbols().into_iter().map(|s| s.reference).collect();
        let mut pins = Vec::new();
        for r in &refs {
            if let Ok(p) = sch.pin_points(r) {
                pins.extend(p.into_iter().map(|(n, at)| (r.clone(), n, at)));
            }
        }
        for line in text.lines().collect::<Vec<_>>().windows(2) {
            if line[0].trim() == "(no_connect" {
                let nums: Vec<f64> = line[1].trim().trim_start_matches("(at").trim_end_matches(')').split_whitespace().filter_map(|t| t.parse().ok()).collect();
                if nums.len() < 2 { continue }
                flags += 1;
                if pins.iter().any(|(_, _, (x, y))| (x - nums[0]).abs() < 1e-3 && (y - nums[1]).abs() < 1e-3) {
                    hit += 1;
                } else {
                    misses.push(format!("{}: ({}, {})", e.file_name().to_string_lossy(), nums[0], nums[1]));
                }
            }
        }
    }
    eprintln!("{hit} of {flags} no-connect flags on a computed pin");
    assert!(flags == 0 || hit == flags, "{} missed: {:?}", misses.len(), &misses[..misses.len().min(8)]);
}

#[test]
fn a_flag_lands_on_a_named_pin_of_the_fixture_sheet() {
    let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../../tour-pack-rp2040/template/rp2040-breakout.kicad_sch");
    let mut sch = Schematic::parse(&std::fs::read_to_string(&path).unwrap()).unwrap();
    let pins = sch.pin_points("U1").unwrap();
    let (_, at) = pins.iter().find(|(n, _)| n == "1").expect("U1 pin 1");
    let uuid = sch.add_no_connect(*at).unwrap();
    let text = sch.to_text();
    let again = Schematic::parse(&text).unwrap();
    assert!(text.contains(&format!("(uuid \"{uuid}\")")));
    assert!(again.pin_points("U1").unwrap().iter().any(|(_, p)| p == at));
    assert!(text.contains("(no_connect"));
}