diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2022-05-19 13:48:45 +0200 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2022-06-03 22:37:50 +0200 |
commit | 343e0ff485de36e27c0a62781dc512a4bda22fce (patch) | |
tree | 800a71669093a5d9bcd60048f9be9f8badbe0367 /src/testlib/qtestresult.cpp | |
parent | 9327d1aaf79d4214db78ec86b8b6df7738bd1875 (diff) |
Add QCOMPARE_{EQ,NE,LT,LE,GT,GE}()
[ChangeLog][QTestLib] Add QCOMPARE_{EQ,NE,LT,LE,GT,GE}()
macros. These new macros behave similarly to QVERIFY(a op b),
where 'op' is ==, !=, <, <=, >, >= respectively, but print
a formatted error message with argument values in case of failure.
The formatting is done lazily, which means that the strings will
be generated only when the comparison fails.
Also add a new test for tst_selftest and generate expected output
for it.
Fixes: QTBUG-98873
Task-number: QTBUG-98874
Change-Id: Ic8074798901d7a469b1f58d5cd28bbf49a3da1db
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/testlib/qtestresult.cpp')
-rw-r--r-- | src/testlib/qtestresult.cpp | 116 |
1 files changed, 105 insertions, 11 deletions
diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp index 40e76146ba..22d8f11424 100644 --- a/src/testlib/qtestresult.cpp +++ b/src/testlib/qtestresult.cpp @@ -311,22 +311,34 @@ bool QTestResult::verify(bool statement, const char *statementStr, return checkStatement(statement, msg, file, line); } +static const char *leftArgNameForOp(QTest::ComparisonOperation op) +{ + return op == QTest::ComparisonOperation::CustomCompare ? "Actual " : "Left "; +} + +static const char *rightArgNameForOp(QTest::ComparisonOperation op) +{ + return op == QTest::ComparisonOperation::CustomCompare ? "Expected " : "Right "; +} + // Format failures using the toString() template template <class Actual, class Expected> void formatFailMessage(char *msg, size_t maxMsgLen, const char *failureMsg, const Actual &val1, const Expected &val2, - const char *actual, const char *expected) + const char *actual, const char *expected, + QTest::ComparisonOperation op) { auto val1S = QTest::toString(val1); auto val2S = QTest::toString(val2); size_t len1 = mbstowcs(nullptr, actual, maxMsgLen); // Last parameter is not ignored on QNX size_t len2 = mbstowcs(nullptr, expected, maxMsgLen); // (result is never larger than this). - qsnprintf(msg, maxMsgLen, "%s\n Actual (%s)%*s %s\n Expected (%s)%*s %s", - failureMsg, - actual, qMax(len1, len2) - len1 + 1, ":", val1S ? val1S : "<null>", - expected, qMax(len1, len2) - len2 + 1, ":", val2S ? val2S : "<null>"); + qsnprintf(msg, maxMsgLen, "%s\n %s(%s)%*s %s\n %s(%s)%*s %s", failureMsg, + leftArgNameForOp(op), actual, qMax(len1, len2) - len1 + 1, ":", + val1S ? val1S : "<null>", + rightArgNameForOp(op), expected, qMax(len1, len2) - len2 + 1, ":", + val2S ? val2S : "<null>"); delete [] val1S; delete [] val2S; @@ -336,14 +348,16 @@ void formatFailMessage(char *msg, size_t maxMsgLen, void formatFailMessage(char *msg, size_t maxMsgLen, const char *failureMsg, const char *val1, const char *val2, - const char *actual, const char *expected) + const char *actual, const char *expected, + QTest::ComparisonOperation op) { size_t len1 = mbstowcs(nullptr, actual, maxMsgLen); // Last parameter is not ignored on QNX size_t len2 = mbstowcs(nullptr, expected, maxMsgLen); // (result is never larger than this). - qsnprintf(msg, maxMsgLen, "%s\n Actual (%s)%*s %s\n Expected (%s)%*s %s", - failureMsg, - actual, qMax(len1, len2) - len1 + 1, ":", val1 ? val1 : "<null>", - expected, qMax(len1, len2) - len2 + 1, ":", val2 ? val2 : "<null>"); + qsnprintf(msg, maxMsgLen, "%s\n %s(%s)%*s %s\n %s(%s)%*s %s", failureMsg, + leftArgNameForOp(op), actual, qMax(len1, len2) - len1 + 1, ":", + val1 ? val1 : "<null>", + rightArgNameForOp(op), expected, qMax(len1, len2) - len2 + 1, ":", + val2 ? val2 : "<null>"); } template <class Actual, class Expected> @@ -382,7 +396,8 @@ static bool compareHelper(bool success, const char *failureMsg, return checkStatement(success, msg, file, line); } - formatFailMessage(msg, maxMsgLen, failureMsg, val1, val2, actual, expected); + formatFailMessage(msg, maxMsgLen, failureMsg, val1, val2, actual, expected, + QTest::ComparisonOperation::CustomCompare); return checkStatement(success, msg, file, line); } @@ -520,4 +535,83 @@ const char *QTestResult::currentAppName() return ::currentAppName; } +static const char *macroNameForOp(QTest::ComparisonOperation op) +{ + using namespace QTest; + switch (op) { + case ComparisonOperation::CustomCompare: + return "QCOMPARE"; /* not used */ + case ComparisonOperation::Equal: + return "QCOMPARE_EQ"; + case ComparisonOperation::NotEqual: + return "QCOMPARE_NE"; + case ComparisonOperation::LessThan: + return "QCOMPARE_LT"; + case ComparisonOperation::LessThanOrEqual: + return "QCOMPARE_LE"; + case ComparisonOperation::GreaterThan: + return "QCOMPARE_GT"; + case ComparisonOperation::GreaterThanOrEqual: + return "QCOMPARE_GE"; + } + Q_UNREACHABLE(); + return ""; +} + +static const char *failureMessageForOp(QTest::ComparisonOperation op) +{ + using namespace QTest; + switch (op) { + case ComparisonOperation::CustomCompare: + return "Compared values are not the same"; /* not used */ + case ComparisonOperation::Equal: + return "Left value is expected to be equal to right value, but is not"; + case ComparisonOperation::NotEqual: + return "Left value is expected to be different from right value, but is not"; + case ComparisonOperation::LessThan: + return "Left value is expected to be less than right value, but is not"; + case ComparisonOperation::LessThanOrEqual: + return "Left value is expected to be less than or equal to right value, but is not"; + case ComparisonOperation::GreaterThan: + return "Left value is expected to be greater than right value, but is not"; + case ComparisonOperation::GreaterThanOrEqual: + return "Left value is expected to be greater than or equal to right value, but is not"; + } + Q_UNREACHABLE(); + return ""; +} + +bool QTestResult::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 size_t maxMsgLen = 1024; + char msg[maxMsgLen] = {'\0'}; + + QTEST_ASSERT(lhsExpr); + QTEST_ASSERT(rhsExpr); + + if (QTestLog::verboseLevel() >= 2) { + qsnprintf(msg, maxMsgLen, "%s(%s, %s)", macroNameForOp(op), lhsExpr, rhsExpr); + QTestLog::info(msg, file, line); + } + + if (success) { + if (QTest::expectFailMode) { + qsnprintf(msg, maxMsgLen, "%s(%s, %s) returned TRUE unexpectedly.", + macroNameForOp(op), lhsExpr, rhsExpr); + } + return checkStatement(success, msg, file, line); + } + + const std::unique_ptr<const char[]> lhsPtr{ lhs() }; + const std::unique_ptr<const char[]> rhsPtr{ rhs() }; + + formatFailMessage(msg, maxMsgLen, failureMessageForOp(op), lhsPtr.get(), rhsPtr.get(), + lhsExpr, rhsExpr, op); + + return checkStatement(success, msg, file, line); +} + QT_END_NAMESPACE |