]>
Commit | Line | Data |
---|---|---|
ece5e6a4 VZ |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Name: tests/log/logtest.cpp | |
3 | // Purpose: wxLog unit test | |
4 | // Author: Vadim Zeitlin | |
5 | // Created: 2009-07-07 | |
ece5e6a4 VZ |
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" | |
f9136b63 | 21 | #include "wx/filefn.h" |
ece5e6a4 VZ |
22 | #endif // WX_PRECOMP |
23 | ||
bc73d5ae VZ |
24 | #include "wx/scopeguard.h" |
25 | ||
48557701 VZ |
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 | ||
c602c59b VZ |
34 | // all calls to wxLogXXX() functions from this file will use this log component |
35 | #define wxLOG_COMPONENT "test" | |
36 | ||
ece5e6a4 | 37 | // ---------------------------------------------------------------------------- |
bc73d5ae | 38 | // test loggers |
ece5e6a4 VZ |
39 | // ---------------------------------------------------------------------------- |
40 | ||
bc73d5ae VZ |
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 | |
ece5e6a4 VZ |
44 | { |
45 | public: | |
bc73d5ae | 46 | TestLogBase() { } |
ece5e6a4 | 47 | |
c602c59b | 48 | const wxString& GetLog(wxLogLevel level) const |
ece5e6a4 VZ |
49 | { |
50 | return m_logs[level]; | |
51 | } | |
52 | ||
c602c59b VZ |
53 | const wxLogRecordInfo& GetInfo(wxLogLevel level) const |
54 | { | |
55 | return m_logsInfo[level]; | |
56 | } | |
57 | ||
ece5e6a4 VZ |
58 | void Clear() |
59 | { | |
60 | for ( unsigned n = 0; n < WXSIZEOF(m_logs); n++ ) | |
c602c59b | 61 | { |
ece5e6a4 | 62 | m_logs[n].clear(); |
c602c59b VZ |
63 | m_logsInfo[n] = wxLogRecordInfo(); |
64 | } | |
ece5e6a4 VZ |
65 | } |
66 | ||
67 | protected: | |
bc73d5ae | 68 | wxString m_logs[wxLOG_Trace + 1]; |
c602c59b | 69 | wxLogRecordInfo m_logsInfo[wxLOG_Trace + 1]; |
bc73d5ae VZ |
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, | |
c602c59b | 83 | const wxLogRecordInfo& info) |
bc73d5ae VZ |
84 | { |
85 | m_logs[level] = msg; | |
c602c59b | 86 | m_logsInfo[level] = info; |
bc73d5ae VZ |
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)) | |
ece5e6a4 VZ |
105 | { |
106 | m_logs[level] = str; | |
107 | } | |
108 | ||
bc73d5ae VZ |
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 | } | |
ece5e6a4 VZ |
115 | |
116 | private: | |
bc73d5ae VZ |
117 | wxDECLARE_NO_COPY_CLASS(CompatTestLog); |
118 | }; | |
ece5e6a4 | 119 | |
bc73d5ae VZ |
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); | |
ece5e6a4 VZ |
143 | }; |
144 | ||
bc73d5ae VZ |
145 | #endif // WXWIN_COMPATIBILITY_2_8 |
146 | ||
ece5e6a4 VZ |
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 ); | |
c602c59b | 163 | CPPUNIT_TEST( Component ); |
ece5e6a4 VZ |
164 | #if wxDEBUG_LEVEL |
165 | CPPUNIT_TEST( Trace ); | |
166 | #endif // wxDEBUG_LEVEL | |
bc73d5ae VZ |
167 | #if WXWIN_COMPATIBILITY_2_8 |
168 | CPPUNIT_TEST( CompatLogger ); | |
169 | CPPUNIT_TEST( CompatLogger2 ); | |
170 | #endif // WXWIN_COMPATIBILITY_2_8 | |
b804f992 | 171 | CPPUNIT_TEST( SysError ); |
66b370d0 | 172 | CPPUNIT_TEST( NoWarnings ); |
ece5e6a4 VZ |
173 | CPPUNIT_TEST_SUITE_END(); |
174 | ||
175 | void Functions(); | |
176 | void Null(); | |
c602c59b | 177 | void Component(); |
ece5e6a4 VZ |
178 | #if wxDEBUG_LEVEL |
179 | void Trace(); | |
180 | #endif // wxDEBUG_LEVEL | |
bc73d5ae VZ |
181 | #if WXWIN_COMPATIBILITY_2_8 |
182 | void CompatLogger(); | |
183 | void CompatLogger2(); | |
184 | #endif // WXWIN_COMPATIBILITY_2_8 | |
b804f992 | 185 | void SysError(); |
66b370d0 | 186 | void NoWarnings(); |
ece5e6a4 VZ |
187 | |
188 | TestLog *m_log; | |
189 | wxLog *m_logOld; | |
190 | bool m_logWasEnabled; | |
191 | ||
192 | wxDECLARE_NO_COPY_CLASS(LogTestCase); | |
193 | }; | |
194 | ||
195 | // register in the unnamed registry so that these tests are run by default | |
196 | CPPUNIT_TEST_SUITE_REGISTRATION( LogTestCase ); | |
197 | ||
e3778b4d | 198 | // also include in its own registry so that these tests can be run alone |
ece5e6a4 VZ |
199 | CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( LogTestCase, "LogTestCase" ); |
200 | ||
201 | void LogTestCase::setUp() | |
202 | { | |
203 | m_logOld = wxLog::SetActiveTarget(m_log = new TestLog); | |
204 | m_logWasEnabled = wxLog::EnableLogging(); | |
205 | } | |
206 | ||
207 | void LogTestCase::tearDown() | |
208 | { | |
209 | delete wxLog::SetActiveTarget(m_logOld); | |
210 | wxLog::EnableLogging(m_logWasEnabled); | |
211 | } | |
212 | ||
213 | void LogTestCase::Functions() | |
214 | { | |
215 | wxLogMessage("Message"); | |
216 | CPPUNIT_ASSERT_EQUAL( "Message", m_log->GetLog(wxLOG_Message) ); | |
217 | ||
218 | wxLogError("Error %d", 17); | |
219 | CPPUNIT_ASSERT_EQUAL( "Error 17", m_log->GetLog(wxLOG_Error) ); | |
220 | ||
221 | wxLogDebug("Debug"); | |
222 | #if wxDEBUG_LEVEL | |
223 | CPPUNIT_ASSERT_EQUAL( "Debug", m_log->GetLog(wxLOG_Debug) ); | |
224 | #else | |
225 | CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Debug) ); | |
226 | #endif | |
227 | } | |
228 | ||
229 | void LogTestCase::Null() | |
230 | { | |
231 | { | |
232 | wxLogNull noLog; | |
233 | wxLogWarning("%s warning", "Not important"); | |
234 | ||
235 | CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Warning) ); | |
236 | } | |
237 | ||
238 | wxLogWarning("%s warning", "Important"); | |
239 | CPPUNIT_ASSERT_EQUAL( "Important warning", m_log->GetLog(wxLOG_Warning) ); | |
240 | } | |
241 | ||
c602c59b VZ |
242 | void LogTestCase::Component() |
243 | { | |
244 | wxLogMessage("Message"); | |
245 | CPPUNIT_ASSERT_EQUAL( wxLOG_COMPONENT, | |
246 | m_log->GetInfo(wxLOG_Message).component ); | |
247 | ||
248 | // completely disable logging for this component | |
249 | wxLog::SetComponentLevel("test/ignore", wxLOG_FatalError); | |
250 | ||
251 | // but enable it for one of its subcomponents | |
252 | wxLog::SetComponentLevel("test/ignore/not", wxLOG_Max); | |
253 | ||
254 | #undef wxLOG_COMPONENT | |
255 | #define wxLOG_COMPONENT "test/ignore" | |
256 | ||
257 | // this shouldn't be output as this component is ignored | |
258 | wxLogError("Error"); | |
259 | CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Error) ); | |
260 | ||
261 | // and so are its subcomponents | |
262 | #undef wxLOG_COMPONENT | |
263 | #define wxLOG_COMPONENT "test/ignore/sub/subsub" | |
264 | wxLogError("Error"); | |
265 | CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Error) ); | |
266 | ||
267 | // but one subcomponent is not | |
268 | #undef wxLOG_COMPONENT | |
269 | #define wxLOG_COMPONENT "test/ignore/not" | |
270 | wxLogError("Error"); | |
271 | CPPUNIT_ASSERT_EQUAL( "Error", m_log->GetLog(wxLOG_Error) ); | |
272 | ||
273 | // restore the original value | |
274 | #undef wxLOG_COMPONENT | |
275 | #define wxLOG_COMPONENT "test" | |
276 | } | |
277 | ||
ece5e6a4 VZ |
278 | #if wxDEBUG_LEVEL |
279 | ||
89d62794 VZ |
280 | namespace |
281 | { | |
282 | ||
283 | const char *TEST_MASK = "test"; | |
284 | ||
285 | // this is a test vararg function (a real one, not a variadic-template-like as | |
286 | // wxVLogTrace(), so care should be taken with its arguments) | |
287 | void TraceTest(const char *format, ...) | |
288 | { | |
289 | va_list argptr; | |
290 | va_start(argptr, format); | |
291 | wxVLogTrace(TEST_MASK, format, argptr); | |
292 | va_end(argptr); | |
293 | } | |
294 | ||
295 | } // anonymous namespace | |
296 | ||
ece5e6a4 VZ |
297 | void LogTestCase::Trace() |
298 | { | |
89d62794 VZ |
299 | // we use wxLogTrace() or wxVLogTrace() from inside TraceTest() |
300 | // interchangeably here, it shouldn't make any difference | |
ece5e6a4 VZ |
301 | |
302 | wxLogTrace(TEST_MASK, "Not shown"); | |
303 | CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Trace) ); | |
304 | ||
305 | wxLog::AddTraceMask(TEST_MASK); | |
89d62794 | 306 | TraceTest("Shown"); |
ece5e6a4 VZ |
307 | CPPUNIT_ASSERT_EQUAL( wxString::Format("(%s) Shown", TEST_MASK), |
308 | m_log->GetLog(wxLOG_Trace) ); | |
309 | ||
310 | wxLog::RemoveTraceMask(TEST_MASK); | |
311 | m_log->Clear(); | |
312 | ||
89d62794 | 313 | TraceTest("Not shown again"); |
ece5e6a4 VZ |
314 | CPPUNIT_ASSERT_EQUAL( "", m_log->GetLog(wxLOG_Trace) ); |
315 | } | |
316 | ||
317 | #endif // wxDEBUG_LEVEL | |
bc73d5ae VZ |
318 | |
319 | #if WXWIN_COMPATIBILITY_2_8 | |
320 | ||
321 | void LogTestCase::CompatLogger() | |
322 | { | |
323 | CompatTestLog log; | |
324 | wxLog * const logOld = wxLog::SetActiveTarget(&log); | |
325 | wxON_BLOCK_EXIT1( wxLog::SetActiveTarget, logOld ); | |
326 | ||
327 | wxLogError("Old error"); | |
328 | CPPUNIT_ASSERT_EQUAL( "Old error", log.GetLog(wxLOG_Error) ); | |
329 | } | |
330 | ||
331 | void LogTestCase::CompatLogger2() | |
332 | { | |
333 | CompatTestLog2 log; | |
334 | wxLog * const logOld = wxLog::SetActiveTarget(&log); | |
335 | wxON_BLOCK_EXIT1( wxLog::SetActiveTarget, logOld ); | |
336 | ||
337 | wxLogWarning("Old warning"); | |
338 | CPPUNIT_ASSERT_EQUAL( "Old warning", log.Get() ); | |
339 | } | |
340 | ||
341 | #endif // WXWIN_COMPATIBILITY_2_8 | |
b804f992 VZ |
342 | |
343 | void LogTestCase::SysError() | |
344 | { | |
345 | wxString s; | |
b804f992 VZ |
346 | |
347 | wxLogSysError(17, "Error"); | |
348 | CPPUNIT_ASSERT( m_log->GetLog(wxLOG_Error).StartsWith("Error (", &s) ); | |
3cfa70b7 VZ |
349 | WX_ASSERT_MESSAGE( ("Error message is \"(%s\"", s), s.StartsWith("error 17") ); |
350 | ||
351 | // The last error code seems to be set somewhere in MinGW CRT as its value | |
352 | // is just not what we expect (ERROR_INVALID_PARAMETER instead of 0 and 0 | |
353 | // instead of ERROR_FILE_NOT_FOUND) so exclude the tests which rely on last | |
354 | // error being preserved for this compiler. | |
355 | #ifndef __MINGW32__ | |
356 | wxLogSysError("Success"); | |
357 | CPPUNIT_ASSERT( m_log->GetLog(wxLOG_Error).StartsWith("Success (", &s) ); | |
358 | WX_ASSERT_MESSAGE( ("Error message is \"(%s\"", s), s.StartsWith("error 0") ); | |
b804f992 VZ |
359 | |
360 | wxOpen("no-such-file", 0, 0); | |
361 | wxLogSysError("Not found"); | |
362 | CPPUNIT_ASSERT( m_log->GetLog(wxLOG_Error).StartsWith("Not found (", &s) ); | |
363 | WX_ASSERT_MESSAGE( ("Error message is \"(%s\"", s), s.StartsWith("error 2") ); | |
3cfa70b7 | 364 | #endif // __MINGW32__ |
b804f992 VZ |
365 | } |
366 | ||
66b370d0 VZ |
367 | void LogTestCase::NoWarnings() |
368 | { | |
369 | // Check that "else" branch is [not] taken as expected and that this code | |
370 | // compiles without warnings (which used to not be the case). | |
371 | ||
372 | bool b = wxFalse; | |
373 | if ( b ) | |
374 | wxLogError("Not logged"); | |
375 | else | |
376 | b = !b; | |
377 | ||
378 | CPPUNIT_ASSERT( b ); | |
379 | ||
380 | if ( b ) | |
381 | wxLogError("If"); | |
382 | else | |
383 | CPPUNIT_FAIL("Should not be taken"); | |
384 | ||
385 | CPPUNIT_ASSERT_EQUAL( "If", m_log->GetLog(wxLOG_Error) ); | |
386 | } |