KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_fabmaster_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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
28
32
34
35#include <board.h>
36#include <footprint.h>
37#include <pad.h>
38#include <padstack.h>
39#include <zone.h>
40
41
48
49
50BOOST_FIXTURE_TEST_SUITE( FabmasterImport, FABMASTER_IMPORT_FIXTURE )
51
52
53
62BOOST_AUTO_TEST_CASE( EmptyRefdesInPins )
63{
64 std::string dataPath =
65 KI_TEST::GetPcbnewTestDataDir() + "plugins/fabmaster/cds2f_only_2_comp.txt";
66
67 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
68
69 m_fabmasterPlugin.LoadBoard( dataPath, board.get(), nullptr );
70
71 BOOST_REQUIRE( board );
72
73 // The board should have footprints
74 BOOST_REQUIRE_GT( board->Footprints().size(), 0 );
75
76 // Each footprint should have pads (before the fix, pads were missing because
77 // the lookup by empty REFDES failed)
78 int totalPads = 0;
79
80 for( const FOOTPRINT* fp : board->Footprints() )
81 {
82 totalPads += fp->Pads().size();
83 }
84
85 BOOST_CHECK_MESSAGE( totalPads > 0,
86 "Footprints should have pads when REFDES is empty in PIN section" );
87}
88
89
101BOOST_AUTO_TEST_CASE( StaticShapesPreserved )
102{
103 std::string dataPath =
104 KI_TEST::GetPcbnewTestDataDir() + "plugins/fabmaster/cds2f_14066-20316FBRD.txt";
105
106 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
107
108 m_fabmasterPlugin.LoadBoard( dataPath, board.get(), nullptr );
109
110 BOOST_REQUIRE( board );
111
112 // Count zones - static shapes should be preserved as zones with net codes
113 int zonesWithNets = 0;
114
115 for( ZONE* zone : board->Zones() )
116 {
117 if( zone->GetNetCode() > 0 )
118 zonesWithNets++;
119 }
120
121 // The board should have some zones with nets assigned (static shapes).
122 // Before the fix, all netted zones were deleted because they were considered
123 // redundant fills. With the fix, unmatched static shapes are preserved.
124 BOOST_CHECK_MESSAGE( zonesWithNets > 0,
125 "Static shape zones with nets should be preserved" );
126}
127
128
132static const PAD* findPadByNumber( const FOOTPRINT* aFp, const wxString& aNumber )
133{
134 for( const PAD* pad : aFp->Pads() )
135 {
136 if( pad->GetNumber() == aNumber )
137 return pad;
138 }
139
140 return nullptr;
141}
142
143
153BOOST_AUTO_TEST_CASE( PadStackDifferentLayers )
154{
155 std::string dataPath =
156 KI_TEST::GetPcbnewTestDataDir() + "plugins/fabmaster/cds2f_padstack_test.txt";
157
158 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
159
160 m_fabmasterPlugin.LoadBoard( dataPath, board.get(), nullptr );
161
162 BOOST_REQUIRE( board );
163 BOOST_REQUIRE_GT( board->Footprints().size(), 0 );
164
165 const FOOTPRINT* fp = board->Footprints().front();
166 BOOST_REQUIRE_EQUAL( fp->Pads().size(), 3 );
167
168 // Pin 1 uses DIFF_PAD which has CIRCLE on TOP and RECTANGLE on BOTTOM.
169 // This should use FRONT_INNER_BACK padstack mode.
170 const PAD* pad1 = findPadByNumber( fp, wxT( "1" ) );
171 BOOST_REQUIRE( pad1 );
172 BOOST_CHECK_EQUAL( static_cast<int>( pad1->Padstack().Mode() ),
173 static_cast<int>( PADSTACK::MODE::FRONT_INNER_BACK ) );
174 BOOST_CHECK_EQUAL( static_cast<int>( pad1->GetShape( F_Cu ) ),
175 static_cast<int>( PAD_SHAPE::CIRCLE ) );
176 BOOST_CHECK_EQUAL( static_cast<int>( pad1->GetShape( B_Cu ) ),
177 static_cast<int>( PAD_SHAPE::RECTANGLE ) );
178
179 // Verify front layer size (2.0mm circle)
180 VECTOR2I pad1_front_size = pad1->GetSize( F_Cu );
181 BOOST_CHECK_GT( pad1_front_size.x, 0 );
182 BOOST_CHECK_EQUAL( pad1_front_size.x, pad1_front_size.y );
183
184 // Verify back layer size (1.5x3.0mm rectangle, height > width)
185 VECTOR2I pad1_back_size = pad1->GetSize( B_Cu );
186 BOOST_CHECK_GT( pad1_back_size.x, 0 );
187 BOOST_CHECK_GT( pad1_back_size.y, pad1_back_size.x );
188
189 // Verify drill is present
190 BOOST_CHECK_EQUAL( static_cast<int>( pad1->GetAttribute() ),
191 static_cast<int>( PAD_ATTRIB::PTH ) );
192 BOOST_CHECK_GT( pad1->GetDrillSizeX(), 0 );
193}
194
195
199BOOST_AUTO_TEST_CASE( PadStackSameLayers )
200{
201 std::string dataPath =
202 KI_TEST::GetPcbnewTestDataDir() + "plugins/fabmaster/cds2f_padstack_test.txt";
203
204 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
205
206 m_fabmasterPlugin.LoadBoard( dataPath, board.get(), nullptr );
207
208 BOOST_REQUIRE( board );
209 BOOST_REQUIRE_GT( board->Footprints().size(), 0 );
210
211 const FOOTPRINT* fp = board->Footprints().front();
212
213 // Pin 2 uses SAME_PAD which has RECTANGLE 1.0x2.0 on both TOP and BOTTOM.
214 // This should stay in NORMAL mode since shapes are identical.
215 const PAD* pad2 = findPadByNumber( fp, wxT( "2" ) );
216 BOOST_REQUIRE( pad2 );
217 BOOST_CHECK_EQUAL( static_cast<int>( pad2->Padstack().Mode() ),
218 static_cast<int>( PADSTACK::MODE::NORMAL ) );
219 BOOST_CHECK_EQUAL( static_cast<int>( pad2->GetShape( F_Cu ) ),
220 static_cast<int>( PAD_SHAPE::RECTANGLE ) );
221}
222
223
227BOOST_AUTO_TEST_CASE( PadStackSmdPad )
228{
229 std::string dataPath =
230 KI_TEST::GetPcbnewTestDataDir() + "plugins/fabmaster/cds2f_padstack_test.txt";
231
232 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
233
234 m_fabmasterPlugin.LoadBoard( dataPath, board.get(), nullptr );
235
236 BOOST_REQUIRE( board );
237 BOOST_REQUIRE_GT( board->Footprints().size(), 0 );
238
239 const FOOTPRINT* fp = board->Footprints().front();
240
241 // Pin 3 uses SMD_DIFF which is an OVAL on TOP only (no BOTTOM pad, no drill).
242 const PAD* pad3 = findPadByNumber( fp, wxT( "3" ) );
243 BOOST_REQUIRE( pad3 );
244 BOOST_CHECK_EQUAL( static_cast<int>( pad3->GetAttribute() ),
245 static_cast<int>( PAD_ATTRIB::SMD ) );
246 BOOST_CHECK_EQUAL( static_cast<int>( pad3->GetShape( F_Cu ) ),
247 static_cast<int>( PAD_SHAPE::OVAL ) );
248}
249
250
General utilities for PCB file IO for QA programs.
std::deque< PAD * > & Pads()
Definition footprint.h:377
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:171
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
Definition padstack.h:172
MODE Mode() const
Definition padstack.h:335
Definition pad.h:65
PAD_ATTRIB GetAttribute() const
Definition pad.h:583
int GetDrillSizeX() const
Definition pad.h:339
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:206
const PADSTACK & Padstack() const
Definition pad.h:353
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
Definition pad.h:274
Handle a list of polygons defining a copper zone.
Definition zone.h:74
@ B_Cu
Definition layer_ids.h:65
@ F_Cu
Definition layer_ids.h:64
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:99
@ PTH
Plated through hole pad.
Definition padstack.h:98
@ RECTANGLE
Definition padstack.h:54
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
static const PAD * findPadByNumber(const FOOTPRINT *aFp, const wxString &aNumber)
Helper to find a pad by its number within a footprint.
BOOST_AUTO_TEST_CASE(EmptyRefdesInPins)
Test that footprints with pads are properly imported when the REFDES column is empty in the PIN secti...
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687