summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-10-13 13:48:29 -0700
committerIvan Solovev <ivan.solovev@qt.io>2024-04-26 18:19:36 +0200
commitf7e9bb77839722a91aa2c6b794b0c7b2e18c66cb (patch)
treeabda008c6f1b988b6f5e9e2e3b7f714954fad169
parent0756cc1eae5fd8981983319fef1d084762a67b8d (diff)
QTest: replace the majority of the ugly QCOMPARE_xx macro
Using templates to make the code look nicer and be more debuggable. Previously, if you tried to step into the QCOMPARE_xx, you'd have the creations of qxp::function_ref from the lambdas before you got to the actual comparison. And all of this was in-place from macro expansion, so you couldn't tell what was happening. Now, if you step into QCOMPARE_xx, you go to qCompareOp. There are 5 frames between that point and the actual comparison (four std::forward() and the Compare::compare()) and debuggers could step over std::forward. Even if they can't, both libstdc++ and libc++ implementations are simple casts, so there's nothing more to step into. Change-Id: I12a088d1ae424825abd3fffd171dbbf7adb7e7e2 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/testlib/qtestcase.h62
1 files changed, 43 insertions, 19 deletions
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index 6dddcb5045..0ae1a787e2 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -84,23 +84,10 @@ do {\
QTEST_FAIL_ACTION; \
} while (false)
-// A wrapper lambda is introduced to extend the lifetime of lhs and rhs in
-// case they are temporary objects.
-// We also use IILE to prevent potential name clashes and shadowing of variables
-// from user code. A drawback of the approach is that it looks ugly :(
#define QCOMPARE_OP_IMPL(lhs, rhs, op, opId) \
do { \
- if (![](auto &&qt_lhs_arg, auto &&qt_rhs_arg) { \
- /* assumes that op does not actually move from qt_{lhs, rhs}_arg */ \
- return QTest::reportResult(std::forward<decltype(qt_lhs_arg)>(qt_lhs_arg) \
- op \
- std::forward<decltype(qt_rhs_arg)>(qt_rhs_arg), \
- qt_lhs_arg, qt_rhs_arg, \
- #lhs, #rhs, QTest::ComparisonOperation::opId, \
- __FILE__, __LINE__); \
- }(lhs, rhs)) { \
+ if (!QTest::qCompareOp<QTest::ComparisonOperation::opId>(lhs, rhs, #lhs, #rhs, __FILE__, __LINE__)) \
QTEST_FAIL_ACTION; \
- } \
} while (false)
#define QCOMPARE_EQ(computed, baseline) QCOMPARE_OP_IMPL(computed, baseline, ==, Equal)
@@ -239,7 +226,8 @@ do { \
#define QTRY_COMPARE_OP_WITH_TIMEOUT_IMPL(computed, baseline, op, opId, timeout) \
do { \
- QTRY_IMPL(((computed) op (baseline)), timeout) \
+ using Q_Cmp = QTest::Internal::Compare<QTest::ComparisonOperation::opId>; \
+ QTRY_IMPL(Q_Cmp::compare((computed), (baseline)), timeout) \
QCOMPARE_OP_IMPL(computed, baseline, op, opId); \
} while (false)
@@ -329,6 +317,38 @@ namespace QTest
Q_TESTLIB_EXPORT QString formatTryTimeoutDebugMessage(q_no_char8_t::QUtf8StringView expr, int timeout, int actual);
+ template <ComparisonOperation> struct Compare;
+ template <> struct Compare<ComparisonOperation::Equal>
+ {
+ template <typename T1, typename T2> static bool compare(T1 &&lhs, T2 &&rhs)
+ { return std::forward<T1>(lhs) == std::forward<T2>(rhs); }
+ };
+ template <> struct Compare<ComparisonOperation::NotEqual>
+ {
+ template <typename T1, typename T2> static bool compare(T1 &&lhs, T2 &&rhs)
+ { return std::forward<T1>(lhs) != std::forward<T2>(rhs); }
+ };
+ template <> struct Compare<ComparisonOperation::LessThan>
+ {
+ template <typename T1, typename T2> static bool compare(T1 &&lhs, T2 &&rhs)
+ { return std::forward<T1>(lhs) < std::forward<T2>(rhs); }
+ };
+ template <> struct Compare<ComparisonOperation::LessThanOrEqual>
+ {
+ template <typename T1, typename T2> static bool compare(T1 &&lhs, T2 &&rhs)
+ { return std::forward<T1>(lhs) <= std::forward<T2>(rhs); }
+ };
+ template <> struct Compare<ComparisonOperation::GreaterThan>
+ {
+ template <typename T1, typename T2> static bool compare(T1 &&lhs, T2 &&rhs)
+ { return std::forward<T1>(lhs) > std::forward<T2>(rhs); }
+ };
+ template <> struct Compare<ComparisonOperation::GreaterThanOrEqual>
+ {
+ template <typename T1, typename T2> static bool compare(T1 &&lhs, T2 &&rhs)
+ { return std::forward<T1>(lhs) >= std::forward<T2>(rhs); }
+ };
+
template <typename T1> const char *genericToString(const void *arg)
{
using QTest::toString;
@@ -700,17 +720,21 @@ namespace QTest
const char *lhsExpr, const char *rhsExpr,
ComparisonOperation op, const char *file, int line);
- template <typename T1, typename T2>
- inline bool reportResult(bool result, const T1 &lhs, const T2 &rhs,
- const char *lhsExpr, const char *rhsExpr,
- ComparisonOperation op, const char *file, int line)
+ template <ComparisonOperation op, typename T1, typename T2 = T1>
+ inline bool qCompareOp(T1 &&lhs, T2 &&rhs, const char *lhsExpr, const char *rhsExpr,
+ const char *file, int line)
{
using D1 = std::decay_t<T1>;
using D2 = std::decay_t<T2>;
using Internal::genericToString;
+ using Comparator = Internal::Compare<op>;
+
+ /* assumes that op does not actually move from lhs and rhs */
+ bool result = Comparator::compare(std::forward<T1>(lhs), std::forward<T2>(rhs));
return reportResult(result, std::addressof(lhs), std::addressof(rhs),
genericToString<D1>, genericToString<D2>,
lhsExpr, rhsExpr, op, file, line);
+
}
}