KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_net_chain_hierarchical_roundtrip.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>
24#include <sch_netchain.h>
25#include <sch_screen.h>
26#include <sch_sheet.h>
27#include <schematic.h>
29#include <locale_io.h>
31
32#include <wx/ffile.h>
33#include <wx/filename.h>
34#include <wx/stdpaths.h>
35
36
37// Test backdoor declared in connection_graph.h. Pushes a fully-formed committed chain
38// into the graph so SaveSchematicFile has something to serialize.
40 std::unique_ptr<SCH_NETCHAIN> aChain );
41
42
44{
47 {
48 m_workDir.AssignDir( wxStandardPaths::Get().GetTempDir() );
49 m_workDir.AppendDir(
50 wxString::Format( wxT( "kicad_qa_netchain_hier_%lu" ),
51 static_cast<unsigned long>( wxGetProcessId() ) ) );
52
53 wxFileName::Mkdir( m_workDir.GetFullPath(), 0755, wxPATH_MKDIR_FULL );
54
55 wxString projectPath = m_workDir.GetFullPath() + wxT( "hier_roundtrip.kicad_pro" );
56 m_tempFiles.push_back( projectPath );
57
58 m_settingsManager.LoadProject( projectPath.ToStdString() );
60 }
61
63 {
64 m_schematic.reset();
65
66 // Release the project lock while its file still exists
67 m_settingsManager.UnloadProject( m_project, false );
68
69 for( const wxString& file : m_tempFiles )
70 {
71 if( wxFileExists( file ) )
72 wxRemoveFile( file );
73 }
74
75 if( m_workDir.DirExists() )
76 wxFileName::Rmdir( m_workDir.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
77 }
78
79 wxString PathInWorkDir( const wxString& aLeaf )
80 {
81 wxString full = m_workDir.GetFullPath() + aLeaf;
82 m_tempFiles.push_back( full );
83 return full;
84 }
85
87 PROJECT* m_project = nullptr;
88 std::unique_ptr<SCHEMATIC> m_schematic;
89 wxFileName m_workDir;
90 std::vector<wxString> m_tempFiles;
91};
92
93
108BOOST_FIXTURE_TEST_CASE( NetChainHierarchicalRoundTripPreservesOverrides,
110{
112
113 const wxString chainName = wxT( "TEST_HIER_CHAIN" );
114 const wxString chainNetClass = wxT( "HighSpeed" );
115 const KIGFX::COLOR4D chainColor( 0.5, 0.25, 0.75, 1.0 );
116
117 m_schematic = std::make_unique<SCHEMATIC>( nullptr );
118 m_schematic->SetProject( m_project );
119 m_schematic->CreateDefaultScreens();
120
121 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
122 BOOST_REQUIRE( !topSheets.empty() );
123
124 SCH_SHEET* topSheet = topSheets[0];
125 SCH_SCREEN* topScreen = topSheet->GetScreen();
126 BOOST_REQUIRE( topScreen );
127
128 wxString rootFileName = PathInWorkDir( wxT( "hier_roundtrip.kicad_sch" ) );
129 wxString subFileName = PathInWorkDir( wxT( "hier_roundtrip_sub.kicad_sch" ) );
130
131 topSheet->SetFileName( wxT( "hier_roundtrip.kicad_sch" ) );
132 topScreen->SetFileName( rootFileName );
133
134 SCH_SHEET* subSheet = new SCH_SHEET( m_schematic.get() );
135 SCH_SCREEN* subScreen = new SCH_SCREEN( m_schematic.get() );
136 subSheet->SetName( wxT( "SubSheet" ) );
137 subSheet->SetFileName( wxT( "hier_roundtrip_sub.kicad_sch" ) );
138 subSheet->SetScreen( subScreen );
139 subScreen->SetFileName( subFileName );
140 topScreen->Append( subSheet );
141
142 m_schematic->RefreshHierarchy();
143
144 auto chain = std::make_unique<SCH_NETCHAIN>();
145 chain->SetName( chainName );
146 chain->AddNet( wxT( "/NET_A" ) );
147 chain->AddNet( wxT( "/NET_B" ) );
148 chain->SetTerminalRefs( wxT( "U1" ), wxT( "1" ), wxT( "U2" ), wxT( "2" ) );
149 chain->SetNetClass( chainNetClass );
150 chain->SetColor( chainColor );
151
152 boost_test_inject_committed_net_chain( *m_schematic->ConnectionGraph(), std::move( chain ) );
153
154 BOOST_REQUIRE_EQUAL( m_schematic->ConnectionGraph()->GetCommittedNetChains().size(), 1u );
155
156 SCH_IO_KICAD_SEXPR saver;
157 BOOST_REQUIRE_NO_THROW( saver.SaveSchematicFile( rootFileName, topSheet, m_schematic.get() ) );
158 BOOST_REQUIRE_NO_THROW( saver.SaveSchematicFile( subFileName, subSheet, m_schematic.get() ) );
159
160 BOOST_REQUIRE( wxFileExists( rootFileName ) );
161 BOOST_REQUIRE( wxFileExists( subFileName ) );
162
163 // Drop the in-memory schematic and reload from disk through the full IO plugin so
164 // that loadHierarchy walks both files via loadFile, exercising the gate.
165 m_schematic.reset();
166
167 auto reloaded = std::make_unique<SCHEMATIC>( nullptr );
168 reloaded->SetProject( m_project );
169
170 SCH_IO_KICAD_SEXPR loader;
171 SCH_SHEET* loadedRoot = nullptr;
172
173 BOOST_REQUIRE_NO_THROW( loadedRoot = loader.LoadSchematicFile( rootFileName, reloaded.get() ) );
174 BOOST_REQUIRE( loadedRoot );
175
176 reloaded->SetTopLevelSheets( { loadedRoot } );
177 reloaded->RefreshHierarchy();
178
179 const auto& classOverrides = reloaded->ConnectionGraph()->GetNetChainNetClassOverrides();
180 const auto& colorOverrides = reloaded->ConnectionGraph()->GetNetChainColorOverrides();
181 const auto& terminalOverrides = reloaded->ConnectionGraph()->GetNetChainTerminalRefOverrides();
182
183 BOOST_CHECK_MESSAGE(
184 classOverrides.size() == 1u,
185 "Net-chain netclass overrides were wiped during hierarchical load (size = "
186 << classOverrides.size() << ")" );
187
188 BOOST_CHECK_MESSAGE(
189 colorOverrides.size() == 1u,
190 "Net-chain color overrides were wiped during hierarchical load (size = "
191 << colorOverrides.size() << ")" );
192
193 BOOST_CHECK_MESSAGE(
194 terminalOverrides.size() == 1u,
195 "Net-chain terminal-ref overrides were wiped during hierarchical load (size = "
196 << terminalOverrides.size() << ")" );
197
198 auto classIt = classOverrides.find( chainName );
199 BOOST_REQUIRE( classIt != classOverrides.end() );
200 BOOST_CHECK_EQUAL( classIt->second, chainNetClass );
201
202 auto colorIt = colorOverrides.find( chainName );
203 BOOST_REQUIRE( colorIt != colorOverrides.end() );
204
205 // RGB channels are serialized as 0..255 integers and reconstructed by dividing by 255,
206 // so an exact equality check is not appropriate. Allow slightly more than 0.5/255 of
207 // slack to absorb rounding in either direction.
208 constexpr double colorTolerance = 1.0 / 255.0 + 1e-9;
209 BOOST_CHECK_SMALL( colorIt->second.r - chainColor.r, colorTolerance );
210 BOOST_CHECK_SMALL( colorIt->second.g - chainColor.g, colorTolerance );
211 BOOST_CHECK_SMALL( colorIt->second.b - chainColor.b, colorTolerance );
212 BOOST_CHECK_SMALL( colorIt->second.a - chainColor.a, 1e-3 );
213
214 auto termIt = terminalOverrides.find( chainName );
215 BOOST_REQUIRE( termIt != terminalOverrides.end() );
216 BOOST_CHECK_EQUAL( termIt->second.first.ref, wxT( "U1" ) );
217 BOOST_CHECK_EQUAL( termIt->second.first.pin, wxT( "1" ) );
218 BOOST_CHECK_EQUAL( termIt->second.second.ref, wxT( "U2" ) );
219 BOOST_CHECK_EQUAL( termIt->second.second.pin, wxT( "2" ) );
220
221 reloaded.reset();
222}
Calculate the connectivity of a schematic and generate netlists.
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
double r
Red component.
Definition color4d.h:390
double g
Green component.
Definition color4d.h:391
double a
Alpha component.
Definition color4d.h:393
double b
Blue component.
Definition color4d.h:392
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
Container for project specific data.
Definition project.h:63
A SCH_IO derivation for loading schematic files using the new s-expression file format.
void SaveSchematicFile(const wxString &aFileName, SCH_SHEET *aSheet, SCHEMATIC *aSchematic, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aSchematic to a storage file in a format that this SCH_IO implementation knows about,...
SCH_SHEET * LoadSchematicFile(const wxString &aFileName, SCHEMATIC *aSchematic, SCH_SHEET *aAppendToMe=nullptr, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load information from some input file format that this SCH_IO implementation knows about,...
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:390
void SetName(const wxString &aName)
Definition sch_sheet.h:143
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
std::vector< FAB_LAYER_COLOR > dummy
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
void boost_test_inject_committed_net_chain(CONNECTION_GRAPH &aGraph, std::unique_ptr< SCH_NETCHAIN > aChain)
BOOST_FIXTURE_TEST_CASE(NetChainHierarchicalRoundTripPreservesOverrides, NETCHAIN_HIER_ROUNDTRIP_FIXTURE)
Regression: net-chain override maps (class, color, terminal refs) are schematic-level state owned by ...
const SHAPE_LINE_CHAIN chain
BOOST_CHECK_EQUAL(result, "25.4")