KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_net_chains.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, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <boost/test/unit_test.hpp>
21
24
25#include <connection_graph.h>
26#include <schematic.h>
27#include <sch_sheet.h>
28#include <sch_screen.h>
29#include <netclass.h>
30#include <sch_label.h>
31#include <sch_line.h>
33#include <project.h>
37#include <locale_io.h>
38
46
47BOOST_FIXTURE_TEST_CASE( RebuildSignals_GroupsFourNetsIntoOneSignal, SIGNALS_TEST_FIXTURE )
48{
50 KI_TEST::LoadSchematic( m_settingsManager, wxString( "net_chains_four_nets" ), m_schematic );
51 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
52 CONNECTION_GRAPH* graph = m_schematic->ConnectionGraph();
53 graph->Recalculate( sheets, /*aUnconditional=*/true );
54
55 const auto& netChains = graph->GetPotentialNetChains();
56 bool foundFourNetSignal = false;
57 for( const auto& sig : netChains )
58 {
59 if( sig && sig->GetNets().size() == 4 )
60 {
61 foundFourNetSignal = true;
62 break;
63 }
64 }
65
66 BOOST_CHECK_MESSAGE( foundFourNetSignal,
67 "Expected at least one signal composed of exactly 4 nets to be built" );
68}
69
70BOOST_FIXTURE_TEST_CASE( RebuildSignals_RespectsSignalLabelAndKeepsGrouping, SIGNALS_TEST_FIXTURE )
71{
73 KI_TEST::LoadSchematic( m_settingsManager, wxString( "net_chains_four_nets_labeled" ), m_schematic );
74 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
75 CONNECTION_GRAPH* graph = m_schematic->ConnectionGraph();
76 graph->Recalculate( sheets, /*aUnconditional=*/true );
77
78 const auto& netChains = graph->GetPotentialNetChains();
79 bool foundLabeled = false;
80 for( const auto& sig : netChains )
81 {
82 if( !sig )
83 continue;
84
85 wxString name = sig->GetName();
86 if( name.StartsWith( wxString( "/" ) ) )
87 name = name.Mid( 1 );
88
89 if( sig->GetNets().size() == 4 && name == wxString( "SIG" ) )
90 {
91 foundLabeled = true;
92 break;
93 }
94 }
95
96 BOOST_CHECK_MESSAGE( foundLabeled,
97 "Expected a 4-net signal named 'SIG' to be built from label" );
98}
99
100BOOST_FIXTURE_TEST_CASE( RebuildSignals_WithPullupBranch_ExcludesPowerBranch, SIGNALS_TEST_FIXTURE )
101{
103 KI_TEST::LoadSchematic( m_settingsManager, wxString( "net_chains_with_pullup" ), m_schematic );
104 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
105 CONNECTION_GRAPH* graph = m_schematic->ConnectionGraph();
106 graph->Recalculate( sheets, /*aUnconditional=*/true );
107
108 const auto& netChains = graph->GetPotentialNetChains();
109
110 // Pullup fixture has two resistors driving a single net through a pullup to VCC. The chain
111 // walker should produce a multi-net chain that does NOT pull VCC into the group, since power
112 // nets are sinks rather than chain participants.
113 bool mainSignalExcludesVCC = false;
114 for( const auto& sig : netChains )
115 {
116 if( !sig )
117 continue;
118
119 const auto& nets = sig->GetNets();
120
121 if( nets.size() < 2 )
122 continue;
123
124 bool containsVCC = false;
125 for( const wxString& n : nets )
126 {
127 wxString nn = n;
128
129 if( nn.StartsWith( wxString( "/" ) ) )
130 nn = nn.Mid( 1 );
131
132 if( nn.CmpNoCase( wxString( "VCC" ) ) == 0 )
133 {
134 containsVCC = true;
135 break;
136 }
137 }
138
139 if( !containsVCC )
140 {
141 mainSignalExcludesVCC = true;
142 break;
143 }
144 }
145
146 BOOST_CHECK_MESSAGE( mainSignalExcludesVCC,
147 "Expected at least one multi-net signal that does not include VCC "
148 "(power branch should not be merged into the main signal)" );
149}
150
151BOOST_FIXTURE_TEST_CASE( RebuildSignals_WithBypassCap_ExcludesPowerBranch, SIGNALS_TEST_FIXTURE )
152{
154 KI_TEST::LoadSchematic( m_settingsManager, wxString( "net_chains_with_bypass" ), m_schematic );
155 SCH_SHEET_LIST sheets = m_schematic->BuildSheetListSortedByPageNumbers();
156 CONNECTION_GRAPH* graph = m_schematic->ConnectionGraph();
157 graph->Recalculate( sheets, /*aUnconditional=*/true );
158
159 const auto& netChains = graph->GetPotentialNetChains();
160
161 // Bypass-cap fixture has a signal path with a decoupling capacitor to GND. The chain walker
162 // should produce a multi-net chain that does NOT pull GND into the group, since power nets
163 // are sinks rather than chain participants.
164 bool mainSignalExcludesGND = false;
165 for( const auto& sig : netChains )
166 {
167 if( !sig )
168 continue;
169
170 const auto& nets = sig->GetNets();
171
172 if( nets.size() < 2 )
173 continue;
174
175 bool containsGND = false;
176 for( const wxString& n : nets )
177 {
178 wxString nn = n;
179
180 if( nn.StartsWith( wxString( "/" ) ) )
181 nn = nn.Mid( 1 );
182
183 if( nn.CmpNoCase( wxString( "GND" ) ) == 0 )
184 {
185 containsGND = true;
186 break;
187 }
188 }
189
190 if( !containsGND )
191 {
192 mainSignalExcludesGND = true;
193 break;
194 }
195 }
196
197 BOOST_CHECK_MESSAGE( mainSignalExcludesGND,
198 "Expected at least one multi-net signal that does not include GND "
199 "(power branch should not be merged into the main signal)" );
200}
201
202BOOST_FIXTURE_TEST_CASE( NetChain_AppendAdoptionKeepsCommittedChains, SIGNALS_TEST_FIXTURE )
203{
205 KI_TEST::LoadSchematic( m_settingsManager, wxString( "net_chains_four_nets_labeled" ), m_schematic );
206 m_schematic->ConnectionGraph()->Recalculate( m_schematic->Hierarchy(), true );
207
208 CONNECTION_GRAPH* graph = m_schematic->ConnectionGraph();
209 BOOST_REQUIRE( !graph->GetPotentialNetChains().empty() );
210
211 SCH_NETCHAIN* committed =
212 graph->CreateNetChainFromPotential( graph->GetPotentialNetChains().front().get(), "APPEND_CHAIN" );
213 BOOST_REQUIRE( committed );
214
215 const std::set<wxString> nets = committed->GetNets();
216 const SCH_SHEET_PATH path = m_schematic->Hierarchy().front();
217
218 SCHEMATIC_CONTENT content;
219 content.targetSheet = path.Last();
220 content.hierarchy = m_schematic->Hierarchy();
221 content.currentSheet = path;
222 content.connectionGraph = std::make_unique<CONNECTION_GRAPH>( m_schematic.get() );
223 content.preserveNetChains = true;
224
225 for( SCH_ITEM* item : path.LastScreen()->Items() )
226 content.screenItems.insert( item );
227
228 m_schematic->AdoptContent( std::move( content ) );
229
230 graph = m_schematic->ConnectionGraph();
231 BOOST_REQUIRE( graph->GetNetChainByName( "APPEND_CHAIN" ) == committed );
232
233 graph->Recalculate( m_schematic->Hierarchy(), true );
234 BOOST_CHECK( committed->GetNets() == nets );
235 BOOST_CHECK( !committed->GetSymbols().empty() );
236}
237
238
239
240BOOST_FIXTURE_TEST_CASE( NetChain_TemporaryGraphPreservesProjectAssignments, SIGNALS_TEST_FIXTURE )
241{
243 KI_TEST::LoadSchematic( m_settingsManager, wxString( "net_chains_four_nets_labeled" ), m_schematic );
244 m_schematic->ConnectionGraph()->Recalculate( m_schematic->Hierarchy(), true );
245
246 CONNECTION_GRAPH* graph = m_schematic->ConnectionGraph();
247 BOOST_REQUIRE( !graph->GetPotentialNetChains().empty() );
248
249 SCH_NETCHAIN* committed =
250 graph->CreateNetChainFromPotential( graph->GetPotentialNetChains().front().get(), "NETCLASS_CHAIN" );
251 BOOST_REQUIRE( committed );
252
253 std::shared_ptr<NET_SETTINGS> ns = m_schematic->Project().GetProjectFile().NetSettings();
254 std::shared_ptr<NETCLASS> highSpeed = std::make_shared<NETCLASS>( wxT( "HighSpeed" ) );
255 ns->SetNetclass( wxT( "HighSpeed" ), highSpeed );
256 committed->SetNetClass( wxT( "HighSpeed" ) );
258 BOOST_REQUIRE( ns->HasChainPatternAssignments( NET_CHAIN_SOURCE::SCHEMATIC ) );
259
260 CONNECTION_GRAPH temporary( m_schematic.get() );
261 temporary.Recalculate( m_schematic->Hierarchy(), true );
262 BOOST_CHECK( ns->HasChainPatternAssignments( NET_CHAIN_SOURCE::SCHEMATIC ) );
263}
264
265
266BOOST_FIXTURE_TEST_CASE( RebuildSignals_SelectsLabelNameIndependentlyOfItemOrder, SIGNALS_TEST_FIXTURE )
267{
268 LOCALE_IO locale;
269 KI_TEST::LoadSchematic( m_settingsManager, "net_chains_four_nets_labeled", m_schematic );
270 SCH_SCREEN* screen = m_schematic->GetTopLevelSheet()->GetScreen();
271 SCH_LABEL* original = nullptr;
272
273 for( SCH_ITEM* item : screen->Items().OfType( SCH_LABEL_T ) )
274 {
275 original = static_cast<SCH_LABEL*>( item );
276 break;
277 }
278
279 BOOST_REQUIRE( original );
280 auto copy = std::unique_ptr<SCH_LABEL>( static_cast<SCH_LABEL*>( original->Clone() ) );
281 const_cast<KIID&>( copy->m_Uuid ) = KIID();
282 SCH_LABEL* second = copy.get();
283 screen->Append( copy.release() );
284 auto* graph = m_schematic->ConnectionGraph();
285
286 for( bool reverse : { false, true } )
287 {
288 original->SetText( reverse ? "ZZZ" : "AAA" );
289 second->SetText( reverse ? "AAA" : "ZZZ" );
290 graph->Recalculate( m_schematic->Hierarchy(), true );
291 const auto& chains = graph->GetPotentialNetChains();
292 BOOST_REQUIRE_EQUAL( chains.size(), 1 );
293 BOOST_CHECK_EQUAL( chains.front()->GetName(), wxString( "AAA" ) );
294 }
295}
296
297BOOST_FIXTURE_TEST_CASE( RebuildSignals_DistinguishesSharedScreenInstances, SIGNALS_TEST_FIXTURE )
298{
299 LOCALE_IO locale;
300 KI_TEST::LoadSchematic( m_settingsManager, "net_chains_four_nets_labeled", m_schematic );
301 SCH_SHEET* original = m_schematic->GetTopLevelSheet();
302 auto copy = std::unique_ptr<SCH_SHEET>( static_cast<SCH_SHEET*>( original->Clone() ) );
303 const_cast<KIID&>( copy->m_Uuid ) = KIID();
304 copy->SetName( "Second" );
305 BOOST_REQUIRE( copy->GetScreen() == original->GetScreen() );
306 m_schematic->AddTopLevelSheet( copy.release() );
307 const SCH_SHEET_LIST sheets = m_schematic->Hierarchy();
308 BOOST_REQUIRE_EQUAL( sheets.size(), 2 );
309 auto& manager = m_schematic->NetChains();
310
311 m_schematic->ConnectionGraph()->Recalculate( sheets, true );
312 const auto& chains = manager.GetPotentialNetChains();
313 BOOST_REQUIRE_EQUAL( chains.size(), 2 );
314 BOOST_CHECK_EQUAL( chains[0]->GetNets().size(), 4 );
315 BOOST_CHECK_EQUAL( chains[1]->GetNets().size(), 4 );
316
317 for( const auto& chain : chains )
318 {
319 BOOST_CHECK_EQUAL( chain->GetName(), wxString( "SIG" ) );
320 BOOST_CHECK_EQUAL( chain->GetSymbols().size(), 3u );
321 std::set<wxString> references;
322
323 for( SCH_SYMBOL* symbol : chain->GetSymbols() )
324 references.insert( symbol->GetRef( &sheets[0] ) );
325
326 const std::set<wxString> expected{ "R1", "R2", "R3" };
327 BOOST_CHECK( references == expected );
328 }
329
330 for( const wxString& net : chains[0]->GetNets() )
331 BOOST_CHECK( !chains[1]->GetNets().contains( net ) );
332
333 BOOST_REQUIRE( !chains[0]->GetSymbols().empty() );
334 auto* bridge = *chains[0]->GetSymbols().begin();
335 const auto pins = bridge->GetPins( &sheets[0] );
336 BOOST_REQUIRE_EQUAL( pins.size(), 2u );
337 auto* first = manager.FindPotentialNetChainBetweenPins( pins[0], sheets[0], pins[1], sheets[0] );
338 auto* second = manager.FindPotentialNetChainBetweenPins( pins[0], sheets[1], pins[1], sheets[1] );
339 BOOST_REQUIRE( first );
340 BOOST_REQUIRE( second );
341 BOOST_CHECK( first != second );
342
343 for( int endpoint : { 0, 1 } )
344 {
345 BOOST_CHECK( first->GetTerminalPath( endpoint ) == sheets[0].Path() );
346 BOOST_CHECK( second->GetTerminalPath( endpoint ) == sheets[1].Path() );
347 }
348
349 BOOST_CHECK( !manager.FindPotentialNetChainBetweenPins( pins[0], sheets[0], pins[1], sheets[1] ) );
350
351 auto* ambiguous = manager.CreateManualNetChain(
352 "AMBIGUOUS_INSTANCE", first->GetSymbols(), first->GetNets(),
353 first->GetTerminalPinA(), first->GetTerminalPinB(),
354 first->GetTerminalRef( 0 ), first->GetTerminalPinNum( 0 ),
355 first->GetTerminalRef( 1 ), first->GetTerminalPinNum( 1 ) );
356 BOOST_CHECK( !ambiguous );
357
358 if( ambiguous )
359 manager.DeleteCommittedNetChain( "AMBIGUOUS_INSTANCE" );
360
361 auto* firstCommitted = manager.CreateNetChainFromPotential( first, "FIRST_INSTANCE" );
362 auto* secondCommitted = manager.CreateNetChainFromPotential( second, "SECOND_INSTANCE" );
363 BOOST_REQUIRE( firstCommitted );
364 BOOST_REQUIRE( secondCommitted );
365 const auto firstNets = firstCommitted->GetNets();
366 const auto secondNets = secondCommitted->GetNets();
367 BOOST_CHECK( !manager.ReplaceNetChainTerminalPin(
368 { "FIRST_INSTANCE", 0, pins[0]->m_Uuid, sheets[1].Path() } ) );
369 BOOST_CHECK( firstCommitted->GetTerminalPath( 0 ) == sheets[0].Path() );
370 BOOST_REQUIRE( manager.ReplaceNetChainTerminalPin(
371 { "FIRST_INSTANCE", 0, pins[0]->m_Uuid, sheets[0].Path() } ) );
372 BOOST_REQUIRE( manager.ReplaceNetChainTerminalPin(
373 { "SECOND_INSTANCE", 0, pins[0]->m_Uuid, sheets[1].Path() } ) );
374 m_schematic->ConnectionGraph()->Recalculate( sheets, true );
375 BOOST_CHECK( firstCommitted->GetTerminalPath( 0 ) == sheets[0].Path() );
376 BOOST_CHECK( secondCommitted->GetTerminalPath( 0 ) == sheets[1].Path() );
377 BOOST_CHECK( firstCommitted->GetNets() == firstNets );
378 BOOST_CHECK( secondCommitted->GetNets() == secondNets );
379 BOOST_REQUIRE( manager.DeleteCommittedNetChain( "FIRST_INSTANCE" ) );
380 BOOST_REQUIRE( manager.DeleteCommittedNetChain( "SECOND_INSTANCE" ) );
381}
382
383BOOST_AUTO_TEST_CASE( WholeNetQueryIncludesSeparatedNativeLabelIsland )
384{
385 SETTINGS_MANAGER settings;
386 std::unique_ptr<SCHEMATIC> schematic;
387 KI_TEST::LoadSchematic( settings, "net_chains_four_nets_labeled", schematic );
388 const auto path = schematic->Hierarchy().front();
389 SCH_PIN* left = nullptr;
390 SCH_PIN* right = nullptr;
391 SCH_LABEL* label = nullptr;
392 SCH_LINE* wire = nullptr;
393
394 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
395 {
396 auto* symbol = static_cast<SCH_SYMBOL*>( item );
397
398 if( symbol->GetRef( &path ) == wxString( "R1" ) )
399 left = symbol->GetPin( wxString( "2" ) );
400 else if( symbol->GetRef( &path ) == wxString( "R2" ) )
401 right = symbol->GetPin( wxString( "1" ) );
402 }
403
406
407 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_LABEL_T ) )
408 {
409 if( static_cast<SCH_LABEL*>( item )->GetText() == wxString( "SIG" ) )
410 label = static_cast<SCH_LABEL*>( item );
411 }
412
413 for( SCH_ITEM* item : path.LastScreen()->Items().OfType( SCH_LINE_T ) )
414 {
415 if( item->IsConnected( left->GetPosition() ) && item->IsConnected( right->GetPosition() ) )
416 wire = static_cast<SCH_LINE*>( item );
417 }
418
419 BOOST_REQUIRE( label );
420 BOOST_REQUIRE( wire );
421 auto* copiedWire = static_cast<SCH_LINE*>( wire->Clone() );
422 auto* copiedLabel = static_cast<SCH_LABEL*>( label->Clone() );
423 const_cast<KIID&>( copiedWire->m_Uuid ) = KIID();
424 const_cast<KIID&>( copiedLabel->m_Uuid ) = KIID();
425 copiedWire->Move( VECTOR2I( 0, 10000000 ) );
426 copiedLabel->Move( VECTOR2I( 0, 10000000 ) );
427 path.LastScreen()->Append( copiedWire );
428 path.LastScreen()->Append( copiedLabel );
429 const std::set<SCH_ITEM*> expected{ left, right, wire, label, copiedWire, copiedLabel };
430
431 schematic->ConnectionGraph()->Recalculate( schematic->Hierarchy(), true );
432 const SCH_CONNECTIVITY::NAVIGATION_QUERY query( *schematic );
433 const auto items = query.WholeNetItems( { wire, wire, nullptr }, path );
434 BOOST_CHECK_EQUAL( items.size(), expected.size() );
435 BOOST_CHECK( std::set<SCH_ITEM*>( items.begin(), items.end() ) == expected );
436 BOOST_CHECK( query.WholeNetItems( {}, path ).empty() );
437 BOOST_CHECK( query.WholeNetItems( { wire }, SCH_SHEET_PATH() ).empty() );
438}
439
440// EOF
const char * name
Calculate the connectivity of a schematic and generate netlists.
SCH_NETCHAIN * GetNetChainByName(const wxString &aName)
SCH_NETCHAIN * CreateNetChainFromPotential(SCH_NETCHAIN *aPotential, const wxString &aName)
Promote a potential net chain to an actual user net chain with the provided name.
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Update the connection graph for the given list of sheets.
const std::vector< std::unique_ptr< SCH_NETCHAIN > > & GetPotentialNetChains() const
Potential net chains are inferred groupings produced by RebuildNetChains() but not yet user-committed...
void ApplyNetChainNetclasses()
Mirror each committed net chain's netclass override into the project NET_SETTINGS as a chain-derived ...
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:231
void insert(SCH_ITEM *aItem)
Insert an item into the tree.
Definition sch_rtree.h:70
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:248
Definition kiid.h:46
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
Net membership for one UI operation.
std::vector< SCH_ITEM * > WholeNetItems(const std::vector< SCH_ITEM * > &aSeeds, const SCH_SHEET_PATH &aSheet) const
Whole nets containing the seeds on this instance; excludes bus parents and members.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition sch_label.h:421
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:39
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition sch_line.cpp:241
A net chain is a collection of nets that are connected together through passive components.
const std::set< wxString > & GetNets() const
const std::set< class SCH_SYMBOL * > & GetSymbols() const
void SetNetClass(const wxString &aNetClass)
Net chains may override the netclass applied to every member net.
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:118
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...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
Schematic symbol object.
Definition sch_symbol.h:75
static bool empty(const wxTextEntryBase *aCtrl)
void LoadSchematic(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< SCHEMATIC > &aSchematic)
std::vector< FAB_LAYER_COLOR > dummy
A schematic staged off to the side by an importer, ready to be swapped into a live SCHEMATIC in one s...
Definition schematic.h:108
std::optional< SCH_SHEET_PATH > currentSheet
Definition schematic.h:130
SCH_SHEET_LIST hierarchy
Definition schematic.h:129
std::unique_ptr< CONNECTION_GRAPH > connectionGraph
Definition schematic.h:131
bool preserveNetChains
Keep the schematic's net chains instead of the staged graph's, for append.
Definition schematic.h:134
SCH_SHEET * targetSheet
Sheet whose screen receives the content. Null names the schematic's virtual root.
Definition schematic.h:110
EE_RTREE screenItems
Spatial index that replaces the target screen's own.
Definition schematic.h:118
SETTINGS_MANAGER m_settingsManager
std::unique_ptr< SCHEMATIC > m_schematic
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
std::string path
VECTOR3I expected(15, 30, 45)
BOOST_FIXTURE_TEST_CASE(RebuildSignals_GroupsFourNetsIntoOneSignal, SIGNALS_TEST_FIXTURE)
BOOST_AUTO_TEST_CASE(WholeNetQueryIncludesSeparatedNativeLabelIsland)
const SHAPE_LINE_CHAIN chain
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_LINE_T
Definition typeinfo.h:159
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_LABEL_T
Definition typeinfo.h:163
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683