KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_expand_text_vars.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
21#define BOOST_TEST_NO_MAIN
22#include <boost/test/unit_test.hpp>
23#include <common.h>
24
29{
30 // Simple resolver that maps VAR->value, X->5, Y->2
31 std::function<bool( wxString* )> resolver = []( wxString* token ) -> bool
32 {
33 if( *token == wxT( "VAR" ) )
34 {
35 *token = wxT( "value" );
36 return true;
37 }
38 else if( *token == wxT( "X" ) )
39 {
40 *token = wxT( "5" );
41 return true;
42 }
43 else if( *token == wxT( "Y" ) )
44 {
45 *token = wxT( "2" );
46 return true;
47 }
48
49 return false;
50 };
51};
52
53BOOST_FIXTURE_TEST_SUITE( ExpandTextVarsTests, ExpandTextVarsFixture )
54
55// Basic variable expansion
56BOOST_AUTO_TEST_CASE( SimpleVariable )
57{
58 wxString result = ExpandTextVars( wxT( "${VAR}" ), &resolver );
59 BOOST_CHECK( result == wxT( "value" ) );
60}
61
62// Multiple variables in one string
63BOOST_AUTO_TEST_CASE( MultipleVariables )
64{
65 wxString result = ExpandTextVars( wxT( "${X}+${Y}" ), &resolver );
66 BOOST_CHECK( result == wxT( "5+2" ) );
67}
68
69// Escaped variable should produce escape marker (not expanded)
70BOOST_AUTO_TEST_CASE( EscapedVariable )
71{
72 wxString result = ExpandTextVars( wxT( "\\${VAR}" ), &resolver );
73 // The escape marker should be in the output
74 BOOST_CHECK( result.Contains( wxT( "<<<ESC_DOLLAR:" ) ) );
75}
76
77// Escaped variable followed by regular variable - both should be processed correctly
78BOOST_AUTO_TEST_CASE( EscapedThenRegularVariable )
79{
80 wxString result = ExpandTextVars( wxT( "\\${literal}${VAR}" ), &resolver );
81 // Should have escape marker for literal, and "value" for VAR
82 BOOST_CHECK( result.Contains( wxT( "<<<ESC_DOLLAR:" ) ) );
83 BOOST_CHECK( result.Contains( wxT( "value" ) ) );
84}
85
86// Regular variable followed by escaped variable
87BOOST_AUTO_TEST_CASE( RegularThenEscapedVariable )
88{
89 wxString result = ExpandTextVars( wxT( "${VAR}\\${literal}" ), &resolver );
90 // Should have "value" for VAR and escape marker for literal
91 BOOST_CHECK( result.StartsWith( wxT( "value" ) ) );
92 BOOST_CHECK( result.Contains( wxT( "<<<ESC_DOLLAR:" ) ) );
93}
94
95// Issue 22497: Escaped variable inside math expression should not prevent other expansions
96// This is the key test case for the bug fix
97BOOST_AUTO_TEST_CASE( EscapedInsideMathExpression )
98{
99 // First pass: @{\${X}+${Y}} should become @{<<<ESC_DOLLAR:X}+2}
100 // Second pass: the marker should be preserved and +2 should NOT be lost
101 wxString result = ExpandTextVars( wxT( "@{\\${X}+${Y}}" ), &resolver );
102
103 // The result should contain the escape marker
104 BOOST_CHECK_MESSAGE( result.Contains( wxT( "<<<ESC_DOLLAR:" ) ),
105 "Expected escape marker in result" );
106
107 // The result should also contain +2 (the expanded Y variable)
108 BOOST_CHECK_MESSAGE( result.Contains( wxT( "+2" ) ),
109 "Expected '+2' (from ${Y} expansion) in result" );
110
111 // The result should be @{<<<ESC_DOLLAR:X}+2}
112 BOOST_CHECK( result == wxT( "@{<<<ESC_DOLLAR:X}+2}" ) );
113}
114
115// Nested escaped variable in regular variable reference
116BOOST_AUTO_TEST_CASE( EscapedInsideVariableReference )
117{
118 // ${prefix\${suffix}} - looking up variable with literal ${suffix} in name
119 // This should try to resolve "prefix\${suffix}" which won't resolve,
120 // but the recursive expansion should convert \${suffix} to the marker
121 wxString result = ExpandTextVars( wxT( "${prefix\\${suffix}}" ), &resolver );
122
123 // The unresolved reference should be preserved with escape marker
124 BOOST_CHECK( result.Contains( wxT( "<<<ESC_DOLLAR:" ) ) );
125}
126
127// Multiple escape markers in a math expression
128BOOST_AUTO_TEST_CASE( MultipleEscapedInMathExpression )
129{
130 wxString result = ExpandTextVars( wxT( "@{\\${A}+\\${B}+${Y}}" ), &resolver );
131
132 // Should have two escape markers and the expanded Y (2)
133 BOOST_CHECK_MESSAGE( result.Contains( wxT( "+2" ) ),
134 "Expected '+2' (from ${Y} expansion) in: " + result );
135
136 // Count escape markers (should be 2)
137 int dollarCount = 0;
138 size_t pos = 0;
139
140 while( ( pos = result.find( wxT( "<<<ESC_DOLLAR:" ), pos ) ) != wxString::npos )
141 {
142 dollarCount++;
143 pos += 14;
144 }
145
146 BOOST_CHECK_EQUAL( dollarCount, 2 );
147}
148
149// Math expression with escaped @ sign
150BOOST_AUTO_TEST_CASE( EscapedAtInExpression )
151{
152 wxString result = ExpandTextVars( wxT( "${VAR}\\@{literal}" ), &resolver );
153
154 // Should have "value" for VAR and escape marker for @{literal}
155 BOOST_CHECK( result.StartsWith( wxT( "value" ) ) );
156 BOOST_CHECK( result.Contains( wxT( "<<<ESC_AT:" ) ) );
157}
158
159// Escaped followed by escaped (both should be preserved)
160BOOST_AUTO_TEST_CASE( ConsecutiveEscaped )
161{
162 wxString result = ExpandTextVars( wxT( "\\${A}\\${B}" ), &resolver );
163
164 // Should have two escape markers
165 int dollarCount = 0;
166 size_t pos = 0;
167
168 while( ( pos = result.find( wxT( "<<<ESC_DOLLAR:" ), pos ) ) != wxString::npos )
169 {
170 dollarCount++;
171 pos += 14;
172 }
173
174 BOOST_CHECK_EQUAL( dollarCount, 2 );
175}
176
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition common.cpp:61
The common library.
static FILENAME_RESOLVER * resolver
Test fixture for ExpandTextVars tests.
std::function< bool(wxString *)> resolver
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_CASE(SimpleVariable)
BOOST_AUTO_TEST_SUITE_END()
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")