logtest.cpp 9.9 KB

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