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 <QCoreApplication>
23 #include <QDebug>
24 #include <QSignalSpy>
25
26 // CTK includes
27 #include "ctkErrorLogFDMessageHandler.h"
28 #include "ctkErrorLogQtMessageHandler.h"
29 #include "ctkErrorLogStreamMessageHandler.h"
30 #include "ctkModelTester.h"
31
32 // STL includes
33 #include <cstdlib>
34 #include <iostream>
35
36 // Helper functions
37 #include "Testing/Cpp/ctkErrorLogModelTestHelper.cpp"
38
39 //-----------------------------------------------------------------------------
ctkErrorLogModelTest1(int argc,char * argv[])40 int ctkErrorLogModelTest1(int argc, char * argv [])
41 {
42 QCoreApplication app(argc, argv);
43 Q_UNUSED(app);
44 ctkErrorLogModel model;
45 ctkModelTester modelTester;
46 modelTester.setVerbose(false);
47 QString errorMsg;
48
49 QStringList enabledMessageHandlers = model.msgHandlerEnabled();
50 int currentEnabledMessageHandlersCount = enabledMessageHandlers.count();
51 errorMsg = checkInteger(__LINE__, "EnabledMessageHandlersCount", currentEnabledMessageHandlersCount, 0);
52 if (!errorMsg.isEmpty())
53 {
54 model.disableAllMsgHandler();
55 printErrorMessage(errorMsg);
56 return EXIT_FAILURE;
57 }
58
59 try
60 {
61 modelTester.setModel(&model);
62
63 // --------------------------------------------------------------------------
64 // Monitor Qt messages
65 {
66 model.registerMsgHandler(new ctkErrorLogQtMessageHandler);
67 model.setMsgHandlerEnabled(ctkErrorLogQtMessageHandler::HandlerName, true);
68
69 QSignalSpy entryAddedSpy(&model, SIGNAL(entryAdded(ctkErrorLogLevel::LogLevel)));
70
71 errorMsg = checkRowCount(__LINE__, model.logEntryCount(), /* expected = */ 0);
72 if (!errorMsg.isEmpty())
73 {
74 model.disableAllMsgHandler();
75 printErrorMessage(errorMsg);
76 printTextMessages(model);
77 return EXIT_FAILURE;
78 }
79
80 errorMsg = checkSpyCount(__LINE__, entryAddedSpy.count(), /* expected = */ 0);
81 if (!errorMsg.isEmpty())
82 {
83 model.disableAllMsgHandler();
84 printErrorMessage(errorMsg);
85 printTextMessages(model);
86 return EXIT_FAILURE;
87 }
88
89 QString qtMessage0("This is a qDebug message");
90 qDebug().nospace() << qPrintable(qtMessage0);
91
92 QString qtMessage1("This is a qWarning message");
93 qWarning().nospace() << qPrintable(qtMessage1);
94
95 QString qtMessage2("This is a qCritical message");
96 qCritical().nospace() << qPrintable(qtMessage2);
97
98 // Give enough time to the ErrorLogModel to consider the queued messages.
99 processEvents(1000);
100
101 QStringList expectedQtMessages;
102 expectedQtMessages << qtMessage0 << qtMessage1 << qtMessage2;
103
104 errorMsg = checkRowCount(__LINE__, model.logEntryCount(), /* expected = */ expectedQtMessages.count());
105 if (!errorMsg.isEmpty())
106 {
107 model.disableAllMsgHandler();
108 printErrorMessage(errorMsg);
109 printTextMessages(model);
110 return EXIT_FAILURE;
111 }
112
113 errorMsg = checkSpyCount(__LINE__, entryAddedSpy.count(), /* expected = */ expectedQtMessages.count());
114 if (!errorMsg.isEmpty())
115 {
116 model.disableAllMsgHandler();
117 printErrorMessage(errorMsg);
118 printTextMessages(model);
119 return EXIT_FAILURE;
120 }
121
122 errorMsg = checkTextMessages(__LINE__, model, expectedQtMessages);
123 if (!errorMsg.isEmpty())
124 {
125 model.disableAllMsgHandler();
126 printErrorMessage(errorMsg);
127 printTextMessages(model);
128 return EXIT_FAILURE;
129 }
130
131 // Check if msgHandlerEnabled() works as expected
132 enabledMessageHandlers = model.msgHandlerEnabled();
133 currentEnabledMessageHandlersCount = enabledMessageHandlers.count();
134 errorMsg = checkInteger(__LINE__, "EnabledMessageHandlersCount", currentEnabledMessageHandlersCount, 1);
135 if (!errorMsg.isEmpty())
136 {
137 model.disableAllMsgHandler();
138 printErrorMessage(errorMsg);
139 printTextMessages(model);
140 return EXIT_FAILURE;
141 }
142
143 // Check if handler can be enabled / disabled multiple times in a row
144 for (int idx = 0; idx < 3; ++idx)
145 {
146 model.setMsgHandlerEnabled(ctkErrorLogQtMessageHandler::HandlerName, false);
147 model.setMsgHandlerEnabled(ctkErrorLogQtMessageHandler::HandlerName, true);
148 }
149
150 // Clear
151 model.clear();
152 entryAddedSpy.clear();
153
154 // Disable Qt messages monitoring
155 model.setMsgHandlerEnabled(ctkErrorLogQtMessageHandler::HandlerName, false);
156
157 qDebug() << "This qDebug message should appear in the console";
158 qWarning() << "This qWarning message should appear in the console";
159 qCritical() << "This qCritical message should appear in the console";
160
161 errorMsg = checkRowCount(__LINE__, model.logEntryCount(), /* expected = */ 0);
162 if (!errorMsg.isEmpty())
163 {
164 model.disableAllMsgHandler();
165 printErrorMessage(errorMsg);
166 printTextMessages(model);
167 return EXIT_FAILURE;
168 }
169
170 errorMsg = checkSpyCount(__LINE__, entryAddedSpy.count(), /* expected = */ 0);
171 if (!errorMsg.isEmpty())
172 {
173 model.disableAllMsgHandler();
174 printErrorMessage(errorMsg);
175 printTextMessages(model);
176 return EXIT_FAILURE;
177 }
178 }
179
180 // --------------------------------------------------------------------------
181 // Monitor Stream messages
182 {
183 model.registerMsgHandler(new ctkErrorLogStreamMessageHandler);
184 model.setMsgHandlerEnabled(ctkErrorLogStreamMessageHandler::HandlerName, true);
185
186 QSignalSpy entryAddedSpy(&model, SIGNAL(entryAdded(ctkErrorLogLevel::LogLevel)));
187
188 // Make sure Qt message handler is still disabled
189 if (model.msgHandlerEnabled(ctkErrorLogQtMessageHandler::HandlerName))
190 {
191 model.disableAllMsgHandler();
192 errorMsg = QLatin1String("Line %1 - Qt message handler should be disabled");
193 printErrorMessage(errorMsg.arg(__LINE__));
194 printTextMessages(model);
195 return EXIT_FAILURE;
196 }
197
198 errorMsg = checkRowCount(__LINE__, model.logEntryCount(), /* expected = */ 0);
199 if (!errorMsg.isEmpty())
200 {
201 model.disableAllMsgHandler();
202 printErrorMessage(errorMsg);
203 printTextMessages(model);
204 return EXIT_FAILURE;
205 }
206
207 errorMsg = checkSpyCount(__LINE__, entryAddedSpy.count(), /* expected = */ 0);
208 if (!errorMsg.isEmpty())
209 {
210 model.disableAllMsgHandler();
211 printErrorMessage(errorMsg);
212 printTextMessages(model);
213 return EXIT_FAILURE;
214 }
215
216 QString streamMessage0("This is a Cout message");
217 std::cout << qPrintable(streamMessage0) << std::endl;
218
219 QString streamMessage1("This is a Cerr message");
220 std::cerr << qPrintable(streamMessage1) << std::endl;
221
222 // Give enough time to the ErrorLogModel to consider the queued messages.
223 processEvents(1000);
224
225 QStringList expectedStreamMessages;
226 expectedStreamMessages << streamMessage0 << streamMessage1;
227
228 errorMsg = checkRowCount(__LINE__, model.logEntryCount(), /* expected = */ expectedStreamMessages.count());
229 if (!errorMsg.isEmpty())
230 {
231 model.disableAllMsgHandler();
232 printErrorMessage(errorMsg);
233 printTextMessages(model);
234 return EXIT_FAILURE;
235 }
236
237 errorMsg = checkSpyCount(__LINE__, entryAddedSpy.count(), /* expected = */ expectedStreamMessages.count());
238 if (!errorMsg.isEmpty())
239 {
240 model.disableAllMsgHandler();
241 printErrorMessage(errorMsg);
242 printTextMessages(model);
243 return EXIT_FAILURE;
244 }
245
246 errorMsg = checkTextMessages(__LINE__, model, expectedStreamMessages);
247 if (!errorMsg.isEmpty())
248 {
249 model.disableAllMsgHandler();
250 printErrorMessage(errorMsg);
251 printTextMessages(model);
252 return EXIT_FAILURE;
253 }
254
255 // Check if handler can be enabled / disabled multiple times in a row
256 for (int idx = 0; idx < 3; ++idx)
257 {
258 model.setMsgHandlerEnabled(ctkErrorLogStreamMessageHandler::HandlerName, false);
259 model.setMsgHandlerEnabled(ctkErrorLogStreamMessageHandler::HandlerName, true);
260 }
261
262 // Clear
263 model.clear();
264 entryAddedSpy.clear();
265
266 // Disable Stream messages monitoring
267 model.setMsgHandlerEnabled(ctkErrorLogStreamMessageHandler::HandlerName, false);
268
269 std::cout << "This std::cout message should appear in the console" << std::endl;
270 std::cerr << "This std::cerr message should appear in the console" << std::endl;
271
272 errorMsg = checkRowCount(__LINE__, model.logEntryCount(), /* expected = */ 0);
273 if (!errorMsg.isEmpty())
274 {
275 model.disableAllMsgHandler();
276 printErrorMessage(errorMsg);
277 printTextMessages(model);
278 return EXIT_FAILURE;
279 }
280
281 errorMsg = checkSpyCount(__LINE__, entryAddedSpy.count(), /* expected = */ 0);
282 if (!errorMsg.isEmpty())
283 {
284 model.disableAllMsgHandler();
285 printErrorMessage(errorMsg);
286 printTextMessages(model);
287 return EXIT_FAILURE;
288 }
289 }
290
291 // --------------------------------------------------------------------------
292 // Monitor FD messages
293 {
294 model.registerMsgHandler(new ctkErrorLogFDMessageHandler);
295 model.setMsgHandlerEnabled(ctkErrorLogFDMessageHandler::HandlerName, true);
296
297 QSignalSpy entryAddedSpy(&model, SIGNAL(entryAdded(ctkErrorLogLevel::LogLevel)));
298
299 errorMsg = checkRowCount(__LINE__, model.logEntryCount(), /* expected = */ 0);
300 if (!errorMsg.isEmpty())
301 {
302 model.disableAllMsgHandler();
303 printErrorMessage(errorMsg);
304 printTextMessages(model);
305 return EXIT_FAILURE;
306 }
307
308 errorMsg = checkSpyCount(__LINE__, entryAddedSpy.count(), /* expected = */ 0);
309 if (!errorMsg.isEmpty())
310 {
311 model.disableAllMsgHandler();
312 printErrorMessage(errorMsg);
313 printTextMessages(model);
314 return EXIT_FAILURE;
315 }
316
317 QString fdMessage0("This is a stdout");
318 fprintf(stdout, "%s", qPrintable(fdMessage0));
319 QString fdMessage0b(" message");
320 fprintf(stdout, "%s\n", qPrintable(fdMessage0b));
321 fdMessage0.append(fdMessage0b);
322 fflush(stdout);
323
324 QString fdMessage1("This is a 2nd stdout message");
325 fprintf(stdout, "%s\n", qPrintable(fdMessage1));
326 fflush(stdout);
327
328 QString fdMessage2("This is a stderr");
329 fprintf(stderr, "%s", qPrintable(fdMessage2));
330 QString fdMessage2b(" message");
331 fprintf(stderr, "%s\n", qPrintable(fdMessage2b));
332 fdMessage2.append(fdMessage2b);
333 fflush(stderr);
334
335 QString fdMessage3("This is a 2nd stderr message");
336 fprintf(stderr, "%s\n", qPrintable(fdMessage3));
337 fflush(stderr);
338
339 QStringList expectedFDMessages;
340 expectedFDMessages << fdMessage0 << fdMessage1 << fdMessage2 << fdMessage3;
341
342 // Give enough time to the ErrorLogModel to consider the queued messages.
343 // and also to the QFileSystemWatcher used internally by ctkErrorLogFDMessageHandler
344 // to consider the updated files.
345 processEvents(1500);
346
347 errorMsg = checkRowCount(__LINE__, model.logEntryCount(), /* expected = */ expectedFDMessages.count());
348 if (!errorMsg.isEmpty())
349 {
350 model.disableAllMsgHandler();
351 printErrorMessage(errorMsg);
352 printTextMessages(model);
353 return EXIT_FAILURE;
354 }
355
356 errorMsg = checkSpyCount(__LINE__, entryAddedSpy.count(), /* expected = */ expectedFDMessages.count());
357 if (!errorMsg.isEmpty())
358 {
359 model.disableAllMsgHandler();
360 printErrorMessage(errorMsg);
361 printTextMessages(model);
362 return EXIT_FAILURE;
363 }
364
365 errorMsg = checkTextMessages(__LINE__, model, expectedFDMessages);
366 if (!errorMsg.isEmpty())
367 {
368 model.disableAllMsgHandler();
369 printErrorMessage(errorMsg);
370 printTextMessages(model);
371 return EXIT_FAILURE;
372 }
373
374 // Check if handler can be enabled / disabled multiple times in a row
375 for (int idx = 0; idx < 3; ++idx)
376 {
377 model.setMsgHandlerEnabled(ctkErrorLogFDMessageHandler::HandlerName, false);
378 model.setMsgHandlerEnabled(ctkErrorLogFDMessageHandler::HandlerName, true);
379 }
380
381 // Clear
382 model.clear();
383 entryAddedSpy.clear();
384
385 // Disable FD messages monitoring
386 model.setMsgHandlerEnabled(ctkErrorLogFDMessageHandler::HandlerName, false);
387
388 fprintf(stdout, "%s", "This stdout message should appear in the console\n");
389 fprintf(stderr, "%s", "This stderr message should appear in the console\n");
390 fflush(stderr);
391
392 errorMsg = checkRowCount(__LINE__, model.logEntryCount(), /* expected = */ 0);
393 if (!errorMsg.isEmpty())
394 {
395 model.disableAllMsgHandler();
396 printErrorMessage(errorMsg);
397 printTextMessages(model);
398 return EXIT_FAILURE;
399 }
400
401 errorMsg = checkSpyCount(__LINE__, entryAddedSpy.count(), /* expected = */ 0);
402 if (!errorMsg.isEmpty())
403 {
404 model.disableAllMsgHandler();
405 printErrorMessage(errorMsg);
406 printTextMessages(model);
407 return EXIT_FAILURE;
408 }
409 }
410
411 }
412 catch (const char* error)
413 {
414 model.disableAllMsgHandler();
415 std::cerr << error << std::endl;
416 return EXIT_FAILURE;
417 }
418
419 return EXIT_SUCCESS;
420 }
421