From 9098a7c128f586e7d96cb2d9e49d6b48d81fe3ce Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Tue, 27 Jun 2023 12:27:34 -0700 Subject: [PATCH] Add QA test to guard net ties The QA checks that net-ties correctly knock out the zone fill underneath them. --- qa/data/pcbnew/issue15069.kicad_pcb | 271 +++++++++++++++++++++++ qa/data/pcbnew/issue15069.kicad_pro | 229 +++++++++++++++++++ qa/unittests/pcbnew/test_zone_filler.cpp | 25 +++ 3 files changed, 525 insertions(+) create mode 100644 qa/data/pcbnew/issue15069.kicad_pcb create mode 100644 qa/data/pcbnew/issue15069.kicad_pro diff --git a/qa/data/pcbnew/issue15069.kicad_pcb b/qa/data/pcbnew/issue15069.kicad_pcb new file mode 100644 index 0000000000..4d1556cf42 --- /dev/null +++ b/qa/data/pcbnew/issue15069.kicad_pcb @@ -0,0 +1,271 @@ +(kicad_pcb (version 20221018) (generator pcbnew) + + (general + (thickness 1.6) + ) + + (paper "A4") + (layers + (0 "F.Cu" signal) + (31 "B.Cu" signal) + (32 "B.Adhes" user "B.Adhesive") + (33 "F.Adhes" user "F.Adhesive") + (34 "B.Paste" user) + (35 "F.Paste" user) + (36 "B.SilkS" user "B.Silkscreen") + (37 "F.SilkS" user "F.Silkscreen") + (38 "B.Mask" user) + (39 "F.Mask" user) + (40 "Dwgs.User" user "User.Drawings") + (41 "Cmts.User" user "User.Comments") + (42 "Eco1.User" user "User.Eco1") + (43 "Eco2.User" user "User.Eco2") + (44 "Edge.Cuts" user) + (45 "Margin" user) + (46 "B.CrtYd" user "B.Courtyard") + (47 "F.CrtYd" user "F.Courtyard") + (48 "B.Fab" user) + (49 "F.Fab" user) + (50 "User.1" user) + (51 "User.2" user) + (52 "User.3" user) + (53 "User.4" user) + (54 "User.5" user) + (55 "User.6" user) + (56 "User.7" user) + (57 "User.8" user) + (58 "User.9" user) + ) + + (setup + (pad_to_mask_clearance 0) + (pcbplotparams + (layerselection 0x00010fc_ffffffff) + (plot_on_all_layers_selection 0x0000000_00000000) + (disableapertmacros false) + (usegerberextensions false) + (usegerberattributes true) + (usegerberadvancedattributes true) + (creategerberjobfile true) + (dashed_line_dash_ratio 12.000000) + (dashed_line_gap_ratio 3.000000) + (svgprecision 4) + (plotframeref false) + (viasonmask false) + (mode 1) + (useauxorigin false) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (dxfpolygonmode true) + (dxfimperialunits true) + (dxfusepcbnewfont true) + (psnegative false) + (psa4output false) + (plotreference true) + (plotvalue true) + (plotinvisibletext false) + (sketchpadsonfab false) + (subtractmaskfromsilk false) + (outputformat 1) + (mirror false) + (drillshape 1) + (scaleselection 1) + (outputdirectory "") + ) + ) + + (net 0 "") + (net 1 "Test1") + (net 2 "Test2") + (net 3 "Test3") + + (footprint "Connector_Wire:SolderWirePad_1x01_SMD_1x2mm" (layer "B.Cu") + (tstamp ca5993ae-dd71-48b4-90b5-80f8f75da987) + (at 154.15 84.05 180) + (descr "Wire Pad, Square, SMD Pad, 5mm x 10mm,") + (tags "MesurementPoint Square SMDPad 5mmx10mm ") + (attr exclude_from_pos_files exclude_from_bom) + (fp_text reference "REF**" (at 0 2.54) (layer "B.SilkS") + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + (tstamp 6399a8cf-5382-4bce-ba64-4dfde3ade47a) + ) + (fp_text value "SolderWirePad_1x01_SMD_1x2mm" (at 0 -2.54) (layer "B.Fab") + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + (tstamp 430c8d54-ab51-43c0-92b3-5d6fbb078310) + ) + (fp_text user "${REFERENCE}" (at 0 0) (layer "B.Fab") + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + (tstamp a917afff-2f63-452d-b185-91ecbe43eead) + ) + (fp_line (start -0.63 -1.27) (end 0.63 -1.27) + (stroke (width 0.05) (type solid)) (layer "B.CrtYd") (tstamp 6ca357af-ad11-43da-b598-c0750bdfde27)) + (fp_line (start -0.63 1.27) (end -0.63 -1.27) + (stroke (width 0.05) (type solid)) (layer "B.CrtYd") (tstamp 310f9ca4-b0af-47f2-a88a-b7ef1cf6fb3a)) + (fp_line (start 0.63 -1.27) (end 0.63 1.27) + (stroke (width 0.05) (type solid)) (layer "B.CrtYd") (tstamp d66c1cf8-e4ab-4443-a7d8-edb1da6d4316)) + (fp_line (start 0.63 1.27) (end -0.63 1.27) + (stroke (width 0.05) (type solid)) (layer "B.CrtYd") (tstamp ee1db011-af60-43d7-8b53-6f3509e93f29)) + (fp_line (start -0.63 -1.27) (end -0.63 1.27) + (stroke (width 0.1) (type solid)) (layer "B.Fab") (tstamp ff006fc0-ed05-4222-8abb-c96ac6671151)) + (fp_line (start -0.63 1.27) (end 0.63 1.27) + (stroke (width 0.1) (type solid)) (layer "B.Fab") (tstamp c7131b36-fc5f-41c4-aa20-7fd3da3905b2)) + (fp_line (start 0.63 -1.27) (end -0.63 -1.27) + (stroke (width 0.1) (type solid)) (layer "B.Fab") (tstamp b2b534d0-5721-4e67-bcf2-5e13a3b4a76b)) + (fp_line (start 0.63 1.27) (end 0.63 -1.27) + (stroke (width 0.1) (type solid)) (layer "B.Fab") (tstamp 5e2f4003-df05-4479-b514-2002705ba3c5)) + (pad "1" smd roundrect (at 0 0 180) (size 1 2) (layers "B.Cu" "B.Paste" "B.Mask") (roundrect_rratio 0.25) + (net 3 "Test3") (tstamp 5b7a22ae-aba8-4d28-b413-f13f01e1b3b7)) + ) + + (footprint "NetTie:NetTie-2_SMD_Pad0.5mm" (layer "B.Cu") + (tstamp e79c5996-ed5b-4e02-88ac-11f9036c04c1) + (at 155.35 85.75 -90) + (descr "Net tie, 2 pin, 0.5mm square SMD pads") + (tags "net tie") + (property "Sheetfile" "UAVNav_Core.kicad_sch") + (property "Sheetname" "UAVNav_Core") + (property "exclude_from_bom" "") + (property "ki_description" "Net tie, 2 pins") + (property "ki_keywords" "net tie short") + (attr exclude_from_pos_files exclude_from_bom) + (net_tie_pad_groups "1, 2") + (fp_text reference "NT2" (at 0 1.2 90) (layer "B.SilkS") hide + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + (tstamp 146ccf02-58cd-48fa-91d5-369ef2b2fc43) + ) + (fp_text value "Net-Tie_2" (at 0 -1.2 90) (layer "B.Fab") + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + (tstamp 8ecd81aa-f7ad-48a3-ad05-c7ce3d88a782) + ) + (fp_poly + (pts + (xy -0.5 0.25) + (xy 0.5 0.25) + (xy 0.5 -0.25) + (xy -0.5 -0.25) + ) + + (stroke (width 0) (type solid)) (fill solid) (layer "B.Cu") (tstamp 4e729321-142d-4160-a36b-2f04a38006f8)) + (pad "1" smd circle (at -0.5 0 270) (size 0.5 0.5) (layers "B.Cu") + (net 1 "Test1") (pinfunction "1") (pintype "passive") (tstamp 1032c1e0-1464-4daf-9a92-755e91fe89e6)) + (pad "2" smd circle (at 0.5 0 270) (size 0.5 0.5) (layers "B.Cu") + (net 2 "Test2") (pinfunction "2") (pintype "passive") (tstamp f61d1578-8818-4727-8655-15416c8bd70b)) + ) + + (gr_rect (start 152.9 82.2) (end 157.25 88) + (stroke (width 0.05) (type default)) (fill none) (layer "Edge.Cuts") (tstamp 96b93bd5-07cf-451a-9f2e-1dc40c216fab)) + (gr_text_box "The net-tie should prevent the zone-fill from joining. This means that we should have only one hole in the zone polygon, not two" + (start 158.05 80.9) (end 185.65 89.5) (layer "Cmts.User") (tstamp d1e20399-67d9-4b68-b3d7-eca8558598b4) + (effects (font (size 1 1) (thickness 0.15)) (justify left top)) + (stroke (width 0.1) (type solid)) ) + + (zone (net 3) (net_name "Test3") (layer "B.Cu") (tstamp d8faf083-2cf6-4659-b189-791fef968e17) (hatch edge 0.5) + (connect_pads yes (clearance 0.01)) + (min_thickness 0.1) (filled_areas_thickness no) + (fill yes (thermal_gap 0.5) (thermal_bridge_width 0.5)) + (polygon + (pts + (xy 157.4 82.05) + (xy 157.4 88.1) + (xy 152.7 88.1) + (xy 152.7 82.05) + ) + ) + (filled_polygon + (layer "B.Cu") + (pts + (xy 156.735148 82.714852) + (xy 156.7495 82.7495) + (xy 156.7495 87.4505) + (xy 156.735148 87.485148) + (xy 156.7005 87.4995) + (xy 153.4495 87.4995) + (xy 153.414852 87.485148) + (xy 153.4005 87.4505) + (xy 153.4005 86.250002) + (xy 154.894867 86.250002) + (xy 154.913301 86.378223) + (xy 154.967118 86.496062) + (xy 154.967118 86.496063) + (xy 155.051951 86.593967) + (xy 155.160931 86.664004) + (xy 155.230093 86.684311) + (xy 155.285223 86.700499) + (xy 155.285228 86.7005) + (xy 155.414772 86.7005) + (xy 155.414776 86.700499) + (xy 155.435324 86.694465) + (xy 155.539069 86.664004) + (xy 155.648049 86.593967) + (xy 155.732882 86.496063) + (xy 155.786697 86.378226) + (xy 155.786697 86.378224) + (xy 155.786698 86.378223) + (xy 155.805133 86.250002) + (xy 155.805133 86.249997) + (xy 155.786698 86.121776) + (xy 155.779297 86.105572) + (xy 155.732882 86.003937) + (xy 155.648049 85.906033) + (xy 155.539069 85.835996) + (xy 155.539066 85.835995) + (xy 155.414776 85.7995) + (xy 155.414772 85.7995) + (xy 155.285228 85.7995) + (xy 155.285223 85.7995) + (xy 155.160933 85.835995) + (xy 155.05195 85.906033) + (xy 154.967119 86.003936) + (xy 154.967118 86.003936) + (xy 154.913301 86.121776) + (xy 154.894867 86.249997) + (xy 154.894867 86.250002) + (xy 153.4005 86.250002) + (xy 153.4005 85.250002) + (xy 154.894867 85.250002) + (xy 154.913301 85.378223) + (xy 154.967117 85.496062) + (xy 154.967118 85.496063) + (xy 155.051951 85.593967) + (xy 155.160931 85.664004) + (xy 155.230093 85.684311) + (xy 155.285223 85.700499) + (xy 155.285228 85.7005) + (xy 155.414772 85.7005) + (xy 155.414776 85.700499) + (xy 155.435324 85.694465) + (xy 155.539069 85.664004) + (xy 155.648049 85.593967) + (xy 155.732882 85.496063) + (xy 155.786697 85.378226) + (xy 155.786697 85.378224) + (xy 155.786698 85.378223) + (xy 155.805133 85.250002) + (xy 155.805133 85.249997) + (xy 155.786698 85.121776) + (xy 155.779297 85.105572) + (xy 155.732882 85.003937) + (xy 155.648049 84.906033) + (xy 155.539069 84.835996) + (xy 155.539066 84.835995) + (xy 155.414776 84.7995) + (xy 155.414772 84.7995) + (xy 155.285228 84.7995) + (xy 155.285223 84.7995) + (xy 155.160933 84.835995) + (xy 155.05195 84.906033) + (xy 154.967119 85.003936) + (xy 154.967118 85.003936) + (xy 154.913301 85.121776) + (xy 154.894867 85.249997) + (xy 154.894867 85.250002) + (xy 153.4005 85.250002) + (xy 153.4005 82.7495) + (xy 153.414852 82.714852) + (xy 153.4495 82.7005) + (xy 156.7005 82.7005) + ) + ) + ) +) diff --git a/qa/data/pcbnew/issue15069.kicad_pro b/qa/data/pcbnew/issue15069.kicad_pro new file mode 100644 index 0000000000..25bd4f2cea --- /dev/null +++ b/qa/data/pcbnew/issue15069.kicad_pro @@ -0,0 +1,229 @@ +{ + "board": { + "3dviewports": [], + "design_settings": { + "defaults": { + "board_outline_line_width": 0.049999999999999996, + "copper_line_width": 0.19999999999999998, + "copper_text_italic": false, + "copper_text_size_h": 1.5, + "copper_text_size_v": 1.5, + "copper_text_thickness": 0.3, + "copper_text_upright": false, + "courtyard_line_width": 0.049999999999999996, + "dimension_precision": 4, + "dimension_units": 3, + "dimensions": { + "arrow_length": 1270000, + "extension_offset": 500000, + "keep_text_aligned": true, + "suppress_zeroes": false, + "text_position": 0, + "units_format": 1 + }, + "fab_line_width": 0.09999999999999999, + "fab_text_italic": false, + "fab_text_size_h": 1.0, + "fab_text_size_v": 1.0, + "fab_text_thickness": 0.15, + "fab_text_upright": false, + "other_line_width": 0.09999999999999999, + "other_text_italic": false, + "other_text_size_h": 1.0, + "other_text_size_v": 1.0, + "other_text_thickness": 0.15, + "other_text_upright": false, + "pads": { + "drill": 0.0, + "height": 2.0, + "width": 1.0 + }, + "silk_line_width": 0.09999999999999999, + "silk_text_italic": false, + "silk_text_size_h": 1.0, + "silk_text_size_v": 1.0, + "silk_text_thickness": 0.09999999999999999, + "silk_text_upright": false, + "zones": { + "min_clearance": 0.01 + } + }, + "diff_pair_dimensions": [], + "drc_exclusions": [], + "meta": { + "version": 2 + }, + "rule_severities": { + "annular_width": "error", + "clearance": "error", + "connection_width": "warning", + "copper_edge_clearance": "error", + "copper_sliver": "warning", + "courtyards_overlap": "error", + "diff_pair_gap_out_of_range": "error", + "diff_pair_uncoupled_length_too_long": "error", + "drill_out_of_range": "error", + "duplicate_footprints": "warning", + "extra_footprint": "warning", + "footprint": "error", + "footprint_type_mismatch": "ignore", + "hole_clearance": "error", + "hole_near_hole": "error", + "invalid_outline": "error", + "isolated_copper": "warning", + "item_on_disabled_layer": "error", + "items_not_allowed": "error", + "length_out_of_range": "error", + "lib_footprint_issues": "warning", + "lib_footprint_mismatch": "warning", + "malformed_courtyard": "error", + "microvia_drill_out_of_range": "error", + "missing_courtyard": "ignore", + "missing_footprint": "warning", + "net_conflict": "warning", + "npth_inside_courtyard": "ignore", + "padstack": "warning", + "pth_inside_courtyard": "ignore", + "shorting_items": "error", + "silk_edge_clearance": "warning", + "silk_over_copper": "warning", + "silk_overlap": "warning", + "skew_out_of_range": "error", + "solder_mask_bridge": "error", + "starved_thermal": "error", + "text_height": "warning", + "text_thickness": "warning", + "through_hole_pad_without_hole": "error", + "too_many_vias": "error", + "track_dangling": "warning", + "track_width": "error", + "tracks_crossing": "error", + "unconnected_items": "error", + "unresolved_variable": "error", + "via_dangling": "warning", + "zones_intersect": "error" + }, + "rules": { + "max_error": 0.005, + "min_clearance": 0.0, + "min_connection": 0.0, + "min_copper_edge_clearance": 0.5, + "min_hole_clearance": 0.25, + "min_hole_to_hole": 0.25, + "min_microvia_diameter": 0.19999999999999998, + "min_microvia_drill": 0.09999999999999999, + "min_resolved_spokes": 2, + "min_silk_clearance": 0.0, + "min_text_height": 0.7999999999999999, + "min_text_thickness": 0.08, + "min_through_hole_diameter": 0.3, + "min_track_width": 0.0, + "min_via_annular_width": 0.09999999999999999, + "min_via_diameter": 0.5, + "solder_mask_to_copper_clearance": 0.0, + "use_height_for_length_calcs": true + }, + "teardrop_options": [ + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 5, + "td_on_pad_in_zone": false, + "td_onpadsmd": true, + "td_onroundshapesonly": false, + "td_ontrackend": false, + "td_onviapad": true + } + ], + "teardrop_parameters": [ + { + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_target_name": "td_round_shape", + "td_width_to_size_filter_ratio": 0.9 + }, + { + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_target_name": "td_rect_shape", + "td_width_to_size_filter_ratio": 0.9 + }, + { + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_target_name": "td_track_end", + "td_width_to_size_filter_ratio": 0.9 + } + ], + "track_widths": [], + "via_dimensions": [], + "zones_allow_external_fillets": false + }, + "layer_presets": [], + "viewports": [] + }, + "boards": [], + "cvpcb": { + "equivalence_files": [] + }, + "libraries": { + "pinned_footprint_libs": [], + "pinned_symbol_libs": [] + }, + "meta": { + "filename": "issue15069.kicad_pro", + "version": 1 + }, + "net_settings": { + "classes": [ + { + "bus_width": 12, + "clearance": 0.2, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "name": "Default", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "schematic_color": "rgba(0, 0, 0, 0.000)", + "track_width": 0.2, + "via_diameter": 0.6, + "via_drill": 0.3, + "wire_width": 6 + } + ], + "meta": { + "version": 3 + }, + "net_colors": null, + "netclass_assignments": null, + "netclass_patterns": [] + }, + "pcbnew": { + "last_paths": { + "gencad": "", + "idf": "", + "netlist": "", + "specctra_dsn": "", + "step": "", + "vrml": "" + }, + "page_layout_descr_file": "" + }, + "schematic": { + "legacy_lib_dir": "", + "legacy_lib_list": [] + }, + "sheets": [], + "text_variables": {} +} diff --git a/qa/unittests/pcbnew/test_zone_filler.cpp b/qa/unittests/pcbnew/test_zone_filler.cpp index 7842481af1..140dba8057 100644 --- a/qa/unittests/pcbnew/test_zone_filler.cpp +++ b/qa/unittests/pcbnew/test_zone_filler.cpp @@ -32,6 +32,9 @@ #include #include +#include +#include + struct ZONE_FILL_TEST_FIXTURE { @@ -233,3 +236,25 @@ BOOST_FIXTURE_TEST_CASE( RegressionZoneFillTests, ZONE_FILL_TEST_FIXTURE ) } } +BOOST_FIXTURE_TEST_CASE( NetTies, ZONE_FILL_TEST_FIXTURE ) +{ + std::vector> tests = { { "issue15069", B_Cu, 1 } }; + + for( auto& t : tests ) + { + KI_TEST::LoadBoard( m_settingsManager, std::get<0>( t ), m_board ); + + BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); + + KI_TEST::FillZones( m_board.get() ); + + ZONE* zone = m_board->Zones().front(); + SHAPE_POLY_SET copper = *zone->GetFilledPolysList( std::get<1>( t ) ); + + copper.Unfracture( SHAPE_POLY_SET::PM_FAST ); + int holeCount = copper.HoleCount( 0 ); + int expectedHoleCount = std::get<2>( t ); + + BOOST_CHECK_EQUAL( holeCount, expectedHoleCount ); + } +} \ No newline at end of file