KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_io_mgr.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 (C) 2023 Roberto Fernandez Bautista <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
22#include <boost/test/data/test_case.hpp>
23
24#include <cstring>
25
26#include <wx/filename.h>
27#include <wx/wfstream.h>
28
31
35
36
38
39
41{
42 std::string m_case_name;
43 std::string m_file_rel_path;
45
46 friend std::ostream& operator<<( std::ostream& os, const PCB_IO_PLUGIN_CASE& aCase )
47 {
48 os << aCase.m_case_name;
49 return os;
50 }
51};
52
53
54// clang-format off
55static const std::vector<PCB_IO_PLUGIN_CASE> BoardPluginCases = {
56
57 //
58 // FAKE Boards (should return FILE_TYPE_NONE):
59 //
60 {
61 "Fake Board file (KiCad *Legacy* / EAGLE file ext)",
62 "plugins/fakeboard.brd",
64 },
65 {
66 "Fake Board file (KiCad file ext)",
67 "plugins/fakeboard.kicad_pcb",
69 },
70 {
71 "Fake Board file (PCAD file ext)",
72 "plugins/fakeboard.pcb",
74 },
75 {
76 "Fake Board file (CADSTAR file ext)",
77 "plugins/fakeboard.cpa",
79 },
80 {
81 "Fake Board file (Altium Circuit Studio file ext)",
82 "plugins/fakeboard.CSPcbDoc",
84 },
85 {
86 "Fake Board file (Altium Circuit Maker file ext)",
87 "plugins/fakeboard.CMPcbDoc",
89 },
90 {
91 "Fake Board file (Altium Designer file ext)",
92 "plugins/fakeboard.PcbDoc",
94 },
95
96 {
97 "Fake Board file (Solid Works PCB file ext)",
98 "plugins/fakeboard.SWPcbDoc",
100 },
101
102 //
103 // REAL Boards:
104 //
105
106 {
107 "Basic KiCad *Legacy* board file",
108 "plugins/legacy_demos/flat_hierarchy/flat_hierarchy.brd",
110 },
111 {
112 "Basic KiCad board file",
113 "complex_hierarchy.kicad_pcb",
115 },
116 {
117 "Basic Eagle board file",
118 "plugins/eagle/Adafruit-AHT20-PCB/Adafruit AHT20 Temperature & Humidity.brd",
120 },
121 {
122 "Basic PCAD board file",
123 "plugins/pcad/pcad_4layer_glyph_test_ascii.PCB",
125 },
126 {
127 "Basic CADSTAR board file",
128 "plugins/cadstar/route_offset/minimal_route_offset_curved_track.cpa",
130 },
131 {
132 "Basic EasyEDA Std board json file",
133 "plugins/easyeda/PCB_USBMETER-PD QC修改版_2023-09-02.json",
135 },
136 {
137 "Basic EasyEDA Std backup file",
138 "plugins/easyeda/BackupProjects_ESP32-PICO-D4_smart_watch.zip",
140 },
141 {
142 "Basic EasyEDA Pro zip board project",
143 "plugins/easyedapro/Scanning Tunneling Microscope OpenSTM ControlBoard.zip",
145 },
146 {
147 "Basic EasyEDA Pro epro project",
148 "plugins/easyedapro/ProProject_Yuzuki Chameleon_2023-09-02.epro",
150 },
151 {
152 "Basic EasyEDA Pro v3 epro2 project",
153 "plugins/easyedapro/ProProject_LS2K0300Core_2025-11-14.epro2",
155 },
156 {
157 "Basic Altium Designer board file",
158 "plugins/altium/eDP_adapter_dvt1_source/eDP_adapter_dvt1.PcbDoc",
160 }
161 // Todo: Add Altium derivatives and Fabmaster tests
162};
163
164
165static const std::vector<PCB_IO_PLUGIN_CASE> LibraryPluginCases = {
166
167 //
168 // NOT libraries (should return FILE_TYPE_NONE):
169 //
170 {
171 "Non-Library file (KiCad *Legacy* / EAGLE file ext)",
172 "plugins/fakeboard.brd",
174 },
175 {
176 "Non-Library file (KiCad file ext)",
177 "plugins/fakeboard.kicad_pcb",
179 },
180 {
181 "Non-Library file (PCAD file ext)",
182 "plugins/fakeboard.pcb",
184 },
185 {
186 "Non-Library file (CADSTAR file ext)",
187 "plugins/fakeboard.cpa",
189 },
190 {
191 "Non-Library file (Altium Circuit Studio file ext)",
192 "plugins/fakeboard.CSPcbDoc",
194 },
195 {
196 "Non-Library file (Altium Circuit Maker file ext)",
197 "plugins/fakeboard.CMPcbDoc",
199 },
200 {
201 "Non-Library file (Altium Designer file ext)",
202 "plugins/fakeboard.PcbDoc",
204 },
205
206 {
207 "Non-Library file (Solid Works PCB file ext)",
208 "plugins/fakeboard.SWPcbDoc",
210 },
211
212 //
213 // REAL Libraries:
214 //
215
216 {
217 "Basic KiCad footprint .pretty library",
218 "plugins/eagle/lbr/SparkFun-GPS.pretty",
220 },
221 {
222 "Basic Eagle library file",
223 "plugins/eagle/lbr/SparkFun-GPS.lbr",
225 },
226 {
227 "Basic CADSTAR PCB Archive library file",
228 "plugins/cadstar/lib/footprint-with-thermal-pad.cpa",
230 },
231 {
232 "Basic EasyEDA Std board json file",
233 "plugins/easyeda/PCB_USBMETER-PD QC修改版_2023-09-02.json",
235 },
236 {
237 "Basic EasyEDA Std backup file",
238 "plugins/easyeda/BackupProjects_ESP32-PICO-D4_smart_watch.zip",
240 },
241 {
242 "Basic EasyEDA Pro zip board project",
243 "plugins/easyedapro/Scanning Tunneling Microscope OpenSTM ControlBoard.zip",
245 },
246 {
247 "Basic EasyEDA Pro epro project",
248 "plugins/easyedapro/ProProject_Yuzuki Chameleon_2023-09-02.epro",
250 },
251 {
252 "Altium Designer 'Espressif ESP32-WROOM-32.PcbLib' library file",
253 "plugins/altium/pcblib/Espressif ESP32-WROOM-32.PcbLib",
255 },
256 {
257 "Altium Designer 'Tracks.v6.PcbLib' library file",
258 "plugins/altium/pcblib/Tracks.v6.PcbLib",
260 }
261 // Todo: Add Altium derivatives and Fabmaster tests
262};
263// clang-format on
264
265
266BOOST_DATA_TEST_CASE( FindBoardPluginType, boost::unit_test::data::make( BoardPluginCases ), c )
267{
268 wxString dataPath =
269 wxString::FromUTF8( KI_TEST::GetPcbnewTestDataDir() + c.m_file_rel_path );
270
272 c.m_expected_type );
273
274 // Todo add tests to check if it still works with upper/lower case ext.
275 // ( FindPluginTypeFromBoardPath should be case insensitive)
276}
277
278
279BOOST_DATA_TEST_CASE( GuessLibraryPluginType, boost::unit_test::data::make( LibraryPluginCases ), c )
280{
281 wxString dataPath =
282 wxString::FromUTF8( KI_TEST::GetPcbnewTestDataDir() + c.m_file_rel_path );
283
285
286 // Todo add tests to check if it still works with upper/lower case ext.
287 // ( GuessPluginTypeFromLibPath should be case insensitive)
288}
289
290
291BOOST_DATA_TEST_CASE( CheckCanReadBoard, boost::unit_test::data::make( BoardPluginCases ), c )
292{
293 wxString dataPath =
294 wxString::FromUTF8( KI_TEST::GetPcbnewTestDataDir() + c.m_file_rel_path );
295
297
298 for( auto& entry : pluginEntries )
299 {
300 BOOST_TEST_CONTEXT( entry.m_name )
301 {
302 auto plugin = IO_RELEASER<PCB_IO>( PCB_IO_MGR::FindPlugin( entry.m_type ) );
303 bool expectValidHeader = c.m_expected_type == entry.m_type;
304
305 BOOST_CHECK_EQUAL( plugin->CanReadBoard( dataPath ), expectValidHeader );
306 }
307 }
308}
309
311
312
313
317BOOST_AUTO_TEST_SUITE( Issue23291NestedTableMigrate )
318
319
320BOOST_AUTO_TEST_CASE( NestedTableRejectedByConvertLibrary )
321{
322 wxFileName table( wxFileName::CreateTempFileName( "kicad_qa_issue23291_" ) );
323
324 {
325 wxFFileOutputStream out( table.GetFullPath() );
326 BOOST_REQUIRE( out.IsOk() );
327 const char* contents =
328 "(fp_lib_table\n"
329 " (version 7)\n"
330 " (lib (name \"Battery\") (type \"KiCad\")"
331 " (uri \"${KICAD9_FOOTPRINT_DIR}/Battery.pretty\") (options \"\") (descr \"\"))\n"
332 ")\n";
333 out.WriteAll( contents, std::strlen( contents ) );
334 }
335
336 BOOST_REQUIRE_EQUAL( PCB_IO_MGR::GuessPluginTypeFromLibPath( table.GetFullPath() ),
338
339 // Migration appends the destination name as a .pretty directory; mirror that to confirm
340 // nothing is written for a nested table.
341 wxFileName outLib( table );
343
344 std::map<std::string, UTF8> props;
345
346 BOOST_CHECK( !PCB_IO_MGR::ConvertLibrary( props, table.GetFullPath(), outLib.GetFullPath(),
347 nullptr ) );
348
349 // DirExists() on a full path tests the directory portion.
350 BOOST_CHECK( !wxFileName::DirExists( outLib.GetFullPath() ) );
351
352 wxRemoveFile( table.GetFullPath() );
353}
354
355
General utilities for PCB file IO for QA programs.
const std::vector< ENTRY > & AllPlugins() const
Definition pcb_io_mgr.h:131
static PLUGIN_REGISTRY * Instance()
Definition pcb_io_mgr.h:97
static bool ConvertLibrary(const std::map< std::string, UTF8 > &aOldFileProps, const wxString &aOldFilePath, const wxString &aNewFilePath, REPORTER *aReporter)
Convert a schematic symbol library to the latest KiCad format.
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition pcb_io_mgr.h:52
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:54
@ ALTIUM_DESIGNER
Definition pcb_io_mgr.h:59
@ LEGACY
Legacy Pcbnew file formats prior to s-expression.
Definition pcb_io_mgr.h:55
@ CADSTAR_PCB_ARCHIVE
Definition pcb_io_mgr.h:60
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
static PCB_FILE_T FindPluginTypeFromBoardPath(const wxString &aFileName, int aCtl=0)
Return a plugin type given a path for a board file.
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a footprint library's libPath.
static const std::string KiCadFootprintLibPathExtension
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 GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
std::string m_file_rel_path
PCB_IO_MGR::PCB_FILE_T m_expected_type
friend std::ostream & operator<<(std::ostream &os, const PCB_IO_PLUGIN_CASE &aCase)
std::string m_case_name
BOOST_DATA_TEST_CASE(ConvertToKicadUnit, boost::unit_test::data::make(altium_to_kicad_unit), input_value, expected_result)
Test conversation from Altium internal units into KiCad internal units.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
static const std::vector< PCB_IO_PLUGIN_CASE > BoardPluginCases
BOOST_CHECK_EQUAL(PCB_IO_MGR::FindPluginTypeFromBoardPath(dataPath), c.m_expected_type)
auto & pluginEntries
static const std::vector< PCB_IO_PLUGIN_CASE > LibraryPluginCases
BOOST_TEST_CONTEXT("Test Clearance")
Definition of file extensions used in Kicad.