KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_bus_net_name_determinism.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
29
32
33#include <connection_graph.h>
34#include <schematic.h>
35#include <sch_sheet.h>
36#include <sch_screen.h>
37#include <sch_symbol.h>
38#include <sch_pin.h>
40#include <locale_io.h>
43#include <richio.h>
44#include <wx/filename.h>
45#include <filesystem>
46#include <cstdlib>
47
56
57
68BOOST_FIXTURE_TEST_CASE( ShortedBusNetsHaveDeterministicName, BUS_NET_NAME_DETERMINISM_FIXTURE )
69{
71
72 // Load the test schematic multiple times to verify determinism
73 for( int iteration = 0; iteration < 3; ++iteration )
74 {
75 KI_TEST::LoadSchematic( m_settingsManager, "issue18606/issue18606", m_schematic );
76
77 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
78
79 // Find the resistor R201 in the child sheet and check its pin's net name
80 wxString foundNetName;
81 bool foundResistor = false;
82
83 for( const SCH_SHEET_PATH& path : sheets )
84 {
85 SCH_SCREEN* screen = path.LastScreen();
86
87 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
88 {
89 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
90
91 if( symbol->GetRef( &path ) == "R201" )
92 {
93 foundResistor = true;
94
95 for( SCH_PIN* pin : symbol->GetPins( &path ) )
96 {
97 SCH_CONNECTION* conn = pin->Connection( &path );
98
99 if( conn )
100 {
101 foundNetName = conn->Name();
102 break;
103 }
104 }
105
106 break;
107 }
108 }
109
110 if( foundResistor )
111 break;
112 }
113
114 BOOST_CHECK_MESSAGE( foundResistor, "R201 should be found in the schematic" );
115
116 // The net name should be deterministic - alphabetically "A0" should win
117 // when A0, A1, A2, A3 are shorted together.
118 // The path is "/" (not "/test/") because the net name is inherited from the
119 // parent sheet's bus A[0..3] during hierarchical propagation.
120 BOOST_CHECK_MESSAGE( foundNetName == "/A0",
121 "Net name should be '/A0' (alphabetically first bus member), "
122 "but got '" << foundNetName.ToStdString() << "' on iteration "
123 << iteration );
124 }
125}
126
127
128BOOST_FIXTURE_TEST_CASE( WeakPinNetNameSuffixesSurviveReload, BUS_NET_NAME_DETERMINISM_FIXTURE )
129{
130 const char* corpus = std::getenv( "KICAD_ORCAD_CORPUS" );
131
132 if( !corpus || !*corpus )
133 return;
134
135 for( const char* relativePath : { "PADS/adi-eval/DC1366B/DC1366B-2.DSN",
136 "OrCAD/_zulip-dm/S-593487-REV-B.DSN" } )
137 {
138 std::filesystem::path source = std::filesystem::path( corpus ) / relativePath;
139 bool equivalentDrivers = source.filename() == "S-593487-REV-B.DSN";
140
141 if( !std::filesystem::exists( source ) )
142 {
143 BOOST_TEST_MESSAGE( source.filename().string() << " not present; skipping weak-driver reload check." );
144 continue;
145 }
146
147 LOCALE_IO locale;
148 m_settingsManager.LoadProject( "" );
149 m_schematic = std::make_unique<SCHEMATIC>( &m_settingsManager.Prj() );
150 SCH_IO_ORCAD importer;
151 importer.LoadSchematicFile( source.string(), m_schematic.get() );
152
153 auto names = [&]()
154 {
155 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
156 m_schematic->ConnectionGraph()->Recalculate( sheets, true );
157 std::map<std::pair<wxString, wxString>, wxString> terminals;
158
159 for( const SCH_SHEET_PATH& sheet : sheets )
160 {
161 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
162 {
163 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
164 wxString reference = symbol->GetRef( &sheet, false );
165
166 if( reference != wxS( "J4" ) && reference != wxS( "T2" )
167 && reference != wxS( "T3" ) && reference != wxS( "T4" ) && reference != wxS( "U9" ) )
168 {
169 continue;
170 }
171
172 for( SCH_PIN* pin : symbol->GetPins( &sheet ) )
173 {
174 SCH_CONNECTION* connection = pin->Connection( &sheet );
175
176 if( connection )
177 terminals[{ reference, pin->GetNumber() }] = connection->Name();
178 }
179 }
180 }
181
182 std::map<wxString, wxString> result;
183
184 if( equivalentDrivers )
185 {
186 for( const wxString& number : { wxString( "3" ), wxString( "5" ), wxString( "10" ), wxString( "12" ) } )
187 {
188 auto terminal = terminals.find( { wxS( "U9" ), number } );
189 BOOST_REQUIRE( terminal != terminals.end() );
190 BOOST_CHECK( terminal->second.StartsWith( wxS( "Net-(U9-IN+)" ) ) );
191 result[number] = terminal->second;
192 }
193
194 BOOST_CHECK_EQUAL( result.at( wxS( "3" ) ), result.at( wxS( "10" ) ) );
195 BOOST_CHECK_NE( result.at( wxS( "3" ) ), result.at( wxS( "5" ) ) );
196 BOOST_CHECK_NE( result.at( wxS( "3" ) ), result.at( wxS( "12" ) ) );
197 BOOST_CHECK_NE( result.at( wxS( "5" ) ), result.at( wxS( "12" ) ) );
198 return result;
199 }
200
201 for( const auto& [number, transformer] :
202 { std::pair{ wxString( "9" ), wxString( "T2" ) },
203 std::pair{ wxString( "17" ), wxString( "T3" ) },
204 std::pair{ wxString( "25" ), wxString( "T4" ) } } )
205 {
206 auto connector = terminals.find( { wxS( "J4" ), number } );
207 auto peer = terminals.find( { transformer, wxS( "1" ) } );
208 BOOST_REQUIRE( connector != terminals.end() );
209 BOOST_REQUIRE( peer != terminals.end() );
210 BOOST_CHECK_EQUAL( connector->second, peer->second );
211 BOOST_CHECK( connector->second.StartsWith( wxS( "Net-(J4-1)" ) ) );
212 result[number] = connector->second;
213 }
214
215 std::set<wxString> distinct;
216
217 for( const auto& [number, name] : result )
218 distinct.insert( name );
219
220 BOOST_CHECK_EQUAL( distinct.size(), 3u );
221 return result;
222 };
223
224 auto before = names();
226 std::vector<wxString> files;
227 std::vector<std::pair<KIID, wxString>> identities;
228
229 for( SCH_SHEET* sheet : m_schematic->GetTopLevelSheets() )
230 {
231 wxString file = wxFileName::CreateTempFileName( wxS( "weak_net_reload_" ) );
232 io.SaveSchematicFile( file, sheet, m_schematic.get() );
233 files.push_back( file );
234 identities.emplace_back( sheet->m_Uuid, sheet->GetName() );
235 }
236
237 m_schematic->Reset();
238 std::vector<SCH_SHEET*> reloaded;
239
240 for( size_t i = 0; i < files.size(); ++i )
241 {
242 SCH_SHEET* sheet = io.LoadSchematicFile( files[i], m_schematic.get() );
243 BOOST_REQUIRE( sheet );
244 const_cast<KIID&>( sheet->m_Uuid ) = identities[i].first;
245 sheet->SetName( identities[i].second );
246 reloaded.push_back( sheet );
247 }
248
249 m_schematic->SetTopLevelSheets( reloaded );
250 m_schematic->RefreshHierarchy();
251
252 for( const SCH_SHEET_PATH& sheet : m_schematic->BuildSheetListSortedByPageNumbers() )
253 sheet.LastScreen()->UpdateLocalLibSymbolLinks();
254
255 auto after = names();
256
257 for( const auto& [number, name] : before )
258 BOOST_CHECK_EQUAL( after.at( number ), name );
259
260 for( const wxString& file : files )
261 wxRemoveFile( file );
262 }
263}
const char * name
const KIID m_Uuid
Definition eda_item.h:597
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:248
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
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString Name(bool aIgnoreSheet=false) const
A SCH_IO derivation for loading schematic files using the new s-expression file format.
void SaveSchematicFile(const wxString &aFileName, SCH_SHEET *aSheet, SCHEMATIC *aSchematic, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aSchematic to a storage file in a format that this SCH_IO implementation knows about,...
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:118
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void SetName(const wxString &aName)
Definition sch_sheet.h:143
Schematic symbol object.
Definition sch_symbol.h:75
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
void LoadSchematic(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< SCHEMATIC > &aSchematic)
std::vector< FAB_LAYER_COLOR > dummy
BOOST_FIXTURE_TEST_CASE(ShortedBusNetsHaveDeterministicName, BUS_NET_NAME_DETERMINISM_FIXTURE)
Test that when bus member nets (A0, A1, A2, A3) are shorted together, the resulting net name is deter...
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
std::string path
KIBIS_PIN * pin
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_SYMBOL_T
Definition typeinfo.h:168