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