Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
81
86
91
96
101
106
114
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}
153
170{
173 addFailure("Not all expected messages were received");
174 }
175
176 // If the current test hasn't failed or been skipped, then it passes.
180 else
182 }
183
186}
187
204
209
211{
212 return QTest::currentTestData ? QTest::currentTestData->dataTag() : nullptr;
213}
214
216{
218}
219
220static bool isExpectFailData(const char *dataIndex)
221{
222 if (!dataIndex || dataIndex[0] == '\0')
223 return true;
225 return false;
226 if (strcmp(dataIndex, QTest::currentTestData->dataTag()) == 0)
227 return true;
228 return false;
229}
230
231bool QTestResult::expectFail(const char *dataIndex, const char *comment,
232 QTest::TestFailMode mode, const char *file, int line)
233{
234 QTEST_ASSERT(comment);
235 QTEST_ASSERT(mode > 0);
236
237 if (!isExpectFailData(dataIndex)) {
238 delete[] comment;
239 return true; // we don't care
240 }
241
243 delete[] comment;
244 addFailure("Already expecting a fail", file, line);
245 return false;
246 }
247
249 QTest::expectFailComment = comment;
250 return true;
251}
252
253static bool checkStatement(bool statement, const char *msg, const char *file, int line)
254{
255 if (statement) {
259 else
261
262 QTest::setFailed(true);
263 // Should B?XPass always (a) continue or (b) abort, regardless of mode ?
264 bool doContinue = (QTest::expectFailMode == QTest::Continue);
266 return doContinue;
267 }
268 return true;
269 }
270
274 else
276 bool doContinue = (QTest::expectFailMode == QTest::Continue);
278 return doContinue;
279 }
280
282 return false;
283}
284
285void QTestResult::fail(const char *msg, const char *file, int line)
286{
287 checkStatement(false, msg, file, line);
288}
289
290// QPalette's << operator produces 1363 characters. A comparison failure
291// involving two palettes can therefore require 2726 characters, not including
292// the other output produced by QTest. Users might also have their own types
293// with large amounts of output, so use a sufficiently high value here.
294static constexpr size_t maxMsgLen = 4096;
295
296bool QTestResult::verify(bool statement, const char *statementStr,
297 const char *description, const char *file, int line)
298{
299 QTEST_ASSERT(statementStr);
300
301 char msg[maxMsgLen];
302 msg[0] = '\0';
303
304 if (QTestLog::verboseLevel() >= 2) {
305 qsnprintf(msg, maxMsgLen, "QVERIFY(%s)", statementStr);
306 QTestLog::info(msg, file, line);
307 }
308
309 if (statement == !!QTest::expectFailMode) {
310 qsnprintf(msg, maxMsgLen,
311 statement ? "'%s' returned TRUE unexpectedly. (%s)" : "'%s' returned FALSE. (%s)",
312 statementStr, description ? description : "");
313 }
314
315 return checkStatement(statement, msg, file, line);
316}
317
319{
320 return op == QTest::ComparisonOperation::CustomCompare ? "Actual " : "Computed ";
321}
322
324{
325 return op == QTest::ComparisonOperation::CustomCompare ? "Expected " : "Baseline ";
326}
327
328// Overload to format failures for "const char *" - no need to strdup().
329void formatFailMessage(char *msg, size_t maxMsgLen,
330 const char *failureMsg,
331 const char *val1, const char *val2,
332 const char *actual, const char *expected,
334{
335 size_t len1 = mbstowcs(nullptr, actual, maxMsgLen); // Last parameter is not ignored on QNX
336 size_t len2 = mbstowcs(nullptr, expected, maxMsgLen); // (result is never larger than this).
337 const int written = qsnprintf(msg, maxMsgLen, "%s\n", failureMsg);
338 msg += written;
339 maxMsgLen -= written;
340
341 if (val1 || val2) {
342 qsnprintf(msg, maxMsgLen, " %s(%s)%*s %s\n %s(%s)%*s %s",
343 leftArgNameForOp(op), actual, qMax(len1, len2) - len1 + 1, ":",
344 val1 ? val1 : "<null>",
345 rightArgNameForOp(op), expected, qMax(len1, len2) - len2 + 1, ":",
346 val2 ? val2 : "<null>");
347 } else {
348 // only print variable names if neither value can be represented as a string
349 qsnprintf(msg, maxMsgLen, " %s: %s\n %s: %s",
351 }
352}
353
354// Format failures using the toString() template
355template <class Actual, class Expected>
356void formatFailMessage(char *msg, size_t maxMsgLen,
357 const char *failureMsg,
358 const Actual &val1, const Expected &val2,
359 const char *actual, const char *expected,
361{
362 const char *val1S = QTest::toString(val1);
363 const char *val2S = QTest::toString(val2);
364
365 formatFailMessage(msg, maxMsgLen, failureMsg, val1S, val2S, actual, expected, op);
366
367 delete [] val1S;
368 delete [] val2S;
369}
370
371template <class Actual, class Expected>
372static bool compareHelper(bool success, const char *failureMsg,
373 const Actual &val1, const Expected &val2,
374 const char *actual, const char *expected,
375 const char *file, int line,
376 bool hasValues = true)
377{
378 char msg[maxMsgLen];
379 msg[0] = '\0';
380
382 QTEST_ASSERT(actual);
383
384 if (QTestLog::verboseLevel() >= 2) {
385 qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected);
386 QTestLog::info(msg, file, line);
387 }
388
389 if (!failureMsg)
390 failureMsg = "Compared values are not the same";
391
392 if (success) {
394 qsnprintf(msg, maxMsgLen,
395 "QCOMPARE(%s, %s) returned TRUE unexpectedly.", actual, expected);
396 }
397 return checkStatement(success, msg, file, line);
398 }
399
400
401 if (!hasValues) {
402 qsnprintf(msg, maxMsgLen, "%s", failureMsg);
403 return checkStatement(success, msg, file, line);
404 }
405
406 formatFailMessage(msg, maxMsgLen, failureMsg, val1, val2, actual, expected,
408
409 return checkStatement(success, msg, file, line);
410}
411
412// A simplified version of compareHelper that does not use string
413// representations of the values, and prints only failureMsg when the
414// comparison fails.
415static bool compareHelper(bool success, const char *failureMsg,
416 const char *actual, const char *expected,
417 const char *file, int line)
418{
419 const size_t maxMsgLen = 1024;
420 char msg[maxMsgLen];
421 msg[0] = '\0';
422
424 QTEST_ASSERT(actual);
425 // failureMsg can be null, if we do not use it
426 QTEST_ASSERT(success || failureMsg);
427
428 if (QTestLog::verboseLevel() >= 2) {
429 qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected);
430 QTestLog::info(msg, file, line);
431 }
432
433 if (success) {
435 qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s) returned TRUE unexpectedly.",
436 actual, expected);
437 }
438 return checkStatement(success, msg, file, line);
439 }
440
441 return checkStatement(success, failureMsg, file, line);
442}
443
444bool QTestResult::compare(bool success, const char *failureMsg,
445 char *val1, char *val2,
446 const char *actual, const char *expected,
447 const char *file, int line)
448{
449 const bool result = compareHelper(success, failureMsg,
450 val1 != nullptr ? val1 : "<null>",
451 val2 != nullptr ? val2 : "<null>",
452 actual, expected, file, line,
453 val1 != nullptr && val2 != nullptr);
454
455 // Our caller got these from QTest::toString()
456 delete [] val1;
457 delete [] val2;
458
459 return result;
460}
461
462bool QTestResult::compare(bool success, const char *failureMsg,
463 double val1, double val2,
464 const char *actual, const char *expected,
465 const char *file, int line)
466{
467 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
468}
469
470bool QTestResult::compare(bool success, const char *failureMsg,
471 float val1, float val2,
472 const char *actual, const char *expected,
473 const char *file, int line)
474{
475 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
476}
477
478bool QTestResult::compare(bool success, const char *failureMsg,
479 int val1, int val2,
480 const char *actual, const char *expected,
481 const char *file, int line)
482{
483 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
484}
485
486#if QT_POINTER_SIZE == 8
487bool QTestResult::compare(bool success, const char *failureMsg,
488 qsizetype val1, qsizetype val2,
489 const char *actual, const char *expected,
490 const char *file, int line)
491{
492 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
493}
494#endif // QT_POINTER_SIZE == 8
495
496bool QTestResult::compare(bool success, const char *failureMsg,
497 unsigned val1, unsigned val2,
498 const char *actual, const char *expected,
499 const char *file, int line)
500{
501 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
502}
503
504bool QTestResult::compare(bool success, const char *failureMsg,
505 QStringView val1, QStringView val2,
506 const char *actual, const char *expected,
507 const char *file, int line)
508{
509 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
510}
511
512bool QTestResult::compare(bool success, const char *failureMsg,
513 QStringView val1, const QLatin1StringView &val2,
514 const char *actual, const char *expected,
515 const char *file, int line)
516{
517 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
518}
519
520bool QTestResult::compare(bool success, const char *failureMsg,
521 const QLatin1StringView & val1, QStringView val2,
522 const char *actual, const char *expected,
523 const char *file, int line)
524{
525 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
526}
527
528// Simplified version of compare() that does not take the values, because they
529// can't be converted to strings (or the user didn't want to do that).
530bool QTestResult::compare(bool success, const char *failureMsg,
531 const char *actual, const char *expeceted,
532 const char *file, int line)
533{
534 return compareHelper(success, failureMsg, actual, expeceted, file, line);
535}
536
537void QTestResult::addFailure(const char *message, const char *file, int line)
538{
540 if (qApp && QThread::currentThread() == qApp->thread())
541 QTestEventLoop::instance().exitLoop();
542
545 else
547 QTest::setFailed(true);
548}
549
550void QTestResult::addSkip(const char *message, const char *file, int line)
551{
553
555}
556
561
566
571
576
577void QTestResult::setCurrentAppName(const char *appName)
578{
579 ::currentAppName = appName;
580}
581
583{
584 return ::currentAppName;
585}
586
588{
589 using namespace QTest;
590 switch (op) {
591 case ComparisonOperation::CustomCompare:
592 return "QCOMPARE"; /* not used */
593 case ComparisonOperation::Equal:
594 return "QCOMPARE_EQ";
595 case ComparisonOperation::NotEqual:
596 return "QCOMPARE_NE";
597 case ComparisonOperation::LessThan:
598 return "QCOMPARE_LT";
599 case ComparisonOperation::LessThanOrEqual:
600 return "QCOMPARE_LE";
601 case ComparisonOperation::GreaterThan:
602 return "QCOMPARE_GT";
603 case ComparisonOperation::GreaterThanOrEqual:
604 return "QCOMPARE_GE";
605 }
606 Q_UNREACHABLE_RETURN("");
607}
608
610{
611 using namespace QTest;
612 switch (op) {
613 case ComparisonOperation::CustomCompare:
614 return "Compared values are not the same"; /* not used */
615 case ComparisonOperation::Equal:
616 return "The computed value is expected to be equal to the baseline, but is not";
617 case ComparisonOperation::NotEqual:
618 return "The computed value is expected to be different from the baseline, but is not";
619 case ComparisonOperation::LessThan:
620 return "The computed value is expected to be less than the baseline, but is not";
621 case ComparisonOperation::LessThanOrEqual:
622 return "The computed value is expected to be less than or equal to the baseline, but is not";
623 case ComparisonOperation::GreaterThan:
624 return "The computed value is expected to be greater than the baseline, but is not";
625 case ComparisonOperation::GreaterThanOrEqual:
626 return "The computed value is expected to be greater than or equal to the baseline, but is not";
627 }
628 Q_UNREACHABLE_RETURN("");
629}
630
631bool QTestResult::reportResult(bool success, const void *lhs, const void *rhs,
632 const char *(*lhsFormatter)(const void*),
633 const char *(*rhsFormatter)(const void*),
634 const char *lhsExpr, const char *rhsExpr,
635 QTest::ComparisonOperation op, const char *file, int line,
636 const char *failureMessage)
637{
638 char msg[maxMsgLen];
639 msg[0] = '\0';
640
641 QTEST_ASSERT(lhsExpr);
642 QTEST_ASSERT(rhsExpr);
643
644 if (QTestLog::verboseLevel() >= 2) {
645 qsnprintf(msg, maxMsgLen, "%s(%s, %s)", macroNameForOp(op), lhsExpr, rhsExpr);
646 QTestLog::info(msg, file, line);
647 }
648
649 if (success) {
651 qsnprintf(msg, maxMsgLen, "%s(%s, %s) returned TRUE unexpectedly.",
652 macroNameForOp(op), lhsExpr, rhsExpr);
653 }
654 return checkStatement(success, msg, file, line);
655 }
656
657 const std::unique_ptr<const char[]> lhsPtr{ lhsFormatter(lhs) };
658 const std::unique_ptr<const char[]> rhsPtr{ rhsFormatter(rhs) };
659
660 if (!failureMessage)
661 failureMessage = failureMessageForOp(op);
662
663 formatFailMessage(msg, maxMsgLen, failureMessage, lhsPtr.get(), rhsPtr.get(),
664 lhsExpr, rhsExpr, op);
665
666 return checkStatement(success, msg, file, line);
667}
668
\inmodule QtCore
Definition qstringview.h:78
static QTestEventLoop & instance()
static void clearCurrentTestState()
Definition qtestlog.cpp:326
static void addPass(const char *msg)
Definition qtestlog.cpp:333
static int verboseLevel()
Definition qtestlog.cpp:609
static void addSkip(const char *msg, const char *file, int line)
Definition qtestlog.cpp:454
static void addFail(const char *msg, const char *file, int line)
Definition qtestlog.cpp:348
static void enterTestData(QTestData *data)
Definition qtestlog.cpp:265
static void enterTestFunction(const char *function)
Definition qtestlog.cpp:253
static void addXPass(const char *msg, const char *file, int line)
Definition qtestlog.cpp:378
static void addXFail(const char *msg, const char *file, int line)
Definition qtestlog.cpp:368
static void addBPass(const char *msg)
Definition qtestlog.cpp:396
static int unhandledIgnoreMessages()
Definition qtestlog.cpp:273
static void addBFail(const char *msg, const char *file, int line)
Definition qtestlog.cpp:408
static void addBXFail(const char *msg, const char *file, int line)
Definition qtestlog.cpp:444
static void info(const char *msg, const char *file, int line)
Definition qtestlog.cpp:596
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:426
static void resetCounters()
Definition qtestlog.cpp:688
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 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 bool reportResult(bool success, const void *lhs, const void *rhs, const char *(*lhsFormatter)(const void *), const char *(*rhsFormatter)(const void *), const char *lhsExpr, const char *rhsExpr, QTest::ComparisonOperation op, const char *file, int line, const char *failureMessage=nullptr)
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:1039
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
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLsizei const GLchar * message
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:11
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 constexpr size_t maxMsgLen
static const char * leftArgNameForOp(QTest::ComparisonOperation op)
static void clearExpectFail()
ptrdiff_t qsizetype
Definition qtypes.h:165
QFile file
[0]