KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_solder_mask_bridge_all_tracks.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
29
32#include <board.h>
34#include <drc/drc_engine.h>
35#include <pcb_marker.h>
36#include <pcb_track.h>
37#include <drc/drc_engine.h>
38#include <drc/drc_item.h>
40
41#include <set>
42
43
52
53
55{
56 // Test board has:
57 // - Net "a" with 4 track segments
58 // - Net "b" with 4 track segments
59 // - A soldermask opening (gr_rect on F.Mask) covering where tracks from both nets pass through
60 //
61 // With "report all track errors" enabled, we expect all combinations of net A tracks vs net B
62 // tracks to be reported. Each track from net A that bridges with each track from net B should
63 // generate a violation.
64
65 wxString brd_name( wxT( "soldermask_bridge_all_tracks" ) );
66 KI_TEST::LoadBoard( m_settingsManager, brd_name, m_board );
67
68 std::vector<DRC_ITEM> violations;
69 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
70
71 // Disable DRC tests not relevant to this test
77
79 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& aPos, int aLayer,
80 const std::function<void( PCB_MARKER* )>& aPathGenerator )
81 {
82 if( aItem->GetErrorCode() == DRCE_SOLDERMASK_BRIDGE )
83 violations.push_back( *aItem );
84 } );
85
86 // Count tracks per net to understand expected violations
87 int netA_tracks = 0;
88 int netB_tracks = 0;
89
90 for( PCB_TRACK* track : m_board->Tracks() )
91 {
92 if( track->GetNetname() == wxT( "a" ) )
93 netA_tracks++;
94 else if( track->GetNetname() == wxT( "b" ) )
95 netB_tracks++;
96 }
97
98 BOOST_TEST_MESSAGE( wxString::Format( "Net A has %d tracks, Net B has %d tracks",
99 netA_tracks, netB_tracks ) );
100
101 // Run DRC with "report all track errors" = true
102 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true /* aReportAllTrackErrors */, false );
103
104 // With "report all track errors" enabled, we expect all track pair combinations to be reported.
105 // In the test board, both nets have 4 track segments each that pass through the soldermask
106 // opening. The soldermask aperture (gr_rect) bridges copper from different nets.
107 //
108 // Each track from net A that is close enough to each track from net B within the soldermask
109 // opening should generate a violation. For this test case, we expect multiple violations,
110 // not just one.
111 //
112 // The exact number depends on which track segments are actually within clearance distance
113 // in the soldermask opening area.
114
115 // We expect MORE violations when reporting all track errors than in single error mode.
116 // With 4 tracks + 1 pad on each net passing through the soldermask opening:
117 // - Non-track items (pads) always get all combinations reported
118 // - Track items get all combinations only when "report all track errors" is enabled
119 //
120 // The original bug was that all violations showed the same track from net A (the first
121 // one cached), regardless of how many tracks actually violated. Now:
122 // - All non-track items from net A are reported against each net B collision
123 // - All track items from net A are reported (when option is set) against each net B collision
124 BOOST_CHECK_GT( violations.size(), 5 );
125
126 BOOST_TEST_MESSAGE( wxString::Format( "Found %zu soldermask bridge violations",
127 violations.size() ) );
128
129 // Verify that we're reporting different items from net A (not just the first cached one)
130 std::set<KIID> netAItemIds;
131
132 for( const DRC_ITEM& item : violations )
133 {
134 if( item.GetAuxItemID() != niluuid )
135 netAItemIds.insert( item.GetAuxItemID() );
136 }
137
138 // With 4 tracks + 1 pad on net A, we should see multiple different items reported
139 BOOST_CHECK_GE( netAItemIds.size(), 4 );
140
141 BOOST_TEST_MESSAGE( wxString::Format( "Found %zu different net A items in violations",
142 netAItemIds.size() ) );
143}
144
145
147{
148 // When "report all track errors" is disabled, we should get fewer violations
149 // (the original behavior - only report one error per track connection)
150
151 wxString brd_name( wxT( "soldermask_bridge_all_tracks" ) );
152 KI_TEST::LoadBoard( m_settingsManager, brd_name, m_board );
153
154 std::vector<DRC_ITEM> violations;
155 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
156
162
164 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& aPos, int aLayer,
165 const std::function<void( PCB_MARKER* )>& aPathGenerator )
166 {
167 if( aItem->GetErrorCode() == DRCE_SOLDERMASK_BRIDGE )
168 violations.push_back( *aItem );
169 } );
170
171 // Run DRC with "report all track errors" = false
172 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, false /* aReportAllTrackErrors */, false );
173
174 size_t singleErrorViolations = violations.size();
175
176 BOOST_TEST_MESSAGE( wxString::Format( "Single error mode: Found %zu soldermask bridge violations",
177 singleErrorViolations ) );
178
179 // Run again with "report all track errors" = true for comparison
180 violations.clear();
181 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true /* aReportAllTrackErrors */, false );
182
183 size_t allErrorsViolations = violations.size();
184
185 BOOST_TEST_MESSAGE( wxString::Format( "All errors mode: Found %zu soldermask bridge violations",
186 allErrorsViolations ) );
187
188 // When reporting all errors, we should have at least as many (likely more) violations
189 BOOST_CHECK_GE( allErrorsViolations, singleErrorViolations );
190}
Container for design settings for a BOARD object.
std::map< int, SEVERITY > m_DRCSeverities
std::shared_ptr< DRC_ENGINE > m_DRCEngine
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints, BOARD_COMMIT *aCommit=nullptr)
Run the DRC tests.
void SetViolationHandler(DRC_VIOLATION_HANDLER aHandler)
Set an optional DRC violation handler (receives DRC_ITEMs and positions).
Definition drc_engine.h:164
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition drc_item.h:79
@ DRCE_STARVED_THERMAL
Definition drc_item.h:46
@ DRCE_COPPER_SLIVER
Definition drc_item.h:90
@ DRCE_SOLDERMASK_BRIDGE
Definition drc_item.h:91
@ DRCE_SILK_CLEARANCE
Definition drc_item.h:97
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition drc_item.h:80
KIID niluuid(0)
void LoadBoard(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< BOARD > &aBoard)
@ RPT_SEVERITY_IGNORE
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
BOOST_FIXTURE_TEST_CASE(DRCSolderMaskBridgeAllTracksTest, DRC_SOLDER_MASK_BRIDGE_ALL_TRACKS_FIXTURE)
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683