Remove all lines containing cvs/svn "$Id$" keyword.
[wxWidgets.git] / tests / log / logtest.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/log/logtest.cpp
3 // Purpose: wxLog unit test
4 // Author: Vadim Zeitlin
5 // Created: 2009-07-07
6 // Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
7 ///////////////////////////////////////////////////////////////////////////////
8
9 // ----------------------------------------------------------------------------
10 // headers
11 // ----------------------------------------------------------------------------
12
13 #include "testprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/log.h"
21 #include "wx/filefn.h"
22 #endif // WX_PRECOMP
23
24 #include "wx/scopeguard.h"
25
26 #if WXWIN_COMPATIBILITY_2_8
27 // we override deprecated DoLog() and DoLogString() in this test, suppress
28 // warnings about it
29 #if wxCHECK_VISUALC_VERSION(7)
30 #pragma warning(disable: 4996)
31 #endif // VC++ 7+
32 #endif // WXWIN_COMPATIBILITY_2_8
33
34 // all calls to wxLogXXX() functions from this file will use this log component
35 #define wxLOG_COMPONENT "test"
36
37 // ----------------------------------------------------------------------------
38 // test loggers
39 // ----------------------------------------------------------------------------
40
41 // base class for all test loggers which simply store all logged messages for
42 // future examination in the test code
43 class TestLogBase : public wxLog
44 {
45 public:
46 TestLogBase() { }
47
48 const wxString& GetLog(wxLogLevel level) const
49 {
50 return m_logs[level];
51 }
52
53 const wxLogRecordInfo& GetInfo(wxLogLevel level) const
54 {
55 return m_logsInfo[level];
56 }
57
58 void Clear()
59 {
60 for ( unsigned n = 0; n < WXSIZEOF(m_logs); n++ )
61 {
62 m_logs[n].clear();
63 m_logsInfo[n] = wxLogRecordInfo();
64 }
65 }
66
67 protected:
68 wxString m_logs[wxLOG_Trace + 1];
69 wxLogRecordInfo m_logsInfo[wxLOG_Trace + 1];
70
71 wxDECLARE_NO_COPY_CLASS(TestLogBase);
72 };
73
74 // simple log sink which just stores the messages logged for each level
75 class TestLog : public TestLogBase
76 {
77 public:
78 TestLog() { }
79
80 protected:
81 virtual void DoLogRecord(wxLogLevel level,
82 const wxString& msg,
83 const wxLogRecordInfo& info)
84 {
85 m_logs[level] = msg;
86 m_logsInfo[level] = info;
87 }
88
89 private:
90 wxDECLARE_NO_COPY_CLASS(TestLog);
91 };
92
93 #if WXWIN_COMPATIBILITY_2_8
94
95 // log sink overriding the old DoLogXXX() functions should still work too
96
97 // this one overrides DoLog(char*)
98 class CompatTestLog : public TestLogBase
99 {
100 public:
101 CompatTestLog() { }
102
103 protected:
104 virtual void DoLog(wxLogLevel level, const char *str, time_t WXUNUSED(t))
105 {
106 m_logs[level] = str;
107 }
108
109 // get rid of the warning about hiding the other overload
110 virtual void DoLog(wxLogLevel WXUNUSED(level),
111 const wchar_t *WXUNUSED(str),
112 time_t WXUNUSED(t))
113 {
114 }
115
116 private:
117 wxDECLARE_NO_COPY_CLASS(CompatTestLog);
118 };
119
120 // and this one overload DoLogString(wchar_t*)
121 class CompatTestLog2 : public wxLog
122 {
123 public:
124 CompatTestLog2() { }
125
126 const wxString& Get() const { return m_msg; }
127
128 protected:
129 virtual void DoLogString(const wchar_t *msg, time_t WXUNUSED(t))
130 {
131 m_msg = msg;
132 }
133
134 // get rid of the warning
135 virtual void DoLogString(const char *WXUNUSED(msg), time_t WXUNUSED(t))
136 {
137 }
138
139 private:
140 wxString m_msg;
141
142 wxDECLARE_NO_COPY_CLASS(CompatTestLog2);
143 };
144
145 #endif // WXWIN_COMPATIBILITY_2_8
146
147 // ----------------------------------------------------------------------------
148 // test class
149 // ----------------------------------------------------------------------------
150
151 class LogTestCase : public CppUnit::TestCase
152 {
153 public:
154 LogTestCase() { }
155
156 virtual void setUp();
157 virtual void tearDown();
158
159 private:
160 CPPUNIT_TEST_SUITE( LogTestCase );
161 CPPUNIT_TEST( Functions );
162 CPPUNIT_TEST( Null );
163 CPPUNIT_TEST( Component );
164 #if wxDEBUG_LEVEL
165 CPPUNIT_TEST( Trace );
166 #endif // wxDEBUG_LEVEL
167 #if WXWIN_COMPATIBILITY_2_8
168 CPPUNIT_TEST( CompatLogger );
169 CPPUNIT_TEST( CompatLogger2 );
170 #endif // WXWIN_COMPATIBILITY_2_8
171 CPPUNIT_TEST( SysError );
172 CPPUNIT_TEST_SUITE_END();
173
174 void Functions();
175 void Null();
176 void Component();
177 #if wxDEBUG_LEVEL
178 void Trace();
179 #endif // wxDEBUG_LEVEL
180 #if WXWIN_COMPATIBILITY_2_8
181 void CompatLogger();
182 void CompatLogger2();
183 #endif // WXWIN_COMPATIBILITY_2_8
184 void SysError();
185
186 TestLog *m_log;
187 wxLog *m_logOld;
188 bool m_logWasEnabled;
189
190 wxDECLARE_NO_COPY_CLASS(LogTestCase);
191 };
192
193 // register in the unnamed registry so that these tests are run by default
194 CPPUNIT_TEST_SUITE_REGISTRATION( LogTestCase );
195
196 // also include in its own registry so that these tests can be run alone
197 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( LogTestCase, "LogTestCase" );
198
199 void LogTestCase::setUp()
200 {
201 m_logOld = wxLog::SetActiveTarget(m_log = new TestLog);
202 m_logWasEnabled = wxLog::EnableLogging();
203 }
204
205 void LogTestCase::tearDown()
206 {
207 delete wxLog::SetActiveTarget(m_logOld);
208 wxLog::EnableLogging(m_logWasEnabled);
209 }
210
211 void LogTestCase::Functions()
212 {
213 wxLogMessage("Message");
214 CPPUNIT_ASSERT_EQUAL( "Message", m_log->GetLog(wxLOG_Message) );
215
216 wxLogError("Error %d", 17);
217 CPPUNIT_ASSERT_EQUAL( "Error 17", m_log->GetLog(wxLOG_Error) );
218
219 wxLogDebug("Debug");
220 #if wxDEBUG_LEVEL
221 CPPUNIT_ASSERT_EQUAL( "Debug", m_log->GetLog(wxLOG_Debug) );
222 #else
223 CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Debug) );
224 #endif
225 }
226
227 void LogTestCase::Null()
228 {
229 {
230 wxLogNull noLog;
231 wxLogWarning("%s warning", "Not important");
232
233 CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Warning) );
234 }
235
236 wxLogWarning("%s warning", "Important");
237 CPPUNIT_ASSERT_EQUAL( "Important warning", m_log->GetLog(wxLOG_Warning) );
238 }
239
240 void LogTestCase::Component()
241 {
242 wxLogMessage("Message");
243 CPPUNIT_ASSERT_EQUAL( wxLOG_COMPONENT,
244 m_log->GetInfo(wxLOG_Message).component );
245
246 // completely disable logging for this component
247 wxLog::SetComponentLevel("test/ignore", wxLOG_FatalError);
248
249 // but enable it for one of its subcomponents
250 wxLog::SetComponentLevel("test/ignore/not", wxLOG_Max);
251
252 #undef wxLOG_COMPONENT
253 #define wxLOG_COMPONENT "test/ignore"
254
255 // this shouldn't be output as this component is ignored
256 wxLogError("Error");
257 CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Error) );
258
259 // and so are its subcomponents
260 #undef wxLOG_COMPONENT
261 #define wxLOG_COMPONENT "test/ignore/sub/subsub"
262 wxLogError("Error");
263 CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Error) );
264
265 // but one subcomponent is not
266 #undef wxLOG_COMPONENT
267 #define wxLOG_COMPONENT "test/ignore/not"
268 wxLogError("Error");
269 CPPUNIT_ASSERT_EQUAL( "Error", m_log->GetLog(wxLOG_Error) );
270
271 // restore the original value
272 #undef wxLOG_COMPONENT
273 #define wxLOG_COMPONENT "test"
274 }
275
276 #if wxDEBUG_LEVEL
277
278 namespace
279 {
280
281 const char *TEST_MASK = "test";
282
283 // this is a test vararg function (a real one, not a variadic-template-like as
284 // wxVLogTrace(), so care should be taken with its arguments)
285 void TraceTest(const char *format, ...)
286 {
287 va_list argptr;
288 va_start(argptr, format);
289 wxVLogTrace(TEST_MASK, format, argptr);
290 va_end(argptr);
291 }
292
293 } // anonymous namespace
294
295 void LogTestCase::Trace()
296 {
297 // we use wxLogTrace() or wxVLogTrace() from inside TraceTest()
298 // interchangeably here, it shouldn't make any difference
299
300 wxLogTrace(TEST_MASK, "Not shown");
301 CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Trace) );
302
303 wxLog::AddTraceMask(TEST_MASK);
304 TraceTest("Shown");
305 CPPUNIT_ASSERT_EQUAL( wxString::Format("(%s) Shown", TEST_MASK),
306 m_log->GetLog(wxLOG_Trace) );
307
308 wxLog::RemoveTraceMask(TEST_MASK);
309 m_log->Clear();
310
311 TraceTest("Not shown again");
312 CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Trace) );
313 }
314
315 #endif // wxDEBUG_LEVEL
316
317 #if WXWIN_COMPATIBILITY_2_8
318
319 void LogTestCase::CompatLogger()
320 {
321 CompatTestLog log;
322 wxLog * const logOld = wxLog::SetActiveTarget(&log);
323 wxON_BLOCK_EXIT1( wxLog::SetActiveTarget, logOld );
324
325 wxLogError("Old error");
326 CPPUNIT_ASSERT_EQUAL( "Old error", log.GetLog(wxLOG_Error) );
327 }
328
329 void LogTestCase::CompatLogger2()
330 {
331 CompatTestLog2 log;
332 wxLog * const logOld = wxLog::SetActiveTarget(&log);
333 wxON_BLOCK_EXIT1( wxLog::SetActiveTarget, logOld );
334
335 wxLogWarning("Old warning");
336 CPPUNIT_ASSERT_EQUAL( "Old warning", log.Get() );
337 }
338
339 #endif // WXWIN_COMPATIBILITY_2_8
340
341 void LogTestCase::SysError()
342 {
343 wxString s;
344
345 wxLogSysError(17, "Error");
346 CPPUNIT_ASSERT( m_log->GetLog(wxLOG_Error).StartsWith("Error (", &s) );
347 WX_ASSERT_MESSAGE( ("Error message is \"(%s\"", s), s.StartsWith("error 17") );
348
349 // The last error code seems to be set somewhere in MinGW CRT as its value
350 // is just not what we expect (ERROR_INVALID_PARAMETER instead of 0 and 0
351 // instead of ERROR_FILE_NOT_FOUND) so exclude the tests which rely on last
352 // error being preserved for this compiler.
353 #ifndef __MINGW32__
354 wxLogSysError("Success");
355 CPPUNIT_ASSERT( m_log->GetLog(wxLOG_Error).StartsWith("Success (", &s) );
356 WX_ASSERT_MESSAGE( ("Error message is \"(%s\"", s), s.StartsWith("error 0") );
357
358 wxOpen("no-such-file", 0, 0);
359 wxLogSysError("Not found");
360 CPPUNIT_ASSERT( m_log->GetLog(wxLOG_Error).StartsWith("Not found (", &s) );
361 WX_ASSERT_MESSAGE( ("Error message is \"(%s\"", s), s.StartsWith("error 2") );
362 #endif // __MINGW32__
363 }
364