KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_reporting.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 <reporter.h>
22#include <wx/string.h>
23#include <wx/textctrl.h>
24#include <wx/statusbr.h>
25#include <wx/log.h>
26#include <vector>
27#include <sstream>
28
29// Mock TEST_REPORTER to test base REPORTER functionality
30class TEST_REPORTER : public REPORTER
31{
32public:
34
35 REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override
36 {
37 REPORTER::Report( aText, aSeverity ); // Call base to update severity mask
38 m_messages.push_back( std::make_pair( aText, aSeverity ) );
39 m_hasMessage = true;
41 return *this;
42 }
43
44 bool HasMessage() const override
45 {
46 return m_hasMessage;
47 }
48
49 void Clear() override
50 {
52 m_messages.clear();
53 m_hasMessage = false;
55 }
56
57 const std::vector<std::pair<wxString, SEVERITY>>& GetMessages() const { return m_messages; }
58 int GetMessageCount() const { return m_messageCount; }
59
60private:
61 std::vector<std::pair<wxString, SEVERITY>> m_messages;
64};
65
66// Mock wxTextCtrl for testing
68{
69public:
71 void AppendText( const wxString& text ) { m_content += text; }
72 void SetValue( const wxString& text ) { m_content = text; }
73 wxString GetValue() const { return m_content; }
74 bool IsEmpty() const { return m_content.IsEmpty(); }
75 void Clear() { m_content.Clear(); }
76
77private:
78 wxString m_content;
79};
80
81// Mock wxStatusBar for testing
83{
84public:
85 MockStatusBar() { m_fields.resize( 3 ); } // Default 3 fields
86 void SetStatusText( const wxString& text, int field = 0 )
87 {
88 if( field >= 0 && field < (int)m_fields.size() )
89 m_fields[field] = text;
90 }
91 wxString GetStatusText( int field = 0 ) const
92 {
93 if( field >= 0 && field < (int)m_fields.size() )
94 return m_fields[field];
95 return wxEmptyString;
96 }
97
98private:
99 std::vector<wxString> m_fields;
100};
101
102BOOST_AUTO_TEST_SUITE( ReporterTests )
103
104BOOST_AUTO_TEST_CASE( BaseReporter_Constructor )
105{
106 TEST_REPORTER reporter;
107
108 BOOST_CHECK( !reporter.HasMessage() );
109 BOOST_CHECK( reporter.GetUnits() == EDA_UNITS::MM );
110 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
111}
112
113BOOST_AUTO_TEST_CASE( BaseReporter_SingleReport )
114{
115 TEST_REPORTER reporter;
116
117 reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO );
118
119 BOOST_CHECK( reporter.HasMessage() );
120 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
121 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
122
123 const auto& messages = reporter.GetMessages();
124 BOOST_CHECK_EQUAL( messages.size(), 1 );
125 BOOST_CHECK_EQUAL( messages[0].first, wxString("Test message") );
126 BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_INFO );
127}
128
129BOOST_AUTO_TEST_CASE( BaseReporter_MultipleReports )
130{
131 TEST_REPORTER reporter;
132
133 reporter.Report( wxT("Info message"), RPT_SEVERITY_INFO );
134 reporter.Report( wxT("Warning message"), RPT_SEVERITY_WARNING );
135 reporter.Report( wxT("Error message"), RPT_SEVERITY_ERROR );
136
137 BOOST_CHECK( reporter.HasMessage() );
138 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 3 );
139
140 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
141 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
142 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
144}
145
146BOOST_AUTO_TEST_CASE( BaseReporter_ReportTail )
147{
148 TEST_REPORTER reporter;
149
150 reporter.ReportTail( wxT("Tail message"), RPT_SEVERITY_INFO );
151
152 BOOST_CHECK( reporter.HasMessage() );
153 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
154
155 const auto& messages = reporter.GetMessages();
156 BOOST_CHECK_EQUAL( messages[0].first, wxString("Tail message") );
157 BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_INFO );
158}
159
160BOOST_AUTO_TEST_CASE( BaseReporter_ReportHead )
161{
162 TEST_REPORTER reporter;
163
164 reporter.ReportHead( wxT("Head message"), RPT_SEVERITY_WARNING );
165
166 BOOST_CHECK( reporter.HasMessage() );
167 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
168
169 const auto& messages = reporter.GetMessages();
170 BOOST_CHECK_EQUAL( messages[0].first, wxString("Head message") );
171 BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_WARNING );
172}
173
174BOOST_AUTO_TEST_CASE( BaseReporter_OperatorLeftShift )
175{
176 TEST_REPORTER reporter;
177
178 reporter << wxT("Stream message");
179
180 BOOST_CHECK( reporter.HasMessage() );
181 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
182
183 const auto& messages = reporter.GetMessages();
184 BOOST_CHECK_EQUAL( messages[0].first, wxString("Stream message") );
185 BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_UNDEFINED );
186}
187
188BOOST_AUTO_TEST_CASE( BaseReporter_CharPointerReport )
189{
190 TEST_REPORTER reporter;
191
192 reporter.Report( "C-style string", RPT_SEVERITY_ERROR );
193
194 BOOST_CHECK( reporter.HasMessage() );
195 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
196 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
197}
198
199BOOST_AUTO_TEST_CASE( BaseReporter_Clear )
200{
201 TEST_REPORTER reporter;
202
203 reporter.Report( wxT("Message 1"), RPT_SEVERITY_INFO );
204 reporter.Report( wxT("Message 2"), RPT_SEVERITY_WARNING );
205
206 BOOST_CHECK( reporter.HasMessage() );
207 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
208 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
209
210 reporter.Clear();
211
212 BOOST_CHECK( !reporter.HasMessage() );
213 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
214 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
215 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 0 );
216}
217
218BOOST_AUTO_TEST_CASE( BaseReporter_SeverityMask )
219{
220 TEST_REPORTER reporter;
221
222 // Test individual severities
223 reporter.Report( wxT("Info"), RPT_SEVERITY_INFO );
224 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
225 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
226
227 reporter.Report( wxT("Warning"), RPT_SEVERITY_WARNING );
228 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
229 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
231
232 // Test combined mask
233 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
234 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ACTION ) );
235}
236
237BOOST_AUTO_TEST_CASE( BaseReporter_EmptyMessage )
238{
239 TEST_REPORTER reporter;
240
241 reporter.Report( wxT(""), RPT_SEVERITY_INFO );
242
243 BOOST_CHECK( reporter.HasMessage() );
244 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
245
246 const auto& messages = reporter.GetMessages();
247 BOOST_CHECK_EQUAL( messages[0].first, wxString("") );
248}
249
250BOOST_AUTO_TEST_CASE( BaseReporter_LongMessage )
251{
252 TEST_REPORTER reporter;
253 wxString longMessage( 10000, 'A' );
254
255 reporter.Report( longMessage, RPT_SEVERITY_INFO );
256
257 BOOST_CHECK( reporter.HasMessage() );
258 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
259
260 const auto& messages = reporter.GetMessages();
261 BOOST_CHECK_EQUAL( messages[0].first, longMessage );
262}
263
264BOOST_AUTO_TEST_CASE( WxStringReporter_BasicFunctionality )
265{
266 WX_STRING_REPORTER reporter;
267
268 BOOST_CHECK( !reporter.HasMessage() );
269
270 reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO );
271
272 BOOST_CHECK( reporter.HasMessage() );
273 BOOST_CHECK( !reporter.GetMessages().IsEmpty() );
274 BOOST_CHECK( reporter.GetMessages().Contains( wxT("Test message") ) );
275}
276
277BOOST_AUTO_TEST_CASE( WxStringReporter_MultipleMessages )
278{
279 WX_STRING_REPORTER reporter;
280
281 reporter.Report( wxT("Message 1"), RPT_SEVERITY_INFO );
282 reporter.Report( wxT("Message 2"), RPT_SEVERITY_WARNING );
283
284 BOOST_CHECK( reporter.HasMessage() );
285
286 const wxString& messages = reporter.GetMessages();
287 BOOST_CHECK( messages.Contains( wxT("Message 1") ) );
288 BOOST_CHECK( messages.Contains( wxT("Message 2") ) );
289}
290
291BOOST_AUTO_TEST_CASE( WxStringReporter_Clear )
292{
293 WX_STRING_REPORTER reporter;
294
295 reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO );
296 BOOST_CHECK( reporter.HasMessage() );
297
298 reporter.Clear();
299
300 BOOST_CHECK( !reporter.HasMessage() );
301 BOOST_CHECK( reporter.GetMessages().IsEmpty() );
302}
303
304BOOST_AUTO_TEST_CASE( WxStringReporter_SeverityMask )
305{
306 WX_STRING_REPORTER reporter;
307
308 reporter.Report( wxT("Info"), RPT_SEVERITY_INFO );
309 reporter.Report( wxT("Warning"), RPT_SEVERITY_WARNING );
310
311 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
312 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
314 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
315}
316
317BOOST_AUTO_TEST_CASE( WxStringReporter_OperatorChaining )
318{
319 WX_STRING_REPORTER reporter;
320
321 reporter.Report( wxT("First"), RPT_SEVERITY_INFO )
322 .Report( wxT("Second"), RPT_SEVERITY_WARNING )
323 << wxT("Third");
324
325 BOOST_CHECK( reporter.HasMessage() );
326 const wxString& messages = reporter.GetMessages();
327 BOOST_CHECK( messages.Contains( wxT("First") ) );
328 BOOST_CHECK( messages.Contains( wxT("Second") ) );
329 BOOST_CHECK( messages.Contains( wxT("Third") ) );
330}
331
332BOOST_AUTO_TEST_CASE( NullReporter_Singleton )
333{
336
337 BOOST_CHECK_EQUAL( &reporter1, &reporter2 );
338}
339
340BOOST_AUTO_TEST_CASE( NullReporter_SeverityMask )
341{
343
344 reporter.Report( wxT("Info"), RPT_SEVERITY_INFO );
345 reporter.Report( wxT("Warning"), RPT_SEVERITY_WARNING );
346
347 // NULL_REPORTER should track severity mask even though it doesn't store messages
348 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
349 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
350}
351
352BOOST_AUTO_TEST_CASE( CliReporter_Singleton )
353{
354 REPORTER& reporter1 = CLI_REPORTER::GetInstance();
355 REPORTER& reporter2 = CLI_REPORTER::GetInstance();
356
357 BOOST_CHECK_EQUAL( &reporter1, &reporter2 );
358}
359
360BOOST_AUTO_TEST_CASE( StdoutReporter_Singleton )
361{
364
365 BOOST_CHECK_EQUAL( &reporter1, &reporter2 );
366}
367
368BOOST_AUTO_TEST_CASE( WxLogReporter_Singleton )
369{
372
373 BOOST_CHECK_EQUAL( &reporter1, &reporter2 );
374}
375
376// Note: WX_TEXT_CTRL_REPORTER and STATUSBAR_REPORTER tests would require
377// actual wxWidgets objects or more sophisticated mocking
378
379BOOST_AUTO_TEST_CASE( ReporterInterface_Polymorphism )
380{
381 std::vector<std::unique_ptr<REPORTER>> reporters;
382 reporters.push_back( std::make_unique<WX_STRING_REPORTER>() );
383 reporters.push_back( std::make_unique<TEST_REPORTER>() );
384
385 for( auto& reporter : reporters )
386 {
387 reporter->Report( wxT( "Polymorphic test" ), RPT_SEVERITY_INFO );
388
389 BOOST_CHECK( reporter->HasMessage() );
390 }
391}
392
393BOOST_AUTO_TEST_CASE( ReporterInterface_ChainedOperations )
394{
395 WX_STRING_REPORTER reporter;
396
397 // Test method chaining
398 REPORTER& result = reporter.Report( wxT("First"), RPT_SEVERITY_INFO )
399 .ReportHead( wxT("Head"), RPT_SEVERITY_WARNING )
400 .ReportTail( wxT("Tail"), RPT_SEVERITY_ERROR );
401
402 BOOST_CHECK_EQUAL( &result, &reporter ); // Should return reference to self
403 BOOST_CHECK( reporter.HasMessage() );
404
405 const wxString& messages = reporter.GetMessages();
406 BOOST_CHECK( messages.Contains( wxT("First") ) );
407 BOOST_CHECK( messages.Contains( wxT("Head") ) );
408 BOOST_CHECK( messages.Contains( wxT("Tail") ) );
409}
410
411BOOST_AUTO_TEST_CASE( ReporterInterface_DefaultSeverity )
412{
413 TEST_REPORTER reporter;
414
415 // Test default severity parameter
416 reporter.Report( wxT("Default severity") );
417
418 const auto& messages = reporter.GetMessages();
419 BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_UNDEFINED );
420}
421
422BOOST_AUTO_TEST_CASE( ReporterInterface_UnitsDefault )
423{
424 TEST_REPORTER reporter;
425
426 BOOST_CHECK( reporter.GetUnits() == EDA_UNITS::MM );
427}
428
static REPORTER & GetInstance()
Definition reporter.cpp:129
void SetStatusText(const wxString &text, int field=0)
wxString GetStatusText(int field=0) const
std::vector< wxString > m_fields
bool IsEmpty() const
void AppendText(const wxString &text)
void SetValue(const wxString &text)
wxString GetValue() const
static REPORTER & GetInstance()
Definition reporter.cpp:96
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual EDA_UNITS GetUnits() const
Definition reporter.h:148
virtual REPORTER & ReportHead(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the beginning of the list for objects that support ordering.
Definition reporter.h:121
virtual void Clear()
Definition reporter.h:153
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition reporter.h:112
virtual bool HasMessageOfSeverity(int aSeverityMask) const
Returns true if the reporter has one or more messages matching the specified severity mask.
Definition reporter.h:143
REPORTER()
Definition reporter.h:75
virtual bool HasMessage() const
Returns true if any messages were reported.
Definition reporter.h:134
static REPORTER & GetInstance()
Definition reporter.cpp:159
std::vector< std::pair< wxString, SEVERITY > > m_messages
const std::vector< std::pair< wxString, SEVERITY > > & GetMessages() const
void Clear() override
int GetMessageCount() const
bool HasMessage() const override
Returns true if any messages were reported.
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
static REPORTER & GetInstance()
Definition reporter.cpp:190
A wrapper for reporting to a wxString object.
Definition reporter.h:191
void Clear() override
Definition reporter.cpp:83
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:68
const wxString & GetMessages() const
Definition reporter.cpp:77
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_UNDEFINED
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(BaseReporter_Constructor)
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")