diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2022-10-13 13:48:29 -0700 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2024-04-26 18:19:36 +0200 |
commit | f7e9bb77839722a91aa2c6b794b0c7b2e18c66cb (patch) | |
tree | abda008c6f1b988b6f5e9e2e3b7f714954fad169 | |
parent | 0756cc1eae5fd8981983319fef1d084762a67b8d (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.h | 62 |
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); + } } |