KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_component_classes.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, see <https://www.gnu.org/licenses/>.
18 */
19
22#include <board.h>
26#include <pad.h>
27#include <pcb_track.h>
28#include <pcb_marker.h>
29#include <footprint.h>
30#include <drc/drc_item.h>
32
33
42
43
45{
46 KI_TEST::LoadBoard( m_settingsManager, "component_classes", m_board );
47
48 std::vector<DRC_ITEM> violations;
49 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
50
51 std::vector<wxString> allClasses{ "ANY", "CAP_1", "CAP_2", "CLASS_1",
52 "CLASS_2", "CLASS_3", "CLASS_4", "MULTI_REF",
53 "REF_WILDCARD", "REF_WILDCARD2", "RES_1", "RES_2",
54 "RES_3", "RES_4" };
55
56 auto testClasses = [&allClasses](const wxString& ref, const COMPONENT_CLASS* compClass, std::vector<wxString> assignedClasses)
57 {
58 std::vector<wxString> unassignedClasses;
59 std::ranges::set_difference(allClasses, assignedClasses, std::back_inserter(unassignedClasses));
60
61 for( const wxString& className : assignedClasses )
62 {
63 if( !compClass->ContainsClassName( className ) )
64 {
65 BOOST_ERROR( wxString::Format(
66 "%s component class failed (%s expected but not found - full class %s)",
67 ref, className, compClass->GetName() ) );
68 }
69 }
70
71 for( const wxString& className : unassignedClasses )
72 {
73 if( compClass->ContainsClassName( className ) )
74 {
75 BOOST_ERROR( wxString::Format(
76 "%s component class failed (%s found but not expected - full class %s)",
77 ref, className, compClass->GetName() ) );
78 }
79 }
80 };
81
82 for( const auto fp : m_board->Footprints() )
83 {
84 if( fp->Reference().GetText() == wxT( "C1" ) )
85 {
86 testClasses( "C1", fp->GetComponentClass(), {"CAP_1", "CLASS_3", "CLASS_4"});
87 }
88
89 if( fp->Reference().GetText() == wxT( "C2" ) )
90 {
91 testClasses( "C2", fp->GetComponentClass(), {"CAP_2", "CLASS_3"});
92 }
93
94 if( fp->Reference().GetText() == wxT( "C3" ) )
95 {
96 testClasses( "C2", fp->GetComponentClass(), {});
97 }
98
99 if( fp->Reference().GetText() == wxT( "R8" ) )
100 {
101 testClasses( "R8", fp->GetComponentClass(), {"RES_1", "RES_2"});
102 }
103
104 if( fp->Reference().GetText() == wxT( "R88" ) )
105 {
106 testClasses( "R88", fp->GetComponentClass(), {"RES_2"});
107 }
108
109 if( fp->Reference().GetText() == wxT( "R2" ) )
110 {
111 testClasses( "R2", fp->GetComponentClass(), {"CLASS_1", "RES_1", "RES_2", "RES_3"});
112 }
113
114 if( fp->Reference().GetText() == wxT( "R1" ) )
115 {
116 testClasses( "R1", fp->GetComponentClass(), {"CLASS_1", "CLASS_2", "RES_1", "RES_2", "RES_4"});
117 }
118
119 if( fp->Reference().GetText() == wxT( "U1" ) )
120 {
121 testClasses( "U1", fp->GetComponentClass(), { "ANY" } );
122 }
123
124 if( fp->Reference().GetText() == wxT( "U2" ) )
125 {
126 testClasses( "U2", fp->GetComponentClass(), { "ANY" } );
127 }
128
129 if( fp->Reference().GetText() == wxT( "U3" ) )
130 {
131 testClasses( "U3", fp->GetComponentClass(), { "MULTI_REF" } );
132 }
133
134 if( fp->Reference().GetText() == wxT( "U4" ) )
135 {
136 testClasses( "U4", fp->GetComponentClass(), { "MULTI_REF" } );
137 }
138
139 if( fp->Reference().GetText() == wxT( "U55" ) )
140 {
141 testClasses( "U55", fp->GetComponentClass(), { "REF_WILDCARD", "REF_WILDCARD2" } );
142 }
143
144 if( fp->Reference().GetText() == wxT( "U555" ) )
145 {
146 testClasses( "U555", fp->GetComponentClass(), { "REF_WILDCARD2" } );
147 }
148
149 if( fp->Reference().GetText() == wxT( "R3" ) )
150 {
151 testClasses( "R3", fp->GetComponentClass(), { "/SHEET1/", "RES_1", "RES_2" } );
152 }
153 }
154
155}
156
157
163BOOST_FIXTURE_TEST_CASE( FinishNetlistUpdateClearsDeletedClassPointers, PCB_COMPONENT_CLASS_FIXTURE )
164{
165 // Create a board with a footprint
166 m_board = std::make_unique<BOARD>();
167 FOOTPRINT* fp = new FOOTPRINT( m_board.get() );
168 fp->SetReference( wxT( "U1" ) );
169 m_board->Add( fp );
170
171 COMPONENT_CLASS_MANAGER& mgr = m_board->GetComponentClassManager();
172
173 // Simulate a previous netlist update that assigned a component class
174 mgr.InitNetlistUpdate();
175 std::unordered_set<wxString> classNames = { wxT( "TEST_CLASS" ) };
176 COMPONENT_CLASS* testClass = mgr.GetEffectiveStaticComponentClass( classNames );
177 BOOST_REQUIRE( testClass != nullptr );
178 fp->SetStaticComponentClass( testClass );
180
181 // Verify the class exists and footprint has it
182 BOOST_CHECK( fp->GetStaticComponentClass() == testClass );
183 BOOST_CHECK( !testClass->IsEmpty() );
184
185 // Now simulate a NEW netlist update where the class is no longer used
186 // InitNetlistUpdate() caches existing static classes, then FinishNetlistUpdate()
187 // deletes any that weren't used during the update
188 mgr.InitNetlistUpdate();
189
190 // Don't call GetEffectiveStaticComponentClass for TEST_CLASS - simulates the class
191 // no longer being in the netlist
192
194
195 // Verify the footprint's pointer was cleared since the class was deleted
196 BOOST_CHECK( fp->GetStaticComponentClass() == nullptr );
197}
198
199
204BOOST_FIXTURE_TEST_CASE( FinishNetlistUpdatePreservesActiveClassPointers, PCB_COMPONENT_CLASS_FIXTURE )
205{
206 // Create a board with a footprint
207 m_board = std::make_unique<BOARD>();
208 FOOTPRINT* fp = new FOOTPRINT( m_board.get() );
209 fp->SetReference( wxT( "U1" ) );
210 m_board->Add( fp );
211
212 COMPONENT_CLASS_MANAGER& mgr = m_board->GetComponentClassManager();
213
214 // Begin netlist update and assign a static component class to the footprint
215 mgr.InitNetlistUpdate();
216
217 std::unordered_set<wxString> classNames = { wxT( "TEST_CLASS" ) };
218 COMPONENT_CLASS* testClass = mgr.GetEffectiveStaticComponentClass( classNames );
219 BOOST_REQUIRE( testClass != nullptr );
220
221 fp->SetStaticComponentClass( testClass );
222
223 // Simulate the class being used in this netlist update by calling GetEffectiveStaticComponentClass
224 // again, which removes it from the cache of unused classes
225 testClass = mgr.GetEffectiveStaticComponentClass( classNames );
226 fp->SetStaticComponentClass( testClass );
227
229
230 // The footprint's pointer should still be valid since the class is still in use
231 BOOST_CHECK( fp->GetStaticComponentClass() == testClass );
232 BOOST_CHECK( fp->GetStaticComponentClass() != nullptr );
233}
Container for design settings for a BOARD object.
A class to manage Component Classes in a board context.
COMPONENT_CLASS * GetEffectiveStaticComponentClass(const std::unordered_set< wxString > &classNames)
Gets an effective component class for the given constituent class names.
void FinishNetlistUpdate()
Cleans up the manager after a board update Must be called after updating the PCB from the netlist.
void InitNetlistUpdate()
Prepare the manager for a board update Must be called prior to updating the PCB from the netlist.
A lightweight representation of a component class.
bool IsEmpty() const
Determines if this (effective) component class is empty (i.e. no classes defined)
void SetStaticComponentClass(const COMPONENT_CLASS *aClass) const
Sets the component class object pointer for this footprint.
void SetReference(const wxString &aReference)
Definition footprint.h:847
const COMPONENT_CLASS * GetStaticComponentClass() const
Returns the component class for this footprint.
void LoadBoard(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< BOARD > &aBoard)
BOOST_FIXTURE_TEST_CASE(ComponentClasses, PCB_COMPONENT_CLASS_FIXTURE)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())