KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_wx_data_view_hyperlink_renderer.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
*/
20
21
#include <boost/test/unit_test.hpp>
22
23
#include <vector>
24
#include <wx/string.h>
25
26
#include <
widgets/wx_data_view_hyperlink_renderer.h
>
27
28
29
using
RUN
=
HYPERLINK_DV_RENDERER::RUN
;
30
31
32
BOOST_AUTO_TEST_SUITE
( HyperlinkDvRenderer )
33
34
35
BOOST_AUTO_TEST_CASE
( PlainText )
36
{
37
std::vector<RUN> runs;
38
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"plain text"
), runs );
39
40
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
41
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"plain text"
) );
42
BOOST_CHECK( runs[0].href.IsEmpty() );
43
}
44
45
46
BOOST_AUTO_TEST_CASE
( SingleLink )
47
{
48
std::vector<RUN> runs;
49
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[label](https://example.com)"
), runs );
50
51
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
52
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"label"
) );
53
BOOST_CHECK_EQUAL
( runs[0].href, wxString(
"https://example.com"
) );
54
}
55
56
57
BOOST_AUTO_TEST_CASE
( TextLinkText )
58
{
59
std::vector<RUN> runs;
60
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"before [label](https://example.com) after"
), runs );
61
62
BOOST_REQUIRE_EQUAL( runs.size(), 3u );
63
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"before "
) );
64
BOOST_CHECK( runs[0].href.IsEmpty() );
65
BOOST_CHECK_EQUAL
( runs[1].
text
, wxString(
"label"
) );
66
BOOST_CHECK_EQUAL
( runs[1].href, wxString(
"https://example.com"
) );
67
BOOST_CHECK_EQUAL
( runs[2].
text
, wxString(
" after"
) );
68
BOOST_CHECK( runs[2].href.IsEmpty() );
69
}
70
71
72
BOOST_AUTO_TEST_CASE
( AdjacentLinks )
73
{
74
std::vector<RUN> runs;
75
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[a](https://a.test)[b](https://b.test)"
), runs );
76
77
BOOST_REQUIRE_EQUAL( runs.size(), 2u );
78
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"a"
) );
79
BOOST_CHECK_EQUAL
( runs[0].href, wxString(
"https://a.test"
) );
80
BOOST_CHECK_EQUAL
( runs[1].
text
, wxString(
"b"
) );
81
BOOST_CHECK_EQUAL
( runs[1].href, wxString(
"https://b.test"
) );
82
}
83
84
85
BOOST_AUTO_TEST_CASE
( UnclosedBracket )
86
{
87
std::vector<RUN> runs;
88
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"unclosed [bracket"
), runs );
89
90
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
91
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"unclosed [bracket"
) );
92
BOOST_CHECK( runs[0].href.IsEmpty() );
93
}
94
95
96
BOOST_AUTO_TEST_CASE
( BracketsNoParens )
97
{
98
std::vector<RUN> runs;
99
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[label] no parens"
), runs );
100
101
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
102
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"[label] no parens"
) );
103
BOOST_CHECK( runs[0].href.IsEmpty() );
104
}
105
106
107
BOOST_AUTO_TEST_CASE
( EmptyLabel )
108
{
109
std::vector<RUN> runs;
110
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[](https://example.com)"
), runs );
111
112
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
113
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
""
) );
114
BOOST_CHECK_EQUAL
( runs[0].href, wxString(
"https://example.com"
) );
115
}
116
117
118
BOOST_AUTO_TEST_CASE
( EmptyHrefRejected )
119
{
120
std::vector<RUN> runs;
121
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[label]()"
), runs );
122
123
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
124
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"label"
) );
125
BOOST_CHECK( runs[0].href.IsEmpty() );
126
}
127
128
129
BOOST_AUTO_TEST_CASE
( BalancedParensInUrl )
130
{
131
std::vector<RUN> runs;
132
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[doc](file:///foo (1).pdf)"
), runs );
133
134
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
135
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"doc"
) );
136
BOOST_CHECK_EQUAL
( runs[0].href, wxString(
"file:///foo (1).pdf"
) );
137
}
138
139
140
BOOST_AUTO_TEST_CASE
( ArrayIndexInPlainText )
141
{
142
std::vector<RUN> runs;
143
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"array[0] index"
), runs );
144
145
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
146
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"array[0] index"
) );
147
BOOST_CHECK( runs[0].href.IsEmpty() );
148
}
149
150
151
BOOST_AUTO_TEST_CASE
( Empty )
152
{
153
std::vector<RUN> runs;
154
HYPERLINK_DV_RENDERER::ParseRuns
( wxEmptyString, runs );
155
156
BOOST_CHECK( runs.empty() );
157
}
158
159
160
BOOST_AUTO_TEST_CASE
( LinkPlainLink )
161
{
162
std::vector<RUN> runs;
163
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[a](https://a.test) middle [b](https://b.test)"
), runs );
164
165
BOOST_REQUIRE_EQUAL( runs.size(), 3u );
166
BOOST_CHECK_EQUAL
( runs[0].href, wxString(
"https://a.test"
) );
167
BOOST_CHECK_EQUAL
( runs[1].
text
, wxString(
" middle "
) );
168
BOOST_CHECK( runs[1].href.IsEmpty() );
169
BOOST_CHECK_EQUAL
( runs[2].href, wxString(
"https://b.test"
) );
170
}
171
172
173
BOOST_AUTO_TEST_CASE
( NestedBracketInLabel )
174
{
175
std::vector<RUN> runs;
176
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[foo [bar]](https://example.com)"
), runs );
177
178
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
179
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"[foo [bar]](https://example.com)"
) );
180
BOOST_CHECK( runs[0].href.IsEmpty() );
181
}
182
183
184
BOOST_AUTO_TEST_CASE
( UnsafeUncPathRejected )
185
{
186
std::vector<RUN> runs;
187
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[click](\\\\server\\share\\foo.exe)"
), runs );
188
189
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
190
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"click"
) );
191
BOOST_CHECK( runs[0].href.IsEmpty() );
192
}
193
194
195
BOOST_AUTO_TEST_CASE
( UnsafeJavascriptRejected )
196
{
197
std::vector<RUN> runs;
198
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[click](javascript:alert(1))"
), runs );
199
200
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
201
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"click"
) );
202
BOOST_CHECK( runs[0].href.IsEmpty() );
203
}
204
205
206
BOOST_AUTO_TEST_CASE
( UnsafeFileExeRejected )
207
{
208
std::vector<RUN> runs;
209
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[click](file:///C:/Windows/System32/cmd.exe)"
), runs );
210
211
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
212
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"click"
) );
213
BOOST_CHECK( runs[0].href.IsEmpty() );
214
}
215
216
217
BOOST_AUTO_TEST_CASE
( SafeFilePdfAccepted )
218
{
219
std::vector<RUN> runs;
220
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[spec](file:///docs/spec.pdf)"
), runs );
221
222
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
223
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"spec"
) );
224
BOOST_CHECK_EQUAL
( runs[0].href, wxString(
"file:///docs/spec.pdf"
) );
225
}
226
227
228
BOOST_AUTO_TEST_CASE
( SafeUncPathAccepted )
229
{
230
std::vector<RUN> runs;
231
HYPERLINK_DV_RENDERER::ParseRuns
( wxString(
"[spec](\\\\server\\share\\foo.pdf)"
), runs );
232
233
BOOST_REQUIRE_EQUAL( runs.size(), 1u );
234
BOOST_CHECK_EQUAL
( runs[0].
text
, wxString(
"spec"
) );
235
BOOST_CHECK_EQUAL
( runs[0].href, wxString(
"\\\\server\\share\\foo.pdf"
) );
236
}
237
238
239
BOOST_AUTO_TEST_CASE
( IsSafeUrlDirect )
240
{
241
BOOST_CHECK(
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"http://example.com"
) ) );
242
BOOST_CHECK(
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"HTTPS://EXAMPLE.COM"
) ) );
243
BOOST_CHECK(
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"file:///home/user/doc.pdf"
) ) );
244
245
BOOST_CHECK( !
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
""
) ) );
246
BOOST_CHECK( !
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"ftp://example.com"
) ) );
247
BOOST_CHECK( !
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"javascript:alert(1)"
) ) );
248
BOOST_CHECK( !
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"data:text/html,<script>"
) ) );
249
BOOST_CHECK( !
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"\\\\server\\share\\foo.exe"
) ) );
250
BOOST_CHECK( !
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"mailto:
[email protected]
"
) ) );
251
BOOST_CHECK( !
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"file:///foo.exe"
) ) );
252
BOOST_CHECK( !
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"file:///FOO.EXE"
) ) );
253
BOOST_CHECK( !
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"file:///foo.bat"
) ) );
254
255
BOOST_CHECK(
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"\\\\server\\share\\foo.pdf"
) ) );
256
BOOST_CHECK(
HYPERLINK_DV_RENDERER::IsSafeUrl
( wxString(
"\\\\server\\share\\Spec.PDF"
) ) );
257
}
258
259
260
BOOST_AUTO_TEST_CASE
( StripMarkupPlainText )
261
{
262
BOOST_CHECK_EQUAL
(
HYPERLINK_DV_RENDERER::StripMarkup
( wxString(
"plain text"
) ), wxString(
"plain text"
) );
263
}
264
265
266
BOOST_AUTO_TEST_CASE
( StripMarkupSingleLink )
267
{
268
BOOST_CHECK_EQUAL
(
HYPERLINK_DV_RENDERER::StripMarkup
( wxString(
"See [the spec](https://foo.com/spec) here"
) ),
269
wxString(
"See the spec here"
) );
270
}
271
272
273
BOOST_AUTO_TEST_CASE
( StripMarkupDropsUnsafeUrl )
274
{
275
BOOST_CHECK_EQUAL
(
HYPERLINK_DV_RENDERER::StripMarkup
( wxString(
"Run [this](\\\\evil\\foo.exe) now"
) ),
276
wxString(
"Run this now"
) );
277
}
278
279
280
BOOST_AUTO_TEST_CASE
( StripMarkupEmpty )
281
{
282
BOOST_CHECK_EQUAL
(
HYPERLINK_DV_RENDERER::StripMarkup
( wxEmptyString ), wxEmptyString );
283
}
284
285
286
BOOST_AUTO_TEST_SUITE_END
()
BITMAPS::text
@ text
Definition
bitmaps_list.h:618
HYPERLINK_DV_RENDERER::ParseRuns
static void ParseRuns(const wxString &aValue, std::vector< RUN > &aRuns)
Split aValue into plain text and link runs.
Definition
wx_data_view_hyperlink_renderer.cpp:128
HYPERLINK_DV_RENDERER::StripMarkup
static wxString StripMarkup(const wxString &aValue)
Flatten [label](url) markup, keeping just the label.
Definition
wx_data_view_hyperlink_renderer.cpp:114
HYPERLINK_DV_RENDERER::IsSafeUrl
static bool IsSafeUrl(const wxString &aHref)
Accept only schemes that wxLaunchDefaultBrowser cannot turn into program execution.
Definition
wx_data_view_hyperlink_renderer.cpp:85
HYPERLINK_DV_RENDERER::RUN
Definition
wx_data_view_hyperlink_renderer.h:50
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
Definition
test_api_enums.cpp:71
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")
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(PlainText)
Definition
test_wx_data_view_hyperlink_renderer.cpp:35
RUN
HYPERLINK_DV_RENDERER::RUN RUN
Definition
test_wx_data_view_hyperlink_renderer.cpp:29
wx_data_view_hyperlink_renderer.h
src
qa
tests
common
test_wx_data_view_hyperlink_renderer.cpp
Generated on Sat May 16 2026 00:07:11 for KiCad PCB EDA Suite by
1.13.2