KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_connectivity_text.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * 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#include <eda_search_data.h>
24#include <widgets/msgpanel.h>
25#include <advanced_config.h>
26#include <connection_graph.h>
27#include <netclass.h>
28#include <sch_connection.h>
29#include <project.h>
33#include <locale_io.h>
34#include <sch_label.h>
35#include <sch_pin.h>
36#include <sch_screen.h>
37#include <sch_sheet_path.h>
38#include <sch_symbol.h>
39#include <schematic.h>
40#include <scoped_set_reset.h>
42
43#include <algorithm>
44#include <map>
45
46using namespace SCH_CONNECTIVITY;
47
48BOOST_AUTO_TEST_SUITE( ConnectivityText )
49
50BOOST_AUTO_TEST_CASE( DerivedPinTokensUsePublishedConnectivity )
51{
52 LOCALE_IO locale;
53 auto& enabled = const_cast<ADVANCED_CFG&>( ADVANCED_CFG::GetCfg() ).m_ConnectivityEngine;
54 SCOPED_SET_RESET restore( enabled, true );
55 size_t siblingChecks = 0;
56 size_t ncChecks = 0;
57 size_t knownNetChecks = 0;
58
59 for( const wxString& fixture : { wxString( "netlists/multinetclasses/multinetclasses" ),
60 wxString( "netlists/video/video" ),
61 wxString( "spice_netlists/multiunit_repeat_opamp/multiunit_repeat_opamp" ) } )
62 {
63 SETTINGS_MANAGER settings;
64 std::unique_ptr<SCHEMATIC> schematic;
65 KI_TEST::LoadSchematic( settings, fixture, schematic );
66 schematic->ConnectionGraph()->Reset();
67 schematic->Connectivity().Recalculate( *schematic, true );
68 const auto& netSettings = schematic->Project().GetProjectFile().NetSettings();
69 size_t checked = 0;
70 std::map<wxString, std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>>> units;
71
72 for( const SCH_SHEET_PATH& path : schematic->Hierarchy() )
73 {
74 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
75 {
76 auto* symbol = static_cast<SCH_SYMBOL*>( item );
77 units[symbol->GetRef( &path )].emplace_back( symbol, path );
78 }
79 }
80
81 for( const SCH_SHEET_PATH& path : schematic->Hierarchy() )
82 {
83 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
84 {
85 auto* symbol = static_cast<SCH_SYMBOL*>( item );
86
87 for( const SCH_PIN* pin : symbol->GetPins( &path ) )
88 {
89 if( SCH_CONNECTION* legacy = pin->Connection( &path ) )
90 legacy->Reset();
91
92 const auto connection = schematic->Connectivity().Connection( pin->m_Uuid, path.Path() );
93 BOOST_REQUIRE( connection );
94 wxString localName = connection->LocalName();
95
96 if( localName.Lower().StartsWith( "unconnected" ) )
97 {
98 localName = "NC";
99 ++ncChecks;
100 }
101
102 for( const auto& [function, expected] :
103 { std::pair{ wxString( "NET_NAME" ), connection->Name() },
104 std::pair{ wxString( "SHORT_NET_NAME" ), localName },
105 std::pair{ wxString( "NET_CLASS" ),
106 netSettings->GetEffectiveNetClass( connection->Name() )->GetName() } } )
107 {
108 wxString token = function + "(" + pin->GetNumber() + ")";
109 BOOST_TEST_CONTEXT( fixture << " " << symbol->GetRef( &path ) << " " << token )
110 {
111 BOOST_REQUIRE( symbol->ResolveTextVar( &path, &token, 0 ) );
112 BOOST_CHECK_EQUAL( token, expected );
113
114 for( const auto& [sibling, siblingPath] : units.at( symbol->GetRef( &path ) ) )
115 {
116 if( sibling->GetUnitSelection( &siblingPath )
117 == symbol->GetUnitSelection( &path ) )
118 continue;
119
120 const auto siblingPins = sibling->GetPins( &siblingPath );
121
122 if( std::any_of( siblingPins.begin(), siblingPins.end(),
123 [&]( const SCH_PIN* candidate )
124 { return candidate->GetNumber() == pin->GetNumber(); } ) )
125 continue;
126
127 wxString siblingToken = function + "(" + pin->GetNumber() + ")";
128 BOOST_REQUIRE( sibling->ResolveTextVar( &siblingPath, &siblingToken, 0 ) );
129 BOOST_CHECK_EQUAL( siblingToken, expected );
130 ++siblingChecks;
131 }
132 }
133 }
134
135 if( fixture == "netlists/multinetclasses/multinetclasses"
136 && symbol->GetRef( &path ) == "R8" && pin->GetNumber() == "1" )
137 {
138 for( const auto& [source, expected] :
139 { std::pair{ wxString( "NET_NAME(1)" ), wxString( "/NET_2" ) },
140 std::pair{ wxString( "SHORT_NET_NAME(1)" ), wxString( "NET_2" ) },
141 std::pair{ wxString( "NET_CLASS(1)" ), wxString( "CLASS_COMPLETE" ) } } )
142 {
143 wxString token = source;
144 BOOST_REQUIRE( symbol->ResolveTextVar( &path, &token, 0 ) );
145 BOOST_CHECK_EQUAL( token, expected );
146 }
147
148 BOOST_CHECK_EQUAL( pin->GetEffectiveNetClass( &path )->GetName(), "CLASS_COMPLETE" );
149 std::vector<MSG_PANEL_ITEM> info;
150 const auto name = AppendConnectionInfo( *pin, info, &path );
152 BOOST_CHECK_EQUAL( *name, "/NET_2" );
153 using ROWS = std::vector<std::pair<wxString, wxString>>;
154 ROWS rows;
155
156 for( const auto& row : info )
157 {
158 if( row.GetUpperText() != "Subgraph Code" && row.GetUpperText() != "Connection Source" )
159 rows.emplace_back( row.GetUpperText(), row.GetLowerText() );
160 }
161
162 const ROWS expectedRows{ { "Connection Name", "/NET_2" },
163 { "Resolved Netclass", "CLASS_COMPLETE" } };
164 BOOST_CHECK( rows == expectedRows );
165 ++knownNetChecks;
166 }
167
168 ++checked;
169 }
170 }
171 }
172
173 if( fixture == "netlists/multinetclasses/multinetclasses" )
174 {
175 size_t labelChecks = 0;
176
177 for( const SCH_SHEET_PATH& path : schematic->Hierarchy() )
178 {
179 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_LABEL_T ) )
180 {
181 auto* label = static_cast<SCH_LABEL*>( item );
182
183 if( label->GetText() != "NET_2" )
184 continue;
185
186 if( SCH_CONNECTION* legacy = label->Connection( &path ) )
187 legacy->Reset();
188
189 for( const auto& [source, expected] :
190 { std::pair{ wxString( "NET_NAME" ), wxString( "/NET_2" ) },
191 std::pair{ wxString( "SHORT_NET_NAME" ), wxString( "NET_2" ) },
192 std::pair{ wxString( "NET_CLASS" ), wxString( "CLASS_COMPLETE" ) } } )
193 {
194 wxString token = source;
195 BOOST_REQUIRE( label->ResolveTextVar( &path, &token, 0 ) );
196 BOOST_CHECK_EQUAL( token, expected );
197 }
198
199 ++labelChecks;
200 }
201 }
202
203 BOOST_CHECK_EQUAL( labelChecks, 1u );
204 }
205
206 BOOST_CHECK_GT( checked, 0u );
207 BOOST_CHECK( schematic->ConnectionGraph()->GetNetMap().empty() );
208 }
209
210 BOOST_CHECK_GT( siblingChecks, 0u );
211 BOOST_CHECK_GT( ncChecks, 0u );
212 BOOST_CHECK_EQUAL( knownNetChecks, 1u );
213}
214
215BOOST_AUTO_TEST_CASE( ConnectionPanelPreservesBusAliasDetails )
216{
217 LOCALE_IO locale;
218 auto& enabled = const_cast<ADVANCED_CFG&>( ADVANCED_CFG::GetCfg() ).m_ConnectivityEngine;
219 SCOPED_SET_RESET restore( enabled, false );
220 SETTINGS_MANAGER settings;
221 std::unique_ptr<SCHEMATIC> schematic;
222 KI_TEST::LoadSchematic( settings, "netlists/hierarchy_aliases/hierarchy_aliases", schematic );
223 using ROWS = std::vector<std::pair<wxString, wxString>>;
224 struct EXPECTED
225 {
226 SCH_ITEM* item;
228 ROWS rows;
229 };
230 auto panel = []( const SCH_ITEM& item, const SCH_SHEET_PATH* path )
231 {
232 std::vector<MSG_PANEL_ITEM> info;
233 BOOST_CHECK( !AppendConnectionInfo( item, info, path ) );
234 ROWS rows;
235
236 for( const auto& row : info )
237 {
238 const wxString& heading = row.GetUpperText();
239
240 if( heading != "Bus Code" && heading != "Subgraph Code" && heading != "Connection Source" )
241 rows.emplace_back( heading, row.GetLowerText() );
242 }
243
244 return rows;
245 };
246 std::vector<EXPECTED> expected;
247
248 for( const SCH_SHEET_PATH& path : schematic->Hierarchy() )
249 {
250 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_LABEL_T ) )
251 {
252 if( const SCH_CONNECTION* connection = item->Connection( &path ); connection && connection->IsBus() )
253 {
254 auto rows = panel( *item, &path );
255 BOOST_REQUIRE_GT( rows.size(), 1u );
256 expected.push_back( { item, path, std::move( rows ) } );
257 }
258 }
259 }
260
261 BOOST_REQUIRE( !expected.empty() );
262 schematic->ConnectionGraph()->Reset();
263 enabled = true;
264 schematic->Connectivity().Recalculate( *schematic, true );
265
266 for( const auto& entry : expected )
267 {
268 entry.item->Connection( &entry.path )->Reset();
269 BOOST_CHECK( panel( *entry.item, &entry.path ) == entry.rows );
270 schematic->SetCurrentSheet( entry.path );
271 BOOST_CHECK( panel( *entry.item, nullptr ) == entry.rows );
272 }
273}
274
275BOOST_AUTO_TEST_CASE( LabelNetSearchUsesPublishedSignalsAndBusMembers )
276{
277 auto& enabled = const_cast<ADVANCED_CFG&>( ADVANCED_CFG::GetCfg() ).m_ConnectivityEngine;
278 SCOPED_SET_RESET restore( enabled, false );
279 SETTINGS_MANAGER settings;
280 std::unique_ptr<SCHEMATIC> schematic;
281 KI_TEST::LoadSchematic( settings, "netlists/multinetclasses/multinetclasses", schematic );
282 schematic->ConnectionGraph()->Reset();
283 enabled = true;
284 schematic->Connectivity().Recalculate( *schematic, true );
285 SCH_SHEET_PATH path = schematic->Hierarchy().front();
286 size_t checked = 0;
287
288 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_LABEL_T ) )
289 {
290 auto* label = static_cast<SCH_LABEL*>( item );
291 const wxString text = label->GetText();
292
293 if( text != "NET_2" && text != "BUS{SIGNAL A[0..2]}" )
294 continue;
295
296 SCH_SEARCH_DATA search;
297 search.findString = text == "NET_2" ? wxString( "/NET_2" ) : wxString( "/BUS.SIGNAL" );
299 BOOST_CHECK( !label->Matches( search, &path ) );
300 search.searchNetNames = true;
301 BOOST_CHECK( label->Matches( search, &path ) );
302 ++checked;
303 }
304
305 BOOST_CHECK_EQUAL( checked, 2u );
306}
307
const char * name
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
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).
bool IsBus() const
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition sch_item.cpp:579
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Schematic symbol object.
Definition sch_symbol.h:74
RAII class that sets an value at construction and resets it to the original value at destruction.
bool m_ConnectivityEngine
Use the schematic connectivity engine instead of CONNECTION_GRAPH.
Message panel definition file.
void LoadSchematic(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< SCHEMATIC > &aSchematic)
Value keys and the key session of the schematic connectivity engine.
std::optional< wxString > AppendConnectionInfo(const SCH_ITEM &aItem, std::vector< MSG_PANEL_ITEM > &aList, const SCH_SHEET_PATH *aPath=nullptr)
Append connection details; return its name for a signal, or no value for a bus/missing row.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
EDA_SEARCH_MATCH_MODE matchMode
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_CASE(DerivedPinTokensUsePublishedConnectivity)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
std::string path
KIBIS_PIN * pin
VECTOR3I expected(15, 30, 45)
BOOST_TEST_CONTEXT("Test Clearance")
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_LABEL_T
Definition typeinfo.h:163