1 /*=========================================================================
2 
3   Library:   CTK
4 
5   Copyright (c) Kitware Inc.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11       http://www.apache.org/licenses/LICENSE-2.0.txt
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 =========================================================================*/
20 
21 // Qt includes
22 #include <QDateTime>
23 #include <QFile>
24 #include <QMutexLocker>
25 #include <QSharedPointer>
26 #include <QStringList>
27 #include <QTextStream>
28 #include <QTimer>
29 #include <QThread>
30 
31 // CTK includes
32 #include "ctkErrorLogModel.h"
33 
34 namespace
35 {
36 //-----------------------------------------------------------------------------
37 // Utility function
38 
39 //-----------------------------------------------------------------------------
checkRowCount(int line,int currentRowCount,int expectedRowCount)40 QString checkRowCount(int line, int currentRowCount, int expectedRowCount)
41 {
42   if (currentRowCount != expectedRowCount)
43     {
44     QString errorMsg("Line %1 - Expected rowCount: %2 - Current rowCount: %3\n");
45     return errorMsg.arg(line).arg(expectedRowCount).arg(currentRowCount);
46     }
47   return QString();
48 }
49 
50 //-----------------------------------------------------------------------------
checkSpyCount(int line,int currentSpyCount,int expectedSpyCount)51 QString checkSpyCount(int line, int currentSpyCount, int expectedSpyCount)
52 {
53   if (currentSpyCount != expectedSpyCount)
54     {
55     QString errorMsg("Line %1 - Expected spyCount: %2 - Current spyCount: %3\n");
56     return errorMsg.arg(line).arg(expectedSpyCount).arg(currentSpyCount);
57     }
58   return QString();
59 }
60 
61 //-----------------------------------------------------------------------------
checkTextMessages(int line,const QStringList & currentMessages,const QStringList & expectedMessages)62 QString checkTextMessages(int line, const QStringList& currentMessages, const QStringList& expectedMessages)
63 {
64   for(int i = 0; i < expectedMessages.count(); ++i)
65     {
66     if (!expectedMessages.contains(currentMessages.at(i)))
67       {
68       QString errorMsg("Line %1 - Problem with logged messages !\n"
69                        "\tMessage [%2] hasn't been logged !\n");
70       return errorMsg.arg(line).arg(expectedMessages.value(i));
71       }
72     }
73   return QString();
74 }
75 
76 //-----------------------------------------------------------------------------
checkTextMessages(int line,const ctkErrorLogModel & model,const QStringList & expectedMessages)77 QString checkTextMessages(int line, const ctkErrorLogModel& model, const QStringList& expectedMessages)
78 {
79   QStringList currentMessages;
80   for(int i = 0; i < expectedMessages.count(); ++i)
81     {
82     QModelIndex descriptionIndex = model.index(i, ctkErrorLogModel::DescriptionColumn);
83     currentMessages << descriptionIndex.data(ctkErrorLogModel::DescriptionTextRole).toString();
84     }
85   return checkTextMessages(line, currentMessages, expectedMessages);
86 }
87 
88 //-----------------------------------------------------------------------------
printTextMessages(const ctkErrorLogModel & model)89 void printTextMessages(const ctkErrorLogModel& model)
90 {
91   fprintf(stdout, "%s", "ErrorLogModel rows:\n");
92   QString text("\trow %1 => [%2]\n");
93   for (int i=0; i < model.rowCount(); ++i)
94     {
95     QString description =
96         model.index(i, ctkErrorLogModel::DescriptionColumn).data().toString();
97     fprintf(stdout, "%s", qPrintable(text.arg(i).arg(description)));
98     }
99   fflush(stdout);
100 }
101 
102 //-----------------------------------------------------------------------------
printErrorMessage(const QString & errorMessage)103 void printErrorMessage(const QString& errorMessage)
104 {
105   fprintf(stderr, "%s", qPrintable(errorMessage));
106   fflush(stderr);
107 }
108 
109 //-----------------------------------------------------------------------------
checkInteger(int line,const char * valueName,int current,int expected)110 QString checkInteger(int line, const char* valueName, int current, int expected)
111 {
112   if (current != expected)
113     {
114     QString errorMsg("Line %1 - Expected %2: %3 - Current %4: %5\n");
115     return errorMsg.arg(line).arg(valueName).
116         arg(expected).arg(valueName).arg(current);
117     }
118   return QString();
119 }
120 
121 //-----------------------------------------------------------------------------
checkBoolean(int line,const char * valueName,bool current,bool expected)122 QString checkBoolean(int line, const char* valueName, bool current, bool expected)
123 {
124   if (current != expected)
125     {
126     QString errorMsg("Line %1 - Expected %2: %3 - Current %4: %5\n");
127     return errorMsg.arg(line).arg(valueName).
128         arg(static_cast<int>(expected)).arg(valueName).arg(static_cast<int>(current));
129     }
130   return QString();
131 }
132 
133 //-----------------------------------------------------------------------------
checkString(int line,const char * valueName,QString current,QString expected)134 QString checkString(int line, const char* valueName, QString current, QString expected)
135 {
136   if (current != expected)
137     {
138     QString errorMsg("Line %1 - Expected %2: %3 - Current %4: %5\n");
139     return errorMsg.arg(line).arg(valueName).
140         arg(static_cast<QString>(expected)).arg(valueName).arg(static_cast<QString>(current));
141     }
142   return QString();
143 }
144 
145 //-----------------------------------------------------------------------------
processEvents(int durationInMSecs)146 void processEvents(int durationInMSecs)
147 {
148   QTimer timer;
149   timer.setSingleShot(true);
150   timer.start(durationInMSecs);
151   while(timer.isActive())
152     {
153     QCoreApplication::processEvents();
154     }
155 }
156 
157 //-----------------------------------------------------------------------------
158 QMutex AppendToFileMutex;
159 
160 //-----------------------------------------------------------------------------
appendToFile(const QString & fileName,const QString & text)161 void appendToFile(const QString& fileName, const QString& text)
162 {
163   QMutexLocker locker(&AppendToFileMutex);
164   QFile f(fileName);
165   f.open(QFile::Append);
166   QTextStream s(&f);
167   s << QDateTime::currentDateTime().toString() << " - " << text << "\n";
168   f.close();
169 }
170 
171 //-----------------------------------------------------------------------------
readFile(const QString & filePath)172 QStringList readFile(const QString& filePath)
173 {
174   QStringList lines;
175   QFile file(filePath);
176   if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
177     {
178     return lines;
179     }
180    QTextStream in(&file);
181    while(!in.atEnd())
182      {
183      lines << in.readLine();
184      }
185    file.close();
186    return lines;
187 }
188 
189 //-----------------------------------------------------------------------------
190 class LogMessageThread : public QThread
191 {
192 public:
LogMessageThread(int id,int maxIteration)193   LogMessageThread(int id, int maxIteration) :
194     Id(id), MaxIteration(maxIteration), Counter(0){}
195 
196 protected:
197   void run();
198 
199   virtual void logMessage(const QDateTime& dateTime, int threadId, int counterIdx) = 0;
200 private:
201   int Id;
202   int MaxIteration;
203   int Counter;
204 };
205 
206 //-----------------------------------------------------------------------------
run()207 void LogMessageThread::run()
208 {
209   while(this->Counter < this->MaxIteration)
210     {
211     this->logMessage(QDateTime::currentDateTime(), this->Id, this->Counter);
212     ++this->Counter;
213     }
214 }
215 
216 ////-----------------------------------------------------------------------------
217 //template<class LogMessageThreadType>
218 //class SynchronousLogMessageStarterThread : public QThread
219 //{
220 //public:
221 //  SynchronousLogMessageStarterThread(ctkErrorLogModel * errorLogModel, int threadCount, int maxIteration) :
222 //    ErrorLogModel(errorLogModel), ThreadCount(threadCount), MaxIteration(maxIteration)
223 //  {
224 //    this->ErrorLogModel->setAsynchronousLogging(false);
225 //  }
226 
227 //protected:
228 //  void run();
229 
230 //private:
231 //  QList<QSharedPointer<LogMessageThread> > ThreadList;
232 //  ctkErrorLogModel * ErrorLogModel;
233 //  int ThreadCount;
234 //  int MaxIteration;
235 //};
236 
237 ////-----------------------------------------------------------------------------
238 //template<class LogMessageThreadType>
239 //void SynchronousLogMessageStarterThread<LogMessageThreadType>::run()
240 //{
241 //  for(int i = 0; i < this->ThreadCount; ++i)
242 //    {
243 //    this->ThreadList << QSharedPointer<LogMessageThread>(new LogMessageThreadType(i, this->MaxIteration));
244 //    this->ThreadList.back()->start();
245 //    }
246 //  foreach(const QSharedPointer<LogMessageThread>& thread, this->ThreadList)
247 //    {
248 //    thread->wait();
249 //    }
250 
251 //  int expectedMessageCount = this->ThreadCount * this->MaxIteration * 2;
252 //  QString errorMsg = checkRowCount(__LINE__, this->ErrorLogModel->rowCount(),
253 //                                   /* expected = */ expectedMessageCount);
254 //  if (!errorMsg.isEmpty())
255 //    {
256 //    this->ErrorLogModel->disableAllMsgHandler();
257 //    printErrorMessage(errorMsg);
258 //    printTextMessages(*this->ErrorLogModel);
259 //    QCoreApplication::exit(EXIT_FAILURE);
260 //    }
261 //}
262 
263 //-----------------------------------------------------------------------------
264 QList<QSharedPointer<LogMessageThread> > ThreadList;
265 
266 //-----------------------------------------------------------------------------
267 template<class LogMessageThreadType>
startLogMessageThreads(int threadCount,int maxIteration)268 void startLogMessageThreads(int threadCount, int maxIteration)
269 {
270   for(int i = 0; i < threadCount; ++i)
271     {
272     ThreadList << QSharedPointer<LogMessageThread>(new LogMessageThreadType(i, maxIteration));
273     ThreadList.back()->start();
274     }
275 }
276 
277 } // end namespace
278