Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
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 <climits>
16#include <cwchar>
17#include <QtCore/q26numeric.h>
18
19#include <stdlib.h>
20#include <stdio.h>
21#include <string.h>
22
23static const char *currentAppName = nullptr;
24
25QT_BEGIN_NAMESPACE
26
27namespace QTest
28{
29 namespace Internal {
30 static bool failed = false;
31 }
32
33 static void setFailed(bool failed)
34 {
35 static const bool fatalFailure = []() {
36 static const char * const environmentVar = "QTEST_FATAL_FAIL";
37 if (!qEnvironmentVariableIsSet(environmentVar))
38 return false;
39
40 bool ok;
41 const int fatal = qEnvironmentVariableIntValue(environmentVar, &ok);
42 return ok && fatal;
43 }();
44
45 if (failed && fatalFailure)
46 std::terminate();
47 Internal::failed = failed;
48 }
49
50 static void resetFailed()
51 {
52 setFailed(false);
53 }
54
55 static bool hasFailed()
56 {
57 return Internal::failed;
58 }
59
60 static QTestData *currentTestData = nullptr;
62 static const char *currentTestFunc = nullptr;
63 static const char *currentTestObjectName = nullptr;
64 static bool skipCurrentTest = false;
65 static bool blacklistCurrentTest = false;
66
67 static const char *expectFailComment = nullptr;
68 static int expectFailMode = 0;
69}
70
71void QTestResult::reset()
72{
73 QTest::currentTestData = nullptr;
74 QTest::currentGlobalTestData = nullptr;
75 QTest::currentTestFunc = nullptr;
76 QTest::currentTestObjectName = nullptr;
77 QTest::resetFailed();
78
79 QTest::expectFailComment = nullptr;
80 QTest::expectFailMode = 0;
81 QTest::blacklistCurrentTest = false;
82
83 QTestLog::resetCounters();
84}
85
86void QTestResult::setBlacklistCurrentTest(bool b)
87{
88 QTest::blacklistCurrentTest = b;
89}
90
91bool QTestResult::currentTestFailed()
92{
93 return QTest::hasFailed();
94}
95
96QTestData *QTestResult::currentGlobalTestData()
97{
98 return QTest::currentGlobalTestData;
99}
100
101QTestData *QTestResult::currentTestData()
102{
103 return QTest::currentTestData;
104}
105
106void QTestResult::setCurrentGlobalTestData(QTestData *data)
107{
108 QTest::currentGlobalTestData = data;
109}
110
111void QTestResult::setCurrentTestData(QTestData *data)
112{
113 QTest::currentTestData = data;
114 QTest::resetFailed();
115 if (data)
116 QTestLog::enterTestData(data);
117}
118
119void QTestResult::setCurrentTestFunction(const char *func)
120{
121 QTest::currentTestFunc = func;
122 QTest::resetFailed();
123 if (func)
124 QTestLog::enterTestFunction(func);
125}
126
127static void clearExpectFail()
128{
130 delete [] const_cast<char *>(QTest::expectFailComment);
131 QTest::expectFailComment = nullptr;
132}
133
134/*!
135 This function is called after completing each test function,
136 including test functions that are not data-driven.
137
138 For data-driven functions, this is called after each call to the test
139 function, with distinct data. Otherwise, this function is called once,
140 with currentTestData() and currentGlobalTestData() set to \nullptr.
141
142 The function is called before the test's cleanup(), if it has one.
143
144 For benchmarks, this will be called after each repeat of a function
145 (with the same data row), when the benchmarking code decides to
146 re-run one to get sufficient data.
147
148 \sa finishedCurrentTestDataCleanup()
149*/
150void QTestResult::finishedCurrentTestData()
151{
152 if (QTest::expectFailMode)
153 addFailure("QEXPECT_FAIL was called without any subsequent verification statements");
154
155 clearExpectFail();
156}
157
158/*!
159 This function is called after completing each test function,
160 including test functions that are not data-driven.
161
162 For data-driven functions, this is called after each call to the test
163 function, with distinct data. Otherwise, this function is called once,
164 with currentTestData() and currentGlobalTestData() set to \nullptr.
165
166 The function is called after the test's cleanup(), if it has one.
167
168 For benchmarks, this is called after all repeat calls to the function
169 (with a given data row).
170
171 \sa finishedCurrentTestData()
172*/
173void QTestResult::finishedCurrentTestDataCleanup()
174{
175 if (!QTest::hasFailed() && QTestLog::unhandledIgnoreMessages()) {
176 QTestLog::printUnhandledIgnoreMessages();
177 addFailure("Not all expected messages were received");
178 }
179
180 // If the current test hasn't failed or been skipped, then it passes.
181 if (!QTest::hasFailed() && !QTest::skipCurrentTest) {
182 if (QTest::blacklistCurrentTest)
183 QTestLog::addBPass("");
184 else
185 QTestLog::addPass("");
186 }
187
188 QTestLog::clearCurrentTestState();
189 QTest::resetFailed();
190}
191
192/*!
193 This function is called after completing each test function,
194 including test functions that are data-driven.
195
196 For data-driven functions, this is called after after all data rows
197 have been tested, and the data table has been cleared, so both
198 currentTestData() and currentGlobalTestData() will be \nullptr.
199*/
200void QTestResult::finishedCurrentTestFunction()
201{
202 QTestLog::clearCurrentTestState(); // Needed if _data() skipped.
203 QTestLog::leaveTestFunction();
204
205 QTest::currentTestFunc = nullptr;
206 QTest::resetFailed();
207}
208
209const char *QTestResult::currentTestFunction()
210{
211 return QTest::currentTestFunc;
212}
213
214const char *QTestResult::currentDataTag()
215{
216 return QTest::currentTestData ? QTest::currentTestData->dataTag() : nullptr;
217}
218
219const char *QTestResult::currentGlobalDataTag()
220{
221 return QTest::currentGlobalTestData ? QTest::currentGlobalTestData->dataTag() : nullptr;
222}
223
224static bool isExpectFailData(const char *dataIndex)
225{
226 if (!dataIndex || dataIndex[0] == '\0')
227 return true;
228 if (!QTest::currentTestData)
229 return false;
230 if (strcmp(dataIndex, QTest::currentTestData->dataTag()) == 0)
231 return true;
232 return false;
233}
234
235bool QTestResult::expectFail(const char *dataIndex, const char *comment,
236 QTest::TestFailMode mode, const char *file, int line)
237{
238 QTEST_ASSERT(comment);
239 QTEST_ASSERT(mode > 0);
240
241 if (!isExpectFailData(dataIndex)) {
242 delete[] comment;
243 return true; // we don't care
244 }
245
246 if (QTest::expectFailMode) {
247 delete[] comment;
248 addFailure("Already expecting a fail", file, line);
249 return false;
250 }
251
252 QTest::expectFailMode = mode;
253 QTest::expectFailComment = comment;
254 return true;
255}
256
257static bool checkStatement(bool statement, const char *msg, const char *file, int line)
258{
259 if (statement) {
261 if (QTest::blacklistCurrentTest)
262 QTestLog::addBXPass(msg, file, line);
263 else
264 QTestLog::addXPass(msg, file, line);
265
267 // Should B?XPass always (a) continue or (b) abort, regardless of mode ?
268 bool doContinue = (QTest::expectFailMode == QTest::Continue);
270 return doContinue;
271 }
272 return true;
273 }
274
276 if (QTest::blacklistCurrentTest)
277 QTestLog::addBXFail(QTest::expectFailComment, file, line);
278 else
279 QTestLog::addXFail(QTest::expectFailComment, file, line);
280 bool doContinue = (QTest::expectFailMode == QTest::Continue);
282 return doContinue;
283 }
284
285 QTestResult::addFailure(msg, file, line);
286 return false;
287}
288
289void QTestResult::fail(const char *msg, const char *file, int line)
290{
291 checkStatement(false, msg, file, line);
292}
293
294// QPalette's << operator produces 1363 characters. A comparison failure
295// involving two palettes can therefore require 2726 characters, not including
296// the other output produced by QTest. Users might also have their own types
297// with large amounts of output, so use a sufficiently high value here.
298static constexpr size_t maxMsgLen = 4096;
299
300bool QTestResult::verify(bool statement, const char *statementStr,
301 const char *description, const char *file, int line)
302{
303 QTEST_ASSERT(statementStr);
304
305 Q_DECL_UNINITIALIZED char msg[maxMsgLen];
306 msg[0] = '\0';
307
308 if (QTestLog::verboseLevel() >= 2) {
309 std::snprintf(msg, maxMsgLen, "QVERIFY(%s)", statementStr);
310 QTestLog::info(msg, file, line);
311 }
312
313 if (statement == !!QTest::expectFailMode) {
314 std::snprintf(msg, maxMsgLen,
315 statement ? "'%s' returned TRUE unexpectedly. (%s)" : "'%s' returned FALSE. (%s)",
316 statementStr, description ? description : "");
317 }
318
319 return checkStatement(statement, msg, file, line);
320}
321
322static const char *leftArgNameForOp(QTest::ComparisonOperation op)
323{
324 switch (op) {
325 case QTest::ComparisonOperation::CustomCompare:
326 return "Actual ";
327 case QTest::ComparisonOperation::ThreeWayCompare:
328 return "Left ";
329 case QTest::ComparisonOperation::Equal:
330 case QTest::ComparisonOperation::NotEqual:
331 case QTest::ComparisonOperation::LessThan:
332 case QTest::ComparisonOperation::LessThanOrEqual:
333 case QTest::ComparisonOperation::GreaterThan:
334 case QTest::ComparisonOperation::GreaterThanOrEqual:
335 return "Computed ";
336 }
337 Q_UNREACHABLE_RETURN("");
338}
339
340static const char *rightArgNameForOp(QTest::ComparisonOperation op)
341{
342 switch (op) {
343 case QTest::ComparisonOperation::CustomCompare:
344 return "Expected ";
345 case QTest::ComparisonOperation::ThreeWayCompare:
346 return "Right ";
347 case QTest::ComparisonOperation::Equal:
348 case QTest::ComparisonOperation::NotEqual:
349 case QTest::ComparisonOperation::LessThan:
350 case QTest::ComparisonOperation::LessThanOrEqual:
351 case QTest::ComparisonOperation::GreaterThan:
352 case QTest::ComparisonOperation::GreaterThanOrEqual:
353 return "Baseline ";
354 }
355 Q_UNREACHABLE_RETURN("");
356}
357
358static int approx_wide_len(const char *s)
359{
360 std::mbstate_t state = {};
361 // QNX might stop at max when dst == nullptr, so pass INT_MAX,
362 // being the largest value this function will return:
363 auto r = std::mbsrtowcs(nullptr, &s, INT_MAX, &state);
364 if (r == size_t(-1)) // encoding error, fall back to strlen()
365 r = strlen(s); // `s` was not advanced since `dst == nullptr`
366 return q26::saturate_cast<int>(r);
367}
368
369// Overload to format failures for "const char *" - no need to strdup().
371void formatFailMessage(char *msg, size_t maxMsgLen,
372 const char *failureMsg,
373 const char *val1, const char *val2,
374 const char *actual, const char *expected,
375 QTest::ComparisonOperation op)
376{
377 const auto len1 = approx_wide_len(actual);
378 const auto len2 = approx_wide_len(expected);
379 const int written = std::snprintf(msg, maxMsgLen, "%s\n", failureMsg);
380 msg += written;
381 maxMsgLen -= written;
382
383 const auto protect = [](const char *s) { return s ? s : "<null>"; };
384
385 if (val1 || val2) {
386 std::snprintf(msg, maxMsgLen, " %s(%s)%*s %s\n %s(%s)%*s %s",
387 leftArgNameForOp(op), actual, qMax(len1, len2) - len1 + 1, ":",
388 protect(val1),
389 rightArgNameForOp(op), expected, qMax(len1, len2) - len2 + 1, ":",
390 protect(val2));
391 } else {
392 // only print variable names if neither value can be represented as a string
393 std::snprintf(msg, maxMsgLen, " %s: %s\n %s: %s",
394 leftArgNameForOp(op), actual, rightArgNameForOp(op), expected);
395 }
396}
397
398const char *
399QTest::Internal::formatPropertyTestHelperFailure(char *msg, size_t maxMsgLen,
400 const char *actual, const char *expected,
401 const char *actualExpr, const char *expectedExpr)
402{
403 formatFailMessage(msg, maxMsgLen, "Comparison failed!",
404 actual, expected, actualExpr, expectedExpr,
405 QTest::ComparisonOperation::CustomCompare);
406 return msg;
407}
408
409// Format failures using the toString() template
410template <class Actual, class Expected>
412void formatFailMessage(char *msg, size_t maxMsgLen,
413 const char *failureMsg,
414 const Actual &val1, const Expected &val2,
415 const char *actual, const char *expected,
416 QTest::ComparisonOperation op)
417{
418 const char *val1S = QTest::toString(val1);
419 const char *val2S = QTest::toString(val2);
420
421 formatFailMessage(msg, maxMsgLen, failureMsg, val1S, val2S, actual, expected, op);
422
423 delete [] val1S;
424 delete [] val2S;
425}
426
427template <class Actual, class Expected>
428static bool compareHelper(bool success, const char *failureMsg,
429 const Actual &val1, const Expected &val2,
430 const char *actual, const char *expected,
431 const char *file, int line,
432 bool hasValues = true)
433{
434 Q_DECL_UNINITIALIZED char msg[maxMsgLen];
435 msg[0] = '\0';
436
437 QTEST_ASSERT(expected);
438 QTEST_ASSERT(actual);
439
440 if (QTestLog::verboseLevel() >= 2) {
441 std::snprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected);
442 QTestLog::info(msg, file, line);
443 }
444
445 if (!failureMsg)
446 failureMsg = "Compared values are not the same";
447
448 if (success) {
450 std::snprintf(msg, maxMsgLen,
451 "QCOMPARE(%s, %s) returned TRUE unexpectedly.", actual, expected);
452 }
453 return checkStatement(success, msg, file, line);
454 }
455
456
457 if (!hasValues) {
458 std::snprintf(msg, maxMsgLen, "%s", failureMsg);
459 return checkStatement(success, msg, file, line);
460 }
461
462 formatFailMessage(msg, maxMsgLen, failureMsg, val1, val2, actual, expected,
463 QTest::ComparisonOperation::CustomCompare);
464
465 return checkStatement(success, msg, file, line);
466}
467
468// A simplified version of compareHelper that does not use string
469// representations of the values, and prints only failureMsg when the
470// comparison fails.
471static bool compareHelper(bool success, const char *failureMsg,
472 const char *actual, const char *expected,
473 const char *file, int line)
474{
475 const size_t maxMsgLen = 1024;
476 Q_DECL_UNINITIALIZED char msg[maxMsgLen];
477 msg[0] = '\0';
478
479 QTEST_ASSERT(expected);
480 QTEST_ASSERT(actual);
481 // failureMsg can be null, if we do not use it
482 QTEST_ASSERT(success || failureMsg);
483
484 if (QTestLog::verboseLevel() >= 2) {
485 std::snprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected);
486 QTestLog::info(msg, file, line);
487 }
488
489 if (success) {
491 std::snprintf(msg, maxMsgLen, "QCOMPARE(%s, %s) returned TRUE unexpectedly.",
492 actual, expected);
493 }
494 return checkStatement(success, msg, file, line);
495 }
496
497 return checkStatement(success, failureMsg, file, line);
498}
499
500bool QTestResult::compare(bool success, const char *failureMsg,
501 char *val1, char *val2,
502 const char *actual, const char *expected,
503 const char *file, int line)
504{
505 const bool result = compareHelper(success, failureMsg,
506 val1 != nullptr ? val1 : "<null>",
507 val2 != nullptr ? val2 : "<null>",
508 actual, expected, file, line,
509 val1 != nullptr && val2 != nullptr);
510
511 // Our caller got these from QTest::toString()
512 delete [] val1;
513 delete [] val2;
514
515 return result;
516}
517
518bool QTestResult::compare(bool success, const char *failureMsg,
519 double val1, double val2,
520 const char *actual, const char *expected,
521 const char *file, int line)
522{
523 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
524}
525
526bool QTestResult::compare(bool success, const char *failureMsg,
527 float val1, float val2,
528 const char *actual, const char *expected,
529 const char *file, int line)
530{
531 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
532}
533
534bool QTestResult::compare(bool success, const char *failureMsg,
535 int val1, int val2,
536 const char *actual, const char *expected,
537 const char *file, int line)
538{
539 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
540}
541
542#if QT_POINTER_SIZE == 8
543bool QTestResult::compare(bool success, const char *failureMsg,
544 qsizetype val1, qsizetype val2,
545 const char *actual, const char *expected,
546 const char *file, int line)
547{
548 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
549}
550#endif // QT_POINTER_SIZE == 8
551
552bool QTestResult::compare(bool success, const char *failureMsg,
553 unsigned val1, unsigned val2,
554 const char *actual, const char *expected,
555 const char *file, int line)
556{
557 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
558}
559
560bool QTestResult::compare(bool success, const char *failureMsg,
561 QStringView val1, QStringView val2,
562 const char *actual, const char *expected,
563 const char *file, int line)
564{
565 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
566}
567
568bool QTestResult::compare(bool success, const char *failureMsg,
569 QStringView val1, const QLatin1StringView &val2,
570 const char *actual, const char *expected,
571 const char *file, int line)
572{
573 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
574}
575
576bool QTestResult::compare(bool success, const char *failureMsg,
577 const QLatin1StringView & val1, QStringView val2,
578 const char *actual, const char *expected,
579 const char *file, int line)
580{
581 return compareHelper(success, failureMsg, val1, val2, actual, expected, file, line);
582}
583
584// Simplified version of compare() that does not take the values, because they
585// can't be converted to strings (or the user didn't want to do that).
586bool QTestResult::compare(bool success, const char *failureMsg,
587 const char *actual, const char *expeceted,
588 const char *file, int line)
589{
590 return compareHelper(success, failureMsg, actual, expeceted, file, line);
591}
592
593void QTestResult::addFailure(const char *message, const char *file, int line)
594{
595 clearExpectFail();
596 if (qApp && QThread::currentThread() == qApp->thread())
597 QTestEventLoop::instance().exitLoop();
598
599 if (QTest::blacklistCurrentTest)
600 QTestLog::addBFail(message, file, line);
601 else
602 QTestLog::addFail(message, file, line);
603 QTest::setFailed(true);
604}
605
606void QTestResult::addSkip(const char *message, const char *file, int line)
607{
608 clearExpectFail();
609
610 QTestLog::addSkip(message, file, line);
611}
612
613void QTestResult::setCurrentTestObject(const char *name)
614{
615 QTest::currentTestObjectName = name;
616}
617
618const char *QTestResult::currentTestObjectName()
619{
620 return QTest::currentTestObjectName ? QTest::currentTestObjectName : "";
621}
622
623void QTestResult::setSkipCurrentTest(bool value)
624{
625 QTest::skipCurrentTest = value;
626}
627
628bool QTestResult::skipCurrentTest()
629{
630 return QTest::skipCurrentTest;
631}
632
633void QTestResult::setCurrentAppName(const char *appName)
634{
635 ::currentAppName = appName;
636}
637
638const char *QTestResult::currentAppName()
639{
640 return ::currentAppName;
641}
642
643static const char *macroNameForOp(QTest::ComparisonOperation op)
644{
645 using namespace QTest;
646 switch (op) {
647 case ComparisonOperation::CustomCompare:
648 return "QCOMPARE"; /* not used */
649 case ComparisonOperation::Equal:
650 return "QCOMPARE_EQ";
651 case ComparisonOperation::NotEqual:
652 return "QCOMPARE_NE";
653 case ComparisonOperation::LessThan:
654 return "QCOMPARE_LT";
655 case ComparisonOperation::LessThanOrEqual:
656 return "QCOMPARE_LE";
657 case ComparisonOperation::GreaterThan:
658 return "QCOMPARE_GT";
659 case ComparisonOperation::GreaterThanOrEqual:
660 return "QCOMPARE_GE";
661 case ComparisonOperation::ThreeWayCompare:
662 return "QCOMPARE_3WAY";
663 }
664 Q_UNREACHABLE_RETURN("");
665}
666
667static const char *failureMessageForOp(QTest::ComparisonOperation op)
668{
669 using namespace QTest;
670 switch (op) {
671 case ComparisonOperation::CustomCompare:
672 return "Compared values are not the same"; /* not used */
673 case ComparisonOperation::ThreeWayCompare:
674 return "The result of operator<=>() is not what was expected";
675 case ComparisonOperation::Equal:
676 return "The computed value is expected to be equal to the baseline, but is not";
677 case ComparisonOperation::NotEqual:
678 return "The computed value is expected to be different from the baseline, but is not";
679 case ComparisonOperation::LessThan:
680 return "The computed value is expected to be less than the baseline, but is not";
681 case ComparisonOperation::LessThanOrEqual:
682 return "The computed value is expected to be less than or equal to the baseline, but is not";
683 case ComparisonOperation::GreaterThan:
684 return "The computed value is expected to be greater than the baseline, but is not";
685 case ComparisonOperation::GreaterThanOrEqual:
686 return "The computed value is expected to be greater than or equal to the baseline, but is not";
687 }
688 Q_UNREACHABLE_RETURN("");
689}
690
691bool QTestResult::reportResult(bool success, const void *lhs, const void *rhs,
692 const char *(*lhsFormatter)(const void*),
693 const char *(*rhsFormatter)(const void*),
694 const char *lhsExpr, const char *rhsExpr,
695 QTest::ComparisonOperation op, const char *file, int line,
696 const char *failureMessage)
697{
698 Q_DECL_UNINITIALIZED char msg[maxMsgLen];
699 msg[0] = '\0';
700
701 QTEST_ASSERT(lhsExpr);
702 QTEST_ASSERT(rhsExpr);
703
704 if (QTestLog::verboseLevel() >= 2) {
705 std::snprintf(msg, maxMsgLen, "%s(%s, %s)", macroNameForOp(op), lhsExpr, rhsExpr);
706 QTestLog::info(msg, file, line);
707 }
708
709 if (success) {
710 if (QTest::expectFailMode) {
711 std::snprintf(msg, maxMsgLen, "%s(%s, %s) returned TRUE unexpectedly.",
712 macroNameForOp(op), lhsExpr, rhsExpr);
713 }
714 return checkStatement(success, msg, file, line);
715 }
716
717 const std::unique_ptr<const char[]> lhsPtr{ lhsFormatter(lhs) };
718 const std::unique_ptr<const char[]> rhsPtr{ rhsFormatter(rhs) };
719
720 if (!failureMessage)
721 failureMessage = failureMessageForOp(op);
722
723 formatFailMessage(msg, maxMsgLen, failureMessage, lhsPtr.get(), rhsPtr.get(),
724 lhsExpr, rhsExpr, op);
725
726 return checkStatement(success, msg, file, line);
727}
728
729bool QTestResult::report3WayResult(bool success,
730 const char *failureMessage,
731 const void *lhs, const void *rhs,
732 const char *(*lhsFormatter)(const void*),
733 const char *(*rhsFormatter)(const void*),
734 const char *lhsExpression, const char *rhsExpression,
735 const char *(*actualOrderFormatter)(const void *),
736 const char *(*expectedOrderFormatter)(const void *),
737 const void *actualOrder, const void *expectedOrder,
738 const char *expectedExpression,
739 const char *file, int line)
740{
741 char msg[maxMsgLen];
742 msg[0] = '\0';
743
744 QTEST_ASSERT(lhsExpression);
745 QTEST_ASSERT(rhsExpression);
746 QTEST_ASSERT(expectedExpression);
747 const char *macroName = macroNameForOp(QTest::ComparisonOperation::ThreeWayCompare);
748 const std::string actualExpression = std::string(lhsExpression) + " <=> " + rhsExpression;
749
750 if (QTestLog::verboseLevel() >= 2) {
751 std::snprintf(msg, maxMsgLen, "%s(%s, %s, %s)",
752 macroName, lhsExpression, rhsExpression, expectedExpression);
753 QTestLog::info(msg, file, line);
754 }
755
756 if (success) {
757 if (QTest::expectFailMode) {
758 std::snprintf(msg, maxMsgLen, "%s(%s, %s, %s) returned TRUE unexpectedly.",
759 macroName, lhsExpression, rhsExpression, expectedExpression);
760 }
761 return checkStatement(success, msg, file, line);
762 }
763 const std::unique_ptr<const char[]> lhsStr{lhsFormatter(lhs)};
764 const std::unique_ptr<const char[]> rhsStr{rhsFormatter(rhs)};
765
766 const std::unique_ptr<const char[]> actual{actualOrderFormatter(actualOrder)};
767 const std::unique_ptr<const char[]> expected{expectedOrderFormatter(expectedOrder)};
768
769 if (!failureMessage)
770 failureMessage = failureMessageForOp(QTest::ComparisonOperation::ThreeWayCompare);
771
772 // Left and Right compared parameters of QCOMPARE_3WAY
773 formatFailMessage(msg, maxMsgLen, failureMessage,
774 lhsStr.get(), rhsStr.get(),
775 lhsExpression, rhsExpression,
776 QTest::ComparisonOperation::ThreeWayCompare);
777
778 // Actual and Expected results of comparison
779 formatFailMessage(msg + strlen(msg), maxMsgLen - strlen(msg), "",
780 actual.get(), expected.get(),
781 actualExpression.c_str(), expectedExpression,
782 QTest::ComparisonOperation::CustomCompare);
783
784 return checkStatement(success, msg, file, line);
785}
786
787QT_END_NAMESPACE
Q_TESTLIB_EXPORT Q_DECL_COLD_FUNCTION const char * formatPropertyTestHelperFailure(char *msg, size_t maxMsgLen, const char *actual, const char *expected, const char *actualExpr, const char *expectedExpr)
static bool failed
static void resetFailed()
static const char * expectFailComment
static bool skipCurrentTest
static bool blacklistCurrentTest
static const char * currentTestFunc
static void setFailed(bool failed)
static bool hasFailed()
static const char * currentTestObjectName
static QTestData * currentTestData
static QTestData * currentGlobalTestData
static int expectFailMode
static Q_DECL_COLD_FUNCTION void formatFailMessage(char *msg, size_t maxMsgLen, const char *failureMsg, const Actual &val1, const Expected &val2, const char *actual, const char *expected, QTest::ComparisonOperation op)
static Q_DECL_COLD_FUNCTION 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 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 constexpr size_t maxMsgLen
static const char * failureMessageForOp(QTest::ComparisonOperation op)
static int approx_wide_len(const char *s)
static bool compareHelper(bool success, const char *failureMsg, const char *actual, const char *expected, const char *file, int line)
static const char * currentAppName
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()