KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_multichannel.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#include <board.h>
28#include <pad.h>
29#include <pcb_track.h>
30#include <pcb_text.h>
31#include <pcb_field.h>
32#include <footprint.h>
33#include <zone.h>
34#include <drc/drc_item.h>
38
46
48{
49public:
52
53 virtual wxWindow* GetToolCanvas() const override { return nullptr; }
54};
55
56BOOST_FIXTURE_TEST_SUITE( MultichannelTool, MULTICHANNEL_TEST_FIXTURE )
57
58RULE_AREA* findRuleAreaByPartialName( MULTICHANNEL_TOOL* aTool, const wxString& aName )
59{
60 for( RULE_AREA& ra : aTool->GetData()->m_areas )
61 {
62 if( ra.m_ruleName.Contains( ( aName ) ) )
63 return &ra;
64 }
65
66 return nullptr;
67}
68
69
71{
73
74 std::vector<wxString> tests = { "vme-wren" };
75
76 for( const wxString& relPath : tests )
77 {
78 KI_TEST::LoadBoard( m_settingsManager, relPath, m_board );
79
80 TOOL_MANAGER toolMgr;
81 MOCK_TOOLS_HOLDER* toolsHolder = new MOCK_TOOLS_HOLDER;
82
83 toolMgr.SetEnvironment( m_board.get(), nullptr, nullptr, nullptr, toolsHolder );
84
85 MULTICHANNEL_TOOL* mtTool = new MULTICHANNEL_TOOL; // TOOL_MANAGER owns the tools
86 toolMgr.RegisterTool( mtTool );
87
88 //RULE_AREAS_DATA* raData = m_parentTool->GetData();
89
91
92 auto ruleData = mtTool->GetData();
93
94 BOOST_TEST_MESSAGE( wxString::Format( "RA multichannel sheets = %d",
95 static_cast<int>( ruleData->m_areas.size() ) ) );
96
97 BOOST_CHECK_EQUAL( ruleData->m_areas.size(), 72 );
98
99 int cnt = 0;
100
101 ruleData->m_replaceExisting = true;
102
103 for( RULE_AREA& ra : ruleData->m_areas )
104 {
105 if( ra.m_sheetName == wxT( "io_driver.kicad_sch" )
106 || ra.m_sheetName == wxT( "pp_driver_2x.kicad_sch" ) )
107 {
108 ra.m_generateEnabled = true;
109 cnt++;
110 }
111 }
112
113 BOOST_TEST_MESSAGE( wxString::Format( "Autogenerating %d RAs", cnt ) );
114
115 TOOL_EVENT dummyEvent;
116
117 mtTool->AutogenerateRuleAreas( dummyEvent );
118 mtTool->FindExistingRuleAreas();
119
120 int n_areas_io = 0, n_areas_pp = 0, n_areas_other = 0;
121
122 BOOST_TEST_MESSAGE( wxString::Format( "Found %d RAs after commit",
123 static_cast<int>(ruleData->m_areas.size() ) ) );
124
125 for( const RULE_AREA& ra : ruleData->m_areas )
126 {
127 BOOST_TEST_MESSAGE( wxString::Format( "SN '%s'", ra.m_ruleName ) );
128
129 if( ra.m_ruleName.Contains( wxT( "io_drivers_fp" ) ) )
130 {
131 n_areas_io++;
132 BOOST_CHECK_EQUAL( ra.m_components.size(), 31 );
133 }
134 else if( ra.m_ruleName.Contains( wxT( "io_drivers_pp" ) ) )
135 {
136 n_areas_pp++;
137 BOOST_CHECK_EQUAL( ra.m_components.size(), 11 );
138 }
139 else
140 {
141 n_areas_other++;
142 }
143 }
144
145 BOOST_TEST_MESSAGE( wxString::Format( "IO areas=%d, PP areas=%d, others=%d",
146 n_areas_io, n_areas_pp, n_areas_other ) );
147
148 BOOST_CHECK_EQUAL( n_areas_io, 16 );
149 BOOST_CHECK_EQUAL( n_areas_pp, 16 );
150 BOOST_CHECK_EQUAL( n_areas_other, 0 );
151
152 const std::vector<wxString> rulesToTest = { wxT( "io_drivers_fp" ),
153 wxT( "io_drivers_pp" ) };
154
155 for( const wxString& ruleName : rulesToTest )
156 {
157 for( const RULE_AREA& refArea : ruleData->m_areas )
158 {
159 if( !refArea.m_ruleName.Contains( ruleName ) )
160 continue;
161
162 BOOST_TEST_MESSAGE( wxString::Format( "REF AREA: '%s'", refArea.m_ruleName ) );
163
164 for( const RULE_AREA& targetArea : ruleData->m_areas )
165 {
166 if( targetArea.m_zone == refArea.m_zone )
167 continue;
168
169 if( !targetArea.m_ruleName.Contains( ruleName ) )
170 continue;
171
172 auto cgRef = CONNECTION_GRAPH::BuildFromFootprintSet( refArea.m_components );
173 auto cgTarget =
174 CONNECTION_GRAPH::BuildFromFootprintSet( targetArea.m_components );
175
177
178 std::vector<TMATCH::TOPOLOGY_MISMATCH_REASON> details;
179 bool status = cgRef->FindIsomorphism( cgTarget.get(), result, details );
180
181 BOOST_TEST_MESSAGE( wxString::Format(
182 "topo match: '%s' [%d] -> '%s' [%d] result %d", refArea.m_ruleName.c_str().AsChar(),
183 static_cast<int>( refArea.m_components.size() ), targetArea.m_ruleName.c_str().AsChar(),
184 static_cast<int>( targetArea.m_components.size() ), status ? 1 : 0 ) );
185
186 for( const auto& iter : result )
187 {
188 BOOST_TEST_MESSAGE( wxString::Format( "%s : %s",
189 iter.second->GetReference(),
190 iter.first->GetReference() ) );
191 }
192
193 BOOST_CHECK( status );
194 BOOST_CHECK( details.empty() );
195 }
196 }
197 }
198
199 auto refArea = findRuleAreaByPartialName( mtTool, wxT( "io_drivers_fp/bank3/io78/" ) );
200
201 BOOST_ASSERT( refArea );
202
203 const std::vector<wxString> targetAreaNames( { wxT( "io_drivers_fp/bank2/io78/" ),
204 wxT( "io_drivers_fp/bank1/io78/" ),
205 wxT( "io_drivers_fp/bank0/io01/" ) } );
206
207 for( const wxString& targetRaName : targetAreaNames )
208 {
209 auto targetRA = findRuleAreaByPartialName( mtTool, targetRaName );
210
211 BOOST_ASSERT( targetRA != nullptr );
212
213 BOOST_TEST_MESSAGE( wxString::Format( "Clone to: %s", targetRA->m_ruleName ) );
214
215 ruleData->m_compatMap[targetRA].m_doCopy = true;
216 }
217
218 int result = mtTool->RepeatLayout( TOOL_EVENT(), refArea->m_zone );
219
220 BOOST_ASSERT( result >= 0 );
221 }
222}
223
224
229BOOST_FIXTURE_TEST_CASE( RepeatLayoutCopiesFootprintProperties, MULTICHANNEL_TEST_FIXTURE )
230{
231 KI_TEST::LoadBoard( m_settingsManager, "issue22548/issue22548", m_board );
232
233 TOOL_MANAGER toolMgr;
234 MOCK_TOOLS_HOLDER* toolsHolder = new MOCK_TOOLS_HOLDER;
235
236 toolMgr.SetEnvironment( m_board.get(), nullptr, nullptr, nullptr, toolsHolder );
237
239 toolMgr.RegisterTool( mtTool );
240
241 mtTool->FindExistingRuleAreas();
242
243 auto ruleData = mtTool->GetData();
244
245 BOOST_TEST_MESSAGE( wxString::Format( "Found %d rule areas",
246 static_cast<int>( ruleData->m_areas.size() ) ) );
247
248 BOOST_CHECK( ruleData->m_areas.size() >= 2 );
249
250 if( ruleData->m_areas.size() < 2 )
251 return;
252
253 RULE_AREA* refArea = nullptr;
254 RULE_AREA* targetArea = nullptr;
255
256 for( RULE_AREA& ra : ruleData->m_areas )
257 {
258 if( ra.m_ruleName.Contains( wxT( "Untitled Sheet/" ) ) )
259 refArea = &ra;
260 else if( ra.m_ruleName.Contains( wxT( "Untitled Sheet1/" ) ) )
261 targetArea = &ra;
262 }
263
264 if( !refArea || !targetArea )
265 {
266 BOOST_TEST_MESSAGE( "Could not find Untitled Sheet and Untitled Sheet1 rule areas, skipping test" );
267 return;
268 }
269
270 BOOST_TEST_MESSAGE( wxString::Format( "Reference area: %s, Target area: %s",
271 refArea->m_ruleName, targetArea->m_ruleName ) );
272
273 FOOTPRINT* refFP = nullptr;
274 FOOTPRINT* targetFP = nullptr;
275
276 for( FOOTPRINT* fp : refArea->m_components )
277 {
278 if( fp->GetReference().StartsWith( wxT( "U1" ) ) )
279 {
280 refFP = fp;
281 break;
282 }
283 }
284
285 for( FOOTPRINT* fp : targetArea->m_components )
286 {
287 if( fp->GetReference().StartsWith( wxT( "U2" ) ) )
288 {
289 targetFP = fp;
290 break;
291 }
292 }
293
294 if( !refFP || !targetFP )
295 {
296 BOOST_TEST_MESSAGE( "Could not find matching footprints in the rule areas, skipping test" );
297 return;
298 }
299
300 PCB_FIELD* refValueField = refFP->GetField( FIELD_T::VALUE );
301 bool refValueVisible = refValueField ? refValueField->IsVisible() : true;
302
303 std::vector<FP_3DMODEL> refModels = refFP->Models();
304
305 mtTool->CheckRACompatibility( refArea->m_zone );
306
307 ruleData->m_compatMap[targetArea].m_doCopy = true;
308 ruleData->m_options.m_copyPlacement = true;
309
310 int result = mtTool->RepeatLayout( TOOL_EVENT(), refArea->m_zone );
311
312 BOOST_CHECK( result >= 0 );
313
314 PCB_FIELD* targetValueField = targetFP->GetField( FIELD_T::VALUE );
315
316 if( targetValueField && refValueField )
317 {
318 BOOST_CHECK_EQUAL( targetValueField->IsVisible(), refValueVisible );
319 BOOST_TEST_MESSAGE( wxString::Format( "Value field visibility: ref=%d, target=%d",
320 refValueVisible, targetValueField->IsVisible() ) );
321 }
322
323 BOOST_CHECK_EQUAL( targetFP->Models().size(), refModels.size() );
324
325 if( !refModels.empty() )
326 {
327 BOOST_TEST_MESSAGE( wxString::Format( "3D models: ref=%d, target=%d",
328 static_cast<int>( refModels.size() ),
329 static_cast<int>( targetFP->Models().size() ) ) );
330 }
331}
332
333
341BOOST_FIXTURE_TEST_CASE( RepeatLayoutDoesNotRemoveReferenceVias, MULTICHANNEL_TEST_FIXTURE )
342{
343 KI_TEST::LoadBoard( m_settingsManager, "issue21184/issue21184", m_board );
344
345 TOOL_MANAGER toolMgr;
346 MOCK_TOOLS_HOLDER* toolsHolder = new MOCK_TOOLS_HOLDER;
347
348 toolMgr.SetEnvironment( m_board.get(), nullptr, nullptr, nullptr, toolsHolder );
349
351 toolMgr.RegisterTool( mtTool );
352
353 mtTool->FindExistingRuleAreas();
354
355 auto ruleData = mtTool->GetData();
356
357 BOOST_TEST_MESSAGE( wxString::Format( "Found %d rule areas",
358 static_cast<int>( ruleData->m_areas.size() ) ) );
359
360 BOOST_CHECK_EQUAL( ruleData->m_areas.size(), 2 );
361
362 if( ruleData->m_areas.size() < 2 )
363 return;
364
365 RULE_AREA* refArea = nullptr;
366 RULE_AREA* targetArea = nullptr;
367
368 for( RULE_AREA& ra : ruleData->m_areas )
369 {
370 if( ra.m_ruleName == wxT( "Test1" ) )
371 refArea = &ra;
372 else if( ra.m_ruleName == wxT( "Test2" ) )
373 targetArea = &ra;
374 }
375
376 BOOST_REQUIRE( refArea != nullptr );
377 BOOST_REQUIRE( targetArea != nullptr );
378
379 int refViaCountBefore = 0;
380
381 for( PCB_TRACK* track : m_board->Tracks() )
382 {
383 if( track->Type() == PCB_VIA_T )
384 {
385 PCB_VIA* via = static_cast<PCB_VIA*>( track );
386 VECTOR2I viaPos = via->GetPosition();
387
388 if( refArea->m_zone->Outline()->Contains( viaPos ) )
389 refViaCountBefore++;
390 }
391 }
392
393 BOOST_TEST_MESSAGE( wxString::Format( "Reference area vias before repeat: %d", refViaCountBefore ) );
394 BOOST_CHECK( refViaCountBefore > 0 );
395
396 mtTool->CheckRACompatibility( refArea->m_zone );
397
398 ruleData->m_compatMap[targetArea].m_doCopy = true;
399 ruleData->m_options.m_copyPlacement = true;
400 ruleData->m_options.m_copyRouting = true;
401
402 int result = mtTool->RepeatLayout( TOOL_EVENT(), refArea->m_zone );
403
404 BOOST_CHECK( result >= 0 );
405
406 int refViaCountAfter = 0;
407
408 for( PCB_TRACK* track : m_board->Tracks() )
409 {
410 if( track->Type() == PCB_VIA_T )
411 {
412 PCB_VIA* via = static_cast<PCB_VIA*>( track );
413 VECTOR2I viaPos = via->GetPosition();
414
415 if( refArea->m_zone->Outline()->Contains( viaPos ) )
416 refViaCountAfter++;
417 }
418 }
419
420 BOOST_TEST_MESSAGE( wxString::Format( "Reference area vias after repeat: %d", refViaCountAfter ) );
421
422 BOOST_CHECK_EQUAL( refViaCountAfter, refViaCountBefore );
423}
424
425
virtual bool IsVisible() const
Definition eda_text.h:187
PCB_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this footprint.
std::vector< FP_3DMODEL > & Models()
Definition footprint.h:321
const wxString & GetReference() const
Definition footprint.h:741
virtual wxWindow * GetToolCanvas() const override
Canvas access.
int CheckRACompatibility(ZONE *aRefZone)
RULE_AREAS_DATA * GetData()
int RepeatLayout(const TOOL_EVENT &aEvent, ZONE *aRefZone)
int AutogenerateRuleAreas(const TOOL_EVENT &aEvent)
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
Generic, UI-independent tool event.
Definition tool_event.h:171
Master controller class:
void RegisterTool(TOOL_BASE *aTool)
Add a tool to the manager set and sets it up.
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, APP_SETTINGS_BASE *aSettings, TOOLS_HOLDER *aFrame)
Set the work environment (model, view, view controls and the parent window).
SHAPE_POLY_SET * Outline()
Definition zone.h:331
void LoadBoard(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< BOARD > &aBoard)
std::map< FOOTPRINT *, FOOTPRINT * > COMPONENT_MATCHES
Definition topo_match.h:156
std::unique_ptr< BOARD > m_board
wxString m_sheetName
std::set< FOOTPRINT * > m_components
wxString m_ruleName
@ VALUE
Field Value of part, i.e. "3.3K".
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
RULE_AREA * findRuleAreaByPartialName(MULTICHANNEL_TOOL *aTool, const wxString &aName)
BOOST_FIXTURE_TEST_CASE(MultichannelToolRegressions, MULTICHANNEL_TEST_FIXTURE)
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:97
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695