KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_eagle_binary_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
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
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
24
28
30
31#include <board.h>
32#include <footprint.h>
33#include <netinfo.h>
34#include <pcb_text.h>
35#include <pcb_track.h>
36#include <zone.h>
37
38#include <map>
39#include <set>
40
41#include <wx/filename.h>
42
43
45{
47
48 BOARD* loadBoard( const std::string& aRelPath )
49 {
50 std::string dataPath = KI_TEST::GetPcbnewTestDataDir() + aRelPath;
51
52 if( !wxFileName::FileExists( dataPath ) )
53 {
54 BOOST_TEST_MESSAGE( "no real binary Eagle sample available at " + dataPath + "; load test skipped" );
55 return nullptr;
56 }
57
58 PCB_IO_EAGLE eaglePlugin;
59
60 // The binary format is identified by content, never by extension.
61 BOOST_CHECK( eaglePlugin.CanReadBoard( dataPath ) );
62
63 BOARD* board = nullptr;
64
65 try
66 {
67 board = eaglePlugin.LoadBoard( dataPath, nullptr, nullptr );
68 }
69 catch( const IO_ERROR& e )
70 {
71 BOOST_FAIL( "IO_ERROR loading binary Eagle board: " + e.What().ToStdString() );
72 }
73 catch( const std::exception& e )
74 {
75 BOOST_FAIL( std::string( "Exception loading binary Eagle board: " ) + e.what() );
76 }
77
78 return board;
79 }
80};
81
82
83BOOST_FIXTURE_TEST_SUITE( EagleBinaryImport, EAGLE_BINARY_IMPORT_FIXTURE )
84
85
86
91BOOST_AUTO_TEST_CASE( LoadBinaryV4V5 )
92{
93 std::unique_ptr<BOARD> board( loadBoard( "plugins/eagle_binary/blink1_b1a.brd" ) );
94
95 if( !board )
96 return;
97
98 BOOST_CHECK_GT( board->Footprints().size(), 0u );
99 BOOST_CHECK_GT( board->Tracks().size(), 0u );
100 BOOST_CHECK_GT( board->GetNetInfo().GetNetCount(), 1u );
101}
102
103
109BOOST_AUTO_TEST_CASE( LoadBinaryV3 )
110{
111 std::unique_ptr<BOARD> board( loadBoard( "plugins/eagle_binary/blink1_v1a.brd" ) );
112
113 if( !board )
114 return;
115
116 BOOST_CHECK_GT( board->Footprints().size(), 0u );
117 BOOST_CHECK_GT( board->Tracks().size(), 0u );
118}
119
120
127BOOST_AUTO_TEST_CASE( LoadV3CustomAttributes )
128{
129 std::unique_ptr<BOARD> board( loadBoard( "plugins/eagle_binary/rocketgps.brd" ) );
130
131 if( !board )
132 return;
133
134 BOOST_CHECK_GT( board->Footprints().size(), 0u );
135 BOOST_CHECK_GT( board->Tracks().size(), 0u );
136 BOOST_CHECK_GT( board->GetNetInfo().GetNetCount(), 1u );
137}
138
139
147BOOST_AUTO_TEST_CASE( LoadV3UnnamedSignals )
148{
149 std::unique_ptr<BOARD> board( loadBoard( "plugins/eagle_binary/boomchak.brd" ) );
150
151 if( !board )
152 return;
153
154 BOOST_CHECK_GT( board->Footprints().size(), 0u );
155 BOOST_CHECK_GT( board->Tracks().size(), 0u );
156 BOOST_CHECK_GT( board->GetNetInfo().GetNetCount(), 1u );
157
158 // Every routed item must resolve to a real net; an orphaned net code would
159 // have aborted the load before this point.
160 for( PCB_TRACK* track : board->Tracks() )
161 BOOST_CHECK( track->GetNet() != nullptr );
162}
163
164
170BOOST_AUTO_TEST_CASE( LoadV4V5DegeneratePolygons )
171{
172 std::unique_ptr<BOARD> board( loadBoard( "plugins/eagle_binary/turnemoff.brd" ) );
173
174 if( !board )
175 return;
176
177 BOOST_CHECK_GT( board->Footprints().size(), 0u );
178 BOOST_CHECK_GT( board->Tracks().size(), 0u );
179}
180
181
190BOOST_AUTO_TEST_CASE( LoadBinaryLongText )
191{
192 std::unique_ptr<BOARD> board( loadBoard( "plugins/eagle_binary/issue24612_nova_usbbox.brd" ) );
193
194 if( !board )
195 return;
196
197 BOOST_CHECK_GT( board->Footprints().size(), 0u );
198 BOOST_CHECK_GT( board->Tracks().size(), 0u );
199
200 std::set<wxString> texts;
201
202 for( BOARD_ITEM* item : board->Drawings() )
203 {
204 if( PCB_TEXT* text = dynamic_cast<PCB_TEXT*>( item ) )
205 texts.insert( text->GetText() );
206 }
207
208 BOOST_CHECK( texts.count( wxS( "ASTROELEKTRONIK" ) ) );
209 BOOST_CHECK( texts.count( wxS( "Nova+ USB-Box" ) ) );
210}
211
212
221BOOST_AUTO_TEST_CASE( LoadV3RecursiveCountOverrun )
222{
223 std::unique_ptr<BOARD> board( loadBoard( "plugins/eagle_binary/Sigma2_e.brd" ) );
224
225 if( !board )
226 return;
227
228 BOOST_CHECK_GT( board->Footprints().size(), 0u );
229 BOOST_CHECK_GT( board->Tracks().size(), 0u );
230 BOOST_CHECK_GT( board->GetNetInfo().GetNetCount(), 1u );
231}
232
233
241BOOST_AUTO_TEST_CASE( LoadV3FootprintRotationRing )
242{
243 std::unique_ptr<BOARD> board( loadBoard( "plugins/eagle_binary/boomchak.brd" ) );
244
245 if( !board )
246 return;
247
248 std::map<int, double> ledRot;
249
250 for( FOOTPRINT* fp : board->Footprints() )
251 {
252 long n = 0;
253
254 if( fp->GetReference().StartsWith( wxS( "LED" ) ) && fp->GetReference().Mid( 3 ).ToLong( &n ) )
255 ledRot[(int) n] = fp->GetOrientation().AsDegrees();
256 }
257
258 for( int n = 1; n < 16; n++ )
259 {
260 BOOST_REQUIRE_MESSAGE( ledRot.count( n ) && ledRot.count( n + 1 ),
261 "expected ring footprints LED" << n << " and LED" << ( n + 1 ) );
262
263 double step = ledRot[n + 1] - ledRot[n];
264
265 while( step > 180.0 )
266 step -= 360.0;
267
268 while( step <= -180.0 )
269 step += 360.0;
270
271 BOOST_CHECK_CLOSE( step, 22.5, 0.5 );
272 }
273}
274
275
285BOOST_AUTO_TEST_CASE( LoadDropsUnmappedLayers )
286{
287 auto invalidLayerItems = []( BOARD* board )
288 {
289 auto bad = []( PCB_LAYER_ID l ) { return (int) l < 0 || (int) l >= PCB_LAYER_ID_COUNT; };
290
291 int count = 0;
292
293 for( BOARD_ITEM* item : board->Drawings() )
294 count += bad( item->GetLayer() );
295
296 for( PCB_TRACK* track : board->Tracks() )
297 count += bad( track->GetLayer() );
298
299 for( FOOTPRINT* fp : board->Footprints() )
300 {
301 for( BOARD_ITEM* item : fp->GraphicalItems() )
302 count += bad( item->GetLayer() );
303 }
304
305 return count;
306 };
307
308 auto ruleAreas = []( BOARD* board )
309 {
310 int count = 0;
311
312 for( ZONE* zone : board->Zones() )
313 count += zone->GetIsRuleArea();
314
315 return count;
316 };
317
318 for( const char* relPath : { "plugins/eagle_binary/boomchak.brd",
319 "plugins/eagle_binary/turnemoff.brd" } )
320 {
321 std::unique_ptr<BOARD> board( loadBoard( relPath ) );
322
323 if( !board )
324 continue;
325
326 BOOST_CHECK_EQUAL( invalidLayerItems( board.get() ), 0 );
327 }
328
329 // turnemoff carries hundreds of via-keepout rectangles on the vRestrict layer; the
330 // unmapped-layer handling must keep them as rule areas, not drop them along with the
331 // unmappable graphics.
332 std::unique_ptr<BOARD> turnemoff( loadBoard( "plugins/eagle_binary/turnemoff.brd" ) );
333
334 if( turnemoff )
335 BOOST_CHECK_GT( ruleAreas( turnemoff.get() ), 500 );
336}
337
338
General utilities for PCB file IO for QA programs.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:81
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
virtual const char * what() const override
std::exception interface, returned as UTF-8
Works with Eagle 6.x XML board files and footprints to implement the Pcbnew #PLUGIN API or a portion ...
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
bool CanReadBoard(const wxString &aFileName) const override
Checks if this PCB_IO can read the specified board file.
Handle a list of polygons defining a copper zone.
Definition zone.h:70
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ PCB_LAYER_ID_COUNT
Definition layer_ids.h:167
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
BOARD * loadBoard(const std::string &aRelPath)
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_CASE(LoadBinaryV4V5)
Load a v4/v5 binary board (magic 0x10 0x00) which also carries the trailing free-text and DRC section...
BOOST_AUTO_TEST_SUITE_END()
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
BOOST_CHECK_EQUAL(result, "25.4")