KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_board_design_settings.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
21
22#include <board.h>
24#include <drc/drc_engine.h>
25#include <drc/drc_rule.h>
30
31#include <json_common.h>
32
33
34namespace
35{
36struct BDS_TEST_FIXTURE
37{
38 BDS_TEST_FIXTURE() :
39 m_board( new BOARD() )
40 { }
41
42 SETTINGS_MANAGER m_settingsManager;
43 std::unique_ptr<BOARD> m_board;
44};
45
46
47// A caller-owned parent so a BOARD_DESIGN_SETTINGS can nest under it without a full project.
48class BDS_TEST_PARENT : public JSON_SETTINGS
49{
50public:
51 BDS_TEST_PARENT() :
52 JSON_SETTINGS( "bds_test_parent", SETTINGS_LOC::NONE, 0, false, false, false )
53 {
54 }
55};
56} // namespace
57
58
59BOOST_FIXTURE_TEST_SUITE( BoardDesignSettings, BDS_TEST_FIXTURE )
60
61
62
69BOOST_AUTO_TEST_CASE( NegativeSilkClearanceRoundTrip )
70{
71 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
72
73 int negativeValue = pcbIUScale.mmToIU( -0.1 );
74 bds.m_SilkClearance = negativeValue;
75
76 // Store all params into the JSON backing store
77 bds.Store();
78
79 // Reset to default
80 bds.m_SilkClearance = 0;
81
82 // Load back from JSON
83 bds.Load();
84
85 BOOST_CHECK_EQUAL( bds.m_SilkClearance, negativeValue );
86}
87
88
98BOOST_AUTO_TEST_CASE( BiggestClearanceIncludesPhysicalHoleClearance )
99{
100 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
101
102 // Larger than any default clearance, so it can only come from the rule below.
103 const int ruleClearance = pcbIUScale.mmToIU( 4.0 );
104
105 auto rule = std::make_shared<DRC_RULE>( wxT( "NPTH Hole to Track Clearance" ) );
106
108 constraint.Value().SetMin( ruleClearance );
109 rule->AddConstraint( constraint );
110
111 auto engine = std::make_shared<DRC_ENGINE>( m_board.get(), &bds );
112 engine->InitEngine( rule );
113 bds.m_DRCEngine = engine;
114
115 BOOST_CHECK_GE( bds.GetBiggestClearanceValue(), ruleClearance );
116}
117
118
119// Regression test for https://gitlab.com/kicad/code/kicad/-/issues/24646
120// Cycling predefined sizes must skip the index-0 netclass placeholder on roll-over and stay
121// monotonic.
122BOOST_AUTO_TEST_CASE( PredefinedTrackWidthCyclingMonotonic )
123{
124 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
125
126 // Index 0 is the netclass placeholder; indices 1..5 are sorted predefined sizes.
127 bds.m_TrackWidthList = { 0,
128 pcbIUScale.mmToIU( 0.5 ),
129 pcbIUScale.mmToIU( 0.6 ),
130 pcbIUScale.mmToIU( 0.8 ),
131 pcbIUScale.mmToIU( 1.0 ),
132 pcbIUScale.mmToIU( 1.2 ) };
133
134 const int lastReal = (int) bds.m_TrackWidthList.size() - 1;
135
136 // Increment: netclass(0) -> smallest(1) -> ... -> largest, then roll over to smallest, never 0.
137 BOOST_CHECK_EQUAL( bds.GetNextTrackWidthIndex( 0, true ), 1 );
138
139 int idx = 1;
140
141 for( int step = 2; step <= lastReal; ++step )
142 {
143 idx = bds.GetNextTrackWidthIndex( idx, true );
144 BOOST_CHECK_EQUAL( idx, step );
145 }
146
147 // Roll-over from the largest must skip the placeholder and land on the smallest real size.
148 BOOST_CHECK_EQUAL( bds.GetNextTrackWidthIndex( lastReal, true ), 1 );
149
150 // Decrement: smallest(1) rolls over to the largest, never to the placeholder.
151 BOOST_CHECK_EQUAL( bds.GetNextTrackWidthIndex( 1, false ), lastReal );
152
153 idx = lastReal;
154
155 for( int step = lastReal - 1; step >= 1; --step )
156 {
157 idx = bds.GetNextTrackWidthIndex( idx, false );
158 BOOST_CHECK_EQUAL( idx, step );
159 }
160
161 // A full forward cycle must never report the netclass placeholder once stepping has started.
162 idx = bds.GetNextTrackWidthIndex( 0, true );
163
164 for( int step = 0; step < lastReal * 3; ++step )
165 {
166 BOOST_CHECK_GE( idx, 1 );
167 idx = bds.GetNextTrackWidthIndex( idx, true );
168 }
169
170 // An empty list (no placeholder, no predefined sizes) must stay at index 0 and never store a
171 // negative index through SetTrackWidthIndex.
172 bds.m_TrackWidthList.clear();
173 BOOST_CHECK_EQUAL( bds.GetNextTrackWidthIndex( 0, true ), 0 );
174 BOOST_CHECK_EQUAL( bds.GetNextTrackWidthIndex( 0, false ), 0 );
175 bds.SetTrackWidthIndex( bds.GetNextTrackWidthIndex( 0, false ) );
177}
178
179
180BOOST_AUTO_TEST_CASE( PredefinedViaSizeCyclingMonotonic )
181{
182 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
183
184 // Index 0 is the netclass placeholder; indices 1..3 are sorted predefined via sizes.
185 bds.m_ViasDimensionsList = { { 0, 0 },
186 { pcbIUScale.mmToIU( 0.6 ), pcbIUScale.mmToIU( 0.3 ) },
187 { pcbIUScale.mmToIU( 0.8 ), pcbIUScale.mmToIU( 0.4 ) },
188 { pcbIUScale.mmToIU( 1.0 ), pcbIUScale.mmToIU( 0.5 ) } };
189
190 const int lastReal = (int) bds.m_ViasDimensionsList.size() - 1;
191
192 BOOST_CHECK_EQUAL( bds.GetNextViaSizeIndex( 0, true ), 1 );
193 BOOST_CHECK_EQUAL( bds.GetNextViaSizeIndex( lastReal, true ), 1 );
194 BOOST_CHECK_EQUAL( bds.GetNextViaSizeIndex( 1, false ), lastReal );
195
196 // A list holding only the netclass placeholder must stay put in both directions.
197 bds.m_ViasDimensionsList = { { 0, 0 } };
198 BOOST_CHECK_EQUAL( bds.GetNextViaSizeIndex( 0, true ), 0 );
199 BOOST_CHECK_EQUAL( bds.GetNextViaSizeIndex( 0, false ), 0 );
200
201 // An empty list must stay at index 0 and never store a negative index.
202 bds.m_ViasDimensionsList.clear();
203 BOOST_CHECK_EQUAL( bds.GetNextViaSizeIndex( 0, true ), 0 );
204 BOOST_CHECK_EQUAL( bds.GetNextViaSizeIndex( 0, false ), 0 );
205 bds.SetViaSizeIndex( bds.GetNextViaSizeIndex( 0, false ) );
207}
208
209
210BOOST_AUTO_TEST_CASE( PredefinedDiffPairCyclingMonotonic )
211{
212 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
213
214 // Index 0 is the netclass placeholder; indices 1..3 are sorted predefined diff-pair dimensions.
215 bds.m_DiffPairDimensionsList = { { 0, 0, 0 },
216 { pcbIUScale.mmToIU( 0.2 ), pcbIUScale.mmToIU( 0.2 ), 0 },
217 { pcbIUScale.mmToIU( 0.25 ), pcbIUScale.mmToIU( 0.25 ), 0 },
218 { pcbIUScale.mmToIU( 0.3 ), pcbIUScale.mmToIU( 0.3 ), 0 } };
219
220 const int lastReal = (int) bds.m_DiffPairDimensionsList.size() - 1;
221
222 BOOST_CHECK_EQUAL( bds.GetNextDiffPairIndex( 0, true ), 1 );
223 BOOST_CHECK_EQUAL( bds.GetNextDiffPairIndex( lastReal, true ), 1 );
224 BOOST_CHECK_EQUAL( bds.GetNextDiffPairIndex( 1, false ), lastReal );
225
226 // An empty list must stay at index 0 and never store a negative index.
227 bds.m_DiffPairDimensionsList.clear();
228 BOOST_CHECK_EQUAL( bds.GetNextDiffPairIndex( 0, true ), 0 );
229 BOOST_CHECK_EQUAL( bds.GetNextDiffPairIndex( 0, false ), 0 );
230 bds.SetDiffPairIndex( bds.GetNextDiffPairIndex( 0, false ) );
232}
233
234
235// Regression test for https://gitlab.com/kicad/code/kicad/-/issues/24644
236// Switching track width from the connected-width placeholder must advance to a real size on the
237// first press. The router gating is GUI bound, so this drives the same GetNextTrackWidthIndex
238// stepping the hotkeys call.
239BOOST_AUTO_TEST_CASE( TrackWidthSwitchAdvancesFromConnectedWidth )
240{
241 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
242
243 const int size1 = pcbIUScale.mmToIU( 0.25 );
244 const int size2 = pcbIUScale.mmToIU( 0.50 );
245 const int size3 = pcbIUScale.mmToIU( 1.00 );
246
247 // Index 0 is the netclass/connected-width placeholder; the rest are real predefined sizes.
248 bds.m_TrackWidthList = { 0, size1, size2, size3 };
249 bds.UseCustomTrackViaSize( false );
250
251 // Start on the connected-width placeholder, as the router does before any override.
252 bds.SetTrackWidthIndex( 0 );
254
255 auto incIndex = [&]() { bds.SetTrackWidthIndex( bds.GetNextTrackWidthIndex( bds.GetTrackWidthIndex(), true ) ); };
256 auto decIndex = [&]() { bds.SetTrackWidthIndex( bds.GetNextTrackWidthIndex( bds.GetTrackWidthIndex(), false ) ); };
257
258 // First "Next" press must move to the first real predefined size, not no-op.
259 incIndex();
262
263 // Subsequent presses step through the list, then roll over to the smallest real size, skipping
264 // the netclass placeholder at index 0.
265 incIndex();
267 incIndex();
269 incIndex();
272
273 // First "Previous" press from the placeholder must roll over to the last real size.
274 bds.SetTrackWidthIndex( 0 );
275 decIndex();
278}
279
280
288BOOST_AUTO_TEST_CASE( SeededBoardValueSurvivesRoundTrip )
289{
290 BDS_TEST_PARENT parent;
291
292 ( *parent.Internals() )["/board/design_settings"_json_pointer] =
293 nlohmann::json{ { "meta", { { "version", 2 } } } };
294
295 const int negativeValue = pcbIUScale.mmToIU( -0.1 );
296
297 {
298 BOARD_DESIGN_SETTINGS bds( &parent, "board.design_settings" );
299
300 bds.m_SilkClearance = negativeValue;
301 bds.LoadFromFile();
302 BOOST_CHECK_EQUAL( bds.m_SilkClearance, negativeValue );
303
304 bds.SaveToFile();
305 }
306
307 BOARD_DESIGN_SETTINGS reloaded( &parent, "board.design_settings" );
308 reloaded.LoadFromFile();
309 BOOST_CHECK_EQUAL( reloaded.m_SilkClearance, negativeValue );
310}
311
312
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
Container for design settings for a BOARD object.
void UseCustomTrackViaSize(bool aEnabled)
Enables/disables custom track/via size settings.
int GetNextDiffPairIndex(int aIndex, bool aForward) const
Compute the next diff pair dimensions list index when cycling predefined sizes, skipping the index-0 ...
void SetViaSizeIndex(int aIndex)
Set the current via size list index to aIndex.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
int GetNextTrackWidthIndex(int aIndex, bool aForward) const
Compute the next track width list index when cycling predefined sizes, skipping the index-0 netclass ...
bool LoadFromFile(const wxString &aDirectory="") override
Loads the backing file from disk and then calls Load()
void SetTrackWidthIndex(int aIndex)
Set the current track width list index to aIndex.
int GetNextViaSizeIndex(int aIndex, bool aForward) const
Compute the next via size list index when cycling predefined sizes, skipping the index-0 netclass pla...
std::vector< int > m_TrackWidthList
std::vector< VIA_DIMENSION > m_ViasDimensionsList
MINOPTMAX< int > & Value()
Definition drc_rule.h:197
virtual void Load()
Updates the parameters of this object based on the current JSON document contents.
virtual bool Store()
Stores the current parameters into the JSON document represented by this object Note: this doesn't do...
void SetMin(T v)
Definition minoptmax.h:38
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
Calls Store() and then saves the JSON document contents into the parent JSON_SETTINGS.
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:83
@ NONE
Definition eda_shape.h:72
SETTINGS_LOC
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_CASE(NegativeSilkClearanceRoundTrip)
Regression test for https://gitlab.com/kicad/code/kicad/-/issues/23327.
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_EQUAL(result, "25.4")