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, you may find one here:
18 * https://www.gnu.org/licenses/gpl-3.0.en.html
19 */
20
21#include <boost/test/unit_test.hpp>
22
23#include <connection_graph.h>
25#include <sch_netchain.h>
26#include <sch_screen.h>
27#include <sch_sheet.h>
28#include <schematic.h>
30#include <locale_io.h>
32
33#include <wx/ffile.h>
34#include <wx/filename.h>
35#include <wx/stdpaths.h>
36
37
38// Test backdoor declared in connection_graph.h. Pushes a fully-formed committed chain
39// into the graph so SaveSchematicFile has something to serialize.
41 std::unique_ptr<SCH_NETCHAIN> aChain );
42
43
45{
48 {
49 m_workDir.AssignDir( wxStandardPaths::Get().GetTempDir() );
50 m_workDir.AppendDir(
51 wxString::Format( wxT( "kicad_qa_netchain_hier_%lu" ),
52 static_cast<unsigned long>( wxGetProcessId() ) ) );
53
54 wxFileName::Mkdir( m_workDir.GetFullPath(), 0755, wxPATH_MKDIR_FULL );
55
56 wxString projectPath = m_workDir.GetFullPath() + wxT( "hier_roundtrip.kicad_pro" );
57 m_tempFiles.push_back( projectPath );
58
59 m_settingsManager.LoadProject( projectPath.ToStdString() );
61 }
62
64 {
65 m_schematic.reset();
66
67 for( const wxString& file : m_tempFiles )
68 {
69 if( wxFileExists( file ) )
70 wxRemoveFile( file );
71 }
72
73 if( m_workDir.DirExists() )
74 wxFileName::Rmdir( m_workDir.GetFullPath(), wxPATH_RMDIR_RECURSIVE );
75 }
76
77 wxString PathInWorkDir( const wxString& aLeaf )
78 {
79 wxString full = m_workDir.GetFullPath() + aLeaf;
80 m_tempFiles.push_back( full );
81 return full;
82 }
83
85 PROJECT* m_project = nullptr;
86 std::unique_ptr<SCHEMATIC> m_schematic;
87 wxFileName m_workDir;
88 std::vector<wxString> m_tempFiles;
89};
90
91
106BOOST_FIXTURE_TEST_CASE( NetChainHierarchicalRoundTripPreservesOverrides,
108{
110
111 const wxString chainName = wxT( "TEST_HIER_CHAIN" );
112 const wxString chainNetClass = wxT( "HighSpeed" );
113 const KIGFX::COLOR4D chainColor( 0.5, 0.25, 0.75, 1.0 );
114
115 m_schematic = std::make_unique<SCHEMATIC>( nullptr );
116 m_schematic->SetProject( m_project );
117 m_schematic->CreateDefaultScreens();
118
119 std::vector<SCH_SHEET*> topSheets = m_schematic->GetTopLevelSheets();
120 BOOST_REQUIRE( !topSheets.empty() );
121
122 SCH_SHEET* topSheet = topSheets[0];
123 SCH_SCREEN* topScreen = topSheet->GetScreen();
124 BOOST_REQUIRE( topScreen );
125
126 wxString rootFileName = PathInWorkDir( wxT( "hier_roundtrip.kicad_sch" ) );
127 wxString subFileName = PathInWorkDir( wxT( "hier_roundtrip_sub.kicad_sch" ) );
128
129 topSheet->SetFileName( wxT( "hier_roundtrip.kicad_sch" ) );
130 topScreen->SetFileName( rootFileName );
131
132 SCH_SHEET* subSheet = new SCH_SHEET( m_schematic.get() );
133 SCH_SCREEN* subScreen = new SCH_SCREEN( m_schematic.get() );
134 subSheet->SetName( wxT( "SubSheet" ) );
135 subSheet->SetFileName( wxT( "hier_roundtrip_sub.kicad_sch" ) );
136 subSheet->SetScreen( subScreen );
137 subScreen->SetFileName( subFileName );
138 topScreen->Append( subSheet );
139
140 m_schematic->RefreshHierarchy();
141
142 auto chain = std::make_unique<SCH_NETCHAIN>();
143 chain->SetName( chainName );
144 chain->AddNet( wxT( "/NET_A" ) );
145 chain->AddNet( wxT( "/NET_B" ) );
146 chain->SetTerminalRefs( wxT( "U1" ), wxT( "1" ), wxT( "U2" ), wxT( "2" ) );
147 chain->SetNetClass( chainNetClass );
148 chain->SetColor( chainColor );
149
150 boost_test_inject_committed_net_chain( *m_schematic->ConnectionGraph(), std::move( chain ) );
151
152 BOOST_REQUIRE_EQUAL( m_schematic->ConnectionGraph()->GetCommittedNetChains().size(), 1u );
153
154 SCH_IO_KICAD_SEXPR saver;
155 BOOST_REQUIRE_NO_THROW( saver.SaveSchematicFile( rootFileName, topSheet, m_schematic.get() ) );
156 BOOST_REQUIRE_NO_THROW( saver.SaveSchematicFile( subFileName, subSheet, m_schematic.get() ) );
157
158 BOOST_REQUIRE( wxFileExists( rootFileName ) );
159 BOOST_REQUIRE( wxFileExists( subFileName ) );
160
161 // Drop the in-memory schematic and reload from disk through the full IO plugin so
162 // that loadHierarchy walks both files via loadFile, exercising the gate.
163 m_schematic.reset();
164
165 auto reloaded = std::make_unique<SCHEMATIC>( nullptr );
166 reloaded->SetProject( m_project );
167
168 SCH_IO_KICAD_SEXPR loader;
169 SCH_SHEET* loadedRoot = nullptr;
170
171 BOOST_REQUIRE_NO_THROW( loadedRoot = loader.LoadSchematicFile( rootFileName, reloaded.get() ) );
172 BOOST_REQUIRE( loadedRoot );
173
174 reloaded->SetTopLevelSheets( { loadedRoot } );
175 reloaded->RefreshHierarchy();
176
177 const auto& classOverrides = reloaded->ConnectionGraph()->GetNetChainNetClassOverrides();
178 const auto& colorOverrides = reloaded->ConnectionGraph()->GetNetChainColorOverrides();
179 const auto& terminalOverrides = reloaded->ConnectionGraph()->GetNetChainTerminalRefOverrides();
180
182 classOverrides.size() == 1u,
183 "Net-chain netclass overrides were wiped during hierarchical load (size = "
184 << classOverrides.size() << ")" );
185
187 colorOverrides.size() == 1u,
188 "Net-chain color overrides were wiped during hierarchical load (size = "
189 << colorOverrides.size() << ")" );
190
192 terminalOverrides.size() == 1u,
193 "Net-chain terminal-ref overrides were wiped during hierarchical load (size = "
194 << terminalOverrides.size() << ")" );
195
196 auto classIt = classOverrides.find( chainName );
197 BOOST_REQUIRE( classIt != classOverrides.end() );
198 BOOST_CHECK_EQUAL( classIt->second, chainNetClass );
199
200 auto colorIt = colorOverrides.find( chainName );
201 BOOST_REQUIRE( colorIt != colorOverrides.end() );
202
203 // RGB channels are serialized as 0..255 integers and reconstructed by dividing by 255,
204 // so an exact equality check is not appropriate. Allow slightly more than 0.5/255 of
205 // slack to absorb rounding in either direction.
206 constexpr double colorTolerance = 1.0 / 255.0 + 1e-9;
207 BOOST_CHECK_SMALL( colorIt->second.r - chainColor.r, colorTolerance );
208 BOOST_CHECK_SMALL( colorIt->second.g - chainColor.g, colorTolerance );
209 BOOST_CHECK_SMALL( colorIt->second.b - chainColor.b, colorTolerance );
210 BOOST_CHECK_SMALL( colorIt->second.a - chainColor.a, 1e-3 );
211
212 auto termIt = terminalOverrides.find( chainName );
213 BOOST_REQUIRE( termIt != terminalOverrides.end() );
214 BOOST_CHECK_EQUAL( termIt->second.first.ref, wxT( "U1" ) );
215 BOOST_CHECK_EQUAL( termIt->second.first.pin, wxT( "1" ) );
216 BOOST_CHECK_EQUAL( termIt->second.second.ref, wxT( "U2" ) );
217 BOOST_CHECK_EQUAL( termIt->second.second.pin, wxT( "2" ) );
218
219 reloaded.reset();
220}
Calculate the connectivity of a schematic and generates netlists.
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
double r
Red component.
Definition color4d.h:393
double g
Green component.
Definition color4d.h:394
double a
Alpha component.
Definition color4d.h:396
double b
Blue component.
Definition color4d.h:395
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:41
Container for project specific data.
Definition project.h:66
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:380
void SetName(const wxString &aName)
Definition sch_sheet.h:141
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:143
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 ...
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
const SHAPE_LINE_CHAIN chain
BOOST_CHECK_EQUAL(result, "25.4")