KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_erc_label_names.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 3
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
22
23#include <advanced_config.h>
24#include <sch_sheet.h>
25#include <sch_sheet_pin.h>
26#include <algorithm>
27#include <set>
28#include <connection_graph.h>
29#include <sch_label.h>
30#include <sch_marker.h>
31#include <schematic.h>
32#include <erc/erc_settings.h>
33#include <erc/erc.h>
34#include <erc/erc_exclusion.h>
35#include <erc/erc_report.h>
37#include <locale_io.h>
38#include <scoped_set_reset.h>
39
41{
43
45 std::unique_ptr<SCHEMATIC> m_schematic;
46};
47
48
49static int CountErrorCode( SHEETLIST_ERC_ITEMS_PROVIDER& aErrors, int aErrorCode )
50{
51 int count = 0;
52
53 for( int i = 0; i < aErrors.GetCount(); ++i )
54 {
55 std::shared_ptr<ERC_ITEM> ercItem = std::static_pointer_cast<ERC_ITEM>( aErrors.GetItem( i ) );
56
57 if( ercItem && ercItem->GetErrorCode() == aErrorCode )
58 ++count;
59 }
60
61 return count;
62}
63
64
66{
68
69 // Check for Errors when using rule area netclass directives
70 std::vector<std::pair<wxString, int>> tests = { { "issue16897", 3 } };
71
72 for( const std::pair<wxString, int>& test : tests )
73 {
74 KI_TEST::LoadSchematic( m_settingsManager, test.first, m_schematic );
75
76 ERC_SETTINGS& settings = m_schematic->ErcSettings();
77 SHEETLIST_ERC_ITEMS_PROVIDER errors( m_schematic.get() );
78
79 // Skip the "Modified symbol" warning
82
83 // Configure the rules under test
87
88 m_schematic->ConnectionGraph()->RunERC();
89
90 ERC_TESTER tester( m_schematic.get() );
91 tester.TestSimilarLabels();
92
94
95 ERC_REPORT reportWriter( m_schematic.get(), EDA_UNITS::MM );
96
97 BOOST_CHECK_MESSAGE( errors.GetCount() == test.second,
98 "Expected " << test.second << " errors in " << test.first.ToStdString()
99 << " but got " << errors.GetCount() << "\n"
100 << reportWriter.GetTextReport() );
101 }
102}
103
104
106{
108
109 // Check for Errors when using rule area netclass directives
110 std::vector<std::pair<wxString, int>> tests = { { "similar_labels", 3 } };
111
112 for( const std::pair<wxString, int>& test : tests )
113 {
114 KI_TEST::LoadSchematic( m_settingsManager, test.first, m_schematic );
115
116 ERC_SETTINGS& settings = m_schematic->ErcSettings();
117 SHEETLIST_ERC_ITEMS_PROVIDER errors( m_schematic.get() );
118
119 // Skip the "Modified symbol" warning
123
124 // Configure the rules under test
126
127 m_schematic->ConnectionGraph()->RunERC();
128
129 ERC_TESTER tester( m_schematic.get() );
130 tester.TestSimilarLabels();
131
133
134 ERC_REPORT reportWriter( m_schematic.get(), EDA_UNITS::MM );
135
136 BOOST_CHECK_MESSAGE( errors.GetCount() == test.second,
137 "Expected " << test.second << " errors in " << test.first.ToStdString()
138 << " but got " << errors.GetCount() << "\n"
139 << reportWriter.GetTextReport() );
140 }
141}
142
143
145{
147
148 // Check for Errors when using rule area netclass directives
149 std::vector<std::pair<wxString, int>> tests = { { "same_local_global_label", 1 } };
150
151 for( const std::pair<wxString, int>& test : tests )
152 {
153 KI_TEST::LoadSchematic( m_settingsManager, test.first, m_schematic );
154
155 ERC_SETTINGS& settings = m_schematic->ErcSettings();
156 SHEETLIST_ERC_ITEMS_PROVIDER errors( m_schematic.get() );
157
158 // Skip the "Modified symbol" warning
161
162 // Configure the rules under test
164
165 m_schematic->ConnectionGraph()->RunERC();
166
167 ERC_TESTER tester( m_schematic.get() );
169
171
172 ERC_REPORT reportWriter( m_schematic.get(), EDA_UNITS::MM );
173
174 BOOST_CHECK_MESSAGE( errors.GetCount() == test.second,
175 "Expected " << test.second << " errors in " << test.first.ToStdString()
176 << " but got " << errors.GetCount() << "\n"
177 << reportWriter.GetTextReport() );
178 }
179}
180
181
183{
185
186 KI_TEST::LoadSchematic( m_settingsManager, "same_local_global_power", m_schematic );
187
188 ERC_SETTINGS& settings = m_schematic->ErcSettings();
189 SHEETLIST_ERC_ITEMS_PROVIDER errors( m_schematic.get() );
190
193
196
197 m_schematic->ConnectionGraph()->RunERC();
198
199 ERC_TESTER tester( m_schematic.get() );
201
203
204 ERC_REPORT reportWriter( m_schematic.get(), EDA_UNITS::MM );
205
206 BOOST_CHECK_MESSAGE( CountErrorCode( errors, ERCE_SAME_LOCAL_GLOBAL_POWER ) == 2,
207 "Expected 2 ERCE_SAME_LOCAL_GLOBAL_POWER violations\n"
208 << reportWriter.GetTextReport() );
209
210 BOOST_CHECK_MESSAGE( CountErrorCode( errors, ERCE_SAME_LOCAL_GLOBAL_LABEL ) == 0,
211 "Expected 0 ERCE_SAME_LOCAL_GLOBAL_LABEL violations\n"
212 << reportWriter.GetTextReport() );
213}
214
215
216BOOST_AUTO_TEST_CASE( ERCLabelNameChecksMatchLegacy )
217{
218 LOCALE_IO locale;
219 auto& enabled = const_cast<ADVANCED_CFG&>( ADVANCED_CFG::GetCfg() ).m_ConnectivityEngine;
220 SCOPED_SET_RESET restore( enabled, enabled );
221 struct CASE
222 {
223 const char* fixture;
224 bool similar;
225 size_t count;
226 };
227
228 for( const CASE& test : { CASE{ "similar_labels", true, 3 },
229 CASE{ "same_local_global_label", false, 1 },
230 CASE{ "same_local_global_power", false, 2 } } )
231 {
232 BOOST_TEST_CONTEXT( test.fixture )
233 {
234 SETTINGS_MANAGER settings;
235 std::unique_ptr<SCHEMATIC> schematic;
236 enabled = false;
237 KI_TEST::LoadSchematic( settings, test.fixture, schematic );
238 schematic->RebuildConnectivity();
239 ERC_TESTER tester( schematic.get() );
240 const auto run = [&]()
241 {
242 if( test.similar )
243 tester.TestSimilarLabels();
244 else
246
247 std::vector<std::string> markers;
248
249 for( const SCH_SHEET_PATH& path : schematic->Hierarchy() )
250 {
251 std::vector<SCH_ITEM*> remove;
252
253 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_MARKER_T ) )
254 {
255 markers.push_back(
256 ERC_EXCLUSION::FromMarker( *static_cast<SCH_MARKER*>( item ) ).GetSortKey() );
257 remove.push_back( item );
258 }
259
260 for( SCH_ITEM* item : remove )
261 path.LastScreen()->DeleteItem( item );
262 }
263
264 std::sort( markers.begin(), markers.end() );
265 return markers;
266 };
267 const auto legacy = run();
268 BOOST_REQUIRE_EQUAL( legacy.size(), test.count );
269 enabled = true;
270 schematic->RebuildConnectivity();
271 schematic->ConnectionGraph()->Reset();
272 const auto engine = run();
273 BOOST_TEST( engine == legacy, boost::test_tools::per_element() );
274 }
275 }
276}
277
278
279BOOST_AUTO_TEST_CASE( ERCLabelNamesPreferShortestSharedInstance )
280{
281 LOCALE_IO locale;
282 auto& enabled = const_cast<ADVANCED_CFG&>( ADVANCED_CFG::GetCfg() ).m_ConnectivityEngine;
283 SCOPED_SET_RESET restore( enabled, enabled );
284 SETTINGS_MANAGER settings;
285 std::unique_ptr<SCHEMATIC> schematic;
286 KI_TEST::LoadSchematic( settings, "issue9673/issue9673", schematic );
287 std::vector<SCH_SHEET*> sheets;
288
289 for( SCH_ITEM* item : schematic->RootScreen()->Items().OfType( SCH_SHEET_T ) )
290 sheets.push_back( static_cast<SCH_SHEET*>( item ) );
291
292 BOOST_REQUIRE_EQUAL( sheets.size(), 2u );
293 std::ranges::sort( sheets,
294 []( const SCH_SHEET* a, const SCH_SHEET* b )
295 {
296 return a->m_Uuid < b->m_Uuid;
297 } );
298 SCH_SHEET* parent = sheets.front();
299 SCH_SHEET* target = sheets.back();
300 auto* nested = static_cast<SCH_SHEET*>( target->Duplicate( false ) );
301
302 for( SCH_SHEET_PIN* pin : nested->GetPins() )
303 const_cast<KIID&>( pin->m_Uuid ) = KIID();
304
305 parent->GetScreen()->Append( nested );
306 schematic->RefreshHierarchy();
307 std::set<KIID_PATH> paths;
308
309 for( const SCH_SHEET_PATH& path : schematic->Hierarchy() )
310 {
311 if( path.LastScreen() == target->GetScreen() )
312 paths.insert( path.Path() );
313 }
314
315 BOOST_REQUIRE_EQUAL( paths.size(), 2u );
316 const KIID_PATH shallow = *paths.begin();
317 const KIID_PATH deep = *paths.rbegin();
318 BOOST_REQUIRE( shallow.size() < deep.size() );
319 BOOST_REQUIRE( deep.AsString() < shallow.AsString() );
320 SETTINGS_MANAGER sourceSettings;
321 std::unique_ptr<SCHEMATIC> source;
322 KI_TEST::LoadSchematic( sourceSettings, "similar_labels", source );
323 SCH_LABEL_BASE* localSource = nullptr;
324 SCH_LABEL_BASE* globalSource = nullptr;
325
326 for( SCH_ITEM* item : source->RootScreen()->Items() )
327 {
328 if( item->Type() == SCH_LABEL_T && ( !localSource || item->m_Uuid < localSource->m_Uuid ) )
329 localSource = static_cast<SCH_LABEL_BASE*>( item );
330 else if( item->Type() == SCH_GLOBAL_LABEL_T && ( !globalSource || item->m_Uuid < globalSource->m_Uuid ) )
331 globalSource = static_cast<SCH_LABEL_BASE*>( item );
332 }
333
334 BOOST_REQUIRE( localSource );
335 BOOST_REQUIRE( globalSource );
336 auto* local = static_cast<SCH_LABEL_BASE*>( localSource->Duplicate( false ) );
337 auto* global = static_cast<SCH_LABEL_BASE*>( globalSource->Duplicate( false ) );
338 auto* lower = static_cast<SCH_LABEL_BASE*>( globalSource->Duplicate( false ) );
339 local->SetText( wxS( "ERC_DEPTH_ORDER" ) );
340 global->SetText( wxS( "ERC_DEPTH_ORDER" ) );
341 lower->SetText( wxS( "erc_depth_order" ) );
342 lower->Move( globalSource->GetPosition() );
343 BOOST_REQUIRE( lower->GetPosition() != global->GetPosition() );
344 target->GetScreen()->Append( local );
345 target->GetScreen()->Append( global );
346 target->GetScreen()->Append( lower );
347 const std::set<KIID> labels{ local->m_Uuid, global->m_Uuid, lower->m_Uuid };
348
349 for( bool backend : { false, true } )
350 {
351 BOOST_TEST_CONTEXT( "new engine " << backend )
352 {
353 enabled = backend;
354 schematic->RebuildConnectivity();
355 SCH_SCREENS screens( schematic->Root() );
357 ERC_TESTER tester( schematic.get() );
359 size_t same = 0;
360
361 for( SCH_ITEM* item : target->GetScreen()->Items().OfType( SCH_MARKER_T ) )
362 {
363 const auto error = std::static_pointer_cast<ERC_ITEM>( static_cast<SCH_MARKER*>( item )->GetRCItem() );
364
365 if( error->GetMainItemID() == global->m_Uuid && error->GetAuxItemID() == local->m_Uuid )
366 {
367 BOOST_CHECK( error->GetMainItemSheetPath().PathRef() == shallow );
368 BOOST_CHECK( error->GetAuxItemSheetPath().PathRef() == shallow );
369 ++same;
370 }
371 }
372
373 BOOST_CHECK_EQUAL( same, 1u );
375 tester.TestSimilarLabels();
376 size_t crossSheet = 0;
377 size_t sameSheet = 0;
378
379 for( SCH_ITEM* item : target->GetScreen()->Items().OfType( SCH_MARKER_T ) )
380 {
381 const auto error = std::static_pointer_cast<ERC_ITEM>( static_cast<SCH_MARKER*>( item )->GetRCItem() );
382
383 if( !labels.contains( error->GetMainItemID() ) || !labels.contains( error->GetAuxItemID() ) )
384 continue;
385
386 BOOST_CHECK_EQUAL( error->GetErrorCode(), ERCE_SIMILAR_LABELS );
387 const auto& main = error->GetMainItemSheetPath().PathRef();
388 const auto& aux = error->GetAuxItemSheetPath().PathRef();
389
390 // Saved exclusions depend on the main item following path text order
391 if( main != aux )
392 {
393 BOOST_CHECK( main == deep );
394 BOOST_CHECK( aux == shallow );
395 ++crossSheet;
396 }
397 else
398 {
399 ++sameSheet;
400 }
401 }
402
403 BOOST_CHECK_EQUAL( crossSheet, 4u );
404 BOOST_CHECK_EQUAL( sameSheet, 4u );
406 }
407 }
408}
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
const KIID m_Uuid
Definition eda_item.h:599
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:236
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:248
static ERC_EXCLUSION FromMarker(const SCH_MARKER &aMarker)
wxString GetTextReport()
Returns the ERC report in "text" (human readable) format in the C-locale.
Container for ERC settings.
std::map< int, SEVERITY > m_ERCSeverities
Runs the electrical rules checks and adds a SCH_MARKER for each violation.
Definition erc.h:60
int TestSimilarLabels()
Checks for labels that differ only in capitalization.
Definition erc.cpp:2696
int TestSameLocalGlobalLabel()
Checks for global and local labels with the same name.
Definition erc.cpp:2655
wxString AsString() const
Definition kiid.cpp:423
Definition kiid.h:46
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
SCH_ITEM * Duplicate(bool addToParentGroup, SCH_COMMIT *aCommit=nullptr, bool aDoClone=false) const
Routine to create a new copy of given item.
Definition sch_item.cpp:191
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:818
void DeleteAllMarkers(enum MARKER_BASE::MARKER_T aMarkerType, bool aIncludeExclusions)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:122
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
VECTOR2I GetPosition() const override
Definition sch_text.h:143
RAII class that sets an value at construction and resets it to the original value at destruction.
An implementation of the RC_ITEM_LIST interface which uses the global SHEETLIST to fulfill the contra...
int GetCount(int aSeverity=-1) const override
void SetSeverities(int aSeverities) override
std::shared_ptr< RC_ITEM > GetItem(int aIndex) const override
Retrieve a RC_ITEM by index.
@ ERCE_SIMILAR_POWER
2 power pins are equal for case insensitive comparisons.
@ ERCE_SIMILAR_LABELS
2 labels are equal for case insensitive comparisons.
@ ERCE_SAME_LOCAL_GLOBAL_LABEL
2 labels are equal for case insensitive comparisons.
@ ERCE_SIMILAR_LABEL_AND_POWER
label and pin are equal for case insensitive comparisons.
@ ERCE_SAME_LOCAL_GLOBAL_POWER
Local power port and global power port have the same name.
@ ERCE_LABEL_SINGLE_PIN
A label is connected only to a single pin.
@ ERCE_LIB_SYMBOL_MISMATCH
Symbol doesn't match copy in library.
@ ERCE_LIB_SYMBOL_ISSUES
Symbol not found in active libraries.
std::string source
void LoadSchematic(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< SCHEMATIC > &aSchematic)
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_IGNORE
std::vector< FAB_LAYER_COLOR > dummy
std::unique_ptr< SCHEMATIC > m_schematic
static int CountErrorCode(SHEETLIST_ERC_ITEMS_PROVIDER &aErrors, int aErrorCode)
BOOST_AUTO_TEST_CASE(ERCLabelNameChecksMatchLegacy)
BOOST_FIXTURE_TEST_CASE(ERCLabelCapitalization, ERC_REGRESSION_TEST_FIXTURE)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_TEST(netlist.find("R_G1 ARM_OUT1 DIE_B R='0.001 / ((SW_STATE)") !=std::string::npos)
std::string path
KIBIS_PIN * pin
BOOST_TEST_CONTEXT("Test Clearance")
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_LABEL_T
Definition typeinfo.h:163
@ SCH_SHEET_T
Definition typeinfo.h:171
@ SCH_MARKER_T
Definition typeinfo.h:154
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:164