KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_sch_pin.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 2
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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
26
27// Code under test
28#include <lib_symbol.h>
29#include <pin_type.h>
30#include <sch_pin.h>
31#include <sch_symbol.h>
32
33
35{
36public:
38 {
39 m_parent_part = new LIB_SYMBOL( "parent_part", nullptr );
40
42 m_parent_part->AddDrawItem( m_lib_pin );
43
44 // give the pin some kind of data we can use to test
45 m_lib_pin->SetNumber( "42" );
46 m_lib_pin->SetName( "pinname" );
48 m_lib_pin->SetPosition( VECTOR2I( 1, 2 ) );
49
51 m_parent_symbol = new SCH_SYMBOL( *m_parent_part, m_parent_part->GetLibId(), &path, 0, 0,
52 VECTOR2I( 1, 2 ) );
53 m_parent_symbol->SetRef( &path, "U2" );
54 m_parent_symbol->UpdatePins();
55
56 m_sch_pin = m_parent_symbol->GetPins( &path )[0];
57 }
58
60 {
61 delete m_parent_symbol;
62 delete m_parent_part;
63 }
64
67
69 SCH_PIN* m_sch_pin; // owned by m_parent_symbol, not us
70};
71
72
76BOOST_FIXTURE_TEST_SUITE( SchPin, TEST_SCH_PIN_FIXTURE )
77
78
81BOOST_AUTO_TEST_CASE( DefaultProperties )
82{
83 BOOST_CHECK_EQUAL( m_sch_pin->GetParentSymbol(), m_parent_symbol );
84
85 BOOST_CHECK_EQUAL( m_sch_pin->GetLocalPosition(), VECTOR2I( 1, 2 ) );
86 BOOST_CHECK_EQUAL( m_sch_pin->GetPosition(), VECTOR2I( 2, 4 ) );
87
88 BOOST_CHECK_EQUAL( m_sch_pin->IsVisible(), m_lib_pin->IsVisible() );
89 BOOST_CHECK_EQUAL( m_sch_pin->GetName(), m_lib_pin->GetName() );
90 BOOST_CHECK_EQUAL( m_sch_pin->GetNumber(), m_lib_pin->GetNumber() );
91
92 BOOST_CHECK( ( m_sch_pin->GetType() == m_lib_pin->GetType() ) );
93
94 BOOST_CHECK_EQUAL( m_sch_pin->IsGlobalPower(), m_lib_pin->IsGlobalPower() );
95 BOOST_CHECK_EQUAL( m_sch_pin->IsLocalPower(), m_lib_pin->IsLocalPower() );
96}
97
102{
103 SCH_PIN assigned = *m_sch_pin;
104
105 BOOST_CHECK_EQUAL( assigned.GetParentSymbol(), m_parent_symbol );
106 BOOST_CHECK_EQUAL( assigned.GetNumber(), m_lib_pin->GetNumber() );
107}
108
113{
114 SCH_PIN copied( *m_sch_pin );
115
116 BOOST_CHECK_EQUAL( copied.GetParentSymbol(), m_parent_symbol );
117 BOOST_CHECK_EQUAL( copied.GetNumber(), m_lib_pin->GetNumber() );
118 BOOST_CHECK_EQUAL( copied.GetAlt(), wxEmptyString );
119
120 SCH_PIN::ALT alt;
121 alt.m_Name = wxS( "alt" );
124 copied.GetAlternates()[ wxS( "alt" ) ] = alt;
125
126 // Set some non-default values
127 copied.SetAlt( "alt" );
128
129 SCH_PIN copied2( copied );
130 BOOST_CHECK_EQUAL( copied2.GetAlt(), "alt" );
131}
132
137{
138 // dangles by default
139 BOOST_CHECK_EQUAL( m_sch_pin->IsDangling(), true );
140
141 // all you have to do to un-dangle is say so
142 m_sch_pin->SetIsDangling( false );
143 BOOST_CHECK_EQUAL( m_sch_pin->IsDangling(), false );
144
145 // and the same to re-dangle
146 m_sch_pin->SetIsDangling( true );
147 BOOST_CHECK_EQUAL( m_sch_pin->IsDangling(), true );
148}
149
153BOOST_AUTO_TEST_CASE( PinNumbering )
154{
156
157 const wxString name = m_sch_pin->GetDefaultNetName( path );
158 BOOST_CHECK_EQUAL( name, "Net-(U2-pinname)" );
159
160 // do it again: this should now (transparently) go though the net name map
161 // can't really check directly, but coverage tools should see this
162 const wxString map_name = m_sch_pin->GetDefaultNetName( path );
163 BOOST_CHECK_EQUAL( map_name, name );
164}
165
169BOOST_AUTO_TEST_CASE( PinNumberingPower )
170{
171 // but if we set isPower...
172 m_lib_pin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN );
173 m_parent_part->SetGlobalPower();
174 BOOST_CHECK_EQUAL( m_lib_pin->IsGlobalPower(), true );
175
176 // and update symbol from library...
178 delete m_parent_symbol;
179 m_parent_symbol = new SCH_SYMBOL( *m_parent_part, m_parent_part->GetLibId(), &path, 0, 0,
180 VECTOR2I( 1, 2 ) );
181 m_parent_symbol->SetRef( &path, "U2" );
182 m_parent_symbol->SetValueFieldText( "voltage_value" );
183 m_parent_symbol->UpdatePins();
184
185 m_sch_pin = m_parent_symbol->GetPins( &path )[0];
186
187 // ... then the name is just the pin name
188 const wxString pwr_name = m_sch_pin->GetDefaultNetName( path );
189 BOOST_CHECK_EQUAL( pwr_name, "voltage_value" );
190}
191
192BOOST_AUTO_TEST_CASE( AlternatePinRenameUpdates )
193{
194 SCH_PIN::ALT alt;
195 alt.m_Name = wxS( "ALT1" );
198 m_lib_pin->GetAlternates()[ wxS( "ALT1" ) ] = alt;
199
200 m_parent_symbol->SetLibSymbol( m_parent_part->Flatten().release() );
201 m_sch_pin = m_parent_symbol->GetPins()[0];
202 m_sch_pin->SetAlt( wxS( "ALT1" ) );
203
204 SCH_PIN::ALT altNew = alt;
205 m_lib_pin->GetAlternates().erase( wxS( "ALT1" ) );
206 altNew.m_Name = wxS( "ALT1_NEW" );
207 m_lib_pin->GetAlternates()[ wxS( "ALT1_NEW" ) ] = altNew;
208
209 m_parent_symbol->SetLibSymbol( m_parent_part->Flatten().release() );
210
211 SCH_PIN* updatedPin = m_parent_symbol->GetPins()[0];
212
213 BOOST_CHECK_EQUAL( updatedPin->GetAlt(), "ALT1_NEW" );
214 BOOST_CHECK( updatedPin->GetAlternates().count( wxS( "ALT1" ) ) == 0 );
215}
216
217
221BOOST_AUTO_TEST_CASE( AlternatePinTypeReturnsCorrectType )
222{
223 // Set the library pin's default type to no_connect
224 m_lib_pin->SetType( ELECTRICAL_PINTYPE::PT_NC );
225
226 // Add an alternate with a different type (power_in)
227 SCH_PIN::ALT powerAlt;
228 powerAlt.m_Name = wxS( "8.pow" );
231 m_lib_pin->GetAlternates()[ wxS( "8.pow" ) ] = powerAlt;
232
233 // Flatten and update the symbol to get a fresh schematic pin
234 m_parent_symbol->SetLibSymbol( m_parent_part->Flatten().release() );
235 m_sch_pin = m_parent_symbol->GetPins()[0];
236
237 // Before selecting alternate, type should be the default (NC)
238 BOOST_CHECK( m_sch_pin->GetType() == ELECTRICAL_PINTYPE::PT_NC );
239
240 // Select the alternate
241 m_sch_pin->SetAlt( wxS( "8.pow" ) );
242
243 // After selecting alternate, type should be the alternate's type (POWER_IN)
244 BOOST_CHECK_EQUAL( m_sch_pin->GetAlt(), "8.pow" );
245 BOOST_CHECK( m_sch_pin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN );
246
247 // Also verify shape changed
248 BOOST_CHECK( m_sch_pin->GetShape() == GRAPHIC_PINSHAPE::LINE );
249}
250
251
257BOOST_AUTO_TEST_CASE( AlternatePinTypePersistsThroughSymbolUpdate )
258{
259 // Set the library pin's default type to no_connect
260 m_lib_pin->SetType( ELECTRICAL_PINTYPE::PT_NC );
261
262 // Add an alternate with a different type (power_in)
263 SCH_PIN::ALT powerAlt;
264 powerAlt.m_Name = wxS( "8.pow" );
267 m_lib_pin->GetAlternates()[ wxS( "8.pow" ) ] = powerAlt;
268
269 // First flatten to set up the symbol
270 m_parent_symbol->SetLibSymbol( m_parent_part->Flatten().release() );
271 m_sch_pin = m_parent_symbol->GetPins()[0];
272
273 // Set the alternate on the schematic pin (like the parser would)
274 m_sch_pin->SetAlt( wxS( "8.pow" ) );
275 BOOST_CHECK_EQUAL( m_sch_pin->GetAlt(), "8.pow" );
276 BOOST_CHECK( m_sch_pin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN );
277
278 // Now simulate what happens when the library symbol is re-resolved
279 // This is similar to what happens after loading a schematic from file
280 m_parent_symbol->SetLibSymbol( m_parent_part->Flatten().release() );
281 m_sch_pin = m_parent_symbol->GetPins()[0];
282
283 // After the symbol update, the alternate should still be set
284 BOOST_CHECK_EQUAL( m_sch_pin->GetAlt(), "8.pow" );
285
286 // And GetType() should return the alternate's type
287 BOOST_CHECK( m_sch_pin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN );
288}
289
290
296BOOST_AUTO_TEST_CASE( ParserCreatedPinWithAlternate )
297{
298 // Create a library symbol with a pin that has alternates
299 LIB_SYMBOL* libSymbol = new LIB_SYMBOL( "test_symbol", nullptr );
300
301 SCH_PIN* libPin = new SCH_PIN( libSymbol );
302 libPin->SetNumber( "8" );
303 libPin->SetName( "PIN8" );
304 libPin->SetType( ELECTRICAL_PINTYPE::PT_NC ); // Default type is NC
305 libPin->SetPosition( VECTOR2I( 0, 0 ) );
306
307 // Add an alternate with power_in type
308 SCH_PIN::ALT powerAlt;
309 powerAlt.m_Name = wxS( "8.pow" );
312 libPin->GetAlternates()[ wxS( "8.pow" ) ] = powerAlt;
313
314 libSymbol->AddDrawItem( libPin );
315
316 // Create a schematic symbol
318 SCH_SYMBOL* symbol = new SCH_SYMBOL( *libSymbol, libSymbol->GetLibId(), &path, 0, 0,
319 VECTOR2I( 0, 0 ) );
320 symbol->SetRef( &path, "J1" );
321
322 // Simulate what the parser does: create a raw pin with alternate set
323 // This bypasses SetAlt() validation by using the constructor directly
324 symbol->GetRawPins().clear(); // Remove auto-created pins
325 symbol->GetRawPins().emplace_back(
326 std::make_unique<SCH_PIN>( symbol, wxS( "8" ), wxS( "8.pow" ), KIID() ) );
327
328 SCH_PIN* parserPin = symbol->GetRawPins()[0].get();
329
330 // At this point, m_alt is set but m_libPin is nullptr
331 BOOST_CHECK_EQUAL( parserPin->GetAlt(), "8.pow" );
332 BOOST_CHECK( parserPin->GetLibPin() == nullptr );
333
334 // GetType() should return PT_UNSPECIFIED when m_libPin is null
335 BOOST_CHECK( parserPin->GetType() == ELECTRICAL_PINTYPE::PT_UNSPECIFIED );
336
337 // Now simulate SetLibSymbol() which calls UpdatePins()
338 symbol->SetLibSymbol( libSymbol->Flatten().release() );
339
340 // Verify the flattened library symbol has pins with alternates
341 BOOST_CHECK( symbol->GetLibSymbolRef() != nullptr );
342 std::vector<SCH_PIN*> libPins = symbol->GetLibSymbolRef()->GetGraphicalPins( 0, 0 );
343 BOOST_CHECK_EQUAL( libPins.size(), 1 );
344
345 if( !libPins.empty() )
346 {
347 SCH_PIN* flattenedLibPin = libPins[0];
348 BOOST_CHECK( !flattenedLibPin->GetAlternates().empty() );
349 BOOST_CHECK( flattenedLibPin->GetAlternates().count( wxS( "8.pow" ) ) > 0 );
350 }
351
352 // Get the pin after the update
353 SCH_PIN* updatedPin = symbol->GetPins( &path )[0];
354
355 // The alternate should still be set
356 BOOST_CHECK_EQUAL( updatedPin->GetAlt(), "8.pow" );
357
358 // m_libPin should now be set
359 BOOST_CHECK( updatedPin->GetLibPin() != nullptr );
360
361 // GetType() should return the alternate's type (PT_POWER_IN)
362 BOOST_CHECK( updatedPin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN );
363
364 delete symbol;
365 delete libSymbol;
366}
367
368
374BOOST_AUTO_TEST_CASE( LibraryPinAlternatesPreservedThroughCopy )
375{
376 // Create original library symbol with pin that has alternates
377 LIB_SYMBOL* origLibSymbol = new LIB_SYMBOL( "test_symbol", nullptr );
378
379 SCH_PIN* origLibPin = new SCH_PIN( origLibSymbol );
380 origLibPin->SetNumber( "8" );
381 origLibPin->SetName( "8" ); // Default name matches number
382 origLibPin->SetType( ELECTRICAL_PINTYPE::PT_NC ); // Default type is NC
383 origLibPin->SetPosition( VECTOR2I( 0, 0 ) );
384
385 // Add alternate with power_in type
386 SCH_PIN::ALT powerAlt;
387 powerAlt.m_Name = wxS( "8.pow" );
390 origLibPin->GetAlternates()[ wxS( "8.pow" ) ] = powerAlt;
391
392 origLibSymbol->AddDrawItem( origLibPin );
393
394 // Verify original has alternates
395 BOOST_CHECK( !origLibPin->GetAlternates().empty() );
396 BOOST_CHECK( origLibPin->GetAlternates().count( wxS( "8.pow" ) ) > 0 );
397
398 // Simulate what happens during loading:
399 // 1. Library symbol is stored in m_libSymbols (just keep the original)
400 // 2. Create a COPY of the library symbol (like UpdateLocalLibSymbolLinks does)
401 LIB_SYMBOL* copiedLibSymbol = new LIB_SYMBOL( *origLibSymbol );
402
403 // Verify the copied library symbol has pins with alternates
404 std::vector<SCH_PIN*> copiedLibPins = copiedLibSymbol->GetGraphicalPins( 0, 0 );
405 BOOST_CHECK_EQUAL( copiedLibPins.size(), 1 );
406
407 if( !copiedLibPins.empty() )
408 {
409 SCH_PIN* copiedLibPin = copiedLibPins[0];
410
411 // This is the critical check - does the copied lib pin have alternates?
412 BOOST_CHECK_MESSAGE( !copiedLibPin->GetAlternates().empty(),
413 "Copied library pin should have alternates" );
414 BOOST_CHECK_MESSAGE( copiedLibPin->GetAlternates().count( wxS( "8.pow" ) ) > 0,
415 "Copied library pin should have '8.pow' alternate" );
416
417 // Check if the alternate has the correct type
418 if( copiedLibPin->GetAlternates().count( wxS( "8.pow" ) ) > 0 )
419 {
420 BOOST_CHECK( copiedLibPin->GetAlternates().at( wxS( "8.pow" ) ).m_Type
422 }
423 }
424
425 // Now create a schematic symbol with parser-created raw pins
427 SCH_SYMBOL* symbol = new SCH_SYMBOL( *origLibSymbol, origLibSymbol->GetLibId(), &path, 0, 0,
428 VECTOR2I( 0, 0 ) );
429 symbol->SetRef( &path, "J1" );
430
431 // Clear auto-created pins and add parser-style raw pin
432 symbol->GetRawPins().clear();
433 symbol->GetRawPins().emplace_back(
434 std::make_unique<SCH_PIN>( symbol, wxS( "8" ), wxS( "8.pow" ), KIID() ) );
435
436 // Verify raw pin state before SetLibSymbol
437 SCH_PIN* rawPin = symbol->GetRawPins()[0].get();
438 BOOST_CHECK_EQUAL( rawPin->GetAlt(), "8.pow" );
439 BOOST_CHECK( rawPin->GetLibPin() == nullptr );
440
441 // Call SetLibSymbol with the COPIED library symbol (like UpdateLocalLibSymbolLinks does)
442 symbol->SetLibSymbol( copiedLibSymbol ); // Takes ownership
443
444 // Get the pin after UpdatePins() was called
445 std::vector<SCH_PIN*> schPins = symbol->GetPins( &path );
446 BOOST_CHECK_EQUAL( schPins.size(), 1 );
447
448 if( !schPins.empty() )
449 {
450 SCH_PIN* schPin = schPins[0];
451
452 // Check that m_libPin is set
453 BOOST_CHECK_MESSAGE( schPin->GetLibPin() != nullptr,
454 "Schematic pin should have m_libPin set after UpdatePins" );
455
456 // Check that the alternate is still set
457 BOOST_CHECK_MESSAGE( schPin->GetAlt() == "8.pow",
458 "Alternate should be preserved as '8.pow'" );
459
460 // Check that GetType() returns the alternate's type
461 BOOST_CHECK_MESSAGE( schPin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN,
462 "GetType() should return alternate's type (PT_POWER_IN)" );
463
464 // Additional diagnostic: check the library pin's alternates
465 if( schPin->GetLibPin() )
466 {
467 BOOST_CHECK_MESSAGE( !schPin->GetLibPin()->GetAlternates().empty(),
468 "Library pin pointed to by schematic pin should have alternates" );
469 BOOST_CHECK_MESSAGE( schPin->GetLibPin()->GetAlternates().count( wxS( "8.pow" ) ) > 0,
470 "Library pin should have '8.pow' in its alternates map" );
471 }
472 }
473
474 delete symbol;
475 delete origLibSymbol;
476}
477
478
484BOOST_AUTO_TEST_CASE( GetTypeBeforeLibPinSet )
485{
486 // Create a schematic symbol with parser-created raw pin
488 LIB_SYMBOL* libSymbol = new LIB_SYMBOL( "test_symbol", nullptr );
489
490 SCH_PIN* libPin = new SCH_PIN( libSymbol );
491 libPin->SetNumber( "8" );
492 libPin->SetName( "8" );
494 libPin->SetPosition( VECTOR2I( 0, 0 ) );
495
496 SCH_PIN::ALT powerAlt;
497 powerAlt.m_Name = wxS( "8.pow" );
500 libPin->GetAlternates()[ wxS( "8.pow" ) ] = powerAlt;
501 libSymbol->AddDrawItem( libPin );
502
503 // Create symbol using default constructor (like parser does)
504 SCH_SYMBOL* symbol = new SCH_SYMBOL();
505 symbol->SetLibId( libSymbol->GetLibId() );
506
507 // Add parser-style raw pin with alternate set but no m_libPin
508 symbol->GetRawPins().emplace_back(
509 std::make_unique<SCH_PIN>( symbol, wxS( "8" ), wxS( "8.pow" ), KIID() ) );
510
511 SCH_PIN* rawPin = symbol->GetRawPins()[0].get();
512
513 // At this point: m_alt is set, m_libPin is nullptr, m_type is PT_INHERIT
514 BOOST_CHECK_EQUAL( rawPin->GetAlt(), "8.pow" );
515 BOOST_CHECK( rawPin->GetLibPin() == nullptr );
516
517 // GetType() with m_alt set but m_libPin=nullptr should return PT_UNSPECIFIED
518 // per the code in GetType()
519 BOOST_CHECK_MESSAGE( rawPin->GetType() == ELECTRICAL_PINTYPE::PT_UNSPECIFIED,
520 "GetType() with m_alt set but m_libPin=nullptr should return PT_UNSPECIFIED" );
521
522 // GetShownName() should still return the alternate name
523 BOOST_CHECK_EQUAL( rawPin->GetShownName(), "8.pow" );
524
525 // Now set the library symbol which triggers UpdatePins()
526 symbol->SetLibSymbol( new LIB_SYMBOL( *libSymbol ) );
527
528 // After UpdatePins(), pin should have correct type
529 std::vector<SCH_PIN*> schPins = symbol->GetPins( &path );
530 BOOST_CHECK_EQUAL( schPins.size(), 1 );
531
532 if( !schPins.empty() )
533 {
534 SCH_PIN* schPin = schPins[0];
535 BOOST_CHECK_EQUAL( schPin->GetAlt(), "8.pow" );
536 BOOST_CHECK( schPin->GetLibPin() != nullptr );
537 BOOST_CHECK_MESSAGE( schPin->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN,
538 "After SetLibSymbol, GetType() should return PT_POWER_IN" );
539 }
540
541 delete symbol;
542 delete libSymbol;
543}
544
545
549BOOST_AUTO_TEST_CASE( ChangeSymbolFewerPinsNoCrash )
550{
551 // Create a symbol with multiple pins (pins 1, 2, 3)
552 LIB_SYMBOL* multiPinPart = new LIB_SYMBOL( "multi_pin_part", nullptr );
553
554 SCH_PIN* pin1 = new SCH_PIN( multiPinPart );
555 pin1->SetNumber( "1" );
556 pin1->SetName( "PIN1" );
558 pin1->SetPosition( VECTOR2I( 0, 0 ) );
559 multiPinPart->AddDrawItem( pin1 );
560
561 SCH_PIN* pin2 = new SCH_PIN( multiPinPart );
562 pin2->SetNumber( "2" );
563 pin2->SetName( "PIN2" );
565 pin2->SetPosition( VECTOR2I( 100, 0 ) );
566 multiPinPart->AddDrawItem( pin2 );
567
568 SCH_PIN* pin3 = new SCH_PIN( multiPinPart );
569 pin3->SetNumber( "3" );
570 pin3->SetName( "PIN3" );
572 pin3->SetPosition( VECTOR2I( 200, 0 ) );
573 multiPinPart->AddDrawItem( pin3 );
574
576 SCH_SYMBOL* symbol = new SCH_SYMBOL( *multiPinPart, multiPinPart->GetLibId(), &path, 0, 0,
577 VECTOR2I( 0, 0 ) );
578 symbol->SetRef( &path, "U1" );
579 symbol->UpdatePins();
580
581 BOOST_CHECK_EQUAL( symbol->GetPins( &path ).size(), 3 );
582
583 // Create a symbol with only one pin (pin 1)
584 LIB_SYMBOL* singlePinPart = new LIB_SYMBOL( "single_pin_part", nullptr );
585
586 SCH_PIN* newPin1 = new SCH_PIN( singlePinPart );
587 newPin1->SetNumber( "1" );
588 newPin1->SetName( "NEW_PIN1" );
590 newPin1->SetPosition( VECTOR2I( 0, 0 ) );
591 singlePinPart->AddDrawItem( newPin1 );
592
593 // Change to the single-pin symbol - this should not crash
594 symbol->SetLibSymbol( singlePinPart->Flatten().release() );
595
596 // Verify the symbol now has only one pin
597 BOOST_CHECK_EQUAL( symbol->GetPins( &path ).size(), 1 );
598
599 // Verify GetPin returns the correct pin for the new lib pin
600 std::vector<SCH_PIN*> libPins = symbol->GetLibSymbolRef()->GetGraphicalPins( 0, 0 );
601 BOOST_CHECK_EQUAL( libPins.size(), 1 );
602
603 SCH_PIN* schPin = symbol->GetPin( libPins[0] );
604 BOOST_CHECK( schPin != nullptr );
605
606 if( schPin )
607 {
608 BOOST_CHECK_EQUAL( schPin->GetNumber(), "1" );
609 }
610
611 delete symbol;
612 delete multiPinPart;
613 delete singlePinPart;
614}
615
621BOOST_AUTO_TEST_CASE( HasConnectivityChangesForPowerPinVisibility )
622{
623 // Create a library symbol with a hidden power pin
624 LIB_SYMBOL* libSymbol = new LIB_SYMBOL( "power_symbol", nullptr );
625
626 SCH_PIN* libPin = new SCH_PIN( libSymbol );
627 libPin->SetNumber( "1" );
628 libPin->SetName( "VCC" );
630 libPin->SetPosition( VECTOR2I( 0, 0 ) );
631 libPin->SetVisible( false ); // Hidden power pin
632 libSymbol->AddDrawItem( libPin );
633
634 // Create a schematic symbol
636 SCH_SYMBOL* symbol1 = new SCH_SYMBOL( *libSymbol, libSymbol->GetLibId(), &path, 0, 0,
637 VECTOR2I( 0, 0 ) );
638 symbol1->SetRef( &path, "U1" );
639 symbol1->UpdatePins();
640
641 SCH_PIN* schPin1 = symbol1->GetPins( &path )[0];
642
643 // Verify initial state - should be a global power pin
644 BOOST_CHECK( schPin1->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN );
645 BOOST_CHECK( !schPin1->IsVisible() );
646 BOOST_CHECK( schPin1->IsGlobalPower() );
647
648 // Create a second symbol with the same pin made visible
649 libPin->SetVisible( true ); // Make pin visible
650 SCH_SYMBOL* symbol2 = new SCH_SYMBOL( *libSymbol, libSymbol->GetLibId(), &path, 0, 0,
651 VECTOR2I( 0, 0 ) );
652 symbol2->SetRef( &path, "U2" );
653 symbol2->UpdatePins();
654
655 SCH_PIN* schPin2 = symbol2->GetPins( &path )[0];
656
657 // Verify second state - should NOT be a global power pin (visible power pins aren't global)
658 BOOST_CHECK( schPin2->GetType() == ELECTRICAL_PINTYPE::PT_POWER_IN );
659 BOOST_CHECK( schPin2->IsVisible() );
660 BOOST_CHECK( !schPin2->IsGlobalPower() );
661
662 // HasConnectivityChanges should detect the visibility difference for power pins
663 BOOST_CHECK_MESSAGE( schPin1->HasConnectivityChanges( schPin2, &path ),
664 "HasConnectivityChanges should detect visibility change for power input pins" );
665
666 BOOST_CHECK_MESSAGE( schPin2->HasConnectivityChanges( schPin1, &path ),
667 "HasConnectivityChanges should detect visibility change for power input pins (reverse)" );
668
669 // Verify that regular (non-power) pins don't trigger connectivity changes on visibility change
670 libPin->SetType( ELECTRICAL_PINTYPE::PT_INPUT ); // Change to regular input
671 libPin->SetVisible( false );
672
673 SCH_SYMBOL* symbol3 = new SCH_SYMBOL( *libSymbol, libSymbol->GetLibId(), &path, 0, 0,
674 VECTOR2I( 0, 0 ) );
675 symbol3->SetRef( &path, "U3" );
676 symbol3->UpdatePins();
677 SCH_PIN* schPin3 = symbol3->GetPins( &path )[0];
678
679 libPin->SetVisible( true ); // Change visibility
680
681 SCH_SYMBOL* symbol4 = new SCH_SYMBOL( *libSymbol, libSymbol->GetLibId(), &path, 0, 0,
682 VECTOR2I( 0, 0 ) );
683 symbol4->SetRef( &path, "U4" );
684 symbol4->UpdatePins();
685 SCH_PIN* schPin4 = symbol4->GetPins( &path )[0];
686
687 // Regular pins shouldn't trigger connectivity changes on visibility change
688 BOOST_CHECK_MESSAGE( !schPin3->HasConnectivityChanges( schPin4, &path ),
689 "HasConnectivityChanges should NOT detect visibility change for regular input pins" );
690
691 delete symbol1;
692 delete symbol2;
693 delete symbol3;
694 delete symbol4;
695 delete libSymbol;
696}
697
698
703BOOST_AUTO_TEST_CASE( HasConnectivityChangesForPinTypeChange )
704{
705 // Create a library symbol with a regular pin
706 LIB_SYMBOL* libSymbol = new LIB_SYMBOL( "test_symbol", nullptr );
707
708 SCH_PIN* libPin = new SCH_PIN( libSymbol );
709 libPin->SetNumber( "1" );
710 libPin->SetName( "PIN1" );
712 libPin->SetPosition( VECTOR2I( 0, 0 ) );
713 libSymbol->AddDrawItem( libPin );
714
715 // Create first schematic symbol with regular input pin
717 SCH_SYMBOL* symbol1 = new SCH_SYMBOL( *libSymbol, libSymbol->GetLibId(), &path, 0, 0,
718 VECTOR2I( 0, 0 ) );
719 symbol1->SetRef( &path, "U1" );
720 symbol1->UpdatePins();
721 SCH_PIN* schPin1 = symbol1->GetPins( &path )[0];
722
723 // Change pin type to power input
725
726 SCH_SYMBOL* symbol2 = new SCH_SYMBOL( *libSymbol, libSymbol->GetLibId(), &path, 0, 0,
727 VECTOR2I( 0, 0 ) );
728 symbol2->SetRef( &path, "U2" );
729 symbol2->UpdatePins();
730 SCH_PIN* schPin2 = symbol2->GetPins( &path )[0];
731
732 // Changing to/from PT_POWER_IN should trigger connectivity changes
733 BOOST_CHECK_MESSAGE( schPin1->HasConnectivityChanges( schPin2, &path ),
734 "HasConnectivityChanges should detect change from INPUT to POWER_IN" );
735
736 BOOST_CHECK_MESSAGE( schPin2->HasConnectivityChanges( schPin1, &path ),
737 "HasConnectivityChanges should detect change from POWER_IN to INPUT" );
738
739 delete symbol1;
740 delete symbol2;
741 delete libSymbol;
742}
743
744
const char * name
Definition kiid.h:49
Define a library symbol object.
Definition lib_symbol.h:83
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:152
std::vector< const SCH_PIN * > GetGraphicalPins(int aUnit=0, int aBodyStyle=0) const
Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body.
std::unique_ptr< LIB_SYMBOL > Flatten() const
Return a flattened symbol inheritance to the caller.
void AddDrawItem(SCH_ITEM *aItem, bool aSort=true)
Add a new draw aItem to the draw object list and sort according to aSort.
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:258
const std::map< wxString, ALT > & GetAlternates() const
Definition sch_pin.h:160
void SetNumber(const wxString &aNumber)
Definition sch_pin.cpp:630
void SetVisible(bool aVisible)
Definition sch_pin.h:114
ALT GetAlt(const wxString &aAlt)
Definition sch_pin.h:174
bool HasConnectivityChanges(const SCH_ITEM *aItem, const SCH_SHEET_PATH *aInstance=nullptr) const override
Check if aItem has connectivity changes against this object.
Definition sch_pin.cpp:1570
void SetName(const wxString &aName)
Definition sch_pin.cpp:409
bool IsGlobalPower() const
Return whether this pin forms a global power connection: i.e., is part of a power symbol and of type ...
Definition sch_pin.cpp:357
bool IsVisible() const
Definition sch_pin.cpp:377
SCH_PIN * GetLibPin() const
Definition sch_pin.h:89
void SetPosition(const VECTOR2I &aPos) override
Definition sch_pin.h:251
const wxString & GetShownName() const
Definition sch_pin.cpp:567
void SetType(ELECTRICAL_PINTYPE aType)
Definition sch_pin.cpp:333
const wxString & GetNumber() const
Definition sch_pin.h:124
ELECTRICAL_PINTYPE GetType() const
Definition sch_pin.cpp:313
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:76
void SetLibId(const LIB_ID &aName)
std::vector< std::unique_ptr< SCH_PIN > > & GetRawPins()
Definition sch_symbol.h:663
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
SCH_PIN * GetPin(const wxString &number) const
Find a symbol pin by number.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition sch_symbol.h:184
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
SCH_SYMBOL * m_parent_symbol
LIB_SYMBOL * m_parent_part
@ PT_INPUT
usual pin input: must be connected
Definition pin_type.h:37
@ PT_NC
not connected (must be left open)
Definition pin_type.h:50
@ PT_OUTPUT
usual output
Definition pin_type.h:38
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
Definition pin_type.h:46
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
Definition pin_type.h:45
wxString m_Name
Definition sch_pin.h:45
GRAPHIC_PINSHAPE m_Shape
Definition sch_pin.h:46
ELECTRICAL_PINTYPE m_Type
Definition sch_pin.h:47
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE_END()
bool copied
std::string path
BOOST_AUTO_TEST_CASE(DefaultProperties)
Declare the test suite.
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695