KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_text_var_reactive.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <boost/test/unit_test.hpp>
21#include <algorithm>
22#include <board.h>
23#include <board_commit.h>
25#include <footprint.h>
26#include <netinfo.h>
27#include <pcb_barcode.h>
28#include <pcb_field.h>
29#include <pcb_text.h>
31#include <text_var_dependency.h>
32#include <tool/tool_manager.h>
33
34
40BOOST_AUTO_TEST_SUITE( BoardTextVarReactive )
41
42
43BOOST_AUTO_TEST_CASE( AdapterIsInstalledOnConstruction )
44{
45 BOARD board;
48}
49
50
51BOOST_AUTO_TEST_CASE( AddingTextItemRegistersDependencies )
52{
53 BOARD board;
54 TOOL_MANAGER mgr;
55 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
57 mgr.RegisterTool( tool );
58 BOARD_COMMIT commit( tool );
59
60 PCB_TEXT* text = new PCB_TEXT( &board );
61 text->SetText( wxT( "${U1:VALUE}" ) );
62 commit.Add( text );
63 commit.Push( wxT( "add text" ), 0 );
64
67 index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "U1:VALUE" ) ) ), 1u );
68}
69
70
71BOOST_AUTO_TEST_CASE( FootprintChangeFiresInvalidation )
72{
73 BOARD board;
74 TOOL_MANAGER mgr;
75 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
77 mgr.RegisterTool( tool );
78
79 // Add a footprint U1 with default fields, and a PCB_TEXT that depends on
80 // its VALUE.
81 {
82 BOARD_COMMIT commit( tool );
83 FOOTPRINT* fp = new FOOTPRINT( &board );
84 fp->SetReference( wxT( "U1" ) );
85 fp->SetValue( wxT( "10k" ) );
86 commit.Add( fp );
87
88 PCB_TEXT* text = new PCB_TEXT( &board );
89 text->SetText( wxT( "${U1:Value}" ) );
90 commit.Add( text );
91
92 commit.Push( wxT( "seed" ), 0 );
93 }
94
95 // Register an invalidate callback and then edit the footprint's value.
96 std::vector<std::pair<EDA_ITEM*, TEXT_VAR_REF_KEY>> invalidations;
98 [&]( EDA_ITEM* dep, const TEXT_VAR_REF_KEY& key )
99 { invalidations.emplace_back( dep, key ); } );
100
101 FOOTPRINT* fp = board.Footprints().front();
102
103 BOARD_COMMIT commit( tool );
104 commit.Modify( fp );
105 fp->SetValue( wxT( "100k" ) );
106 commit.Push( wxT( "edit value" ), 0 );
107
108 // The adapter should have fanned out ${U1:Value} among others. Look for
109 // at least one invalidation that targets a PCB_TEXT dependent.
110 bool sawTextDependent = std::any_of( invalidations.begin(), invalidations.end(),
111 []( const auto& pair )
112 { return pair.first && pair.first->Type() == PCB_TEXT_T; } );
113
114 BOOST_CHECK( sawTextDependent );
115}
116
117
118BOOST_AUTO_TEST_CASE( RemovedItemsAreUnregistered )
119{
120 BOARD board;
121 TOOL_MANAGER mgr;
122 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
124 mgr.RegisterTool( tool );
125
126 PCB_TEXT* text = nullptr;
127
128 {
129 BOARD_COMMIT commit( tool );
130 text = new PCB_TEXT( &board );
131 text->SetText( wxT( "${X}" ) );
132 commit.Add( text );
133 commit.Push( wxT( "add" ), 0 );
134 }
135
137 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "X" ) ) ), 1u );
138
139 {
140 BOARD_COMMIT commit( tool );
141 commit.Remove( text );
142 commit.Push( wxT( "remove" ), 0 );
143 }
144
145 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "X" ) ) ), 0u );
146}
147
148
149BOOST_AUTO_TEST_CASE( SpiceOPTokensAreNotRegistered )
150{
151 BOARD board;
152 TOOL_MANAGER mgr;
153 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
155 mgr.RegisterTool( tool );
156 BOARD_COMMIT commit( tool );
157
158 PCB_TEXT* text = new PCB_TEXT( &board );
159 text->SetText( wxT( "${OP:1}" ) );
160 commit.Add( text );
161 commit.Push( wxT( "add op" ), 0 );
162
163 // IsTrackable() gates OP keys out of registration entirely.
165 BOOST_CHECK_EQUAL( index.ItemCount(), 0u );
166}
167
168
169BOOST_AUTO_TEST_CASE( VariantSwitchFiresCrossRefInvalidation )
170{
171 BOARD board;
172 TOOL_MANAGER mgr;
173 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
175 mgr.RegisterTool( tool );
176
177 {
178 BOARD_COMMIT commit( tool );
179 FOOTPRINT* fp = new FOOTPRINT( &board );
180 fp->SetReference( wxT( "U1" ) );
181 fp->SetValue( wxT( "10k" ) );
182 commit.Add( fp );
183
184 PCB_TEXT* text = new PCB_TEXT( &board );
185 text->SetText( wxT( "${U1:Value}" ) );
186 commit.Add( text );
187
188 commit.Push( wxT( "seed" ), 0 );
189 }
190
191 board.AddVariant( wxT( "HighPrecision" ) );
192
193 std::vector<EDA_ITEM*> invalidations;
195 [&]( EDA_ITEM* dep, const TEXT_VAR_REF_KEY& ) { invalidations.push_back( dep ); } );
196
197 board.SetCurrentVariant( wxT( "HighPrecision" ) );
198
199 // The PCB_TEXT that depends on ${U1:Value} must have been invalidated —
200 // variant overrides change how that cross-ref resolves.
201 bool sawPcbText = std::any_of( invalidations.begin(), invalidations.end(),
202 []( EDA_ITEM* item )
203 { return item && item->Type() == PCB_TEXT_T; } );
204 BOOST_CHECK( sawPcbText );
205
206 // Redundant switch to the same variant must be a no-op.
207 invalidations.clear();
208 board.SetCurrentVariant( wxT( "HighPrecision" ) );
209 BOOST_CHECK( invalidations.empty() );
210}
211
212
220BOOST_AUTO_TEST_CASE( RemoveAllNetInfoDoesNotUseDeletedPointers )
221{
222 BOARD board;
223
224 // Seed the board with an extra net so RemoveAll has real items to remove.
225 NETINFO_ITEM* net = new NETINFO_ITEM( &board, wxT( "net-1" ), 1 );
226 board.Add( net );
227
228 // Default RemoveAll() includes PCB_NETINFO_T. Listeners (including the
229 // BOARD_TEXT_VAR_ADAPTER installed in the BOARD constructor) must not see
230 // dangling pointers.
231 BOOST_CHECK_NO_THROW( board.RemoveAll() );
232}
233
234
235BOOST_AUTO_TEST_CASE( BarcodeIsRegisteredOnAdd )
236{
237 BOARD board;
238 TOOL_MANAGER mgr;
239 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
241 mgr.RegisterTool( tool );
242 BOARD_COMMIT commit( tool );
243
244 PCB_BARCODE* barcode = new PCB_BARCODE( &board );
245 barcode->SetText( wxT( "${SN}" ) );
246 commit.Add( barcode );
247 commit.Push( wxT( "add barcode" ), 0 );
248
250 BOOST_CHECK_EQUAL( index.DependentCount( TEXT_VAR_REF_KEY::FromToken( wxT( "SN" ) ) ), 1u );
251}
252
253
254BOOST_AUTO_TEST_CASE( BarcodeInvalidationFires )
255{
256 BOARD board;
257 TOOL_MANAGER mgr;
258 mgr.SetEnvironment( &board, nullptr, nullptr, nullptr, nullptr );
260 mgr.RegisterTool( tool );
261
262 {
263 BOARD_COMMIT commit( tool );
264 FOOTPRINT* fp = new FOOTPRINT( &board );
265 fp->SetReference( wxT( "U1" ) );
266 fp->SetValue( wxT( "10k" ) );
267 commit.Add( fp );
268
269 PCB_BARCODE* barcode = new PCB_BARCODE( &board );
270 barcode->SetText( wxT( "${U1:Value}" ) );
271 commit.Add( barcode );
272
273 commit.Push( wxT( "seed" ), 0 );
274 }
275
276 std::vector<EDA_ITEM*> invalidations;
278 [&]( EDA_ITEM* dep, const TEXT_VAR_REF_KEY& )
279 {
280 invalidations.push_back( dep );
281 } );
282
283 FOOTPRINT* fp = board.Footprints().front();
284 BOARD_COMMIT commit( tool );
285 commit.Modify( fp );
286 fp->SetValue( wxT( "100k" ) );
287 commit.Push( wxT( "edit value" ), 0 );
288
289 bool sawBarcode = std::any_of( invalidations.begin(), invalidations.end(),
290 []( EDA_ITEM* item )
291 {
292 return item && item->Type() == PCB_BARCODE_T;
293 } );
294 BOOST_CHECK( sawBarcode );
295}
296
297
int index
virtual void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
TEXT_VAR_TRACKER & Tracker()
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:323
BOARD_TEXT_VAR_ADAPTER * GetTextVarAdapter() const
Definition board.h:1705
void SetCurrentVariant(const wxString &aVariant)
Definition board.cpp:2778
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1247
void AddVariant(const wxString &aVariantName)
Definition board.cpp:2810
const FOOTPRINTS & Footprints() const
Definition board.h:364
void RemoveAll(std::initializer_list< KICAD_T > aTypes={ PCB_NETINFO_T, PCB_MARKER_T, PCB_GROUP_T, PCB_ZONE_T, PCB_GENERATOR_T, PCB_FOOTPRINT_T, PCB_TRACE_T, PCB_SHAPE_T })
An efficient way to remove all items of a certain type from the board.
Definition board.cpp:1490
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition commit.h:90
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition commit.h:78
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:100
void SetReference(const wxString &aReference)
Definition footprint.h:835
void SetValue(const wxString &aValue)
Definition footprint.h:856
Handle the data for a net.
Definition netinfo.h:50
void SetText(const wxString &aText)
Set the barcode content text to encode.
Bidirectional index mapping TEXT_VAR_REF_KEY → dependent items and item → keys.
ListenerHandle AddInvalidateListener(InvalidateCallback aCallback)
Register a listener that fires for every invalidation.
TEXT_VAR_DEPENDENCY_INDEX & Index()
Master controller class:
void RegisterTool(TOOL_BASE *aTool)
Add a tool to the manager set and sets it up.
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, APP_SETTINGS_BASE *aSettings, TOOLS_HOLDER *aFrame)
Set the work environment (model, view, view controls and the parent window).
BARCODE class definition.
Identifies a single resolvable source that a text item's ${...} reference depends on.
static TEXT_VAR_REF_KEY FromToken(const wxString &aToken)
Parse a raw token (the text between ${ and }) into a key using lexical classification only — no looku...
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_EQUAL(result, "25.4")
BOOST_AUTO_TEST_CASE(AdapterIsInstalledOnConstruction)
End-to-end reactive pipeline: BOARD commits + TEXT_VAR_TRACKER + BOARD_TEXT_VAR_ADAPTER together.