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