Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkLogTest.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkCommon.h"
18 #include "mitkTestingMacros.h"
19 #include <itkMultiThreader.h>
20 #include <itksys/SystemTools.hxx>
21 #include <mitkLog.h>
22 #include <mitkNumericTypes.h>
24 
31 class TestBackendCout : public mbilog::BackendCout
32 {
33 public:
34  TestBackendCout()
35  {
36  m_Called = false;
38  }
39 
40  void ProcessMessage(const mbilog::LogMessage &l) override
41  {
42  m_Called = true;
44  }
45 
46  bool WasCalled() { return m_Called; }
47 private:
48  bool m_Called;
49 };
57 class mitkTestLoggingThread : public itk::Object
58 {
59 public:
60  mitkClassMacroItkParent(mitkTestLoggingThread, itk::Object);
61  mitkNewMacro1Param(mitkTestLoggingThread, itk::MultiThreader::Pointer);
62 
63  int NumberOfMessages;
64 
65 protected:
66  mitkTestLoggingThread(itk::MultiThreader::Pointer MultiThreader)
67  {
68  ThreadID = -1;
69  NumberOfMessages = 0;
70  m_MultiThreader = MultiThreader;
71  LoggingRunning = true;
72  }
73 
74  bool LoggingRunning;
75 
76  int ThreadID;
77 
78  itk::MultiThreader::Pointer m_MultiThreader;
79 
80  void LogMessages()
81  {
82  while (LoggingRunning)
83  {
84  MITK_INFO << "Test info stream in thread" << ThreadID << "\n even with newlines";
85  MITK_WARN << "Test warning stream in thread " << ThreadID << ". "
86  << "Even with a very long text, even without meaning or implied meaning or content, just a long "
87  "sentence to see whether something has problems with long sentences or output in files or into "
88  "windows or commandlines or whatever.";
89  MITK_DEBUG << "Test debugging stream in thread " << ThreadID;
90  MITK_ERROR << "Test error stream in thread " << ThreadID;
91  MITK_FATAL << "Test fatal stream in thread " << ThreadID;
92 
93  NumberOfMessages += 5;
94  }
95  }
96 
97  static ITK_THREAD_RETURN_TYPE ThreadStartTracking(void *pInfoStruct)
98  {
99  /* extract this pointer from Thread Info structure */
100  struct itk::MultiThreader::ThreadInfoStruct *pInfo = (struct itk::MultiThreader::ThreadInfoStruct *)pInfoStruct;
101  if (pInfo == nullptr)
102  {
103  return ITK_THREAD_RETURN_VALUE;
104  }
105  if (pInfo->UserData == nullptr)
106  {
107  return ITK_THREAD_RETURN_VALUE;
108  }
109  mitkTestLoggingThread *thisthread = (mitkTestLoggingThread *)pInfo->UserData;
110 
111  if (thisthread != nullptr)
112  thisthread->LogMessages();
113 
114  return ITK_THREAD_RETURN_VALUE;
115  }
116 
117 public:
118  int Start()
119  {
120  LoggingRunning = true;
121  this->ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this);
122  return ThreadID;
123  }
124 
125  void Stop() { LoggingRunning = false; }
126 };
127 
132 class mitkLogTestClass
133 {
134 public:
135  static void TestSimpleLog()
136  {
137  bool testSucceded = true;
138  try
139  {
140  MITK_INFO << "Test info stream.";
141  MITK_WARN << "Test warning stream.";
142  MITK_DEBUG << "Test debugging stream."; // only activated if cmake variable is on!
143  // so no worries if you see no output for this line
144  MITK_ERROR << "Test error stream.";
145  MITK_FATAL << "Test fatal stream.";
146  }
147  catch (mitk::Exception &e)
148  {
149  testSucceded = false;
150  }
151  MITK_TEST_CONDITION_REQUIRED(testSucceded, "Test logging streams.");
152  }
153 
154  static void TestObjectInfoLogging()
155  {
156  bool testSucceded = true;
157  try
158  {
159  int i = 123;
160  float f = .32234;
161  double d = 123123;
162  std::string testString = "testString";
163  std::stringstream testStringStream;
164  testStringStream << "test"
165  << "String"
166  << "Stream";
167  mitk::Point3D testMitkPoint;
168  testMitkPoint.Fill(2);
169 
170  MITK_INFO << i;
171  MITK_INFO << f;
172  MITK_INFO << d;
173  MITK_INFO << testString;
174  MITK_INFO << testStringStream.str();
175  MITK_INFO << testMitkPoint;
176  }
177  catch (mitk::Exception &e)
178  {
179  testSucceded = false;
180  }
181  MITK_TEST_CONDITION_REQUIRED(testSucceded, "Test logging of object information.");
182  }
183 
184  static void TestThreadSaveLog(bool toFile)
185  {
186  bool testSucceded = true;
187 
188  try
189  {
190  if (toFile)
191  {
192  std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + "/testthreadlog.log";
193  itksys::SystemTools::RemoveFile(filename.c_str()); // remove old file, we do not want to append to large files
194  mitk::LoggingBackend::SetLogFile(filename.c_str());
195  }
196 
197  unsigned int numberOfThreads = 20;
198  unsigned int threadRuntimeInMilliseconds = 2000;
199 
200  std::vector<unsigned int> threadIDs;
201  std::vector<mitkTestLoggingThread::Pointer> threads;
202 
204  for (unsigned int threadIdx = 0; threadIdx < numberOfThreads; ++threadIdx)
205  {
206  // initialize threads...
208  threads.push_back(newThread);
209  std::cout << "Created " << threadIdx << ". thread." << std::endl;
210  }
211 
212  for (unsigned int threadIdx = 0; threadIdx < numberOfThreads; ++threadIdx)
213  {
214  // start them
215  std::cout << "Start " << threadIdx << ". thread." << std::endl;
216  threadIDs.push_back(threads[threadIdx]->Start());
217  std::cout << threadIdx << ". thread has ID " << threadIDs[threadIdx] << std::endl;
218  }
219 
220  // wait for some time (milliseconds)
221  itksys::SystemTools::Delay(threadRuntimeInMilliseconds);
222 
223  for (unsigned int threadIdx = 0; threadIdx < numberOfThreads; ++threadIdx)
224  {
225  // stop them
226  std::cout << "Stop " << threadIdx << ". thread." << std::endl;
227  threads[threadIdx]->Stop();
228  }
229 
230  for (unsigned int threadIdx = 0; threadIdx < numberOfThreads; ++threadIdx)
231  {
232  // Wait for all threads to end
233  multiThreader->TerminateThread(threadIDs[threadIdx]);
234  std::cout << "Terminated " << threadIdx << ". thread (" << threads[threadIdx]->NumberOfMessages << " messages)."
235  << std::endl;
236  }
237  }
238  catch (std::exception &e)
239  {
240  MITK_ERROR << "exception during 'TestThreadSaveLog': " << e.what();
241  testSucceded = false;
242  }
243  catch (...)
244  {
245  MITK_ERROR << "unknown exception during 'TestThreadSaveLog'";
246  testSucceded = false;
247  }
248 
249  // if no error occured until now, everything is ok
250  MITK_TEST_CONDITION_REQUIRED(testSucceded, "Test logging in different threads.");
251  }
252 
253  static void TestLoggingToFile()
254  {
255  std::string filename = mitk::StandardFileLocations::GetInstance()->GetOptionDirectory() + "/testlog.log";
256  mitk::LoggingBackend::SetLogFile(filename.c_str());
257  MITK_INFO << "Test logging to default filename: " << mitk::LoggingBackend::GetLogFile();
258  MITK_TEST_CONDITION_REQUIRED(itksys::SystemTools::FileExists(filename.c_str()), "Testing if log file exists.");
259  // TODO delete log file?
260  }
261 
262  static void TestAddAndRemoveBackends()
263  {
265  mbilog::RegisterBackend(&myBackend);
266  MITK_INFO << "Test logging";
267  mbilog::UnregisterBackend(&myBackend);
268 
269  // if no error occured until now, everything is ok
270  MITK_TEST_CONDITION_REQUIRED(true, "Test add/remove logging backend.");
271  }
272 
273  static void TestDefaultBackend()
274  {
275  // not possible now, because we cannot unregister the mitk logging backend in the moment. If such a method is added
276  // to mbilog utility one may add this test.
277  }
278 
279  static void TestEnableDisableBackends()
280  {
281  TestBackendCout myCoutBackend = TestBackendCout();
282  mbilog::RegisterBackend(&myCoutBackend);
283 
285  MITK_INFO << "There should be no output!";
286  bool success = !myCoutBackend.WasCalled();
287 
289  MITK_INFO << "Now there should be an output.";
290  success &= myCoutBackend.WasCalled();
291 
292  mbilog::UnregisterBackend(&myCoutBackend);
293  MITK_TEST_CONDITION_REQUIRED(success, "Test disable / enable logging backends.")
294  }
295 };
296 
297 int mitkLogTest(int /* argc */, char * /*argv*/ [])
298 {
299  // always start with this!
300  MITK_TEST_BEGIN("Log")
301 
302  MITK_TEST_OUTPUT(<< "TESTING ALL LOGGING OUTPUTS, ERROR MESSAGES ARE ALSO TESTED AND NOT MEANING AN ERROR OCCURED!")
303 
304  mitkLogTestClass::TestSimpleLog();
305  mitkLogTestClass::TestObjectInfoLogging();
306 
307  mitkLogTestClass::TestLoggingToFile();
308  mitkLogTestClass::TestAddAndRemoveBackends();
309  mitkLogTestClass::TestThreadSaveLog(false); // false = to console
310  mitkLogTestClass::TestThreadSaveLog(true); // true = to file
311  mitkLogTestClass::TestEnableDisableBackends();
312  // TODO actually test file somehow?
313 
314  // always end with this!
315  MITK_TEST_END()
316 }
#define MITK_FATAL
Definition: mitkLogMacros.h:25
itk::SmartPointer< Self > Pointer
void MBILOG_EXPORT UnregisterBackend(BackendBase *backend)
Unregisters a backend.
Definition: mbilog.cpp:35
#define mitkNewMacro1Param(classname, type)
Definition: mitkCommon.h:76
#define MITK_INFO
Definition: mitkLogMacros.h:22
void MBILOG_EXPORT EnableBackends(OutputType type)
Definition: mbilog.cpp:74
#define MITK_ERROR
Definition: mitkLogMacros.h:24
void LogMessages(unsigned int threadID, unsigned int numberOfTimes)
#define MITK_TEST_CONDITION_REQUIRED(COND, MSG)
void MBILOG_EXPORT DisableBackends(OutputType type)
Definition: mbilog.cpp:79
Default backend of the mbi logging mechanism. This backend is used if no other backend is registered...
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
section GeneralTestsDeprecatedOldTestingStyle Deprecated macros All tests with MITK_TEST_BEGIN()
static void TestThreadSaveLog(bool toFile)
Test logging from Qt threads.
An object of this class represents a single logging message (logging event) of the mbi logging mechan...
#define MITK_TEST_OUTPUT(x)
Output some text.
std::string GetOptionDirectory()
Return directory of/for option files.
#define MITK_WARN
Definition: mitkLogMacros.h:23
An object of this class represents an exception of MITK. Please don't instantiate exceptions manually...
Definition: mitkException.h:49
static const std::string filename
#define mitkClassMacroItkParent(className, SuperClassName)
Definition: mitkCommon.h:53
void MBILOG_EXPORT RegisterBackend(BackendBase *backend)
Registeres a backend to the mbi logging mechanism. If a backend is registered here, all mbilog messages are relayed to this backend through the method ProcessMessage. If no backend is registered the default backend is used.
Definition: mbilog.cpp:30
static void SetLogFile(const char *file)
Sets extra log file path (additionally to the console log)
Definition: mitkLog.cpp:94
int mitkLogTest(int, char *[])
virtual void ProcessMessage(const mbilog::LogMessage &l) override
This method is called by the mbi logging mechanism if the object is registered in the mbi logging mec...
static std::string GetLogFile()
Definition: mitkLog.cpp:145
and MITK_TEST_END()
static StandardFileLocations * GetInstance()
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.