KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_issue22576_subsheet_standalone.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, you may find one here:
18 * https://www.gnu.org/licenses/gpl-3.0.en.html
19 * or you may search the http://www.gnu.org website for the version 3 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
38
40
41#include <connection_graph.h>
42#include <schematic.h>
43#include <sch_sheet.h>
44#include <sch_screen.h>
45#include <sch_symbol.h>
46#include <sch_sheet_path.h>
48#include <locale_io.h>
49
50
52{
55
57 std::unique_ptr<SCHEMATIC> m_schematic;
58};
59
60
68BOOST_FIXTURE_TEST_CASE( Issue22576MissingInstancesFallback, ISSUE22576_FIXTURE )
69{
71
72 // Create a minimal schematic with a symbol that has existing instance data
73 m_schematic = std::make_unique<SCHEMATIC>( nullptr );
74 m_schematic->Reset();
75
76 SCH_SHEET* rootSheet = new SCH_SHEET( m_schematic.get() );
77 SCH_SCREEN* screen = new SCH_SCREEN( m_schematic.get() );
78 rootSheet->SetScreen( screen );
79
80 // Create a symbol
81 SCH_SYMBOL* symbol = new SCH_SYMBOL();
82 symbol->SetLibId( LIB_ID( wxT( "Device" ), wxT( "R" ) ) );
83 symbol->SetPosition( VECTOR2I( 0, 0 ) );
84 symbol->GetField( FIELD_T::REFERENCE )->SetText( wxT( "R202" ) );
85 symbol->SetPrefix( wxT( "R" ) );
86 screen->Append( symbol );
87
88 // Add an instance for a "different" project path (simulating the parent hierarchy)
89 // This is what would exist if the file was saved as part of a hierarchical project
90 KIID_PATH existingPath;
91 existingPath.push_back( KIID() ); // Some other root sheet UUID
92 existingPath.push_back( KIID() ); // This sheet's UUID in that hierarchy
93
94 SCH_SYMBOL_INSTANCE existingInstance;
95 existingInstance.m_Path = existingPath;
96 existingInstance.m_Reference = wxT( "R202" );
97 existingInstance.m_Unit = 1;
98 existingInstance.m_ProjectName = wxT( "ParentProject" );
99 symbol->AddHierarchicalReference( existingInstance );
100
101 // Set up the schematic
102 m_schematic->AddTopLevelSheet( rootSheet );
103
104 // Now simulate opening as a standalone project
105 // This creates a NEW path that doesn't match the existing instance
106 SCH_SHEET_PATH newPath;
107 newPath.push_back( rootSheet );
108 newPath.Rehash();
109
110 // Before the fix, CheckForMissingSymbolInstances would set unannotated reference "R?"
111 // After the fix, it should use the existing instance data "R202"
112 wxString newProjectName = wxT( "StandaloneProject" );
113 newPath.CheckForMissingSymbolInstances( newProjectName );
114
115 // Verify the symbol now has an instance for the new path with the correct reference
116 wxString ref = symbol->GetRef( &newPath );
117
118 BOOST_TEST_MESSAGE( "Reference after CheckForMissingSymbolInstances: " << ref );
119
120 // The reference should be "R202" (from existing instance), NOT "R?" (unannotated)
121 BOOST_CHECK_MESSAGE( ref == wxT( "R202" ),
122 "Symbol reference should use existing instance data, not unannotated" );
123 BOOST_CHECK_MESSAGE( !ref.EndsWith( wxT( "?" ) ),
124 "Symbol reference should NOT be unannotated" );
125}
126
127
134BOOST_FIXTURE_TEST_CASE( Issue22576NoInstancesFallback, ISSUE22576_FIXTURE )
135{
137
138 m_schematic = std::make_unique<SCHEMATIC>( nullptr );
139 m_schematic->Reset();
140
141 SCH_SHEET* rootSheet = new SCH_SHEET( m_schematic.get() );
142 SCH_SCREEN* screen = new SCH_SCREEN( m_schematic.get() );
143 rootSheet->SetScreen( screen );
144
145 // Create a symbol with NO instances, only field text
146 SCH_SYMBOL* symbol = new SCH_SYMBOL();
147 symbol->SetLibId( LIB_ID( wxT( "Device" ), wxT( "C" ) ) );
148 symbol->SetPosition( VECTOR2I( 0, 0 ) );
149 symbol->GetField( FIELD_T::REFERENCE )->SetText( wxT( "C101" ) );
150 symbol->SetPrefix( wxT( "C" ) );
151 screen->Append( symbol );
152
153 // Verify no instances exist
154 BOOST_REQUIRE( symbol->GetInstances().empty() );
155
156 m_schematic->AddTopLevelSheet( rootSheet );
157
158 SCH_SHEET_PATH newPath;
159 newPath.push_back( rootSheet );
160 newPath.Rehash();
161
162 wxString newProjectName = wxT( "NewProject" );
163 newPath.CheckForMissingSymbolInstances( newProjectName );
164
165 wxString ref = symbol->GetRef( &newPath );
166
167 BOOST_TEST_MESSAGE( "Reference after CheckForMissingSymbolInstances (no prior instances): " << ref );
168
169 // Should use the field text "C101"
170 BOOST_CHECK_MESSAGE( ref == wxT( "C101" ),
171 "Symbol reference should use field text when no instances exist" );
172}
173
174
181BOOST_FIXTURE_TEST_CASE( Issue22576MultipleSymbolsFallback, ISSUE22576_FIXTURE )
182{
184
185 m_schematic = std::make_unique<SCHEMATIC>( nullptr );
186 m_schematic->Reset();
187
188 SCH_SHEET* rootSheet = new SCH_SHEET( m_schematic.get() );
189 SCH_SCREEN* screen = new SCH_SCREEN( m_schematic.get() );
190 rootSheet->SetScreen( screen );
191
192 // Create the "current" path first
193 m_schematic->AddTopLevelSheet( rootSheet );
194
195 SCH_SHEET_PATH currentPath;
196 currentPath.push_back( rootSheet );
197 currentPath.Rehash();
198
199 // Path for "other project" instances
200 KIID_PATH otherPath;
201 otherPath.push_back( KIID() );
202 otherPath.push_back( KIID() );
203
204 // Symbol 1: Has instance for other path only (should use that instance's ref)
205 SCH_SYMBOL* symbol1 = new SCH_SYMBOL();
206 symbol1->SetLibId( LIB_ID( wxT( "Device" ), wxT( "R" ) ) );
207 symbol1->SetPosition( VECTOR2I( 0, 0 ) );
208 symbol1->GetField( FIELD_T::REFERENCE )->SetText( wxT( "R?" ) ); // Field is unannotated
209 symbol1->SetPrefix( wxT( "R" ) );
210
212 inst1.m_Path = otherPath;
213 inst1.m_Reference = wxT( "R202" );
214 inst1.m_Unit = 1;
215 inst1.m_ProjectName = wxT( "OtherProject" );
216 symbol1->AddHierarchicalReference( inst1 );
217 screen->Append( symbol1 );
218
219 // Symbol 2: Has instance for current path (should keep it)
220 SCH_SYMBOL* symbol2 = new SCH_SYMBOL();
221 symbol2->SetLibId( LIB_ID( wxT( "Device" ), wxT( "C" ) ) );
222 symbol2->SetPosition( VECTOR2I( 1000, 0 ) );
223 symbol2->GetField( FIELD_T::REFERENCE )->SetText( wxT( "C101" ) );
224 symbol2->SetPrefix( wxT( "C" ) );
225 symbol2->SetRef( &currentPath, wxT( "C101" ) );
226 screen->Append( symbol2 );
227
228 // Symbol 3: No instances at all (should use field text)
229 SCH_SYMBOL* symbol3 = new SCH_SYMBOL();
230 symbol3->SetLibId( LIB_ID( wxT( "Device" ), wxT( "L" ) ) );
231 symbol3->SetPosition( VECTOR2I( 2000, 0 ) );
232 symbol3->GetField( FIELD_T::REFERENCE )->SetText( wxT( "L1" ) );
233 symbol3->SetPrefix( wxT( "L" ) );
234 screen->Append( symbol3 );
235
236 wxString projectName = wxT( "CurrentProject" );
237 currentPath.CheckForMissingSymbolInstances( projectName );
238
239 // Verify each symbol
240 wxString ref1 = symbol1->GetRef( &currentPath );
241 wxString ref2 = symbol2->GetRef( &currentPath );
242 wxString ref3 = symbol3->GetRef( &currentPath );
243
244 BOOST_TEST_MESSAGE( "Symbol1 (other instance only): " << ref1 );
245 BOOST_TEST_MESSAGE( "Symbol2 (current instance): " << ref2 );
246 BOOST_TEST_MESSAGE( "Symbol3 (no instances): " << ref3 );
247
248 BOOST_CHECK_MESSAGE( ref1 == wxT( "R202" ),
249 "Symbol with other-path instance should use that reference" );
250 BOOST_CHECK_MESSAGE( ref2 == wxT( "C101" ),
251 "Symbol with current-path instance should keep its reference" );
252 BOOST_CHECK_MESSAGE( ref3 == wxT( "L1" ),
253 "Symbol with no instances should use field text" );
254}
Definition kiid.h:49
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:41
void SetText(const wxString &aText) override
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void CheckForMissingSymbolInstances(const wxString &aProjectName)
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
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:76
void SetLibId(const LIB_ID &aName)
const std::vector< SCH_SYMBOL_INSTANCE > & GetInstances() const
Definition sch_symbol.h:135
void SetPosition(const VECTOR2I &aPosition) override
Definition sch_symbol.h:868
void SetRef(const SCH_SHEET_PATH *aSheet, const wxString &aReference)
Set the reference for the given sheet path for this symbol.
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
void SetPrefix(const wxString &aPrefix)
Definition sch_symbol.h:239
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
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
A simple container for schematic symbol instance information.
@ REFERENCE
Field Reference of part, i.e. "IC21".
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_FIXTURE_TEST_CASE(Issue22576MissingInstancesFallback, ISSUE22576_FIXTURE)
Test that CheckForMissingSymbolInstances uses existing instance data as fallback.
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695