KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_custom_property_roundtrip.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 3
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
21#include <qa_utils/file_utils.h>
22
23#include <board.h>
24#include <footprint.h>
25#include <pad.h>
26#include <pcb_dimension.h>
27#include <pcb_drill_chart.h>
28#include <pcb_drill_map.h>
29#include <pcb_field.h>
30#include <pcb_group.h>
31#include <pcb_shape.h>
32#include <pcb_table.h>
33#include <pcb_tablecell.h>
34#include <pcb_target.h>
35#include <pcb_text.h>
36#include <pcb_textbox.h>
37#include <pcb_track.h>
38#include <zone.h>
40
41#include <filesystem>
42#include <map>
43
44
45namespace
46{
47
48VECTOR2I mm( double aX, double aY )
49{
50 return VECTOR2I( pcbIUScale.mmToIU( aX ), pcbIUScale.mmToIU( aY ) );
51}
52
53
54void buildBoard( BOARD& aBoard )
55{
56 PCB_TRACK* segment = new PCB_TRACK( &aBoard );
57 segment->SetLayer( F_Cu );
58 segment->SetStart( mm( 0, 0 ) );
59 segment->SetEnd( mm( 5, 0 ) );
60 segment->SetWidth( pcbIUScale.mmToIU( 0.25 ) );
61 aBoard.Add( segment );
62
63 PCB_ARC* arc = new PCB_ARC( &aBoard );
64 arc->SetLayer( F_Cu );
65 arc->SetStart( mm( 5, 0 ) );
66 arc->SetMid( mm( 7, 2 ) );
67 arc->SetEnd( mm( 9, 0 ) );
68 arc->SetWidth( pcbIUScale.mmToIU( 0.25 ) );
69 aBoard.Add( arc );
70
71 PCB_VIA* via = new PCB_VIA( &aBoard );
72 via->SetPosition( mm( 9, 0 ) );
73 via->SetLayerPair( F_Cu, B_Cu );
74 via->SetDrill( pcbIUScale.mmToIU( 0.3 ) );
75 via->SetWidth( PADSTACK::ALL_LAYERS, pcbIUScale.mmToIU( 0.6 ) );
76 aBoard.Add( via );
77
78 FOOTPRINT* fp = new FOOTPRINT( &aBoard );
79 fp->SetPosition( mm( 20, 0 ) );
80 fp->SetReference( wxS( "U1" ) );
81
82 PCB_FIELD* userField = new PCB_FIELD( fp, FIELD_T::USER, wxS( "Supplier" ) );
83 userField->SetText( wxS( "ACME" ) );
84 userField->SetLayer( F_Fab );
85 fp->Add( userField );
86
87 PAD* pad = new PAD( fp );
88 pad->SetPosition( mm( 20, 0 ) );
89 pad->SetSize( PADSTACK::ALL_LAYERS, mm( 1, 1 ) );
90 fp->Add( pad );
91
92 PCB_TEXT* fpText = new PCB_TEXT( fp );
93 fpText->SetText( wxS( "fp text" ) );
94 fpText->SetLayer( F_SilkS );
95 fp->Add( fpText );
96 aBoard.Add( fp );
97
98 PCB_SHAPE* shape = new PCB_SHAPE( &aBoard, SHAPE_T::SEGMENT );
99 shape->SetLayer( Edge_Cuts );
100 shape->SetStart( mm( 0, 10 ) );
101 shape->SetEnd( mm( 10, 10 ) );
102 aBoard.Add( shape );
103
104 PCB_TEXT* text = new PCB_TEXT( &aBoard );
105 text->SetText( wxS( "board text" ) );
106 text->SetLayer( F_SilkS );
107 aBoard.Add( text );
108
109 PCB_TEXTBOX* textbox = new PCB_TEXTBOX( &aBoard );
110 textbox->SetText( wxS( "box" ) );
111 textbox->SetLayer( F_SilkS );
112 textbox->SetStart( mm( 0, 20 ) );
113 textbox->SetEnd( mm( 5, 25 ) );
114 aBoard.Add( textbox );
115
116 PCB_DIM_ALIGNED* dimension = new PCB_DIM_ALIGNED( &aBoard );
117 dimension->SetLayer( Cmts_User );
118 dimension->SetStart( mm( 0, 30 ) );
119 dimension->SetEnd( mm( 10, 30 ) );
120 aBoard.Add( dimension );
121
122 PCB_TARGET* target = new PCB_TARGET( &aBoard );
123 target->SetLayer( Edge_Cuts );
124 target->SetPosition( mm( 30, 30 ) );
125 aBoard.Add( target );
126
127 ZONE* zone = new ZONE( &aBoard );
128 zone->SetLayer( F_Cu );
129 zone->AppendCorner( mm( 40, 0 ), -1 );
130 zone->AppendCorner( mm( 45, 0 ), -1 );
131 zone->AppendCorner( mm( 45, 5 ), -1 );
132 aBoard.Add( zone );
133
134 PCB_TABLE* table = new PCB_TABLE( &aBoard, 0 );
135 table->SetLayer( F_SilkS );
136 table->SetColCount( 1 );
137 table->AddCell( new PCB_TABLECELL( table ) );
138 aBoard.Add( table );
139
140 PCB_DRILL_MAP* map = new PCB_DRILL_MAP( &aBoard );
141 map->SetLayer( User_1 );
142 aBoard.Add( map );
143
144 PCB_DRILL_CHART* chart = new PCB_DRILL_CHART( &aBoard );
145 chart->SetLayer( User_2 );
146 aBoard.Add( chart );
147 chart->RebuildCells( aBoard );
148
149 PCB_GROUP* group = new PCB_GROUP( &aBoard );
150 group->AddItem( text );
151 aBoard.Add( group );
152}
153
154} // namespace
155
156
157BOOST_AUTO_TEST_SUITE( CustomPropertyRoundTrip )
158
159
160BOOST_AUTO_TEST_CASE( EveryBoardItemKeepsItsCustomProperty )
161{
162 BOARD board;
163 buildBoard( board );
164
165 // Keyed by uuid so a property that lands on the wrong item still fails
166 std::map<KIID, wxString> expected;
167
168 board.RunOnChildren(
169 [&]( BOARD_ITEM* aItem )
170 {
171 // Chart cells are regenerated from the board, not loaded
172 if( aItem->Type() == PCB_TABLECELL_T && aItem->GetParent()->Type() == PCB_DRILL_CHART_T )
173 return;
174
175 aItem->SetCustomProperty( wxS( "qa" ), aItem->m_Uuid.AsString() );
176 expected[aItem->m_Uuid] = aItem->GetClass();
177 },
179
180 KI_TEST::SCOPED_TEMP_DIR tempDir( "kicad_qa_custom_property" );
181 const std::filesystem::path path = tempDir.Path() / "custom_property.kicad_pcb";
182
184 std::unique_ptr<BOARD> restored = KI_TEST::ReadBoardFromFileOrStream( path.string() );
185 BOOST_REQUIRE( restored );
186
187 std::map<KIID, wxString> found;
188
189 restored->RunOnChildren(
190 [&]( BOARD_ITEM* aItem )
191 {
192 wxString value;
193
194 if( aItem->GetCustomProperty( wxS( "qa" ), value ) && value == aItem->m_Uuid.AsString() )
195 found[aItem->m_Uuid] = aItem->GetClass();
196 },
198
199 for( const auto& [uuid, className] : expected )
200 {
201 BOOST_TEST_CONTEXT( className )
202 {
203 BOOST_CHECK( found.contains( uuid ) );
204 }
205 }
206}
207
208
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
General utilities for PCB file IO for QA programs.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:374
BOARD_ITEM_CONTAINER * GetParent() const
Definition board_item.h:266
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:410
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1524
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
Definition board.cpp:848
bool GetCustomProperty(const wxString &aKey, wxString &aValue) const
Definition eda_item.cpp:188
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void SetCustomProperty(const wxString &aKey, const wxString &aValue)
Definition eda_item.h:255
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:236
void SetPosition(const VECTOR2I &aPos) override
void SetReference(const wxString &aReference)
Definition footprint.h:915
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Adds an item to the container.
virtual wxString GetClass() const =0
Return the class name.
wxString AsString() const
Definition kiid.cpp:264
const std::filesystem::path & Path() const
Get the path to the temporary directory as a std::filesystem::path.
Definition file_utils.h:59
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
Definition pad.h:61
void SetMid(const VECTOR2I &aMid)
Definition pcb_track.h:294
virtual void SetEnd(const VECTOR2I &aPoint)
virtual void SetStart(const VECTOR2I &aPoint)
For better understanding of the points that make a dimension:
A drill chart placed on the board, kept in step with the holes.
Turns on drill symbols at the holes, for one layer.
void RebuildCells(const BOARD &aBoard, GENERATED_TABLE_REFRESH *aRefresh=nullptr)
Regenerate the cells from the board.
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:51
void SetEnd(const VECTOR2I &aEnd) override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStart(const VECTOR2I &aStart) override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetPosition(const VECTOR2I &aPos) override
Definition pcb_target.h:50
void SetEnd(const VECTOR2I &aEnd)
Definition pcb_track.h:94
void SetStart(const VECTOR2I &aStart)
Definition pcb_track.h:97
virtual void SetWidth(int aWidth)
Definition pcb_track.h:91
Handle a list of polygons defining a copper zone.
Definition zone.h:70
bool AppendCorner(const VECTOR2I &aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
Definition zone.cpp:1464
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition zone.cpp:640
@ RECURSE
Definition eda_item.h:51
@ SEGMENT
Definition eda_shape.h:56
@ Edge_Cuts
Definition layer_ids.h:108
@ Cmts_User
Definition layer_ids.h:104
@ B_Cu
Definition layer_ids.h:61
@ F_Fab
Definition layer_ids.h:115
@ F_SilkS
Definition layer_ids.h:96
@ User_1
Definition layer_ids.h:120
@ User_2
Definition layer_ids.h:121
@ F_Cu
Definition layer_ids.h:60
std::unique_ptr< BOARD > ReadBoardFromFileOrStream(const std::string &aFilename, std::istream &aFallback)
Read a board from a file, or another stream, as appropriate.
void DumpBoardToFile(BOARD &board, const std::filesystem::path &aFilename)
Utility function to simply write a Board out to a file.
Class to handle a set of BOARD_ITEMs.
@ USER
The field ID hasn't been set yet; field is invalid.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
std::string path
VECTOR3I expected(15, 30, 45)
BOOST_TEST_CONTEXT("Test Clearance")
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition typeinfo.h:87
@ PCB_DRILL_CHART_T
class PCB_DRILL_CHART, a live drill chart derived from PCB_TABLE
Definition typeinfo.h:239
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708