KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_backdrill_properties.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
24
#include <
qa_utils/wx_utils/unit_test_utils.h
>
25
26
#include <
padstack.h
>
27
#include <
layer_ids.h
>
28
#include <
base_units.h
>
29
30
// Regression tests for GitLab #23901. A backdrill's side is identified by its start layer
31
// (F_Cu = top, B_Cu = bottom), not by which drill slot it occupies. The accessors must read both
32
// the current layout and the one written by KiCad 10.0 (top backdrill in the tertiary slot), and
33
// must write start layers that older KiCad reads back correctly.
34
BOOST_AUTO_TEST_SUITE
( BackdrillProperties )
35
36
37
// Top backdrill -> secondary drill, start F_Cu.
38
BOOST_AUTO_TEST_CASE
( TopBackdrillUsesSecondaryDrill )
39
{
40
PADSTACK
stack(
nullptr
);
41
stack.
Drill
().
size
= {
pcbIUScale
.mmToIU( 0.4 ),
pcbIUScale
.mmToIU( 0.4 ) };
42
43
stack.
SetBackdrillMode
(
BACKDRILL_MODE::BACKDRILL_TOP
);
44
stack.
SetBackdrillSize
(
true
,
pcbIUScale
.mmToIU( 0.7 ) );
45
stack.
SetBackdrillEndLayer
(
true
,
In1_Cu
);
46
47
BOOST_CHECK( stack.
SecondaryDrill
().
size
.
x
> 0 );
48
BOOST_CHECK_EQUAL
( stack.
SecondaryDrill
().
start
,
F_Cu
);
49
BOOST_CHECK_EQUAL
( stack.
SecondaryDrill
().
end
,
In1_Cu
);
50
BOOST_CHECK_EQUAL
( stack.
TertiaryDrill
().
size
.
x
, 0 );
51
52
BOOST_CHECK( stack.
GetBackdrillMode
() ==
BACKDRILL_MODE::BACKDRILL_TOP
);
53
BOOST_CHECK_EQUAL
( stack.
GetBackdrillSize
(
true
).value_or( 0 ),
pcbIUScale
.mmToIU( 0.7 ) );
54
BOOST_CHECK_EQUAL
( stack.
GetBackdrillEndLayer
(
true
),
In1_Cu
);
55
}
56
57
58
// Bottom backdrill -> tertiary drill, start B_Cu.
59
BOOST_AUTO_TEST_CASE
( BottomBackdrillUsesTertiaryDrill )
60
{
61
PADSTACK
stack(
nullptr
);
62
stack.
Drill
().
size
= {
pcbIUScale
.mmToIU( 0.4 ),
pcbIUScale
.mmToIU( 0.4 ) };
63
64
stack.
SetBackdrillMode
(
BACKDRILL_MODE::BACKDRILL_BOTTOM
);
65
stack.
SetBackdrillSize
(
false
,
pcbIUScale
.mmToIU( 0.7 ) );
66
stack.
SetBackdrillEndLayer
(
false
,
In2_Cu
);
67
68
BOOST_CHECK( stack.
TertiaryDrill
().
size
.
x
> 0 );
69
BOOST_CHECK_EQUAL
( stack.
TertiaryDrill
().
start
,
B_Cu
);
70
BOOST_CHECK_EQUAL
( stack.
TertiaryDrill
().
end
,
In2_Cu
);
71
BOOST_CHECK_EQUAL
( stack.
SecondaryDrill
().
size
.
x
, 0 );
72
73
BOOST_CHECK( stack.
GetBackdrillMode
() ==
BACKDRILL_MODE::BACKDRILL_BOTTOM
);
74
BOOST_CHECK_EQUAL
( stack.
GetBackdrillSize
(
false
).value_or( 0 ),
pcbIUScale
.mmToIU( 0.7 ) );
75
BOOST_CHECK_EQUAL
( stack.
GetBackdrillEndLayer
(
false
),
In2_Cu
);
76
}
77
78
79
// Getters must read dialog-written slots back unchanged (no swap).
80
BOOST_AUTO_TEST_CASE
( DialogToPanelRoundTrip )
81
{
82
PADSTACK
stack(
nullptr
);
83
84
// What the dialog writes for a top + bottom backdrill.
85
PADSTACK::DRILL_PROPS
& secondary = stack.
SecondaryDrill
();
86
secondary.
size
= {
pcbIUScale
.mmToIU( 0.9 ),
pcbIUScale
.mmToIU( 0.9 ) };
87
secondary.
start
=
F_Cu
;
88
secondary.
end
=
In1_Cu
;
89
secondary.
shape
=
PAD_DRILL_SHAPE::CIRCLE
;
90
91
PADSTACK::DRILL_PROPS
& tertiary = stack.
TertiaryDrill
();
92
tertiary.
size
= {
pcbIUScale
.mmToIU( 0.7 ),
pcbIUScale
.mmToIU( 0.7 ) };
93
tertiary.
start
=
B_Cu
;
94
tertiary.
end
=
In2_Cu
;
95
tertiary.
shape
=
PAD_DRILL_SHAPE::CIRCLE
;
96
97
BOOST_CHECK( stack.
GetBackdrillMode
() ==
BACKDRILL_MODE::BACKDRILL_BOTH
);
98
99
BOOST_CHECK_EQUAL
( stack.
GetBackdrillSize
(
true
).value_or( 0 ),
pcbIUScale
.mmToIU( 0.9 ) );
100
BOOST_CHECK_EQUAL
( stack.
GetBackdrillEndLayer
(
true
),
In1_Cu
);
101
102
BOOST_CHECK_EQUAL
( stack.
GetBackdrillSize
(
false
).value_or( 0 ),
pcbIUScale
.mmToIU( 0.7 ) );
103
BOOST_CHECK_EQUAL
( stack.
GetBackdrillEndLayer
(
false
),
In2_Cu
);
104
}
105
106
107
// Re-editing a size must not jump slots or zero out.
108
BOOST_AUTO_TEST_CASE
( EditingSizePreservesSlotAndValue )
109
{
110
PADSTACK
stack(
nullptr
);
111
stack.
Drill
().
size
= {
pcbIUScale
.mmToIU( 0.4 ),
pcbIUScale
.mmToIU( 0.4 ) };
112
113
stack.
SetBackdrillMode
(
BACKDRILL_MODE::BACKDRILL_BOTTOM
);
114
stack.
SetBackdrillSize
(
false
,
pcbIUScale
.mmToIU( 0.7 ) );
115
stack.
SetBackdrillEndLayer
(
false
,
In2_Cu
);
116
117
stack.
SetBackdrillSize
(
false
,
pcbIUScale
.mmToIU( 0.8 ) );
118
119
BOOST_CHECK( stack.
GetBackdrillMode
() ==
BACKDRILL_MODE::BACKDRILL_BOTTOM
);
120
BOOST_CHECK_EQUAL
( stack.
GetBackdrillSize
(
false
).value_or( 0 ),
pcbIUScale
.mmToIU( 0.8 ) );
121
BOOST_CHECK_EQUAL
( stack.
GetBackdrillEndLayer
(
false
),
In2_Cu
);
122
BOOST_CHECK_EQUAL
( stack.
SecondaryDrill
().
size
.
x
, 0 );
123
}
124
125
126
// NO_BACKDRILL clears both slots.
127
BOOST_AUTO_TEST_CASE
( ClearingModeRemovesBackdrill )
128
{
129
PADSTACK
stack(
nullptr
);
130
stack.
Drill
().
size
= {
pcbIUScale
.mmToIU( 0.4 ),
pcbIUScale
.mmToIU( 0.4 ) };
131
132
stack.
SetBackdrillMode
(
BACKDRILL_MODE::BACKDRILL_TOP
);
133
stack.
SetBackdrillSize
(
true
,
pcbIUScale
.mmToIU( 0.7 ) );
134
135
stack.
SetBackdrillMode
(
BACKDRILL_MODE::NO_BACKDRILL
);
136
137
BOOST_CHECK( stack.
GetBackdrillMode
() ==
BACKDRILL_MODE::NO_BACKDRILL
);
138
BOOST_CHECK_EQUAL
( stack.
SecondaryDrill
().
size
.
x
, 0 );
139
BOOST_CHECK_EQUAL
( stack.
TertiaryDrill
().
size
.
x
, 0 );
140
}
141
142
143
// Seed a padstack the way KiCad 10.0 wrote it: top backdrill in the tertiary slot (start F_Cu),
144
// bottom backdrill in the secondary slot (start B_Cu). The accessors must read each side from the
145
// slot carrying the matching start layer, not from a fixed slot position.
146
BOOST_AUTO_TEST_CASE
( ReadsLegacyV10SlotLayout )
147
{
148
PADSTACK
stack(
nullptr
);
149
150
PADSTACK::DRILL_PROPS
& secondary = stack.
SecondaryDrill
();
151
secondary.
size
= {
pcbIUScale
.mmToIU( 0.8 ),
pcbIUScale
.mmToIU( 0.8 ) };
152
secondary.
start
=
B_Cu
;
153
secondary.
end
=
In2_Cu
;
154
secondary.
shape
=
PAD_DRILL_SHAPE::CIRCLE
;
155
156
PADSTACK::DRILL_PROPS
& tertiary = stack.
TertiaryDrill
();
157
tertiary.
size
= {
pcbIUScale
.mmToIU( 0.6 ),
pcbIUScale
.mmToIU( 0.6 ) };
158
tertiary.
start
=
F_Cu
;
159
tertiary.
end
=
In1_Cu
;
160
tertiary.
shape
=
PAD_DRILL_SHAPE::CIRCLE
;
161
162
BOOST_CHECK( stack.
GetBackdrillMode
() ==
BACKDRILL_MODE::BACKDRILL_BOTH
);
163
164
BOOST_CHECK_EQUAL
( stack.
GetBackdrillSize
(
true
).value_or( 0 ),
pcbIUScale
.mmToIU( 0.6 ) );
165
BOOST_CHECK_EQUAL
( stack.
GetBackdrillEndLayer
(
true
),
In1_Cu
);
166
167
BOOST_CHECK_EQUAL
( stack.
GetBackdrillSize
(
false
).value_or( 0 ),
pcbIUScale
.mmToIU( 0.8 ) );
168
BOOST_CHECK_EQUAL
( stack.
GetBackdrillEndLayer
(
false
),
In2_Cu
);
169
}
170
171
172
// A 10.0 top-only backdrill lives in the tertiary slot; it must read as a top backdrill, not a
173
// bottom one (the slot-position reading regressed exactly this case).
174
BOOST_AUTO_TEST_CASE
( ReadsLegacyV10TopOnly )
175
{
176
PADSTACK
stack(
nullptr
);
177
178
PADSTACK::DRILL_PROPS
& tertiary = stack.
TertiaryDrill
();
179
tertiary.
size
= {
pcbIUScale
.mmToIU( 0.6 ),
pcbIUScale
.mmToIU( 0.6 ) };
180
tertiary.
start
=
F_Cu
;
181
tertiary.
end
=
In1_Cu
;
182
tertiary.
shape
=
PAD_DRILL_SHAPE::CIRCLE
;
183
184
BOOST_CHECK( stack.
GetBackdrillMode
() ==
BACKDRILL_MODE::BACKDRILL_TOP
);
185
BOOST_CHECK_EQUAL
( stack.
GetBackdrillSize
(
true
).value_or( 0 ),
pcbIUScale
.mmToIU( 0.6 ) );
186
BOOST_CHECK_EQUAL
( stack.
GetBackdrillEndLayer
(
true
),
In1_Cu
);
187
BOOST_CHECK( !stack.
GetBackdrillSize
(
false
).has_value() );
188
}
189
190
191
// Editing a 10.0 top-only backdrill must update it in place (in the tertiary slot it already
192
// occupies) and keep the F_Cu start layer, so the result stays readable by older KiCad and no
193
// duplicate top backdrill appears in the secondary slot.
194
BOOST_AUTO_TEST_CASE
( EditingLegacyBackdrillStaysInPlaceAndReadable )
195
{
196
PADSTACK
stack(
nullptr
);
197
198
PADSTACK::DRILL_PROPS
& tertiary = stack.
TertiaryDrill
();
199
tertiary.
size
= {
pcbIUScale
.mmToIU( 0.6 ),
pcbIUScale
.mmToIU( 0.6 ) };
200
tertiary.
start
=
F_Cu
;
201
tertiary.
end
=
In1_Cu
;
202
tertiary.
shape
=
PAD_DRILL_SHAPE::CIRCLE
;
203
204
stack.
SetBackdrillSize
(
true
,
pcbIUScale
.mmToIU( 0.75 ) );
205
206
BOOST_CHECK_EQUAL
( stack.
TertiaryDrill
().
size
.
x
,
pcbIUScale
.mmToIU( 0.75 ) );
207
BOOST_CHECK_EQUAL
( stack.
TertiaryDrill
().
start
,
F_Cu
);
208
BOOST_CHECK_EQUAL
( stack.
SecondaryDrill
().
size
.
x
, 0 );
209
210
BOOST_CHECK( stack.
GetBackdrillMode
() ==
BACKDRILL_MODE::BACKDRILL_TOP
);
211
BOOST_CHECK_EQUAL
( stack.
GetBackdrillSize
(
true
).value_or( 0 ),
pcbIUScale
.mmToIU( 0.75 ) );
212
}
213
214
215
// Clearing the must-cut layer removes the backdrill: a sized drill with no must-cut does not
216
// exist (the via layer sanitizer enforces the same rule).
217
BOOST_AUTO_TEST_CASE
( ClearingMustCutRemovesBackdrill )
218
{
219
PADSTACK
stack(
nullptr
);
220
stack.
Drill
().
size
= {
pcbIUScale
.mmToIU( 0.4 ),
pcbIUScale
.mmToIU( 0.4 ) };
221
222
stack.
SetBackdrillMode
(
BACKDRILL_MODE::BACKDRILL_TOP
);
223
stack.
SetBackdrillSize
(
true
,
pcbIUScale
.mmToIU( 0.7 ) );
224
stack.
SetBackdrillEndLayer
(
true
,
In1_Cu
);
225
226
stack.
SetBackdrillEndLayer
(
true
,
UNDEFINED_LAYER
);
227
228
BOOST_CHECK( stack.
GetBackdrillMode
() ==
BACKDRILL_MODE::NO_BACKDRILL
);
229
BOOST_CHECK( !stack.
GetBackdrillSize
(
true
).has_value() );
230
BOOST_CHECK_EQUAL
( stack.
SecondaryDrill
().
size
.
x
, 0 );
231
}
232
233
234
// A malformed padstack with the same side duplicated across both slots must be fully cleared, not
235
// left with a surviving duplicate that re-asserts the backdrill.
236
BOOST_AUTO_TEST_CASE
( ClearingCollapsesDuplicateSideSlots )
237
{
238
PADSTACK
stack(
nullptr
);
239
240
PADSTACK::DRILL_PROPS
& secondary = stack.
SecondaryDrill
();
241
secondary.
size
= {
pcbIUScale
.mmToIU( 0.7 ),
pcbIUScale
.mmToIU( 0.7 ) };
242
secondary.
start
=
F_Cu
;
243
secondary.
end
=
In1_Cu
;
244
secondary.
shape
=
PAD_DRILL_SHAPE::CIRCLE
;
245
246
PADSTACK::DRILL_PROPS
& tertiary = stack.
TertiaryDrill
();
247
tertiary.
size
= {
pcbIUScale
.mmToIU( 0.6 ),
pcbIUScale
.mmToIU( 0.6 ) };
248
tertiary.
start
=
F_Cu
;
249
tertiary.
end
=
In1_Cu
;
250
tertiary.
shape
=
PAD_DRILL_SHAPE::CIRCLE
;
251
252
stack.
SetBackdrillSize
(
true
, std::nullopt );
253
254
BOOST_CHECK_EQUAL
( stack.
SecondaryDrill
().
size
.
x
, 0 );
255
BOOST_CHECK_EQUAL
( stack.
TertiaryDrill
().
size
.
x
, 0 );
256
BOOST_CHECK( stack.
GetBackdrillMode
() ==
BACKDRILL_MODE::NO_BACKDRILL
);
257
}
258
259
260
BOOST_AUTO_TEST_SUITE_END
()
base_units.h
pcbIUScale
constexpr EDA_IU_SCALE pcbIUScale
Definition
base_units.h:121
PADSTACK
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
Definition
padstack.h:157
PADSTACK::SetBackdrillMode
void SetBackdrillMode(BACKDRILL_MODE aMode)
Definition
padstack.cpp:539
PADSTACK::SetBackdrillSize
void SetBackdrillSize(bool aTop, std::optional< int > aSize)
Definition
padstack.cpp:572
PADSTACK::TertiaryDrill
DRILL_PROPS & TertiaryDrill()
Definition
padstack.h:357
PADSTACK::Drill
DRILL_PROPS & Drill()
Definition
padstack.h:351
PADSTACK::SetBackdrillEndLayer
void SetBackdrillEndLayer(bool aTop, PCB_LAYER_ID aLayer)
Definition
padstack.cpp:597
PADSTACK::GetBackdrillSize
std::optional< int > GetBackdrillSize(bool aTop) const
Definition
padstack.cpp:563
PADSTACK::GetBackdrillMode
BACKDRILL_MODE GetBackdrillMode() const
Definition
padstack.cpp:521
PADSTACK::SecondaryDrill
DRILL_PROPS & SecondaryDrill()
Definition
padstack.h:354
PADSTACK::GetBackdrillEndLayer
PCB_LAYER_ID GetBackdrillEndLayer(bool aTop) const
Definition
padstack.cpp:588
VECTOR2::x
T x
Definition
vector2d.h:75
layer_ids.h
B_Cu
@ B_Cu
Definition
layer_ids.h:61
In2_Cu
@ In2_Cu
Definition
layer_ids.h:63
UNDEFINED_LAYER
@ UNDEFINED_LAYER
Definition
layer_ids.h:57
In1_Cu
@ In1_Cu
Definition
layer_ids.h:62
F_Cu
@ F_Cu
Definition
layer_ids.h:60
padstack.h
PAD_DRILL_SHAPE::CIRCLE
@ CIRCLE
Definition
padstack.h:71
BACKDRILL_MODE::BACKDRILL_TOP
@ BACKDRILL_TOP
Definition
padstack.h:87
BACKDRILL_MODE::BACKDRILL_BOTTOM
@ BACKDRILL_BOTTOM
Definition
padstack.h:86
BACKDRILL_MODE::BACKDRILL_BOTH
@ BACKDRILL_BOTH
Definition
padstack.h:88
BACKDRILL_MODE::NO_BACKDRILL
@ NO_BACKDRILL
Definition
padstack.h:85
PADSTACK::DRILL_PROPS
! The properties of a padstack drill. Drill position is always the pad position (origin).
Definition
padstack.h:266
PADSTACK::DRILL_PROPS::start
PCB_LAYER_ID start
Definition
padstack.h:269
PADSTACK::DRILL_PROPS::end
PCB_LAYER_ID end
Definition
padstack.h:270
PADSTACK::DRILL_PROPS::size
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
Definition
padstack.h:267
PADSTACK::DRILL_PROPS::shape
PAD_DRILL_SHAPE shape
Definition
padstack.h:268
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
Definition
test_api_enums.cpp:71
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(TopBackdrillUsesSecondaryDrill)
Definition
test_backdrill_properties.cpp:38
BOOST_AUTO_TEST_SUITE
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_EQUAL
BOOST_CHECK_EQUAL(result, "25.4")
unit_test_utils.h
src
qa
tests
pcbnew
test_backdrill_properties.cpp
Generated on Tue Jul 7 2026 00:07:29 for KiCad PCB EDA Suite by
1.13.2