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