KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_net_chain_resolve_terminals.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
22#include <connection_graph.h>
23#include <sch_netchain.h>
25
26#include <map>
27#include <memory>
28#include <utility>
29#include <vector>
30
31
32// Friend shim into CONNECTION_GRAPH::resolvePotentialChainByTerminals so the test can
33// exercise the resolver without exposing it on the public API. Mirrors the existing
34// boost_test_inject_committed_net_chain pattern.
36 const std::pair<std::pair<wxString, wxString>,
37 std::pair<wxString, wxString>>& aTerms,
38 const std::map<std::pair<wxString, wxString>, wxString>& aRefPinToNet,
39 const std::vector<std::unique_ptr<SCH_NETCHAIN>>& aPotentials,
40 const wxString& aChainName )
41{
43 { aTerms.first.first, aTerms.first.second },
44 { aTerms.second.first, aTerms.second.second }
45 };
46
47 return CONNECTION_GRAPH::resolvePotentialChainByTerminals( termRefs, aRefPinToNet,
48 aPotentials, aChainName );
49}
50
51
59BOOST_AUTO_TEST_SUITE( NetChainRestoreResolveBothTerminals )
60
61
62using REF_PIN_KEY = std::pair<wxString, wxString>;
63using REF_PIN_TO_NET = std::map<REF_PIN_KEY, wxString>;
65
66
67static std::unique_ptr<SCH_NETCHAIN> makePotential( const wxString& aName,
68 std::initializer_list<wxString> aNets )
69{
70 auto sig = std::make_unique<SCH_NETCHAIN>();
71 sig->SetName( aName );
72
73 for( const wxString& n : aNets )
74 sig->AddNet( n );
75
76 return sig;
77}
78
79
80BOOST_AUTO_TEST_CASE( PicksChainContainingBothTerminalNets )
81{
82 REF_PIN_TO_NET refPinToNet;
83 refPinToNet[{ wxT( "U1" ), wxT( "1" ) }] = wxT( "/SHARED" );
84 refPinToNet[{ wxT( "U3" ), wxT( "5" ) }] = wxT( "/TARGET_TO" );
85
86 std::vector<std::unique_ptr<SCH_NETCHAIN>> potentials;
87
88 // First in vector shares the 'from' net but ends on a different 'to' net. Old logic
89 // would have wrongly picked this one.
90 potentials.push_back( makePotential( wxT( "potA" ), { wxT( "/SHARED" ), wxT( "/OTHER_TO" ) } ) );
91
92 // Second in vector matches both endpoints. This is the correct candidate.
93 potentials.push_back( makePotential( wxT( "potB" ), { wxT( "/SHARED" ), wxT( "/TARGET_TO" ) } ) );
94
95 TERM_PAIR terms{
96 { wxT( "U1" ), wxT( "1" ) },
97 { wxT( "U3" ), wxT( "5" ) }
98 };
99
101 terms, refPinToNet, potentials, wxT( "TEST_CHAIN" ) );
102
103 BOOST_REQUIRE( match );
104 BOOST_CHECK_EQUAL( match->GetName(), wxT( "potB" ) );
105}
106
107
108BOOST_AUTO_TEST_CASE( ReturnsNullWhenNoPotentialSpansBothEndpoints )
109{
110 REF_PIN_TO_NET refPinToNet;
111 refPinToNet[{ wxT( "U1" ), wxT( "1" ) }] = wxT( "/SHARED" );
112 refPinToNet[{ wxT( "U3" ), wxT( "5" ) }] = wxT( "/TARGET_TO" );
113
114 std::vector<std::unique_ptr<SCH_NETCHAIN>> potentials;
115 potentials.push_back( makePotential( wxT( "potA" ), { wxT( "/SHARED" ), wxT( "/OTHER" ) } ) );
116 potentials.push_back( makePotential( wxT( "potB" ), { wxT( "/UNRELATED_FROM" ),
117 wxT( "/TARGET_TO" ) } ) );
118
119 TERM_PAIR terms{
120 { wxT( "U1" ), wxT( "1" ) },
121 { wxT( "U3" ), wxT( "5" ) }
122 };
123
125 terms, refPinToNet, potentials, wxT( "TEST_CHAIN" ) );
126
127 BOOST_CHECK( match == nullptr );
128}
129
130
131BOOST_AUTO_TEST_CASE( ReturnsNullWhenEitherTerminalUnresolvable )
132{
133 REF_PIN_TO_NET refPinToNet;
134 refPinToNet[{ wxT( "U1" ), wxT( "1" ) }] = wxT( "/SHARED" );
135
136 std::vector<std::unique_ptr<SCH_NETCHAIN>> potentials;
137 potentials.push_back( makePotential( wxT( "potA" ), { wxT( "/SHARED" ), wxT( "/X" ) } ) );
138
139 TERM_PAIR terms{
140 { wxT( "U1" ), wxT( "1" ) },
141 { wxT( "MISSING" ), wxT( "9" ) }
142 };
143
145 terms, refPinToNet, potentials, wxT( "TEST_CHAIN" ) );
146
147 BOOST_CHECK( match == nullptr );
148}
149
150
151BOOST_AUTO_TEST_CASE( SwappedTerminalOrderStillResolves )
152{
153 REF_PIN_TO_NET refPinToNet;
154 refPinToNet[{ wxT( "U1" ), wxT( "1" ) }] = wxT( "/A" );
155 refPinToNet[{ wxT( "U2" ), wxT( "2" ) }] = wxT( "/B" );
156
157 std::vector<std::unique_ptr<SCH_NETCHAIN>> potentials;
158 potentials.push_back( makePotential( wxT( "pot" ), { wxT( "/A" ), wxT( "/B" ) } ) );
159
160 TERM_PAIR terms{
161 { wxT( "U2" ), wxT( "2" ) },
162 { wxT( "U1" ), wxT( "1" ) }
163 };
164
166 terms, refPinToNet, potentials, wxT( "pot" ) );
167
168 BOOST_REQUIRE( match );
169 BOOST_CHECK_EQUAL( match->GetName(), wxT( "pot" ) );
170}
171
172
173// Companion regression for [H-5]. RebuildNetChains constructs both the potential chain net
174// set and the refPin->net lookup using the same normalization: when GetNetName() is empty
175// or contains "<NO NET>", a synthetic key __SG_<code> is substituted. The lookup table here
176// must use that same synthetic key for the unnamed endpoint, otherwise common
177// one-named-one-unnamed chains fail to restore under the strict both-endpoint rule.
178BOOST_AUTO_TEST_CASE( ResolvesWhenOneEndpointIsUnnamedSyntheticName )
179{
180 REF_PIN_TO_NET refPinToNet;
181 refPinToNet[{ wxT( "U1" ), wxT( "1" ) }] = wxT( "/NAMED_SIDE" );
182 refPinToNet[{ wxT( "U2" ), wxT( "2" ) }] = wxT( "__SG_42" );
183
184 std::vector<std::unique_ptr<SCH_NETCHAIN>> potentials;
185 potentials.push_back( makePotential( wxT( "pot" ),
186 { wxT( "/NAMED_SIDE" ), wxT( "__SG_42" ) } ) );
187
188 TERM_PAIR terms{
189 { wxT( "U1" ), wxT( "1" ) },
190 { wxT( "U2" ), wxT( "2" ) }
191 };
192
194 terms, refPinToNet, potentials, wxT( "TEST_CHAIN" ) );
195
196 BOOST_REQUIRE( match );
197 BOOST_CHECK_EQUAL( match->GetName(), wxT( "pot" ) );
198}
199
200
static SCH_NETCHAIN * resolvePotentialChainByTerminals(const CHAIN_TERMINAL_REFS &aTermRefs, const std::map< std::pair< wxString, wxString >, wxString > &aRefPinToNet, const std::vector< std::unique_ptr< SCH_NETCHAIN > > &aPotentials, const wxString &aChainName)
Disambiguate the saved (refA.pinA, refB.pinB) terminal pair against the current set of potential net ...
std::pair< CHAIN_TERMINAL_REF, CHAIN_TERMINAL_REF > CHAIN_TERMINAL_REFS
A net chain is a collection of nets that are connected together through passive components.
const wxString & GetName() const
STL class.
STL namespace.
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
static std::unique_ptr< SCH_NETCHAIN > makePotential(const wxString &aName, std::initializer_list< wxString > aNets)
std::pair< REF_PIN_KEY, REF_PIN_KEY > TERM_PAIR
std::map< REF_PIN_KEY, wxString > REF_PIN_TO_NET
SCH_NETCHAIN * boost_test_resolve_potential_chain_by_terminals(const std::pair< std::pair< wxString, wxString >, std::pair< wxString, wxString > > &aTerms, const std::map< std::pair< wxString, wxString >, wxString > &aRefPinToNet, const std::vector< std::unique_ptr< SCH_NETCHAIN > > &aPotentials, const wxString &aChainName)
BOOST_AUTO_TEST_CASE(PicksChainContainingBothTerminalNets)
std::pair< wxString, wxString > REF_PIN_KEY
Regression for [H-5].
BOOST_CHECK_EQUAL(result, "25.4")