← Commit history

2.22.2: negative-controlled regression tests

John Lauer ·e82e205b13 ·1mo ago ·parent 8306805
7 files changed +97−6
Cargo.lock+1−1
@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"  [[package]] name = "adom-lbr"-version = "2.22.1"+version = "2.22.2" dependencies = [  "altium-codec",  "anyhow",
Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "adom-lbr"-version = "2.22.1"+version = "2.22.2" edition = "2021" description = "adom-lbr generator / EDA translator: the canonical adom-lbr JSON is the hub, with native converters to Altium (.SchLib/.PcbLib/.IntLib), EAGLE/Fusion (.lbr), and KiCad. Altium output is written natively — no Altium needed at conversion time." 
VERSION+1−1
@@ -1 +1 @@-2.22.1+2.22.2
bin/adom-lbr
⋯ 1 unchanged line ⋯
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-lbr",-  "version": "2.22.1",+  "version": "2.22.2",   "type": "app",   "description": "adom-lbr \u2014 the EDA library translator. Bring a component in from any supported EDA tool and convert it to any other (KiCad \u21c4 Altium \u21c4 EAGLE/Fusion) through one canonical adom-lbr JSON \u2014 symbol + footprint + 3D + pin\u2194pad map. Altium is written natively (no Altium needed). Includes the adom-lbr Manager: browse wiki components and view symbol/footprint/3D + the per-EDA layer stackup.",   "dependencies": {},
page.json+2−2
@@ -1,6 +1,6 @@ {   "slug": "adom-lbr",-  "version": "2.22.1",+  "version": "2.22.2",   "type": "app",   "description": "adom-lbr — the EDA library translator. Bring a component in from any supported EDA tool and convert it to any other (KiCad ⇄ Altium ⇄ EAGLE/Fusion) through one canonical adom-lbr JSON — symbol + footprint + 3D + pin↔pad map. Altium is written natively (no Altium needed). Includes the adom-lbr Manager: browse wiki components and view symbol/footprint/3D + the per-EDA layer stackup.",   "dependencies": {},@@ -88,4 +88,4 @@       "label": "Browse parts"     }   ]-}\ No newline at end of file+}
src/main.rs+91
@@ -3060,6 +3060,97 @@ fn cmd_embed(dir: &std::path::Path, out: Option<PathBuf>) -> Result<(), String> mod lint_tests {     use super::{dedup_pad_names, lint_lbr}; +    // ---- 2.21.0 / 2.22.x conversion fidelity -------------------------------------+    // Every one of these guards a bug that reached a user's Fusion install, so each test+    // names the symptom rather than the function.++    #[test]+    fn kicad_pin_length_maps_to_the_nearest_eagle_stop_not_the_next_one_up() {+        use super::pin_length_keyword;+        // 2.794 is the standard 0.11 in pin on the wiki's passives. The old ceiling rule+        // sent it to "middle" (5.08), so a two-pin part drew as one line with its pins+        // overlapping by 2.54 mm.+        assert_eq!(pin_length_keyword(2.794), "short");+        assert_eq!(pin_length_keyword(0.0), "point");+        assert_eq!(pin_length_keyword(2.54), "short");+        assert_eq!(pin_length_keyword(5.08), "middle");+        assert_eq!(pin_length_keyword(7.62), "long");+        assert_eq!(pin_length_keyword(20.0), "long");+        // a value nearer the upper stop still rounds up+        assert_eq!(pin_length_keyword(4.9), "middle");+    }++    #[test]+    fn unnamed_pins_take_the_pad_number_and_a_pin_really_called_p_survives() {+        use super::{dedup_pin_names, KicadPin};+        let pin = |name: &str, number: &str| KicadPin {+            name: name.to_string(), number: number.to_string(),+            x: 0.0, y: 0.0, angle: 0, length: 2.54, pin_type: "passive".to_string(),+        };+        // "~" is KiCad's unnamed marker; it used to sanitise to the literal "P", so an+        // unnamed two-pin part shipped pins called "P" and "P@2".+        let got = dedup_pin_names(&[pin("~", "1"), pin("~", "2")]);+        assert_eq!(got, vec!["1".to_string(), "2".to_string()]);+        // an empty name behaves the same way+        assert_eq!(dedup_pin_names(&[pin("", "7")]), vec!["7".to_string()]);+        // ...but a pin genuinely named P keeps its name+        assert_eq!(dedup_pin_names(&[pin("P", "3")]), vec!["P".to_string()]);+        // and real names are untouched, including the @-suffix for a repeat+        assert_eq!(dedup_pin_names(&[pin("GND", "4"), pin("GND", "5")]),+                   vec!["GND".to_string(), "GND@2".to_string()]);+    }++    #[test]+    fn catalog_boilerplate_is_stripped_without_mangling_decimals() {+        use super::strip_catalog_boilerplate;+        assert_eq!(+            strip_catalog_boilerplate("WCH USB Converters, SOP-16. Datasheet-verified pinout, KiCad symbol/footprint/3D."),+            "WCH USB Converters, SOP-16");+        // the first version split on every '.' and rejoined, turning a voltage into "2. 5V"+        assert_eq!(strip_catalog_boilerplate("2.5V precision reference"), "2.5V precision reference");+        assert_eq!(strip_catalog_boilerplate("STM32F103. 72 MHz Cortex-M3"), "STM32F103. 72 MHz Cortex-M3");+        // nothing but boilerplate: keep the original rather than emit an empty description+        assert!(!strip_catalog_boilerplate("Datasheet-verified pinout").is_empty());+    }++    #[test]+    fn package_description_leads_with_geometry_and_never_states_a_bad_measurement() {+        use super::package_description;+        // Fusion's Description column shows ~20 characters, so the identifying words go first.+        assert_eq!(package_description(None, "SOIC-8_3.9x4.9mm_P1.27mm"),+                   "SOIC-8, 3.9 x 4.9 mm, 1.27 mm pitch");+        // a descr that merely restates the geometry is dropped rather than appended+        let restating = r#"(footprint "SOIC-8_3.9x4.9mm_P1.27mm" (descr "SOIC, 8 Pin"))"#;+        assert_eq!(package_description(Some(restating), "SOIC-8_3.9x4.9mm_P1.27mm"),+                   "SOIC-8, 3.9 x 4.9 mm, 1.27 mm pitch");+        // a descr that adds something is appended AFTER the geometry+        let adds = r#"(footprint "SOIC-8_3.9x4.9mm_P1.27mm" (descr "Analog Devices precision reference"))"#;+        assert!(package_description(Some(adds), "SOIC-8_3.9x4.9mm_P1.27mm")+                    .starts_with("SOIC-8, 3.9 x 4.9 mm, 1.27 mm pitch. "));+        // a URL in the descr does not leave the bracket that introduced it behind+        let urly = r#"(footprint "X" (descr "SOIC, 8 Pin (JEDEC MS-012AA, https://example.com/x.pdf)"))"#;+        let out = package_description(Some(urly), "X");+        assert!(!out.contains("http"), "{out}");+        assert!(!out.ends_with('('), "{out}");+        assert!(out.matches('(').count() == out.matches(')').count(), "unbalanced: {out}");+    }++    #[test]+    fn a_footprint_named_by_mpn_is_measured_rather_than_repeating_its_own_name() {+        use super::package_description;+        // Two 1.0 x 0.5 mm pads 1.0 mm apart: a plain chip land pattern.+        let km = r#"(footprint "0603N101J500CT"+            (pad "1" smd rect (at -0.75 0) (size 1.0 0.5) (layers "F.Cu"))+            (pad "2" smd rect (at 0.75 0) (size 1.0 0.5) (layers "F.Cu")))"#;+        let out = package_description(Some(km), "0603N101J500CT");+        assert!(out.starts_with("2 pads,"), "{out}");+        assert!(!out.contains("0603N101J500CT"), "must not repeat the Name column: {out}");+        // The first version measured the SILKSCREEN, which on a chip part is two ticks, and+        // reported "0.6 x 0.0 mm". A confidently wrong measurement is worse than none.+        assert!(!out.contains("0.0 mm"), "{out}");+        assert!(out.contains("2.5 x 0.5 mm"), "expected the copper extent: {out}");+    }+     #[test]     fn four_sided_symbol_relays_into_two_columns() {         use super::{relayout_two_columns, KicadPin, ParsedSymbol};