KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_issue24044_expression_net_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 <schematic.h>
24#include <schematic_settings.h>
25#include <algorithm>
26#include <sch_sheet.h>
27#include <sch_sheet_path.h>
28#include <sch_sheet_pin.h>
29#include <sch_screen.h>
30#include <sch_label.h>
32#include <locale_io.h>
33
34
36{
38 std::unique_ptr<SCHEMATIC> m_schematic;
39};
40
41
66BOOST_FIXTURE_TEST_CASE( Issue24044ExpressionNetNames, ISSUE_24044_FIXTURE )
67{
69
70 KI_TEST::LoadSchematic( m_settingsManager, "issue24044/issue24044", m_schematic );
71
72 SCH_SHEET_LIST hierarchy = m_schematic->Hierarchy();
73
74 // Collect the two sub-sheet instance paths (both reference channels.kicad_sch but on
75 // different pages).
76 std::vector<SCH_SHEET_PATH> childPaths;
77
78 for( const SCH_SHEET_PATH& path : hierarchy )
79 {
80 if( path.size() == 2 )
81 childPaths.push_back( path );
82 }
83
84 BOOST_REQUIRE_EQUAL( childPaths.size(), 2U );
85
86 for( const SCH_SHEET_PATH& childPath : childPaths )
87 {
88 SCH_SHEET* childSheet = childPath.Last();
89 BOOST_REQUIRE( childSheet );
90
91 // Build the lookup on the child sheet's hierarchical labels
92 std::set<wxString> labelTexts;
93
94 for( SCH_ITEM* item : childSheet->GetScreen()->Items() )
95 {
96 if( item->Type() == SCH_HIER_LABEL_T )
97 {
98 SCH_HIERLABEL* label = static_cast<SCH_HIERLABEL*>( item );
99 labelTexts.insert( label->GetShownText( &childPath, INTERNAL ) );
100 }
101 }
102
103 wxString labelList;
104
105 for( const wxString& t : labelTexts )
106 {
107 if( !labelList.IsEmpty() )
108 labelList += wxT( "," );
109
110 labelList += t;
111 }
112
113 // Every sheet pin's resolved name must appear in the child's hierarchical labels
114 for( SCH_SHEET_PIN* pin : childSheet->GetPins() )
115 {
116 wxString pinText = pin->GetShownText( &childPath, INTERNAL );
117
118 BOOST_CHECK_MESSAGE( !pinText.Contains( wxT( "@{" ) )
119 && !pinText.Contains( wxT( "${" ) ),
120 wxString::Format( "Sheet pin '%s' on path '%s' did not fully "
121 "resolve expression variables",
122 pinText,
123 childPath.PathHumanReadable() ) );
124
125 BOOST_CHECK_MESSAGE( labelTexts.count( pinText ) == 1,
126 wxString::Format( "Sheet pin '%s' on path '%s' has no matching "
127 "hierarchical label inside the child sheet. "
128 "Labels: [%s]",
129 pinText,
130 childPath.PathHumanReadable(),
131 labelList ) );
132 }
133 }
134
135 // Each sheet instance should produce a different resolved name (the expression depends
136 // on the page number, so the two instances must disambiguate).
137 std::set<wxString> allPinTexts;
138
139 for( const SCH_SHEET_PATH& childPath : childPaths )
140 {
141 for( SCH_SHEET_PIN* pin : childPath.Last()->GetPins() )
142 allPinTexts.insert( pin->GetShownText( &childPath, INTERNAL ) );
143 }
144
145 BOOST_CHECK_EQUAL( allPinTexts.size(), 4U );
146
147 // Verify the computed names match the expected formula for each page number
148 for( const SCH_SHEET_PATH& childPath : childPaths )
149 {
150 long page = 0;
151 BOOST_REQUIRE( childPath.GetPageNumber().ToLong( &page ) );
152
153 std::set<wxString> expected = {
154 wxString::Format( "Ch%ld", ( page - 2 ) * 2 + 0 ),
155 wxString::Format( "Ch%ld", ( page - 2 ) * 2 + 1 )
156 };
157
158 std::set<wxString> actual;
159
160 for( SCH_SHEET_PIN* pin : childPath.Last()->GetPins() )
161 actual.insert( pin->GetShownText( &childPath, INTERNAL ) );
162
163 wxString actualList;
164
165 for( const wxString& t : actual )
166 {
167 if( !actualList.IsEmpty() )
168 actualList += wxT( "," );
169
170 actualList += t;
171 }
172
173 BOOST_CHECK_MESSAGE( actual == expected,
174 wxString::Format( "Page %ld expected {Ch%ld, Ch%ld} but got {%s}",
175 page,
176 ( page - 2 ) * 2 + 0,
177 ( page - 2 ) * 2 + 1,
178 actualList ) );
179 }
180}
181
182
196BOOST_FIXTURE_TEST_CASE( Issue24044PathFormEquivalence, ISSUE_24044_FIXTURE )
197{
199
200 KI_TEST::LoadSchematic( m_settingsManager, "issue24044/issue24044", m_schematic );
201
202 std::vector<SCH_SHEET_PATH> childPaths;
203
204 for( const SCH_SHEET_PATH& path : m_schematic->Hierarchy() )
205 {
206 if( path.size() == 2 )
207 childPaths.push_back( path );
208 }
209
210 BOOST_REQUIRE_EQUAL( childPaths.size(), 2U );
211
212 for( const SCH_SHEET_PATH& childPath : childPaths )
213 {
214 SCH_SHEET* childSheet = childPath.Last();
215 BOOST_REQUIRE( childSheet );
216
217 // Build the parent-screen path (drop the trailing child sheet). This is the path
218 // shape that callers such as sch_selection_tool pass in.
219 SCH_SHEET_PATH parentPath = childPath;
220 parentPath.pop_back();
221
222 BOOST_REQUIRE_EQUAL( parentPath.size() + 1U, childPath.size() );
223
224 for( SCH_SHEET_PIN* pin : childSheet->GetPins() )
225 {
226 wxString fromChildPath = pin->GetShownText( &childPath, INTERNAL );
227 wxString fromParentPath = pin->GetShownText( &parentPath, INTERNAL );
228
229 BOOST_CHECK_MESSAGE( fromChildPath == fromParentPath,
230 wxString::Format( "Sheet pin resolution diverged between "
231 "path forms: child='%s' parent='%s'",
232 fromChildPath,
233 fromParentPath ) );
234 }
235 }
236}
237
238
239BOOST_FIXTURE_TEST_CASE( IntersheetReferencesUseTheRequestedInstance, ISSUE_24044_FIXTURE )
240{
241 LOCALE_IO locale;
242 KI_TEST::LoadSchematic( m_settingsManager, "issue23840/BusAndVectors", m_schematic );
243 std::vector<SCH_SHEET_PATH> paths;
244
245 for( const auto& path : m_schematic->Hierarchy() )
246 {
247 if( path.LastScreen()->GetFileName().EndsWith( "LEDs.kicad_sch" ) )
248 paths.push_back( path );
249 }
250
251 BOOST_REQUIRE_EQUAL( paths.size(), 2u );
252 BOOST_REQUIRE( paths[0].LastScreen() == paths[1].LastScreen() );
253 BOOST_REQUIRE( paths[0].GetPageNumber() != paths[1].GetPageNumber() );
254 std::ranges::sort( paths, []( const auto& first, const auto& second )
255 {
256 return first.GetVirtualPageNumber() < second.GetVirtualPageNumber();
257 } );
258 auto sources = m_schematic->RootScreen()->Items().OfType( SCH_GLOBAL_LABEL_T );
259 BOOST_REQUIRE( sources.begin() != sources.end() );
260 auto* label = static_cast<SCH_GLOBALLABEL*>( ( *sources.begin() )->Duplicate( false ) );
261 paths[0].LastScreen()->Append( label );
262 auto& settings = m_schematic->Settings();
263 settings.m_IntersheetRefsShow = false;
264 settings.m_IntersheetRefsFormatShort = false;
265 settings.m_IntersheetRefsPrefix.clear();
266 settings.m_IntersheetRefsSuffix.clear();
267
268 for( bool perPage : { false, true } )
269 {
270 label->SetText( perPage ? wxString( "R21_${#}" ) : wxString( "R21_SHARED" ) );
271 m_schematic->RecomputeIntersheetRefs();
272
273 for( bool ownPage : { false, true } )
274 {
275 settings.m_IntersheetRefsListOwnPage = ownPage;
276
277 for( const auto& displayed : paths )
278 {
279 m_schematic->SetCurrentSheet( displayed );
280
281 for( const auto& requested : paths )
282 {
283 BOOST_TEST_CONTEXT( "per-page=" << perPage << " own-page=" << ownPage
284 << " requested=" << requested.GetPageNumber()
285 << " displayed=" << displayed.GetPageNumber() )
286 {
287 const wxString name = perPage ? "R21_" + requested.GetPageNumber()
288 : wxString( "R21_SHARED" );
289 BOOST_REQUIRE_EQUAL( label->GetShownText( &requested, FOR_GUI ), name );
290 std::vector<wxString> expected;
291 wxString expectedText;
292
293 for( const auto& other : paths )
294 {
295 if( ( perPage && other.Path() != requested.Path() )
296 || ( !ownPage && other.Path() == requested.Path() ) )
297 continue;
298
299 expected.push_back( other.GetPageNumber() );
300
301 if( !expectedText.IsEmpty() )
302 expectedText += ",";
303
304 expectedText += other.GetPageNumber();
305 }
306
307 std::vector<std::pair<wxString, wxString>> references;
308 label->GetIntersheetRefs( &requested, &references );
309 std::vector<wxString> actual;
310
311 for( const auto& [page, sheet] : references )
312 actual.push_back( page );
313
314 BOOST_TEST( actual == expected, boost::test_tools::per_element() );
315 wxString token = "INTERSHEET_REFS";
316 BOOST_REQUIRE( label->ResolveTextVar( &requested, &token, 0 ) );
317 BOOST_CHECK_EQUAL( token, expectedText );
318 }
319 }
320 }
321 }
322 }
323}
const char * name
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:165
wxString GetShownText(const SCH_SHEET_PATH *aPath, RESOLUTION_CONTEXT aContext, int aDepth=0) const override
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...
size_t size() const
Forwarded method from std::vector.
void pop_back()
Forwarded method from std::vector.
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
std::vector< SCH_SHEET_PIN * > & GetPins()
Definition sch_sheet.h:241
@ FOR_GUI
Definition common.h:89
@ INTERNAL
Definition common.h:92
void LoadSchematic(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< SCHEMATIC > &aSchematic)
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
std::vector< FAB_LAYER_COLOR > dummy
std::unique_ptr< SCHEMATIC > m_schematic
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_FIXTURE_TEST_CASE(Issue24044ExpressionNetNames, ISSUE_24044_FIXTURE)
Test for issue #24044: Inconsistent internal evaluation of net names when using expressions.
BOOST_TEST(netlist.find("R_G1 ARM_OUT1 DIE_B R='0.001 / ((SW_STATE)") !=std::string::npos)
std::string path
KIBIS_PIN * pin
VECTOR3I expected(15, 30, 45)
BOOST_TEST_CONTEXT("Test Clearance")
int actual
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_HIER_LABEL_T
Definition typeinfo.h:165
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:164