KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_sch_symbol.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
28
30#include "eeschema_test_utils.h"
31
32// Code under test
33#include <sch_symbol.h>
34#include <sch_edit_frame.h>
36#include <lib_symbol.h>
37#include <eda_search_data.h>
38
39
41{
42public:
44 {
45 if( !m_schematic )
46 return nullptr;
47
48 SCH_SCREEN* screen = m_schematic->RootScreen();
49
50 if( !screen )
51 return nullptr;
52
53 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
54 {
55 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
56
57 if( symbol )
58 return symbol;
59 }
60
61 return nullptr;
62 }
63
66};
67
68
72BOOST_FIXTURE_TEST_SUITE( SchSymbol, TEST_SCH_SYMBOL_FIXTURE )
73
74
75
78BOOST_AUTO_TEST_CASE( DefaultProperties )
79{
80}
81
82
87{
88 TRANSFORM t = m_symbol.GetTransform();
89
90 m_symbol.SetOrientation( SYM_ORIENT_90 );
91 t = m_symbol.GetTransform();
92 m_symbol.SetTransform( TRANSFORM() );
93 m_symbol.SetOrientation( SYM_ORIENT_180 );
94 t = m_symbol.GetTransform();
95 m_symbol.SetTransform( TRANSFORM() );
96 m_symbol.SetOrientation( SYM_ORIENT_270 );
97 t = m_symbol.GetTransform();
98}
99
100
104BOOST_AUTO_TEST_CASE( SchSymbolVariantTest )
105{
106 wxFileName fn;
107 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
108 fn.AppendDir( wxS( "variant_test" ) );
109 fn.SetName( wxS( "variant_test" ) );
111
112 LoadSchematic( fn.GetFullPath() );
113
114 SCH_SYMBOL* symbol = GetFirstSymbol();
115 BOOST_CHECK( symbol );
116
117 // Test for an empty (non-existant) variant.
118 wxString variantName = wxS( "Variant1" );
119 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
120 BOOST_CHECK( !variant );
121
122 // Test DNP property variant.
123 BOOST_CHECK( !symbol->GetDNP() );
124 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
125 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
126
127 // Test exclude from BOM property variant.
128 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
129 symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], variantName );
130 BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], variantName ) );
131
132 // Test exclude from simulation property variant.
133 BOOST_CHECK( !symbol->GetExcludedFromSim() );
134 symbol->SetExcludedFromSim( true, &m_schematic->Hierarchy()[0], variantName );
135 BOOST_CHECK( symbol->GetExcludedFromSim( &m_schematic->Hierarchy()[0], variantName ) );
136
137 // Test exclude from board property variant.
138 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
139 symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], variantName );
140 BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], variantName ) );
141
142 // Test exclude from position files property variant.
143 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
144 symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], variantName );
145 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], variantName ) );
146
147 // Test a value field variant change.
148 BOOST_CHECK( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
149 false, 0 ) == wxS( "1K" ) );
150 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "10K" ), &m_schematic->Hierarchy()[0], variantName );
151 BOOST_CHECK( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
152 false, 0, variantName ) == wxS( "10K" ) );
153 // BOOST_CHECK( symbol->GetFieldText( FIELD_T::VALUE, &m_schematic->Hierarchy()[0], variantName ) == wxS( "10K" ) );
154}
155
156
162BOOST_AUTO_TEST_CASE( FieldAdditionByName )
163{
164 wxFileName fn;
165 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
166 fn.AppendDir( wxS( "variant_test" ) );
167 fn.SetName( wxS( "variant_test" ) );
169
170 LoadSchematic( fn.GetFullPath() );
171
172 SCH_SYMBOL* symbol = GetFirstSymbol();
173 BOOST_REQUIRE( symbol );
174
175 wxString newFieldName = wxS( "Sim.Library" );
176
177 // GetField by name should return null for non-existent field
178 const SCH_FIELD* existing = symbol->GetField( newFieldName );
179 BOOST_CHECK( existing == nullptr );
180
181 // Create a field to add
182 SCH_FIELD newField( symbol, FIELD_T::USER, newFieldName );
183 newField.SetText( wxS( "test_model.lib" ) );
184
185 // AddField should add the field and return a valid pointer
186 SCH_FIELD* addedField = symbol->AddField( newField );
187 BOOST_REQUIRE( addedField != nullptr );
188
189 // After setting the parent, verify the field is correctly configured
190 addedField->SetParent( symbol );
191 BOOST_CHECK( addedField->GetParent() == symbol );
192
193 // Now GetField should find the newly added field
194 const SCH_FIELD* found = symbol->GetField( newFieldName );
195 BOOST_REQUIRE( found != nullptr );
196 BOOST_CHECK( found->GetText() == wxS( "test_model.lib" ) );
197}
198
199
212BOOST_AUTO_TEST_CASE( VariantDialogBatchCommit )
213{
214 wxFileName fn;
215 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
216 fn.AppendDir( wxS( "variant_test" ) );
217 fn.SetName( wxS( "variant_test" ) );
219
220 LoadSchematic( fn.GetFullPath() );
221
222 SCH_SYMBOL* symbol = GetFirstSymbol();
223 BOOST_REQUIRE( symbol );
224
225 SCH_SHEET_LIST hierarchy = m_schematic->Hierarchy();
226 const SCH_SHEET_PATH& sheet = hierarchy[0];
227 wxString variantName = wxS( "DialogTest" );
228
229 // All base properties should start false.
230 BOOST_CHECK( !symbol->GetDNP() );
231 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
232 BOOST_CHECK( !symbol->GetExcludedFromSim() );
233 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
234 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
235
236 // Simulate dialog_symbol_properties TransferDataFromWindow call order.
237 // ExcludeFromSim is left unchecked (false), the other four are checked (true).
238 symbol->SetExcludedFromSim( false, &sheet, variantName );
239 symbol->SetExcludedFromBOM( true, &sheet, variantName );
240 symbol->SetExcludedFromBoard( true, &sheet, variantName );
241 symbol->SetExcludedFromPosFiles( true, &sheet, variantName );
242 symbol->SetDNP( true, &sheet, variantName );
243
244 // All four checked properties must read back as true through the variant.
245 BOOST_CHECK( symbol->GetDNP( &sheet, variantName ) );
246 BOOST_CHECK( symbol->GetExcludedFromBOM( &sheet, variantName ) );
247 BOOST_CHECK( symbol->GetExcludedFromBoard( &sheet, variantName ) );
248 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &sheet, variantName ) );
249 BOOST_CHECK( !symbol->GetExcludedFromSim( &sheet, variantName ) );
250
251 // Base properties must remain unchanged.
252 BOOST_CHECK( !symbol->GetDNP() );
253 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
254 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
255 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
256}
257
258
262BOOST_AUTO_TEST_CASE( VariantDescription )
263{
264 wxFileName fn;
265 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
266 fn.AppendDir( wxS( "variant_test" ) );
267 fn.SetName( wxS( "variant_test" ) );
269
270 LoadSchematic( fn.GetFullPath() );
271 BOOST_REQUIRE( m_schematic );
272
273 wxString variantName = wxS( "TestVariant" );
274 wxString description = wxS( "This is a test variant description" );
275
276 // Add a variant
277 m_schematic->AddVariant( variantName );
278 BOOST_CHECK( m_schematic->GetVariantNames().contains( variantName ) );
279
280 // Set description
281 m_schematic->SetVariantDescription( variantName, description );
282 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( variantName ), description );
283
284 // Empty description for non-existent variant
285 BOOST_CHECK( m_schematic->GetVariantDescription( wxS( "NonExistent" ) ).IsEmpty() );
286
287 // Clear description
288 m_schematic->SetVariantDescription( variantName, wxEmptyString );
289 BOOST_CHECK( m_schematic->GetVariantDescription( variantName ).IsEmpty() );
290}
291
292
296BOOST_AUTO_TEST_CASE( TextVariableVARIANT )
297{
298 wxFileName fn;
299 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
300 fn.AppendDir( wxS( "variant_test" ) );
301 fn.SetName( wxS( "variant_test" ) );
303
304 LoadSchematic( fn.GetFullPath() );
305 BOOST_REQUIRE( m_schematic );
306
307 wxString variantName = wxS( "MilitaryGrade" );
308
309 // Add a variant and set it as current
310 m_schematic->AddVariant( variantName );
311 m_schematic->SetCurrentVariant( variantName );
312
313 // Test that ${VARIANT} resolves to the current variant name
314 wxString token = wxS( "VARIANT" );
315 bool resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
316 BOOST_CHECK( resolved );
317 BOOST_CHECK_EQUAL( token, variantName );
318
319 // Also test VARIANTNAME (legacy/alias)
320 token = wxS( "VARIANTNAME" );
321 resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
322 BOOST_CHECK( resolved );
323 BOOST_CHECK_EQUAL( token, variantName );
324
325 // Empty variant
326 m_schematic->SetCurrentVariant( wxEmptyString );
327 token = wxS( "VARIANT" );
328 resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
329 BOOST_CHECK( resolved );
330 BOOST_CHECK( token.IsEmpty() );
331}
332
333
337BOOST_AUTO_TEST_CASE( TextVariableVARIANT_DESC )
338{
339 wxFileName fn;
340 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
341 fn.AppendDir( wxS( "variant_test" ) );
342 fn.SetName( wxS( "variant_test" ) );
344
345 LoadSchematic( fn.GetFullPath() );
346 BOOST_REQUIRE( m_schematic );
347
348 wxString variantName = wxS( "IndustrialVariant" );
349 wxString description = wxS( "Industrial temperature range components" );
350
351 // Add a variant with description and set it as current
352 m_schematic->AddVariant( variantName );
353 m_schematic->SetVariantDescription( variantName, description );
354 m_schematic->SetCurrentVariant( variantName );
355
356 // Test that ${VARIANT_DESC} resolves to the variant description
357 wxString token = wxS( "VARIANT_DESC" );
358 bool resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
359 BOOST_CHECK( resolved );
360 BOOST_CHECK_EQUAL( token, description );
361
362 // Test with no description set
363 m_schematic->SetVariantDescription( variantName, wxEmptyString );
364 token = wxS( "VARIANT_DESC" );
365 resolved = m_schematic->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, 0 );
366 BOOST_CHECK( resolved );
367 BOOST_CHECK( token.IsEmpty() );
368}
369
370
374BOOST_AUTO_TEST_CASE( RenameVariantPreservesData )
375{
376 wxFileName fn;
377 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
378 fn.AppendDir( wxS( "variant_test" ) );
379 fn.SetName( wxS( "variant_test" ) );
381
382 LoadSchematic( fn.GetFullPath() );
383 BOOST_REQUIRE( m_schematic );
384
385 SCH_SYMBOL* symbol = GetFirstSymbol();
386 BOOST_REQUIRE( symbol );
387
388 wxString oldName = wxS( "OriginalVariant" );
389 wxString newName = wxS( "RenamedVariant" );
390 wxString description = wxS( "Original description" );
391
392 // Set up the variant with data
393 m_schematic->AddVariant( oldName );
394 m_schematic->SetVariantDescription( oldName, description );
395 m_schematic->SetCurrentVariant( oldName );
396
397 // Set symbol variant properties
398 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], oldName );
399 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "100K" ), &m_schematic->Hierarchy()[0], oldName );
400
401 // Verify the data is set
402 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], oldName ) );
403 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
404 false, 0, oldName ), wxS( "100K" ) );
405
406 // Rename the variant
407 m_schematic->RenameVariant( oldName, newName );
408
409 // Verify old name is gone
410 BOOST_CHECK( !m_schematic->GetVariantNames().contains( oldName ) );
411
412 // Verify new name exists
413 BOOST_CHECK( m_schematic->GetVariantNames().contains( newName ) );
414
415 // Verify description was preserved
416 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( newName ), description );
417
418 // Verify current variant was updated
419 BOOST_CHECK_EQUAL( m_schematic->GetCurrentVariant(), newName );
420
421 // Verify symbol variant data was preserved
422 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], newName ) );
423 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
424 false, 0, newName ), wxS( "100K" ) );
425}
426
427
431BOOST_AUTO_TEST_CASE( CopyVariantCreatesIndependentCopy )
432{
433 wxFileName fn;
434 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
435 fn.AppendDir( wxS( "variant_test" ) );
436 fn.SetName( wxS( "variant_test" ) );
438
439 LoadSchematic( fn.GetFullPath() );
440 BOOST_REQUIRE( m_schematic );
441
442 SCH_SYMBOL* symbol = GetFirstSymbol();
443 BOOST_REQUIRE( symbol );
444
445 wxString sourceVariant = wxS( "SourceVariant" );
446 wxString copyVariant = wxS( "CopiedVariant" );
447 wxString description = wxS( "Source description" );
448
449 // Set up the source variant
450 m_schematic->AddVariant( sourceVariant );
451 m_schematic->SetVariantDescription( sourceVariant, description );
452
453 // Set symbol variant properties for source
454 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], sourceVariant );
455 symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], sourceVariant );
456 symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], sourceVariant );
457 symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], sourceVariant );
458 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "47K" ), &m_schematic->Hierarchy()[0], sourceVariant );
459
460 // Copy the variant
461 m_schematic->CopyVariant( sourceVariant, copyVariant );
462
463 // Verify both variants exist
464 BOOST_CHECK( m_schematic->GetVariantNames().contains( sourceVariant ) );
465 BOOST_CHECK( m_schematic->GetVariantNames().contains( copyVariant ) );
466
467 // Verify description was copied
468 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( copyVariant ), description );
469
470 // Verify symbol properties were copied
471 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], copyVariant ) );
472 BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], copyVariant ) );
473 BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], copyVariant ) );
474 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], copyVariant ) );
475 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
476 false, 0, copyVariant ), wxS( "47K" ) );
477
478 // Modify the copy and verify source is unchanged
479 symbol->SetDNP( false, &m_schematic->Hierarchy()[0], copyVariant );
480 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "100K" ), &m_schematic->Hierarchy()[0], copyVariant );
481
482 // Source should still have original values
483 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], sourceVariant ) );
484 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
485 false, 0, sourceVariant ), wxS( "47K" ) );
486
487 // Copy should have modified values
488 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], copyVariant ) );
489 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
490 false, 0, copyVariant ), wxS( "100K" ) );
491}
492
493
497BOOST_AUTO_TEST_CASE( VariantFieldDifferenceDetection )
498{
499 wxFileName fn;
500 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
501 fn.AppendDir( wxS( "variant_test" ) );
502 fn.SetName( wxS( "variant_test" ) );
504
505 LoadSchematic( fn.GetFullPath() );
506 BOOST_REQUIRE( m_schematic );
507
508 SCH_SYMBOL* symbol = GetFirstSymbol();
509 BOOST_REQUIRE( symbol );
510
511 wxString variantName1 = wxS( "DiffTestVariant1" );
512 wxString variantName2 = wxS( "DiffTestVariant2" );
513
514 // Get the default value
515 wxString defaultValue = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
516 false, 0 );
517 BOOST_CHECK_EQUAL( defaultValue, wxS( "1K" ) );
518
519 // Add a variant and set a different value
520 m_schematic->AddVariant( variantName1 );
521 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "2.2K" ), &m_schematic->Hierarchy()[0], variantName1 );
522
523 // Get variant value
524 wxString variantValue = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
525 false, 0, variantName1 );
526 BOOST_CHECK_EQUAL( variantValue, wxS( "2.2K" ) );
527
528 // Verify values differ
529 BOOST_CHECK( defaultValue != variantValue );
530
531 // Add another variant with same value as default to verify equality detection
532 m_schematic->AddVariant( variantName2 );
533 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "1K" ), &m_schematic->Hierarchy()[0], variantName2 );
534 wxString variantValue2 = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
535 false, 0, variantName2 );
536
537 // Second variant should have the same value as default
538 BOOST_CHECK_EQUAL( defaultValue, variantValue2 );
539}
540
541
545BOOST_AUTO_TEST_CASE( VariantDNPFiltering )
546{
547 wxFileName fn;
548 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
549 fn.AppendDir( wxS( "variant_test" ) );
550 fn.SetName( wxS( "variant_test" ) );
552
553 LoadSchematic( fn.GetFullPath() );
554 BOOST_REQUIRE( m_schematic );
555
556 SCH_SYMBOL* symbol = GetFirstSymbol();
557 BOOST_REQUIRE( symbol );
558
559 wxString variantName = wxS( "DNPVariant" );
560
561 // By default, symbol should not be DNP
562 BOOST_CHECK( !symbol->GetDNP() );
563 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxEmptyString ) );
564
565 // Add a variant where symbol is DNP
566 m_schematic->AddVariant( variantName );
567 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
568
569 // Default should still not be DNP
570 BOOST_CHECK( !symbol->GetDNP() );
571 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxEmptyString ) );
572
573 // Variant should be DNP
574 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
575
576 // Test exclude from BOM as well
577 BOOST_CHECK( !symbol->GetExcludedFromBOM() );
578 symbol->SetExcludedFromBOM( true, &m_schematic->Hierarchy()[0], variantName );
579 BOOST_CHECK( symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], variantName ) );
580 BOOST_CHECK( !symbol->GetExcludedFromBOM( &m_schematic->Hierarchy()[0], wxEmptyString ) );
581
582 // Test exclude from board as well
583 BOOST_CHECK( !symbol->GetExcludedFromBoard() );
584 symbol->SetExcludedFromBoard( true, &m_schematic->Hierarchy()[0], variantName );
585 BOOST_CHECK( symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], variantName ) );
586 BOOST_CHECK( !symbol->GetExcludedFromBoard( &m_schematic->Hierarchy()[0], wxEmptyString ) );
587
588 // Test exclude from position files as well
589 BOOST_CHECK( !symbol->GetExcludedFromPosFiles() );
590 symbol->SetExcludedFromPosFiles( true, &m_schematic->Hierarchy()[0], variantName );
591 BOOST_CHECK( symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], variantName ) );
592 BOOST_CHECK( !symbol->GetExcludedFromPosFiles( &m_schematic->Hierarchy()[0], wxEmptyString ) );
593}
594
595
599BOOST_AUTO_TEST_CASE( GetVariantNamesForUI )
600{
601 wxFileName fn;
602 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
603 fn.AppendDir( wxS( "variant_test" ) );
604 fn.SetName( wxS( "variant_test" ) );
606
607 LoadSchematic( fn.GetFullPath() );
608 BOOST_REQUIRE( m_schematic );
609
610 // Add some variants
611 m_schematic->AddVariant( wxS( "Zebra" ) );
612 m_schematic->AddVariant( wxS( "Alpha" ) );
613 m_schematic->AddVariant( wxS( "Beta" ) );
614
615 wxArrayString variantNames = m_schematic->GetVariantNamesForUI();
616
617 // Should have at least 4 items (default + 3 variants)
618 BOOST_CHECK( variantNames.GetCount() >= 4 );
619
620 // First item should be the default placeholder
621 // The actual string may vary but should represent "default"
622 BOOST_CHECK( !variantNames[0].IsEmpty() );
623
624 // Remaining items should be sorted
625 // Alpha, Beta, Zebra
626 bool foundAlpha = false;
627 bool foundBeta = false;
628 bool foundZebra = false;
629
630 for( size_t i = 1; i < variantNames.GetCount(); i++ )
631 {
632 if( variantNames[i] == wxS( "Alpha" ) )
633 foundAlpha = true;
634 else if( variantNames[i] == wxS( "Beta" ) )
635 foundBeta = true;
636 else if( variantNames[i] == wxS( "Zebra" ) )
637 foundZebra = true;
638 }
639
640 BOOST_CHECK( foundAlpha );
641 BOOST_CHECK( foundBeta );
642 BOOST_CHECK( foundZebra );
643}
644
645
651BOOST_AUTO_TEST_CASE( SetValueFieldTextPersistsVariantValue )
652{
653 wxFileName fn;
654 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
655 fn.AppendDir( wxS( "variant_test" ) );
656 fn.SetName( wxS( "variant_test" ) );
658
659 LoadSchematic( fn.GetFullPath() );
660 BOOST_REQUIRE( m_schematic );
661
662 SCH_SYMBOL* symbol = GetFirstSymbol();
663 BOOST_REQUIRE( symbol );
664
665 wxString variantName = wxS( "PersistenceTest" );
666 wxString newValue = wxS( "4.7K" );
667 wxString defaultValue = symbol->GetField( FIELD_T::VALUE )->GetText();
668
669 // Add the variant
670 m_schematic->AddVariant( variantName );
671
672 // Set value using SetValueFieldText (the function that had the bug)
673 symbol->SetValueFieldText( newValue, &m_schematic->Hierarchy()[0], variantName );
674
675 // Verify that the variant value was actually saved by reading it back
676 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
677 BOOST_REQUIRE( variant.has_value() );
678
679 wxString fieldName = symbol->GetField( FIELD_T::VALUE )->GetName();
680 BOOST_CHECK( variant->m_Fields.contains( fieldName ) );
681 BOOST_CHECK_EQUAL( variant->m_Fields.at( fieldName ), newValue );
682
683 // Verify through GetValue method as well
684 wxString retrievedValue = symbol->GetValue( false, &m_schematic->Hierarchy()[0], false, variantName );
685 BOOST_CHECK_EQUAL( retrievedValue, newValue );
686
687 // Verify default value is unchanged
688 wxString retrievedDefault = symbol->GetValue( false, &m_schematic->Hierarchy()[0], false, wxEmptyString );
689 BOOST_CHECK_EQUAL( retrievedDefault, defaultValue );
690}
691
692
696BOOST_AUTO_TEST_CASE( SetFieldTextAndSetValueFieldTextConsistency )
697{
698 wxFileName fn;
699 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
700 fn.AppendDir( wxS( "variant_test" ) );
701 fn.SetName( wxS( "variant_test" ) );
703
704 LoadSchematic( fn.GetFullPath() );
705 BOOST_REQUIRE( m_schematic );
706
707 SCH_SYMBOL* symbol = GetFirstSymbol();
708 BOOST_REQUIRE( symbol );
709
710 wxString variantName1 = wxS( "MethodTest1" );
711 wxString variantName2 = wxS( "MethodTest2" );
712 wxString value1 = wxS( "10K" );
713 wxString value2 = wxS( "22K" );
714 wxString fieldName = symbol->GetField( FIELD_T::VALUE )->GetName();
715
716 m_schematic->AddVariant( variantName1 );
717 m_schematic->AddVariant( variantName2 );
718
719 // Set variant 1 using SetValueFieldText
720 symbol->SetValueFieldText( value1, &m_schematic->Hierarchy()[0], variantName1 );
721
722 // Set variant 2 using SetFieldText
723 symbol->SetFieldText( fieldName, value2, &m_schematic->Hierarchy()[0], variantName2 );
724
725 // Both methods should produce the same result structure
726 std::optional<SCH_SYMBOL_VARIANT> variant1 = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName1 );
727 std::optional<SCH_SYMBOL_VARIANT> variant2 = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName2 );
728
729 BOOST_REQUIRE( variant1.has_value() );
730 BOOST_REQUIRE( variant2.has_value() );
731
732 BOOST_CHECK( variant1->m_Fields.contains( fieldName ) );
733 BOOST_CHECK( variant2->m_Fields.contains( fieldName ) );
734
735 BOOST_CHECK_EQUAL( variant1->m_Fields.at( fieldName ), value1 );
736 BOOST_CHECK_EQUAL( variant2->m_Fields.at( fieldName ), value2 );
737
738 // Verify through GetValue
739 BOOST_CHECK_EQUAL( symbol->GetValue( false, &m_schematic->Hierarchy()[0], false, variantName1 ), value1 );
740 BOOST_CHECK_EQUAL( symbol->GetValue( false, &m_schematic->Hierarchy()[0], false, variantName2 ), value2 );
741
742 // Verify through GetFieldText
743 BOOST_CHECK_EQUAL( symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName1 ), value1 );
744 BOOST_CHECK_EQUAL( symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName2 ), value2 );
745}
746
747
752BOOST_AUTO_TEST_CASE( VariantNameHandling )
753{
754 wxFileName fn;
755 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
756 fn.AppendDir( wxS( "variant_test" ) );
757 fn.SetName( wxS( "variant_test" ) );
759
760 LoadSchematic( fn.GetFullPath() );
761 BOOST_REQUIRE( m_schematic );
762
763 SCH_SYMBOL* symbol = GetFirstSymbol();
764 BOOST_REQUIRE( symbol );
765
766 wxString variantName = wxS( "ProductionVariant" );
767
768 // Add variant with specific casing
769 m_schematic->AddVariant( variantName );
770
771 // Set DNP on variant
772 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
773
774 // Verify with exact case - this should work
775 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], wxS( "ProductionVariant" ) ) );
776
777 // Verify variant exists
778 BOOST_CHECK( m_schematic->GetVariantNames().contains( wxS( "ProductionVariant" ) ) );
779
780 // Set and get current variant
781 m_schematic->SetCurrentVariant( variantName );
782 BOOST_CHECK_EQUAL( m_schematic->GetCurrentVariant(), variantName );
783
784 // Unknown variant should return base DNP (false)
785 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], wxS( "NonExistentVariant" ) ) );
786}
787
788
792BOOST_AUTO_TEST_CASE( VariantDeletionCascade )
793{
794 wxFileName fn;
795 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
796 fn.AppendDir( wxS( "variant_test" ) );
797 fn.SetName( wxS( "variant_test" ) );
799
800 LoadSchematic( fn.GetFullPath() );
801 BOOST_REQUIRE( m_schematic );
802
803 SCH_SYMBOL* symbol = GetFirstSymbol();
804 BOOST_REQUIRE( symbol );
805
806 wxString variantName = wxS( "DeleteMe" );
807
808 // Add variant and set properties
809 m_schematic->AddVariant( variantName );
810 symbol->SetDNP( true, &m_schematic->Hierarchy()[0], variantName );
811 symbol->GetField( FIELD_T::VALUE )->SetText( wxS( "DeletedValue" ), &m_schematic->Hierarchy()[0], variantName );
812
813 // Verify data is set
814 BOOST_CHECK( symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
815 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
816 BOOST_CHECK( variant.has_value() );
817
818 // Delete the variant
819 m_schematic->DeleteVariant( variantName );
820
821 // Variant should no longer exist at schematic level
822 BOOST_CHECK( !m_schematic->GetVariantNames().contains( variantName ) );
823
824 // After deletion, querying DNP for non-existent variant should return base value
825 BOOST_CHECK( !symbol->GetDNP( &m_schematic->Hierarchy()[0], variantName ) );
826}
827
828
832BOOST_AUTO_TEST_CASE( VariantFieldUnicodeAndSpecialChars )
833{
834 wxFileName fn;
835 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
836 fn.AppendDir( wxS( "variant_test" ) );
837 fn.SetName( wxS( "variant_test" ) );
839
840 LoadSchematic( fn.GetFullPath() );
841 BOOST_REQUIRE( m_schematic );
842
843 SCH_SYMBOL* symbol = GetFirstSymbol();
844 BOOST_REQUIRE( symbol );
845
846 wxString variantName = wxS( "UnicodeTest" );
847 m_schematic->AddVariant( variantName );
848
849 // Test Unicode characters in field values
850 wxString unicodeValue = wxS( "1kΩ ±5% 日本語" );
851 symbol->GetField( FIELD_T::VALUE )->SetText( unicodeValue, &m_schematic->Hierarchy()[0], variantName );
852
853 wxString retrieved = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
854 false, 0, variantName );
855 BOOST_CHECK_EQUAL( retrieved, unicodeValue );
856
857 // Test special characters
858 wxString specialChars = wxS( "R<1K>\"test\"'value'" );
859 symbol->GetField( FIELD_T::VALUE )->SetText( specialChars, &m_schematic->Hierarchy()[0], variantName );
860
861 retrieved = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
862 false, 0, variantName );
863 BOOST_CHECK_EQUAL( retrieved, specialChars );
864
865 // Test empty string
866 symbol->GetField( FIELD_T::VALUE )->SetText( wxEmptyString, &m_schematic->Hierarchy()[0], variantName );
867 retrieved = symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0],
868 false, 0, variantName );
869 BOOST_CHECK( retrieved.IsEmpty() );
870
871 // Test description with unicode
872 wxString unicodeDesc = wxS( "Variante für Produktion — 测试" );
873 m_schematic->SetVariantDescription( variantName, unicodeDesc );
874 BOOST_CHECK_EQUAL( m_schematic->GetVariantDescription( variantName ), unicodeDesc );
875}
876
877
881BOOST_AUTO_TEST_CASE( VariantSpecificFieldDereferencing )
882{
883 wxFileName fn;
884 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
885 fn.AppendDir( wxS( "variant_test" ) );
886 fn.SetName( wxS( "variant_test" ) );
888
889 LoadSchematic( fn.GetFullPath() );
890 BOOST_REQUIRE( m_schematic );
891
892 SCH_SYMBOL* symbol = GetFirstSymbol();
893 BOOST_REQUIRE( symbol );
894
895 wxString variantName = wxS( "MilitaryGrade" );
896 wxString variantValue = wxS( "1K-MIL" );
897 wxString defaultValue = wxS( "1K" );
898
899 // Create a variant with a different value field
900 m_schematic->AddVariant( variantName );
901 symbol->GetField( FIELD_T::VALUE )->SetText( variantValue, &m_schematic->Hierarchy()[0], variantName );
902
903 // Verify default value
904 BOOST_CHECK_EQUAL( symbol->GetField( FIELD_T::VALUE )->GetShownText( &m_schematic->Hierarchy()[0], false, 0 ),
905 defaultValue );
906
907 // Get the symbol's reference (R1) for cross-reference testing
908 wxString symbolRef = symbol->GetRef( &m_schematic->Hierarchy()[0], false );
909
910 // Test 1: ResolveCrossReference with variant syntax - should return variant-specific value
911 wxString token = symbolRef + wxS( ":VALUE:" ) + variantName;
912 bool resolved = m_schematic->ResolveCrossReference( &token, 0 );
913 BOOST_CHECK( resolved );
914 BOOST_CHECK_EQUAL( token, variantValue );
915
916 // Test 2: ResolveCrossReference without variant - should return default value
917 token = symbolRef + wxS( ":VALUE" );
918 resolved = m_schematic->ResolveCrossReference( &token, 0 );
919 BOOST_CHECK( resolved );
920 BOOST_CHECK_EQUAL( token, defaultValue );
921
922 // Test 3: ResolveCrossReference with non-existent variant - should return default value
923 token = symbolRef + wxS( ":VALUE:NonExistentVariant" );
924 resolved = m_schematic->ResolveCrossReference( &token, 0 );
925 BOOST_CHECK( resolved );
926 BOOST_CHECK_EQUAL( token, defaultValue );
927
928 // Test 4: ResolveTextVar with variant parameter directly
929 token = wxS( "VALUE" );
930 resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, variantName, 0 );
931 BOOST_CHECK( resolved );
932 BOOST_CHECK_EQUAL( token, variantValue );
933
934 // Test 5: ResolveTextVar with empty variant - should return default
935 token = wxS( "VALUE" );
936 resolved = symbol->ResolveTextVar( &m_schematic->Hierarchy()[0], &token, wxEmptyString, 0 );
937 BOOST_CHECK( resolved );
938 BOOST_CHECK_EQUAL( token, defaultValue );
939}
940
941
947BOOST_AUTO_TEST_CASE( FootprintFieldVariantSupport )
948{
949 wxFileName fn;
950 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
951 fn.AppendDir( wxS( "variant_test" ) );
952 fn.SetName( wxS( "variant_test" ) );
954
955 LoadSchematic( fn.GetFullPath() );
956 BOOST_REQUIRE( m_schematic );
957
958 SCH_SYMBOL* symbol = GetFirstSymbol();
959 BOOST_REQUIRE( symbol );
960
961 wxString variantName = wxS( "FootprintVariant" );
962 wxString baseFootprint = wxS( "Resistor_SMD:R_0805_2012Metric" );
963 wxString variantFootprint = wxS( "Resistor_SMD:R_0402_1005Metric" );
964 wxString fieldName = symbol->GetField( FIELD_T::FOOTPRINT )->GetName();
965
966 // Set a base footprint first
967 symbol->SetFootprintFieldText( baseFootprint );
968 BOOST_CHECK_EQUAL( symbol->GetFootprintFieldText( false, nullptr, false ), baseFootprint );
969
970 // Add the variant
971 m_schematic->AddVariant( variantName );
972
973 // Set a different footprint for the variant using SetFieldText
974 symbol->SetFieldText( fieldName, variantFootprint, &m_schematic->Hierarchy()[0], variantName );
975
976 // Verify base footprint is unchanged
977 wxString retrievedBase = symbol->GetFootprintFieldText( false, nullptr, false );
978 BOOST_CHECK_EQUAL( retrievedBase, baseFootprint );
979
980 // Verify GetFieldText with no variant returns base footprint
981 wxString retrievedDefault = symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], wxEmptyString );
982 BOOST_CHECK_EQUAL( retrievedDefault, baseFootprint );
983
984 // Verify GetFieldText with variant returns variant-specific footprint
985 wxString retrievedVariant = symbol->GetFieldText( fieldName, &m_schematic->Hierarchy()[0], variantName );
986 BOOST_CHECK_EQUAL( retrievedVariant, variantFootprint );
987
988 // Verify that the variant data structure contains the footprint override
989 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
990 BOOST_REQUIRE( variant.has_value() );
991 BOOST_CHECK( variant->m_Fields.contains( fieldName ) );
992 BOOST_CHECK_EQUAL( variant->m_Fields.at( fieldName ), variantFootprint );
993}
994
995
1000BOOST_AUTO_TEST_CASE( FootprintFieldVariantNoOpWhenSame )
1001{
1002 wxFileName fn;
1003 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1004 fn.AppendDir( wxS( "variant_test" ) );
1005 fn.SetName( wxS( "variant_test" ) );
1007
1008 LoadSchematic( fn.GetFullPath() );
1009 BOOST_REQUIRE( m_schematic );
1010
1011 SCH_SYMBOL* symbol = GetFirstSymbol();
1012 BOOST_REQUIRE( symbol );
1013
1014 wxString variantName = wxS( "NoOpTest" );
1015 wxString baseFootprint = wxS( "Resistor_SMD:R_0805_2012Metric" );
1016 wxString fieldName = symbol->GetField( FIELD_T::FOOTPRINT )->GetName();
1017
1018 // Set a base footprint first
1019 symbol->SetFootprintFieldText( baseFootprint );
1020
1021 // Add the variant
1022 m_schematic->AddVariant( variantName );
1023
1024 // Set the same footprint value for the variant
1025 symbol->SetFieldText( fieldName, baseFootprint, &m_schematic->Hierarchy()[0], variantName );
1026
1027 // Verify that no variant override was created since the value is the same
1028 std::optional<SCH_SYMBOL_VARIANT> variant = symbol->GetVariant( m_schematic->Hierarchy()[0], variantName );
1029
1030 // Either no variant was created, or it exists but doesn't have a footprint override
1031 if( variant.has_value() )
1032 {
1033 BOOST_CHECK( !variant->m_Fields.contains( fieldName ) );
1034 }
1035}
1036
1037
1042BOOST_AUTO_TEST_CASE( VariantSwitchInvalidatesBoundingBoxCache )
1043{
1044 wxFileName fn;
1045 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1046 fn.AppendDir( wxS( "variant_test" ) );
1047 fn.SetName( wxS( "variant_test" ) );
1049
1050 LoadSchematic( fn.GetFullPath() );
1051 BOOST_REQUIRE( m_schematic );
1052
1053 // GetShownText(bool) resolves variants via CurrentSheet(), so we must set it
1054 m_schematic->SetCurrentSheet( m_schematic->Hierarchy()[0] );
1055
1056 SCH_SYMBOL* symbol = GetFirstSymbol();
1057 BOOST_REQUIRE( symbol );
1058
1059 SCH_FIELD* fpField = symbol->GetField( FIELD_T::FOOTPRINT );
1060 BOOST_REQUIRE( fpField );
1061
1062 wxString variantName = wxS( "BboxVariant" );
1063 wxString shortFp = wxS( "R_0402" );
1064 wxString longFp = wxS( "Resistor_SMD:R_2512_6332Metric_Pad1.52x3.35mm_HandSolder" );
1065
1066 symbol->SetFootprintFieldText( shortFp );
1067 fpField->SetVisible( true );
1068 fpField->ClearBoundingBoxCache();
1069
1070 m_schematic->AddVariant( variantName );
1071 symbol->SetFieldText( fpField->GetName(), longFp, &m_schematic->Hierarchy()[0], variantName );
1072
1073 // Confirm variant text resolution works
1074 wxString resolvedDefault = fpField->GetShownText( &m_schematic->Hierarchy()[0], false, 0, wxEmptyString );
1075 wxString resolvedVariant = fpField->GetShownText( &m_schematic->Hierarchy()[0], false, 0, variantName );
1076 BOOST_CHECK_EQUAL( resolvedDefault, shortFp );
1077 BOOST_CHECK_EQUAL( resolvedVariant, longFp );
1078
1079 // Verify the implicit text resolution via GetShownText(bool) works for each variant
1080 m_schematic->SetCurrentVariant( wxEmptyString );
1081 wxString implicitDefault = fpField->GetShownText( false );
1082
1083 m_schematic->SetCurrentVariant( variantName );
1084 wxString implicitVariant = fpField->GetShownText( false );
1085
1086 BOOST_CHECK_EQUAL( implicitDefault, shortFp );
1087 BOOST_CHECK_EQUAL( implicitVariant, longFp );
1088
1089 // Prime the bounding box cache with the default variant (short footprint text)
1090 m_schematic->SetCurrentVariant( wxEmptyString );
1091 fpField->ClearBoundingBoxCache();
1092 BOX2I defaultTextBox = fpField->GetTextBox( nullptr );
1093
1094 // Switch to the variant with a much longer footprint string.
1095 // SetCurrentVariant must invalidate caches so the new text is reflected.
1096 m_schematic->SetCurrentVariant( variantName );
1097 BOX2I variantTextBox = fpField->GetTextBox( nullptr );
1098
1099 // The longer text must produce a wider text box. If the bounding box cache was not
1100 // invalidated on variant switch, both boxes would be identical.
1101 BOOST_CHECK_GT( variantTextBox.GetWidth(), defaultTextBox.GetWidth() );
1102
1103 // Switch back and verify it returns to the original width
1104 m_schematic->SetCurrentVariant( wxEmptyString );
1105 BOX2I restoredTextBox = fpField->GetTextBox( nullptr );
1106 BOOST_CHECK_EQUAL( restoredTextBox.GetWidth(), defaultTextBox.GetWidth() );
1107}
1108
1109
1120BOOST_AUTO_TEST_CASE( VariantAttributeInitFromSymbol )
1121{
1122 wxFileName fn;
1123 fn.SetPath( KI_TEST::GetEeschemaTestDataDir() );
1124 fn.AppendDir( wxS( "variant_test" ) );
1125 fn.SetName( wxS( "variant_test" ) );
1127
1128 LoadSchematic( fn.GetFullPath() );
1129 BOOST_REQUIRE( m_schematic );
1130
1131 SCH_SYMBOL* symbol = GetFirstSymbol();
1132 BOOST_REQUIRE( symbol );
1133
1134 // Set all default attributes to true on the symbol
1135 symbol->SetDNP( true );
1136 symbol->SetExcludedFromBOM( true );
1137 symbol->SetExcludedFromSim( true );
1138 symbol->SetExcludedFromBoard( true );
1139 symbol->SetExcludedFromPosFiles( true );
1140
1141 // Default-constructed variant has all-false attributes
1142 SCH_SYMBOL_VARIANT defaultVariant( wxS( "Default" ) );
1143 BOOST_CHECK( !defaultVariant.m_DNP );
1144 BOOST_CHECK( !defaultVariant.m_ExcludedFromBOM );
1145 BOOST_CHECK( !defaultVariant.m_ExcludedFromSim );
1146 BOOST_CHECK( !defaultVariant.m_ExcludedFromBoard );
1147 BOOST_CHECK( !defaultVariant.m_ExcludedFromPosFiles );
1148
1149 // InitializeAttributes should copy the symbol's attributes
1150 SCH_SYMBOL_VARIANT initializedVariant( wxS( "Initialized" ) );
1151 initializedVariant.InitializeAttributes( *symbol );
1152
1153 BOOST_CHECK_MESSAGE( initializedVariant.m_DNP,
1154 "InitializeAttributes should copy DNP from symbol" );
1155 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromBOM,
1156 "InitializeAttributes should copy ExcludedFromBOM from symbol" );
1157 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromSim,
1158 "InitializeAttributes should copy ExcludedFromSim from symbol" );
1159 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromBoard,
1160 "InitializeAttributes should copy ExcludedFromBoard from symbol" );
1161 BOOST_CHECK_MESSAGE( initializedVariant.m_ExcludedFromPosFiles,
1162 "InitializeAttributes should copy ExcludedFromPosFiles from symbol" );
1163}
1164
1165
1174BOOST_AUTO_TEST_CASE( MatchesUsesInstanceFields )
1175{
1176 // Build a minimal lib symbol simulating "+5V"
1177 LIB_SYMBOL* libSym = new LIB_SYMBOL( wxS( "+5V" ) );
1178
1179 // The lib symbol value field text stays as "+5V"
1180 libSym->GetValueField().SetText( wxS( "+5V" ) );
1181 libSym->GetValueField().SetVisible( true );
1182
1183 SCH_SYMBOL symbol( *libSym, libSym->GetLibId(), nullptr, 0, 0, VECTOR2I() );
1184
1185 // Change the instance value to "+5VA" (simulating a user-derived power symbol)
1186 symbol.GetField( FIELD_T::VALUE )->SetText( wxS( "+5VA" ) );
1187
1188 SCH_SEARCH_DATA data;
1189 data.findString = wxS( "+5V" );
1191 data.searchAllFields = false;
1192
1193 // "+5VA" must NOT match a whole-word search for "+5V"
1194 BOOST_CHECK_MESSAGE( !symbol.Matches( data, nullptr ),
1195 "'+5VA' symbol must not match whole-word search for '+5V'" );
1196
1197 // "+5VA" must match a plain search for "+5V" (substring)
1199 BOOST_CHECK_MESSAGE( symbol.Matches( data, nullptr ),
1200 "'+5VA' symbol must match plain search for '+5V'" );
1201
1202 // "+5VA" must match a whole-word search for "+5VA"
1203 data.findString = wxS( "+5VA" );
1205 BOOST_CHECK_MESSAGE( symbol.Matches( data, nullptr ),
1206 "'+5VA' symbol must match whole-word search for '+5VA'" );
1207
1208 delete libSym;
1209}
1210
1211
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr size_type GetWidth() const
Definition box2.h:214
EDA_ITEM * GetParent() const
Definition eda_item.h:114
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:93
BOX2I GetTextBox(const RENDER_SETTINGS *aSettings, int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition eda_text.cpp:739
virtual void SetVisible(bool aVisible)
Definition eda_text.cpp:370
virtual void ClearBoundingBoxCache()
Definition eda_text.cpp:662
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:225
A generic fixture for loading schematics and associated settings for qa tests.
std::unique_ptr< SCHEMATIC > m_schematic
Define a library symbol object.
Definition lib_symbol.h:83
const LIB_ID & GetLibId() const override
Definition lib_symbol.h:152
SCH_FIELD & GetValueField()
Return reference to the value field.
Definition lib_symbol.h:332
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:123
wxString GetShownText(const SCH_SHEET_PATH *aPath, bool aAllowExtraText, int aDepth=0, const wxString &aVariantName=wxEmptyString) const
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
void SetText(const wxString &aText) override
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:168
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:119
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...
Variant information for a schematic symbol.
void InitializeAttributes(const SCH_SYMBOL &aSymbol)
Schematic symbol object.
Definition sch_symbol.h:76
bool GetExcludedFromSim(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
virtual void SetDNP(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
void SetFieldText(const wxString &aFieldName, const wxString &aFieldText, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString)
wxString GetFieldText(const wxString &aFieldName, const SCH_SHEET_PATH *aPath=nullptr, const wxString &aVariantName=wxEmptyString) const
void SetExcludedFromSim(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from simulation flag.
std::optional< SCH_SYMBOL_VARIANT > GetVariant(const SCH_SHEET_PATH &aInstance, const wxString &aVariantName) const
bool GetExcludedFromBOM(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
const wxString GetValue(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText, const wxString &aVariantName=wxEmptyString) const override
const wxString GetFootprintFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText, const wxString &aVariantName=wxEmptyString) const
void SetFootprintFieldText(const wxString &aFootprint)
void SetExcludedFromPosFiles(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
bool ResolveTextVar(const SCH_SHEET_PATH *aPath, wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the symbol.
void SetValueFieldText(const wxString &aValue, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString)
bool GetExcludedFromPosFiles(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
bool GetExcludedFromBoard(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
void SetExcludedFromBOM(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
Set or clear the exclude from schematic bill of materials flag.
virtual bool GetDNP(const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) const override
Set or clear the 'Do Not Populate' flag.
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
void SetExcludedFromBoard(bool aEnable, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
SCH_SYMBOL * GetFirstSymbol()
SCH_SYMBOL object with no extra data set.
for transforming drawing coordinates for a wxDC device context.
Definition transform.h:46
bool m_ExcludedFromBOM
bool m_ExcludedFromPosFiles
bool m_ExcludedFromSim
bool m_ExcludedFromBoard
static const std::string KiCadSchematicFileExtension
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
static void LoadSchematic(SCHEMATIC *aSchematic, SCH_SHEET *aRootSheet, const wxString &aFileName)
EDA_SEARCH_MATCH_MODE matchMode
@ SYM_ORIENT_270
Definition symbol.h:42
@ SYM_ORIENT_180
Definition symbol.h:41
@ SYM_ORIENT_90
Definition symbol.h:40
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ VALUE
Field Value of part, i.e. "3.3K".
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
BOOST_AUTO_TEST_CASE(DefaultProperties)
Declare the test suite.
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_SYMBOL_T
Definition typeinfo.h:173
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
Definition of file extensions used in Kicad.