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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
33
36#include <board.h>
38#include <pcb_marker.h>
39#include <pcb_track.h>
40#include <drc/drc_item.h>
42
43#include <set>
44
45
54
55
57{
58 // Test board has:
59 // - Net "a" with 4 track segments
60 // - Net "b" with 4 track segments
61 // - A soldermask opening (gr_rect on F.Mask) covering where tracks from both nets pass through
62 //
63 // With "report all track errors" enabled, we expect all combinations of net A tracks vs net B
64 // tracks to be reported. Each track from net A that bridges with each track from net B should
65 // generate a violation.
66
67 wxString brd_name( wxT( "soldermask_bridge_all_tracks" ) );
68 KI_TEST::LoadBoard( m_settingsManager, brd_name, m_board );
69
70 std::vector<DRC_ITEM> violations;
71 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
72
73 // Disable DRC tests not relevant to this test
79
81 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& aPos, int aLayer,
82 const std::function<void( PCB_MARKER* )>& aPathGenerator )
83 {
84 if( aItem->GetErrorCode() == DRCE_SOLDERMASK_BRIDGE )
85 violations.push_back( *aItem );
86 } );
87
88 // Count tracks per net to understand expected violations
89 int netA_tracks = 0;
90 int netB_tracks = 0;
91
92 for( PCB_TRACK* track : m_board->Tracks() )
93 {
94 if( track->GetNetname() == wxT( "a" ) )
95 netA_tracks++;
96 else if( track->GetNetname() == wxT( "b" ) )
97 netB_tracks++;
98 }
99
100 BOOST_TEST_MESSAGE( wxString::Format( "Net A has %d tracks, Net B has %d tracks",
101 netA_tracks, netB_tracks ) );
102
103 // Run DRC with "report all track errors" = true
104 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true /* aReportAllTrackErrors */, false );
105
106 // With "report all track errors" enabled, we expect all track pair combinations to be reported.
107 // In the test board, both nets have 4 track segments each that pass through the soldermask
108 // opening. The soldermask aperture (gr_rect) bridges copper from different nets.
109 //
110 // Each track from net A that is close enough to each track from net B within the soldermask
111 // opening should generate a violation. For this test case, we expect multiple violations,
112 // not just one.
113 //
114 // The exact number depends on which track segments are actually within clearance distance
115 // in the soldermask opening area.
116
117 // We expect MORE violations when reporting all track errors than in single error mode.
118 // With 4 tracks + 1 pad on each net passing through the soldermask opening:
119 // - Non-track items (pads) always get all combinations reported
120 // - Track items get all combinations only when "report all track errors" is enabled
121 //
122 // The original bug was that all violations showed the same track from net A (the first
123 // one cached), regardless of how many tracks actually violated. Now:
124 // - All non-track items from net A are reported against each net B collision
125 // - All track items from net A are reported (when option is set) against each net B collision
126 BOOST_CHECK_GT( violations.size(), 5 );
127
128 BOOST_TEST_MESSAGE( wxString::Format( "Found %zu soldermask bridge violations",
129 violations.size() ) );
130
131 // Verify that we're reporting different items from net A (not just the first cached one)
132 std::set<KIID> netAItemIds;
133
134 for( const DRC_ITEM& item : violations )
135 {
136 if( item.GetAuxItemID() != niluuid )
137 netAItemIds.insert( item.GetAuxItemID() );
138 }
139
140 // With 4 tracks + 1 pad on net A, we should see multiple different items reported
141 BOOST_CHECK_GE( netAItemIds.size(), 4 );
142
143 BOOST_TEST_MESSAGE( wxString::Format( "Found %zu different net A items in violations",
144 netAItemIds.size() ) );
145}
146
147
149{
150 // When "report all track errors" is disabled, we should get fewer violations
151 // (the original behavior - only report one error per track connection)
152
153 wxString brd_name( wxT( "soldermask_bridge_all_tracks" ) );
154 KI_TEST::LoadBoard( m_settingsManager, brd_name, m_board );
155
156 std::vector<DRC_ITEM> violations;
157 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
158
164
166 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& aPos, int aLayer,
167 const std::function<void( PCB_MARKER* )>& aPathGenerator )
168 {
169 if( aItem->GetErrorCode() == DRCE_SOLDERMASK_BRIDGE )
170 violations.push_back( *aItem );
171 } );
172
173 // Run DRC with "report all track errors" = false
174 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, false /* aReportAllTrackErrors */, false );
175
176 size_t singleErrorViolations = violations.size();
177
178 BOOST_TEST_MESSAGE( wxString::Format( "Single error mode: Found %zu soldermask bridge violations",
179 singleErrorViolations ) );
180
181 // Run again with "report all track errors" = true for comparison
182 violations.clear();
183 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true /* aReportAllTrackErrors */, false );
184
185 size_t allErrorsViolations = violations.size();
186
187 BOOST_TEST_MESSAGE( wxString::Format( "All errors mode: Found %zu soldermask bridge violations",
188 allErrorsViolations ) );
189
190 // When reporting all errors, we should have at least as many (likely more) violations
191 BOOST_CHECK_GE( allErrorsViolations, singleErrorViolations );
192}
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:168
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition drc_item.h:83
@ DRCE_STARVED_THERMAL
Definition drc_item.h:50
@ DRCE_COPPER_SLIVER
Definition drc_item.h:93
@ DRCE_SOLDERMASK_BRIDGE
Definition drc_item.h:94
@ DRCE_SILK_CLEARANCE
Definition drc_item.h:100
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition drc_item.h:84
KIID niluuid(0)
void LoadBoard(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< BOARD > &aBoard)
@ RPT_SEVERITY_IGNORE
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
BOOST_FIXTURE_TEST_CASE(DRCSolderMaskBridgeAllTracksTest, DRC_SOLDER_MASK_BRIDGE_ALL_TRACKS_FIXTURE)
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695