Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qtestresult.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtTest/private/qtestresult_p.h>
5#include <QtCore/qglobal.h>
6#include <QtCore/qstringview.h>
7
8#include <QtTest/private/qtestlog_p.h>
9#include <QtTest/qtest.h> // toString() specializations for QStringView
10#include <QtTest/qtestdata.h>
11#include <QtTest/qtestcase.h>
12#include <QtTest/qtestassert.h>
13#include <QtTest/qtesteventloop.h>
14
15#include <stdlib.h>
16#include <stdio.h>
17#include <string.h>
18
19static const char *currentAppName = nullptr;
20
22
23namespace QTest
24{
25 namespace Internal {
26 static bool failed = false;
27 }
28
29 static void setFailed(bool failed)
30 {
31 static const bool fatalFailure = []() {
32 static const char * const environmentVar = "QTEST_FATAL_FAIL";
33 if (!qEnvironmentVariableIsSet(environmentVar))
34 return false;
35
36 bool ok;
37 const int fatal = qEnvironmentVariableIntValue(environmentVar, &ok);
38 return ok && fatal;
39 }();
40
41 if (failed && fatalFailure)
42 qTerminate();
43 Internal::failed = failed;
44 }
45
46 static void resetFailed()
47 {
48 setFailed(false);
49 }
50
51 static bool hasFailed()
52 {
53 return Internal::failed;
54 }
55
56 static QTestData *currentTestData = nullptr;
58 static const char *currentTestFunc = nullptr;
59 static const char *currentTestObjectName = nullptr;
60 static bool skipCurrentTest = false;
61 static bool blacklistCurrentTest = false;
62
63 static const char *expectFailComment = nullptr;
64 static int expectFailMode = 0;
65}
66
68{
69 QTest::currentTestData = nullptr;
71 QTest::currentTestFunc = nullptr;
74
78
80}
81
83{
85}
86
88{
89 return QTest::hasFailed();
90}
91
93{
95}
96
98{
100}
101
103{
105}
106
108{
111 if (data)
113}
114
116{
119 if (func)
121}
122
123static void clearExpectFail()
124{
126 delete [] const_cast<char *>(QTest::expectFailComment);
127 QTest::expectFailComment = nullptr;
128}
129
147{
149 addFailure("QEXPECT_FAIL was called without any subsequent verification statements");
150
152
155 addFailure("Not all expected messages were received");
156 }
159}
160
177{
178 // If the current test hasn't failed or been skipped, then it passes.
182 else
184 }
185
188}
189
199{
200 QTestLog::clearCurrentTestState(); // Needed if _data() skipped.
202
203 QTest::currentTestFunc = nullptr;
205}
206
208{
210}
211
213{
215}
216
218{
220}
221
222static bool isExpectFailData(const char *dataIndex)
223{
224 if (!dataIndex || dataIndex[0] == '\0')
225 return true;
227 return false;
228 if (strcmp(dataIndex, QTest::currentTestData->dataTag()) == 0)
229 return true;
230 return false;
231}
232
233bool QTestResult::expectFail(const char *dataIndex, const char *comment,
234 QTest::TestFailMode mode, const char *file, int line)
235{
236 QTEST_ASSERT(comment);
237 QTEST_ASSERT(mode > 0);
238
239 if (!isExpectFailData(dataIndex)) {
240 delete[] comment;
241 return true; // we don't care
242 }
243
245 delete[] comment;
246 addFailure("Already expecting a fail", file, line);
247 return false;
248 }
249
251 QTest::expectFailComment = comment;
252 return true;
253}
254
255static bool checkStatement(bool statement, const char *msg, const char *file, int line)
256{
257 if (statement) {
261 else
263
264 QTest::setFailed(true);
265 // Should B?XPass always (a) continue or (b) abort, regardless of mode ?
266 bool doContinue = (QTest::expectFailMode == QTest::Continue);
268 return doContinue;
269 }
270 return true;
271 }
272
276 else
278 bool doContinue = (QTest::expectFailMode == QTest::Continue);
280 return doContinue;
281 }
282
284 return false;
285}
286
287void QTestResult::fail(const char *msg, const char *file, int line)
288{
289 checkStatement(false, msg, file, line);
290}
291
292bool QTestResult::verify(bool statement, const char *statementStr,
293 const char *description, const char *file, int line)
294{
295 QTEST_ASSERT(statementStr);
296
297 char msg[1024];
298 msg[0] = '\0';
299
300 if (QTestLog::verboseLevel() >= 2) {
301 qsnprintf(msg, 1024, "QVERIFY(%s)", statementStr);
302 QTestLog::info(msg, file, line);
303 }
304
305 if (statement == !!QTest::expectFailMode) {
306 qsnprintf(msg, 1024,
307 statement ? "'%s' returned TRUE unexpectedly. (%s)" : "'%s' returned FALSE. (%s)",
308 statementStr, description ? description : "");
309 }
310
311 return checkStatement(statement, msg, file, line);
312}
313
315{
316 return op == QTest::ComparisonOperation::CustomCompare ? "Actual " : "Computed ";
317}
318
320{
321 return op == QTest::ComparisonOperation::CustomCompare ? "Expected " : "Baseline ";
322}
323
324// Overload to format failures for "const char *" - no need to strdup().
325void formatFailMessage(char *msg, size_t maxMsgLen,
326 const char *failureMsg,
327 const char *val1, const char *val2,
328 const char *actual, const char *expected,
330{
331 size_t len1 = mbstowcs(nullptr, actual, maxMsgLen); // Last parameter is not ignored on QNX
332 size_t len2 = mbstowcs(nullptr, expected, maxMsgLen); // (result is never larger than this).
333 const int written = qsnprintf(msg, maxMsgLen, "%s\n", failureMsg);
334 msg += written;
335 maxMsgLen -= written;
336
337 if (val1 || val2) {
338 qsnprintf(msg, maxMsgLen, " %s(%s)%*s %s\n %s(%s)%*s %s",
339 leftArgNameForOp(op), actual, qMax(len1, len2) - len1 + 1, ":",
340 val1 ? val1 : "<null>",
341 rightArgNameForOp(op), expected, qMax(len1, len2) - len2 + 1, ":",
342 val2 ? val2 : "<null>");
343 } else {
344 // only print variable names if neither value can be represented as a string
345 qsnprintf(msg, maxMsgLen, " %s: %s\n %s: %s",
347 }
348}
349
350// Format failures using the toString() template
351template <class Actual, class Expected>
352void formatFailMessage(char *msg, size_t maxMsgLen,
353 const char *failureMsg,
354 const Actual &val1, const Expected &val2,
355 const char *actual, const char *expected,
357{
358 const char *val1S = QTest::toString(val1);
359 const char *val2S = QTest::toString(val2);
360
361 formatFailMessage(msg, maxMsgLen, failureMsg, val1S, val2S, actual, expected, op);
362
363 delete [] val1S;
364 delete [] val2S;
365}
366
367template <class Actual, class Expected>
368static bool compareHelper(bool success, const char *failureMsg,
369 const Actual &val1, const Expected &val2,
370 const char *actual, const char *expected,
371 const char *file, int line,
372 bool hasValues = true)
373{
374 const size_t maxMsgLen = 1024;
375 char msg[maxMsgLen];
376 msg[0] = '\0';
377
379 QTEST_ASSERT(actual);
380
381 if (QTestLog::verboseLevel() >= 2) {
382 qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected);
383 QTestLog::info(msg, file, line);
384 }
385
386 if (!failureMsg)
387 failureMsg = "Compared values are not the same";
388
389 if (success) {
391 qsnprintf(msg, maxMsgLen,
392 "QCOMPARE(%s, %s) returned TRUE unexpectedly.", actual, expected);
393 }
394 return checkStatement(success, msg, file, line);
395 }
396
397
398 if (!hasValues) {
399 qsnprintf(msg, maxMsgLen, "%s", failureMsg);
400 return checkStatement(success, msg, file, line);
401 }
402
403 formatFailMessage(msg, maxMsgLen, failureMsg, val1, val2, actual, expected,
405
406 return checkStatement(success, msg, file, line);
407}
408
409// A simplified version of compareHelper that does not use string
410// representations of the values, and prints only failureMsg when the
411// comparison fails.
412static bool compareHelper(bool success, const char *failureMsg,
413 const char *actual, const char *expected,
414 const char *file, int line)
415{
416 const size_t maxMsgLen = 1024;
417 char msg[maxMsgLen];
418 msg[0] = '\0';
419
421 QTEST_ASSERT(actual);
422 // failureMsg can be null, if we do not use it
423 QTEST_ASSERT(success || failureMsg);
424
425 if (QTestLog::verboseLevel() >= 2) {
426 qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected);
427 QTestLog::info(msg, file, line);
428 }
429
430 if (success) {
432 qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s) returned TRUE unexpectedly.",
433 actual, expected);
434 }
435 return checkStatement(success, msg, file, line);
436 }
437
438 return checkStatement(success, failureMsg, file, line);
439}
440
441bool QTestResult::compare(bool success, const char *failureMsg,
442 char *val1, char *val2,
443 const char *actual, const char *expected,
444 const char *file, int line)
445{
446 const bool result = compareHelper(success, failureMsg,
447 val1 != nullptr ? val1 : "<null>",
448 val2 != nullptr ? val2 : "<null>",
449 actual, expected, file, line,
450 val1 != nullptr && val2 != nullptr);
451
452 // Our caller got these from QTest::toString()
453 delete [] val1;
454 delete [] val2;
455
456 return result;
457}
458
459bool QTestResult::compare(bool success, const char *failureMsg,
460 double val1, double val2,
461 const char *actual, const char *expected,
462 const char *file, int line)
463{
464 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
465}
466
467bool QTestResult::compare(bool success, const char *failureMsg,
468 float val1, float val2,
469 const char *actual, const char *expected,
470 const char *file, int line)
471{
472 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
473}
474
475bool QTestResult::compare(bool success, const char *failureMsg,
476 int val1, int val2,
477 const char *actual, const char *expected,
478 const char *file, int line)
479{
480 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
481}
482
483#if QT_POINTER_SIZE == 8
484bool QTestResult::compare(bool success, const char *failureMsg,
485 qsizetype val1, qsizetype val2,
486 const char *actual, const char *expected,
487 const char *file, int line)
488{
489 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
490}
491#endif // QT_POINTER_SIZE == 8
492
493bool QTestResult::compare(bool success, const char *failureMsg,
494 unsigned val1, unsigned val2,
495 const char *actual, const char *expected,
496 const char *file, int line)
497{
498 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
499}
500
501bool QTestResult::compare(bool success, const char *failureMsg,
502 QStringView val1, QStringView val2,
503 const char *actual, const char *expected,
504 const char *file, int line)
505{
506 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
507}
508
509bool QTestResult::compare(bool success, const char *failureMsg,
510 QStringView val1, const QLatin1StringView &val2,
511 const char *actual, const char *expected,
512 const char *file, int line)
513{
514 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
515}
516
517bool QTestResult::compare(bool success, const char *failureMsg,
518 const QLatin1StringView & val1, QStringView val2,
519 const char *actual, const char *expected,
520 const char *file, int line)
521{
522 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
523}
524
525// Simplified version of compare() that does not take the values, because they
526// can't be converted to strings (or the user didn't want to do that).
527bool QTestResult::compare(bool success, const char *failureMsg,
528 const char *actual, const char *expeceted,
529 const char *file, int line)
530{
531 return compareHelper(success, failureMsg, actual, expeceted, file, line);
532}
533
534void QTestResult::addFailure(const char *message, const char *file, int line)
535{
537 if (qApp && QThread::currentThread() == qApp->thread())
539
542 else
544 QTest::setFailed(true);
545}
546
547void QTestResult::addSkip(const char *message, const char *file, int line)
548{
550
552}
553
555{
557}
558
560{
562}
563
565{
567}
568
570{
572}
573
574void QTestResult::setCurrentAppName(const char *appName)
575{
576 ::currentAppName = appName;
577}
578
580{
581 return ::currentAppName;
582}
583
585{
586 using namespace QTest;
587 switch (op) {
588 case ComparisonOperation::CustomCompare:
589 return "QCOMPARE"; /* not used */
590 case ComparisonOperation::Equal:
591 return "QCOMPARE_EQ";
592 case ComparisonOperation::NotEqual:
593 return "QCOMPARE_NE";
594 case ComparisonOperation::LessThan:
595 return "QCOMPARE_LT";
596 case ComparisonOperation::LessThanOrEqual:
597 return "QCOMPARE_LE";
598 case ComparisonOperation::GreaterThan:
599 return "QCOMPARE_GT";
600 case ComparisonOperation::GreaterThanOrEqual:
601 return "QCOMPARE_GE";
602 }
603 Q_UNREACHABLE_RETURN("");
604}
605
607{
608 using namespace QTest;
609 switch (op) {
610 case ComparisonOperation::CustomCompare:
611 return "Compared values are not the same"; /* not used */
612 case ComparisonOperation::Equal:
613 return "The computed value is expected to be equal to the baseline, but is not";
614 case ComparisonOperation::NotEqual:
615 return "The computed value is expected to be different from the baseline, but is not";
616 case ComparisonOperation::LessThan:
617 return "The computed value is expected to be less than the baseline, but is not";
618 case ComparisonOperation::LessThanOrEqual:
619 return "The computed value is expected to be less than or equal to the baseline, but is not";
620 case ComparisonOperation::GreaterThan:
621 return "The computed value is expected to be greater than the baseline, but is not";
622 case ComparisonOperation::GreaterThanOrEqual:
623 return "The computed value is expected to be greater than or equal to the baseline, but is not";
624 }
625 Q_UNREACHABLE_RETURN("");
626}
627
628bool QTestResult::reportResult(bool success, qxp::function_ref<const char *()> lhs,
629 qxp::function_ref<const char *()> rhs,
630 const char *lhsExpr, const char *rhsExpr,
631 QTest::ComparisonOperation op, const char *file, int line,
632 const char *failureMessage)
633{
634 const size_t maxMsgLen = 1024;
635 char msg[maxMsgLen];
636 msg[0] = '\0';
637
638 QTEST_ASSERT(lhsExpr);
639 QTEST_ASSERT(rhsExpr);
640
641 if (QTestLog::verboseLevel() >= 2) {
642 qsnprintf(msg, maxMsgLen, "%s(%s, %s)", macroNameForOp(op), lhsExpr, rhsExpr);
643 QTestLog::info(msg, file, line);
644 }
645
646 if (success) {
648 qsnprintf(msg, maxMsgLen, "%s(%s, %s) returned TRUE unexpectedly.",
649 macroNameForOp(op), lhsExpr, rhsExpr);
650 }
651 return checkStatement(success, msg, file, line);
652 }
653
654 const std::unique_ptr<const char[]> lhsPtr{ lhs() };
655 const std::unique_ptr<const char[]> rhsPtr{ rhs() };
656
657 if (!failureMessage)
658 failureMessage = failureMessageForOp(op);
659
660 formatFailMessage(msg, maxMsgLen, failureMessage, lhsPtr.get(), rhsPtr.get(),
661 lhsExpr, rhsExpr, op);
662
663 return checkStatement(success, msg, file, line);
664}
665
\inmodule QtCore
Definition qstringview.h:76
const char * dataTag() const
Definition qtestdata.cpp:87
static QTestEventLoop & instance()
static void clearCurrentTestState()
Definition qtestlog.cpp:327
static void addPass(const char *msg)
Definition qtestlog.cpp:332
static int verboseLevel()
Definition qtestlog.cpp:593
static void addSkip(const char *msg, const char *file, int line)
Definition qtestlog.cpp:453
static void addFail(const char *msg, const char *file, int line)
Definition qtestlog.cpp:347
static void enterTestData(QTestData *data)
Definition qtestlog.cpp:265
static void clearFailOnWarnings()
Definition qtestlog.cpp:322
static void enterTestFunction(const char *function)
Definition qtestlog.cpp:253
static void addXPass(const char *msg, const char *file, int line)
Definition qtestlog.cpp:377
static void addXFail(const char *msg, const char *file, int line)
Definition qtestlog.cpp:367
static void addBPass(const char *msg)
Definition qtestlog.cpp:395
static int unhandledIgnoreMessages()
Definition qtestlog.cpp:273
static void addBFail(const char *msg, const char *file, int line)
Definition qtestlog.cpp:407
static void clearIgnoreMessages()
Definition qtestlog.cpp:315
static void addBXFail(const char *msg, const char *file, int line)
Definition qtestlog.cpp:443
static void info(const char *msg, const char *file, int line)
Definition qtestlog.cpp:580
static void leaveTestFunction()
Definition qtestlog.cpp:285
static void printUnhandledIgnoreMessages()
Definition qtestlog.cpp:294
static void addBXPass(const char *msg, const char *file, int line)
Definition qtestlog.cpp:425
static void resetCounters()
Definition qtestlog.cpp:667
static const char * currentTestObjectName()
static void fail(const char *message, const char *file, int line)
static const char * currentAppName()
static const char * currentGlobalDataTag()
static void finishedCurrentTestDataCleanup()
This function is called after completing each test function, including test functions that are not da...
static void finishedCurrentTestData()
This function is called after completing each test function, including test functions that are not da...
static bool expectFail(const char *dataIndex, const char *comment, QTest::TestFailMode mode, const char *file, int line)
static bool verify(bool statement, const char *statementStr, const char *extraInfo, const char *file, int line)
static bool currentTestFailed()
static void setSkipCurrentTest(bool value)
static void setCurrentAppName(const char *appName)
static void reset()
static void setCurrentTestFunction(const char *func)
static void setBlacklistCurrentTest(bool b)
static void setCurrentTestObject(const char *name)
static const char * currentDataTag()
static bool compare(bool success, const char *failureMsg, char *val1, char *val2, const char *actual, const char *expected, const char *file, int line)
static void addFailure(const char *message, const char *file=nullptr, int line=0)
static bool skipCurrentTest()
static bool reportResult(bool success, qxp::function_ref< const char *()> lhs, qxp::function_ref< const char *()> rhs, const char *lhsExpr, const char *rhsExpr, QTest::ComparisonOperation op, const char *file, int line, const char *failureMessage=nullptr)
static void setCurrentGlobalTestData(QTestData *data)
static void finishedCurrentTestFunction()
This function is called after completing each test function, including test functions that are data-d...
static void setCurrentTestData(QTestData *data)
static void addSkip(const char *message, const char *file, int line)
static QTestData * currentGlobalTestData()
static QTestData * currentTestData()
static const char * currentTestFunction()
static QThread * currentThread()
Definition qthread.cpp:966
QJSValue expected
Definition qjsengine.cpp:12
Combined button and popup list for selecting options.
static bool failed
static QTestData * currentGlobalTestData
static void resetFailed()
static QTestData * currentTestData
static bool skipCurrentTest
char * toString(const MyPoint &point)
static void setFailed(bool failed)
static bool hasFailed()
static const char * currentTestFunc
ComparisonOperation
static bool blacklistCurrentTest
static int expectFailMode
static const char * expectFailComment
static const char * currentTestObjectName
Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt,...)
#define qApp
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
QT_BEGIN_NAMESPACE Q_NORETURN void qTerminate() noexcept
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLboolean GLboolean GLboolean b
GLenum mode
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLenum func
Definition qopenglext.h:663
GLuint64EXT * result
[6]
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define QTEST_ASSERT(cond)
Definition qtestassert.h:12
static const char * currentAppName
static bool checkStatement(bool statement, const char *msg, const char *file, int line)
static bool isExpectFailData(const char *dataIndex)
static const char * rightArgNameForOp(QTest::ComparisonOperation op)
static const char * failureMessageForOp(QTest::ComparisonOperation op)
void formatFailMessage(char *msg, size_t maxMsgLen, const char *failureMsg, const char *val1, const char *val2, const char *actual, const char *expected, QTest::ComparisonOperation op)
static bool compareHelper(bool success, const char *failureMsg, const Actual &val1, const Expected &val2, const char *actual, const char *expected, const char *file, int line, bool hasValues=true)
static const char * macroNameForOp(QTest::ComparisonOperation op)
static const char * leftArgNameForOp(QTest::ComparisonOperation op)
static void clearExpectFail()
ptrdiff_t qsizetype
Definition qtypes.h:70
QFile file
[0]