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>
23#include <wx/string.h>
24#include <wx/textctrl.h>
25#include <wx/statusbr.h>
26#include <wx/log.h>
27#include <vector>
28#include <sstream>
29
30// Mock TEST_REPORTER to test base REPORTER functionality
31class TEST_REPORTER : public REPORTER
32{
33public:
35
36 REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override
37 {
38 REPORTER::Report( aText, aSeverity ); // Call base to update severity mask
39 m_messages.push_back( std::make_pair( aText, aSeverity ) );
40 m_hasMessage = true;
42 return *this;
43 }
44
45 bool HasMessage() const override
46 {
47 return m_hasMessage;
48 }
49
50 void Clear() override
51 {
53 m_messages.clear();
54 m_hasMessage = false;
56 }
57
58 const std::vector<std::pair<wxString, SEVERITY>>& GetMessages() const { return m_messages; }
59 int GetMessageCount() const { return m_messageCount; }
60
61private:
62 std::vector<std::pair<wxString, SEVERITY>> m_messages;
65};
66
67// Mock wxTextCtrl for testing
69{
70public:
72 void AppendText( const wxString& text ) { m_content += text; }
73 void SetValue( const wxString& text ) { m_content = text; }
74 wxString GetValue() const { return m_content; }
75 bool IsEmpty() const { return m_content.IsEmpty(); }
76 void Clear() { m_content.Clear(); }
77
78private:
79 wxString m_content;
80};
81
82// Mock wxStatusBar for testing
84{
85public:
86 MockStatusBar() { m_fields.resize( 3 ); } // Default 3 fields
87 void SetStatusText( const wxString& text, int field = 0 )
88 {
89 if( field >= 0 && field < (int)m_fields.size() )
90 m_fields[field] = text;
91 }
92 wxString GetStatusText( int field = 0 ) const
93 {
94 if( field >= 0 && field < (int)m_fields.size() )
95 return m_fields[field];
96 return wxEmptyString;
97 }
98
99private:
100 std::vector<wxString> m_fields;
101};
102
103BOOST_AUTO_TEST_SUITE( ReporterTests )
104
105BOOST_AUTO_TEST_CASE( BaseReporter_Constructor )
106{
107 TEST_REPORTER reporter;
108
109 BOOST_CHECK( !reporter.HasMessage() );
110 BOOST_CHECK( reporter.GetUnits() == EDA_UNITS::MM );
111 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
112}
113
114BOOST_AUTO_TEST_CASE( BaseReporter_SingleReport )
115{
116 TEST_REPORTER reporter;
117
118 reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO );
119
120 BOOST_CHECK( reporter.HasMessage() );
121 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
122 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
123
124 const auto& messages = reporter.GetMessages();
125 BOOST_CHECK_EQUAL( messages.size(), 1 );
126 BOOST_CHECK_EQUAL( messages[0].first, wxString("Test message") );
127 BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_INFO );
128}
129
130BOOST_AUTO_TEST_CASE( BaseReporter_MultipleReports )
131{
132 TEST_REPORTER reporter;
133
134 reporter.Report( wxT("Info message"), RPT_SEVERITY_INFO );
135 reporter.Report( wxT("Warning message"), RPT_SEVERITY_WARNING );
136 reporter.Report( wxT("Error message"), RPT_SEVERITY_ERROR );
137
138 BOOST_CHECK( reporter.HasMessage() );
139 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 3 );
140
141 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
142 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
143 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
145}
146
147BOOST_AUTO_TEST_CASE( BaseReporter_ReportTail )
148{
149 TEST_REPORTER reporter;
150
151 reporter.ReportTail( wxT("Tail message"), RPT_SEVERITY_INFO );
152
153 BOOST_CHECK( reporter.HasMessage() );
154 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
155
156 const auto& messages = reporter.GetMessages();
157 BOOST_CHECK_EQUAL( messages[0].first, wxString("Tail message") );
158 BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_INFO );
159}
160
161BOOST_AUTO_TEST_CASE( BaseReporter_ReportHead )
162{
163 TEST_REPORTER reporter;
164
165 reporter.ReportHead( wxT("Head message"), RPT_SEVERITY_WARNING );
166
167 BOOST_CHECK( reporter.HasMessage() );
168 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
169
170 const auto& messages = reporter.GetMessages();
171 BOOST_CHECK_EQUAL( messages[0].first, wxString("Head message") );
172 BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_WARNING );
173}
174
175BOOST_AUTO_TEST_CASE( BaseReporter_OperatorLeftShift )
176{
177 TEST_REPORTER reporter;
178
179 reporter << wxT("Stream message");
180
181 BOOST_CHECK( reporter.HasMessage() );
182 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
183
184 const auto& messages = reporter.GetMessages();
185 BOOST_CHECK_EQUAL( messages[0].first, wxString("Stream message") );
186 BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_UNDEFINED );
187}
188
189BOOST_AUTO_TEST_CASE( BaseReporter_CharPointerReport )
190{
191 TEST_REPORTER reporter;
192
193 reporter.Report( "C-style string", RPT_SEVERITY_ERROR );
194
195 BOOST_CHECK( reporter.HasMessage() );
196 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
197 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
198}
199
200BOOST_AUTO_TEST_CASE( BaseReporter_Clear )
201{
202 TEST_REPORTER reporter;
203
204 reporter.Report( wxT("Message 1"), RPT_SEVERITY_INFO );
205 reporter.Report( wxT("Message 2"), RPT_SEVERITY_WARNING );
206
207 BOOST_CHECK( reporter.HasMessage() );
208 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
209 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
210
211 reporter.Clear();
212
213 BOOST_CHECK( !reporter.HasMessage() );
214 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
215 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
216 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 0 );
217}
218
219BOOST_AUTO_TEST_CASE( BaseReporter_SeverityMask )
220{
221 TEST_REPORTER reporter;
222
223 // Test individual severities
224 reporter.Report( wxT("Info"), RPT_SEVERITY_INFO );
225 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
226 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
227
228 reporter.Report( wxT("Warning"), RPT_SEVERITY_WARNING );
229 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
230 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
232
233 // Test combined mask
234 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
235 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ACTION ) );
236}
237
238BOOST_AUTO_TEST_CASE( BaseReporter_EmptyMessage )
239{
240 TEST_REPORTER reporter;
241
242 reporter.Report( wxT(""), RPT_SEVERITY_INFO );
243
244 BOOST_CHECK( reporter.HasMessage() );
245 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
246
247 const auto& messages = reporter.GetMessages();
248 BOOST_CHECK_EQUAL( messages[0].first, wxString("") );
249}
250
251BOOST_AUTO_TEST_CASE( BaseReporter_LongMessage )
252{
253 TEST_REPORTER reporter;
254 wxString longMessage( 10000, 'A' );
255
256 reporter.Report( longMessage, RPT_SEVERITY_INFO );
257
258 BOOST_CHECK( reporter.HasMessage() );
259 BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 );
260
261 const auto& messages = reporter.GetMessages();
262 BOOST_CHECK_EQUAL( messages[0].first, longMessage );
263}
264
265BOOST_AUTO_TEST_CASE( WxStringReporter_BasicFunctionality )
266{
267 WX_STRING_REPORTER reporter;
268
269 BOOST_CHECK( !reporter.HasMessage() );
270
271 reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO );
272
273 BOOST_CHECK( reporter.HasMessage() );
274 BOOST_CHECK( !reporter.GetMessages().IsEmpty() );
275 BOOST_CHECK( reporter.GetMessages().Contains( wxT("Test message") ) );
276}
277
278BOOST_AUTO_TEST_CASE( WxStringReporter_MultipleMessages )
279{
280 WX_STRING_REPORTER reporter;
281
282 reporter.Report( wxT("Message 1"), RPT_SEVERITY_INFO );
283 reporter.Report( wxT("Message 2"), RPT_SEVERITY_WARNING );
284
285 BOOST_CHECK( reporter.HasMessage() );
286
287 const wxString& messages = reporter.GetMessages();
288 BOOST_CHECK( messages.Contains( wxT("Message 1") ) );
289 BOOST_CHECK( messages.Contains( wxT("Message 2") ) );
290}
291
292BOOST_AUTO_TEST_CASE( WxStringReporter_Clear )
293{
294 WX_STRING_REPORTER reporter;
295
296 reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO );
297 BOOST_CHECK( reporter.HasMessage() );
298
299 reporter.Clear();
300
301 BOOST_CHECK( !reporter.HasMessage() );
302 BOOST_CHECK( reporter.GetMessages().IsEmpty() );
303}
304
305BOOST_AUTO_TEST_CASE( WxStringReporter_SeverityMask )
306{
307 WX_STRING_REPORTER reporter;
308
309 reporter.Report( wxT("Info"), RPT_SEVERITY_INFO );
310 reporter.Report( wxT("Warning"), RPT_SEVERITY_WARNING );
311
312 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
313 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
315 BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) );
316}
317
318BOOST_AUTO_TEST_CASE( WxStringReporter_OperatorChaining )
319{
320 WX_STRING_REPORTER reporter;
321
322 reporter.Report( wxT("First"), RPT_SEVERITY_INFO )
323 .Report( wxT("Second"), RPT_SEVERITY_WARNING )
324 << wxT("Third");
325
326 BOOST_CHECK( reporter.HasMessage() );
327 const wxString& messages = reporter.GetMessages();
328 BOOST_CHECK( messages.Contains( wxT("First") ) );
329 BOOST_CHECK( messages.Contains( wxT("Second") ) );
330 BOOST_CHECK( messages.Contains( wxT("Third") ) );
331}
332
333BOOST_AUTO_TEST_CASE( NullReporter_Singleton )
334{
337
338 BOOST_CHECK_EQUAL( &reporter1, &reporter2 );
339}
340
341BOOST_AUTO_TEST_CASE( NullReporter_SeverityMask )
342{
344
345 reporter.Report( wxT("Info"), RPT_SEVERITY_INFO );
346 reporter.Report( wxT("Warning"), RPT_SEVERITY_WARNING );
347
348 // NULL_REPORTER should track severity mask even though it doesn't store messages
349 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) );
350 BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) );
351}
352
353BOOST_AUTO_TEST_CASE( CliReporter_Singleton )
354{
357
358 BOOST_CHECK_EQUAL( &reporter1, &reporter2 );
359}
360
361BOOST_AUTO_TEST_CASE( CliReporter_VerboseDefault )
362{
364
365 // Default should be non-verbose
366 BOOST_CHECK( !reporter.GetVerbose() );
367}
368
369BOOST_AUTO_TEST_CASE( CliReporter_VerboseToggle )
370{
372 bool originalState = reporter.GetVerbose();
373
374 // Toggle verbose on
375 reporter.SetVerbose( true );
376 BOOST_CHECK( reporter.GetVerbose() );
377
378 // Toggle verbose off
379 reporter.SetVerbose( false );
380 BOOST_CHECK( !reporter.GetVerbose() );
381
382 // Restore original state
383 reporter.SetVerbose( originalState );
384}
385
386BOOST_AUTO_TEST_CASE( StdoutReporter_Singleton )
387{
390
391 BOOST_CHECK_EQUAL( &reporter1, &reporter2 );
392}
393
394BOOST_AUTO_TEST_CASE( WxLogReporter_Singleton )
395{
398
399 BOOST_CHECK_EQUAL( &reporter1, &reporter2 );
400}
401
402// Note: WX_TEXT_CTRL_REPORTER and STATUSBAR_REPORTER tests would require
403// actual wxWidgets objects or more sophisticated mocking
404
405BOOST_AUTO_TEST_CASE( ReporterInterface_Polymorphism )
406{
407 std::vector<std::unique_ptr<REPORTER>> reporters;
408 reporters.push_back( std::make_unique<WX_STRING_REPORTER>() );
409 reporters.push_back( std::make_unique<TEST_REPORTER>() );
410
411 for( auto& reporter : reporters )
412 {
413 reporter->Report( wxT( "Polymorphic test" ), RPT_SEVERITY_INFO );
414
415 BOOST_CHECK( reporter->HasMessage() );
416 }
417}
418
419BOOST_AUTO_TEST_CASE( ReporterInterface_ChainedOperations )
420{
421 WX_STRING_REPORTER reporter;
422
423 // Test method chaining
424 REPORTER& result = reporter.Report( wxT("First"), RPT_SEVERITY_INFO )
425 .ReportHead( wxT("Head"), RPT_SEVERITY_WARNING )
426 .ReportTail( wxT("Tail"), RPT_SEVERITY_ERROR );
427
428 BOOST_CHECK_EQUAL( &result, &reporter ); // Should return reference to self
429 BOOST_CHECK( reporter.HasMessage() );
430
431 const wxString& messages = reporter.GetMessages();
432 BOOST_CHECK( messages.Contains( wxT("First") ) );
433 BOOST_CHECK( messages.Contains( wxT("Head") ) );
434 BOOST_CHECK( messages.Contains( wxT("Tail") ) );
435}
436
437BOOST_AUTO_TEST_CASE( ReporterInterface_DefaultSeverity )
438{
439 TEST_REPORTER reporter;
440
441 // Test default severity parameter
442 reporter.Report( wxT("Default severity") );
443
444 const auto& messages = reporter.GetMessages();
445 BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_UNDEFINED );
446}
447
448BOOST_AUTO_TEST_CASE( ReporterInterface_UnitsDefault )
449{
450 TEST_REPORTER reporter;
451
452 BOOST_CHECK( reporter.GetUnits() == EDA_UNITS::MM );
453}
454
455BOOST_AUTO_TEST_CASE( CliProgressReporter_Singleton )
456{
459
460 BOOST_CHECK_EQUAL( &reporter1, &reporter2 );
461}
462
463BOOST_AUTO_TEST_CASE( CliProgressReporter_VerboseDefault )
464{
466
467 // Default should be non-verbose
468 BOOST_CHECK( !reporter.GetVerbose() );
469}
470
471BOOST_AUTO_TEST_CASE( CliProgressReporter_VerboseToggle )
472{
474 bool originalState = reporter.GetVerbose();
475
476 // Toggle verbose on
477 reporter.SetVerbose( true );
478 BOOST_CHECK( reporter.GetVerbose() );
479
480 // Toggle verbose off
481 reporter.SetVerbose( false );
482 BOOST_CHECK( !reporter.GetVerbose() );
483
484 // Restore original state
485 reporter.SetVerbose( originalState );
486}
487
Reporter forwarding messages to stdout or stderr as appropriate.
static CLI_PROGRESS_REPORTER & GetInstance()
void SetVerbose(bool aVerbose)
Enable or disable verbose mode.
Reporter forwarding messages to stdout or stderr as appropriate.
Definition reporter.h:236
static CLI_REPORTER & GetInstance()
Definition reporter.cpp:134
void SetVerbose(bool aVerbose)
Enable or disable verbose mode.
Definition reporter.h:250
bool GetVerbose() const
Definition reporter.h:252
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:97
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:164
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:195
A wrapper for reporting to a wxString object.
Definition reporter.h:191
void Clear() override
Definition reporter.cpp:84
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition reporter.cpp:69
const wxString & GetMessages() const
Definition reporter.cpp:78
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")