KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_issue23058_jumper_pin_groups.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
26
29
30#include <connection_graph.h>
31#include <jumper_group.h>
32#include <schematic.h>
33#include <sch_sheet.h>
34#include <sch_screen.h>
36#include <lib_symbol.h>
37#include <sch_pin.h>
38#include <sch_symbol.h>
39#include <locale_io.h>
40
42{
44 {
45 m_settingsManager.LoadProject( "" );
46 m_schematic = std::make_unique<SCHEMATIC>( &m_settingsManager.Prj() );
47 m_schematic->Reset();
48 SCH_SHEET* defaultSheet = m_schematic->GetTopLevelSheet( 0 );
49
50 SCH_SHEET* root = new SCH_SHEET( m_schematic.get() );
51 SCH_SCREEN* screen = new SCH_SCREEN( m_schematic.get() );
52 root->SetScreen( screen );
53
54 m_schematic->AddTopLevelSheet( root );
55 m_schematic->RemoveTopLevelSheet( defaultSheet );
56 delete defaultSheet;
57 }
58
60 std::unique_ptr<SCHEMATIC> m_schematic;
61};
62
63
65{
66 SCH_SCREEN* screen = m_schematic->RootScreen();
68 path.push_back( &m_schematic->Root() );
69
70 LIB_SYMBOL* libSym = new LIB_SYMBOL( "SW_SPST", nullptr );
71
72 SCH_PIN* pin1 = new SCH_PIN( libSym );
73 pin1->SetNumber( "1" );
75 pin1->SetPosition( VECTOR2I( -508000, 0 ) );
76 libSym->AddDrawItem( pin1 );
77
78 SCH_PIN* pin2 = new SCH_PIN( libSym );
79 pin2->SetNumber( "2" );
81 pin2->SetPosition( VECTOR2I( 508000, 0 ) );
82 libSym->AddDrawItem( pin2 );
83
84 // Add a jumper pin group that references non-existent pin "3"
85 libSym->JumperPinGroups().Add( JUMPER_GROUP::Make( { wxT( "1" ), wxT( "3" ) } ).value() );
86
87 SCH_SYMBOL* sym = new SCH_SYMBOL( *libSym, libSym->GetLibId(), &path, 0, 0,
88 VECTOR2I( 15621000, 6223000 ) );
89 sym->UpdatePins();
90 screen->Append( sym );
91
92 // This must not crash even though pin "3" doesn't exist
93 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
94 BOOST_CHECK_NO_THROW( m_schematic->ConnectionGraph()->Recalculate( sheets, true ) );
95
96 delete libSym;
97}
98
99
101{
102 SCH_SCREEN* screen = m_schematic->RootScreen();
104 path.push_back( &m_schematic->Root() );
105
106 LIB_SYMBOL* libSym = new LIB_SYMBOL( "SW_SPST", nullptr );
107
108 SCH_PIN* pin1 = new SCH_PIN( libSym );
109 pin1->SetNumber( "1" );
111 pin1->SetPosition( VECTOR2I( -508000, 0 ) );
112 libSym->AddDrawItem( pin1 );
113
114 // Add a jumper pin group where ALL pin numbers are invalid
115 libSym->JumperPinGroups().Add( JUMPER_GROUP::Make( { wxT( "5" ), wxT( "6" ) } ).value() );
116
117 SCH_SYMBOL* sym = new SCH_SYMBOL( *libSym, libSym->GetLibId(), &path, 0, 0,
118 VECTOR2I( 15621000, 6223000 ) );
119 sym->UpdatePins();
120 screen->Append( sym );
121
122 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
123 BOOST_CHECK_NO_THROW( m_schematic->ConnectionGraph()->Recalculate( sheets, true ) );
124
125 delete libSym;
126}
127
128
130{
131 SCH_SCREEN* screen = m_schematic->RootScreen();
133 path.push_back( &m_schematic->Root() );
134
135 LIB_SYMBOL* libSym = new LIB_SYMBOL( "SW_SPDT", nullptr );
136
137 SCH_PIN* pin1 = new SCH_PIN( libSym );
138 pin1->SetNumber( "1" );
140 pin1->SetPosition( VECTOR2I( -508000, 0 ) );
141 libSym->AddDrawItem( pin1 );
142
143 SCH_PIN* pin2 = new SCH_PIN( libSym );
144 pin2->SetNumber( "2" );
146 pin2->SetPosition( VECTOR2I( 508000, 0 ) );
147 libSym->AddDrawItem( pin2 );
148
149 SCH_PIN* pin3 = new SCH_PIN( libSym );
150 pin3->SetNumber( "3" );
152 pin3->SetPosition( VECTOR2I( 508000, 254000 ) );
153 libSym->AddDrawItem( pin3 );
154
155 // Add a valid jumper pin group
156 libSym->JumperPinGroups().Add( JUMPER_GROUP::Make( { wxT( "1" ), wxT( "3" ) } ).value() );
157
158 SCH_SYMBOL* sym = new SCH_SYMBOL( *libSym, libSym->GetLibId(), &path, 0, 0,
159 VECTOR2I( 15621000, 6223000 ) );
160 sym->UpdatePins();
161 screen->Append( sym );
162
163 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
164 m_schematic->ConnectionGraph()->Recalculate( sheets, true );
165
166 path = sheets[0];
167
168 // Verify that pins 1 and 3 are connected via the jumper group
169 SCH_PIN* schPin1 = sym->GetPin( wxT( "1" ) );
170 SCH_PIN* schPin3 = sym->GetPin( wxT( "3" ) );
171
172 BOOST_REQUIRE( schPin1 );
173 BOOST_REQUIRE( schPin3 );
174
175 bool connected = false;
176
177 for( SCH_ITEM* item : schPin1->ConnectedItems( path ) )
178 {
179 if( item == schPin3 )
180 {
181 connected = true;
182 break;
183 }
184 }
185
186 BOOST_CHECK_MESSAGE( connected, "Pins 1 and 3 should be connected via jumper pin group" );
187
188 delete libSym;
189}
190
191
192BOOST_FIXTURE_TEST_CASE( JumperPinGroupStackedPinMember, JUMPER_PIN_GROUP_FIXTURE )
193{
194 SCH_SCREEN* screen = m_schematic->RootScreen();
196 path.push_back( &m_schematic->Root() );
197
198 LIB_SYMBOL* libSym = new LIB_SYMBOL( "USB_C", nullptr );
199
200 SCH_PIN* gnd = new SCH_PIN( libSym );
201 gnd->SetNumber( "[A1,A12]" );
203 gnd->SetPosition( VECTOR2I( -508000, 0 ) );
204 libSym->AddDrawItem( gnd );
205
206 SCH_PIN* shield = new SCH_PIN( libSym );
207 shield->SetNumber( "S1" );
209 shield->SetPosition( VECTOR2I( 508000, 0 ) );
210 libSym->AddDrawItem( shield );
211
212 // A1 is one contact of the stacked pin [A1,A12], so the group bonds that pin to S1.
213 libSym->JumperPinGroups().Add( JUMPER_GROUP::Make( { wxT( "A1" ), wxT( "S1" ) } ).value() );
214
215 SCH_SYMBOL* sym = new SCH_SYMBOL( *libSym, libSym->GetLibId(), &path, 0, 0, VECTOR2I( 15621000, 6223000 ) );
216 sym->UpdatePins();
217 screen->Append( sym );
218
219 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
220 m_schematic->ConnectionGraph()->Recalculate( sheets, true );
221
222 path = sheets[0];
223
224 SCH_PIN* schGnd = sym->GetPin( wxT( "[A1,A12]" ) );
225 SCH_PIN* schShield = sym->GetPin( wxT( "S1" ) );
226
227 BOOST_REQUIRE( schGnd );
228 BOOST_REQUIRE( schShield );
229
230 bool connected = false;
231
232 for( SCH_ITEM* item : schGnd->ConnectedItems( path ) )
233 {
234 if( item == schShield )
235 {
236 connected = true;
237 break;
238 }
239 }
240
241 BOOST_CHECK_MESSAGE( connected, "Stacked pin [A1,A12] and pin S1 should be connected via jumper pin group" );
242
243 delete libSym;
244}
245
246
247BOOST_FIXTURE_TEST_CASE( JumperPinGroupAllContactsOfOnePin, JUMPER_PIN_GROUP_FIXTURE )
248{
249 SCH_SCREEN* screen = m_schematic->RootScreen();
251 path.push_back( &m_schematic->Root() );
252
253 LIB_SYMBOL* libSym = new LIB_SYMBOL( "USB_C", nullptr );
254
255 SCH_PIN* gnd = new SCH_PIN( libSym );
256 gnd->SetNumber( "[A1,A12,B1,B12]" );
258 gnd->SetPosition( VECTOR2I( -508000, 0 ) );
259 libSym->AddDrawItem( gnd );
260
261 // Every member names a contact of the same pin, which is the case from issue 25063.
262 libSym->JumperPinGroups().Add(
263 JUMPER_GROUP::Make( { wxT( "A1" ), wxT( "A12" ), wxT( "B1" ), wxT( "B12" ) } ).value() );
264
265 SCH_SYMBOL* sym = new SCH_SYMBOL( *libSym, libSym->GetLibId(), &path, 0, 0, VECTOR2I( 15621000, 6223000 ) );
266 sym->UpdatePins();
267 screen->Append( sym );
268
269 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
270 BOOST_CHECK_NO_THROW( m_schematic->ConnectionGraph()->Recalculate( sheets, true ) );
271
272 path = sheets[0];
273
274 SCH_PIN* schGnd = sym->GetPin( wxT( "[A1,A12,B1,B12]" ) );
275 BOOST_REQUIRE( schGnd );
276
277 bool selfLinked = false;
278
279 for( SCH_ITEM* item : schGnd->ConnectedItems( path ) )
280 {
281 if( item == schGnd )
282 {
283 selfLinked = true;
284 break;
285 }
286 }
287
288 BOOST_CHECK_MESSAGE( !selfLinked, "A pin must not be connected to itself" );
289
290 delete libSym;
291}
292
293
295{
297
298 KI_TEST::LoadSchematic( m_settingsManager, "issue23058/issue23058", m_schematic );
299
300 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
301
302 // This must not crash. The schematic has a jumper pin group referencing
303 // pin "3" but the symbol only has pins "1" and "2".
304 BOOST_CHECK_NO_THROW( m_schematic->ConnectionGraph()->Recalculate( sheets, true ) );
305}
void Add(JUMPER_GROUP aGroup)
Add a JUMPER_GROUP to the set.
static std::optional< JUMPER_GROUP > Make(std::set< wxString > aNames)
Factory method to create a JUMPER_GROUP from a set of names.
Define a library symbol object.
Definition lib_symbol.h:114
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:190
JUMPER_GROUP_SET & JumperPinGroups()
Each jumper pin group is a set of pin numbers that should be treated as internally connected.
Definition lib_symbol.h:891
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
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
const std::vector< SCH_ITEM * > & ConnectedItems(const SCH_SHEET_PATH &aPath) const
Retrieve the set of items connected to this item on the given sheet.
Definition sch_item.cpp:766
void SetNumber(const wxString &aNumber)
Definition sch_pin.cpp:842
void SetPosition(const VECTOR2I &aPos) override
Definition sch_pin.h:318
void SetType(ELECTRICAL_PINTYPE aType)
Definition sch_pin.cpp:455
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
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 SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Schematic symbol object.
Definition sch_symbol.h:73
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
void LoadSchematic(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< SCHEMATIC > &aSchematic)
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
Definition pin_type.h:39
std::vector< FAB_LAYER_COLOR > dummy
Test for issue #23058: Jumper pin groups with out-of-bounds pin numbers cause crash.
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_FIXTURE_TEST_CASE(JumperPinGroupOutOfBounds, JUMPER_PIN_GROUP_FIXTURE)
KIBIS_PIN * pin3
std::string path
KIBIS_PIN * pin1
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708