KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_pads_sch_import.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <boost/test/unit_test.hpp>
22
23#include <lib_symbol.h>
24#include <schematic.h>
26#include <sch_io/sch_io_mgr.h>
27#include <sch_line.h>
28#include <sch_screen.h>
29#include <sch_sheet.h>
30#include <sch_sheet_path.h>
31#include <sch_symbol.h>
32#include <sch_text.h>
34
35#include <algorithm>
36#include <map>
37#include <vector>
38
39
40namespace
41{
42
43struct PADS_SCH_IMPORT_FIXTURE
44{
45 PADS_SCH_IMPORT_FIXTURE() : m_schematic( nullptr )
46 {
47 m_settingsManager.LoadProject( "" );
48 m_schematic.SetProject( &m_settingsManager.Prj() );
49 m_schematic.Reset();
50 }
51
52 ~PADS_SCH_IMPORT_FIXTURE()
53 {
54 m_schematic.Reset();
55 }
56
57 SETTINGS_MANAGER m_settingsManager;
58 SCHEMATIC m_schematic;
59};
60
61} // namespace
62
63
64BOOST_FIXTURE_TEST_SUITE( PadsSchImport, PADS_SCH_IMPORT_FIXTURE )
65
66
67BOOST_AUTO_TEST_CASE( CanReadSchematicFile )
68{
69 SCH_IO_PADS plugin;
70
71 wxString padsFile = wxString::FromUTF8(
72 KI_TEST::GetEeschemaTestDataDir() + "/plugins/pads/simple_schematic.txt" );
73
74 BOOST_CHECK( plugin.CanReadSchematicFile( padsFile ) );
75}
76
77
78BOOST_AUTO_TEST_CASE( CanReadSchematicFile_RejectNonPads )
79{
80 SCH_IO_PADS plugin;
81
82 wxString kicadFile = wxString::FromUTF8(
83 KI_TEST::GetEeschemaTestDataDir() + "/plugins/pads/simple_schematic.txt" );
84
85 BOOST_CHECK( plugin.CanReadSchematicFile( kicadFile ) );
86}
87
88
90{
91 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_PADS ) );
92 BOOST_CHECK_NE( pi.get(), nullptr );
93}
94
95
96BOOST_AUTO_TEST_CASE( MultiGateImport )
97{
98 SCH_IO_PADS plugin;
99
100 wxString padsFile = wxString::FromUTF8(
101 KI_TEST::GetEeschemaTestDataDir() + "/plugins/pads/multigate_schematic.txt" );
102
103 SCH_SHEET* rootSheet = plugin.LoadSchematicFile( padsFile, &m_schematic );
104 BOOST_REQUIRE( rootSheet );
105 BOOST_REQUIRE( rootSheet->GetScreen() );
106
107 SCH_SCREEN* screen = rootSheet->GetScreen();
108
109 // Collect U1 symbols
110 std::vector<SCH_SYMBOL*> u1Symbols;
111 SCH_SHEET_PATH rootPath;
112 rootPath.push_back( rootSheet );
113
114 for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) )
115 {
116 SCH_SYMBOL* sym = static_cast<SCH_SYMBOL*>( item );
117
118 if( sym->GetRef( &rootPath ) == wxT( "U1" ) )
119 u1Symbols.push_back( sym );
120 }
121
122 BOOST_REQUIRE_EQUAL( u1Symbols.size(), 2u );
123
124 // Sort by unit number for deterministic checks
125 std::sort( u1Symbols.begin(), u1Symbols.end(),
126 []( const SCH_SYMBOL* a, const SCH_SYMBOL* b )
127 {
128 return a->GetUnit() < b->GetUnit();
129 } );
130
131 // Unit 1 (gate A with TL082A decal) should have 5 pins
132 BOOST_CHECK_EQUAL( u1Symbols[0]->GetUnit(), 1 );
133 BOOST_CHECK_EQUAL( u1Symbols[0]->GetLibPins().size(), 5u );
134
135 // Unit 2 (gate B with TL082 decal) should have 3 pins
136 BOOST_CHECK_EQUAL( u1Symbols[1]->GetUnit(), 2 );
137 BOOST_CHECK_EQUAL( u1Symbols[1]->GetLibPins().size(), 3u );
138
139 // Both should share the same multi-unit LIB_SYMBOL with 2 units
140 BOOST_CHECK( u1Symbols[0]->IsMultiUnit() );
141 BOOST_CHECK_EQUAL( u1Symbols[0]->GetUnitCount(), 2 );
142
143 // Both references should be "U1" (not "U1-A" or "U1-B")
144 BOOST_CHECK_EQUAL( u1Symbols[0]->GetRef( &rootPath ), wxT( "U1" ) );
145 BOOST_CHECK_EQUAL( u1Symbols[1]->GetRef( &rootPath ), wxT( "U1" ) );
146}
147
148
149BOOST_AUTO_TEST_CASE( Issue23420_HeaderWithCodePageSuffix )
150{
151 // Regression test for https://gitlab.com/kicad/code/kicad/-/issues/23420
152 // PADS Logic schematics exported with a code page suffix in the header
153 // (e.g. *PADS-LOGIC-V9.0-CP1250*) must be detected and parsed.
154 SCH_IO_PADS plugin;
155
156 wxString padsFile = wxString::FromUTF8(
158 + "/plugins/pads/issue23420_codepage_schematic.txt" );
159
160 BOOST_CHECK( plugin.CanReadSchematicFile( padsFile ) );
161
162 SCH_SHEET* rootSheet = plugin.LoadSchematicFile( padsFile, &m_schematic );
163
164 BOOST_REQUIRE( rootSheet );
165 BOOST_REQUIRE( rootSheet->GetScreen() );
166}
167
168
169BOOST_AUTO_TEST_CASE( CanReadLibrary )
170{
171 SCH_IO_PADS plugin;
172
173 wxString padsFile = wxString::FromUTF8(
174 KI_TEST::GetEeschemaTestDataDir() + "/plugins/pads/symbols_schematic.txt" );
175
176 BOOST_CHECK( plugin.CanReadLibrary( padsFile ) );
177}
178
179
180BOOST_AUTO_TEST_CASE( EnumerateSymbolLib_NamesFromSchematic )
181{
182 SCH_IO_PADS plugin;
183
184 wxString padsFile = wxString::FromUTF8(
185 KI_TEST::GetEeschemaTestDataDir() + "/plugins/pads/symbols_schematic.txt" );
186
187 wxArrayString names;
188 BOOST_CHECK_NO_THROW( plugin.EnumerateSymbolLib( names, padsFile ) );
189 BOOST_CHECK_GT( names.GetCount(), 0u );
190}
191
192
193BOOST_AUTO_TEST_CASE( EnumerateSymbolLib_ReturnsLibSymbols )
194{
195 SCH_IO_PADS plugin;
196
197 wxString padsFile = wxString::FromUTF8(
198 KI_TEST::GetEeschemaTestDataDir() + "/plugins/pads/symbols_schematic.txt" );
199
200 std::vector<LIB_SYMBOL*> symbols;
201 BOOST_CHECK_NO_THROW( plugin.EnumerateSymbolLib( symbols, padsFile ) );
202 BOOST_CHECK_GT( symbols.size(), 0u );
203
204 for( LIB_SYMBOL* sym : symbols )
205 BOOST_REQUIRE( sym != nullptr );
206}
207
208
209BOOST_AUTO_TEST_CASE( LoadSymbol_ByName )
210{
211 SCH_IO_PADS plugin;
212
213 wxString padsFile = wxString::FromUTF8(
214 KI_TEST::GetEeschemaTestDataDir() + "/plugins/pads/symbols_schematic.txt" );
215
216 wxArrayString names;
217 plugin.EnumerateSymbolLib( names, padsFile );
218
219 BOOST_REQUIRE_GT( names.GetCount(), 0u );
220
221 LIB_SYMBOL* sym = plugin.LoadSymbol( padsFile, names.Item( 0 ) );
222 BOOST_REQUIRE( sym != nullptr );
223 BOOST_CHECK_EQUAL( sym->GetName(), names.Item( 0 ) );
224}
225
226
227BOOST_AUTO_TEST_CASE( LoadSymbol_UnknownReturnsNull )
228{
229 SCH_IO_PADS plugin;
230
231 wxString padsFile = wxString::FromUTF8(
232 KI_TEST::GetEeschemaTestDataDir() + "/plugins/pads/symbols_schematic.txt" );
233
234 LIB_SYMBOL* sym = plugin.LoadSymbol( padsFile, wxT( "NO_SUCH_SYMBOL_12345" ) );
235 BOOST_CHECK( sym == nullptr );
236}
237
238
239BOOST_AUTO_TEST_CASE( MultiGatePartTypeBecomesMultiUnitLibSymbol )
240{
241 SCH_IO_PADS plugin;
242
243 wxString padsFile = wxString::FromUTF8(
244 KI_TEST::GetEeschemaTestDataDir() + "/plugins/pads/multigate_schematic.txt" );
245
246 std::vector<LIB_SYMBOL*> symbols;
247 BOOST_CHECK_NO_THROW( plugin.EnumerateSymbolLib( symbols, padsFile ) );
248
249 bool foundMultiUnit = false;
250
251 for( LIB_SYMBOL* sym : symbols )
252 {
253 if( sym && sym->GetUnitCount() > 1 )
254 {
255 foundMultiUnit = true;
256 break;
257 }
258 }
259
260 BOOST_CHECK( foundMultiUnit );
261}
262
263
264BOOST_AUTO_TEST_CASE( IsLibraryNotWritable )
265{
266 SCH_IO_PADS plugin;
267
268 wxString padsFile = wxString::FromUTF8(
269 KI_TEST::GetEeschemaTestDataDir() + "/plugins/pads/symbols_schematic.txt" );
270
271 BOOST_CHECK( !plugin.IsLibraryWritable( padsFile ) );
272}
273
274
275BOOST_AUTO_TEST_CASE( Issue24284_TextItemsPlacedOnCorrectSheet )
276{
277 // Regression test for https://gitlab.com/kicad/code/kicad/-/issues/24284
278 // Multi-sheet PADS Logic schematics have one *TEXT* and *LINES* block per
279 // *SHT*. Before the fix every text/line item was placed on the first
280 // sheet, causing page-number text from all sheets to stack on top of each
281 // other and border graphics to overlap.
282 SCH_IO_PADS plugin;
283
284 wxString padsFile = wxString::FromUTF8(
286 + "/plugins/pads/issue24284_multisheet_text.txt" );
287
288 BOOST_REQUIRE( plugin.CanReadSchematicFile( padsFile ) );
289
290 SCH_SHEET* rootSheet = plugin.LoadSchematicFile( padsFile, &m_schematic );
291 BOOST_REQUIRE( rootSheet );
292 BOOST_REQUIRE( rootSheet->GetScreen() );
293
294 // Collect text and line content keyed by hierarchical sheet name.
295 std::map<wxString, std::vector<wxString>> textBySheet;
296 std::map<wxString, int> lineCountBySheet;
297
298 for( SCH_ITEM* item : rootSheet->GetScreen()->Items().OfType( SCH_SHEET_T ) )
299 {
300 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
301 wxString sheetName = sheet->GetField( FIELD_T::SHEET_NAME )->GetText();
302
303 for( SCH_ITEM* screenItem : sheet->GetScreen()->Items().OfType( SCH_TEXT_T ) )
304 {
305 SCH_TEXT* txt = static_cast<SCH_TEXT*>( screenItem );
306 textBySheet[sheetName].push_back( txt->GetText() );
307 }
308
309 for( SCH_ITEM* screenItem : sheet->GetScreen()->Items().OfType( SCH_LINE_T ) )
310 {
311 (void) screenItem;
312 lineCountBySheet[sheetName]++;
313 }
314 }
315
316 for( int sheetNum = 1; sheetNum <= 3; ++sheetNum )
317 {
318 wxString sheetName = wxString::Format( wxT( "Page%d" ), sheetNum );
319 wxString pageText = wxString::Format( wxT( "PAGE %d OF 3" ), sheetNum );
320 wxString bodyText = wxString::Format( wxT( "TEXT ON SHEET %d" ), sheetNum );
321
322 BOOST_REQUIRE_EQUAL( textBySheet.count( sheetName ), 1u );
323 BOOST_CHECK_EQUAL( textBySheet[sheetName].size(), 2u );
324 BOOST_CHECK( std::find( textBySheet[sheetName].begin(), textBySheet[sheetName].end(),
325 pageText ) != textBySheet[sheetName].end() );
326 BOOST_CHECK( std::find( textBySheet[sheetName].begin(), textBySheet[sheetName].end(),
327 bodyText ) != textBySheet[sheetName].end() );
328 BOOST_CHECK_EQUAL( lineCountBySheet[sheetName], 1 );
329 }
330}
331
332
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:114
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:225
Define a library symbol object.
Definition lib_symbol.h:83
wxString GetName() const override
Definition lib_symbol.h:145
virtual const wxString & GetText() const override
Return the string associated with the text object.
Definition sch_field.h:132
A SCH_IO derivation for loading PADS Logic schematic files.
Definition sch_io_pads.h:42
LIB_SYMBOL * LoadSymbol(const wxString &aLibraryPath, const wxString &aPartName, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a LIB_SYMBOL object having aPartName from the aLibraryPath containing a library format that this...
void EnumerateSymbolLib(wxArrayString &aSymbolNameList, const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Populate a list of LIB_SYMBOL alias names contained within the library aLibraryPath.
bool CanReadLibrary(const wxString &aFileName) const override
Checks if this IO object can read the specified library file/directory.
bool IsLibraryWritable(const wxString &aLibraryPath) override
Return true if the library at aLibraryPath is writable.
Definition sch_io_pads.h:75
bool CanReadSchematicFile(const wxString &aFileName) const override
Checks if this SCH_IO can read the specified schematic file.
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,...
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:166
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:119
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this sheet.
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:143
Schematic symbol object.
Definition sch_symbol.h:73
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(CanReadSchematicFile)
VECTOR2I end
BOOST_CHECK_EQUAL(result, "25.4")
@ SCH_LINE_T
Definition typeinfo.h:164
@ SCH_SYMBOL_T
Definition typeinfo.h:173
@ SCH_SHEET_T
Definition typeinfo.h:176
@ SCH_TEXT_T
Definition typeinfo.h:152