summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <[email protected]>2025-05-21 13:14:20 +0200
committerMarc Mutz <[email protected]>2025-05-22 12:08:48 +0000
commit82015992c853b50dac167da26b8b858ac4794c66 (patch)
tree65ffecf6a0d7d5ee9bb2183ecd62695bf7f80e73
parentb9c92154062a1d6c0f62860a9fa775cba6bac9ef (diff)
tst_QScopedPointer: add a test for reset/delete orderingHEADdev
We have implementation divergence with libc++'s ~unique_ptr() behavior, so make sure QScopedPointer behaves the same way as unique_ptr is spec'ed, even though to check it, one has to rely on UB, at least according to LLVM devs (I don't think the test as written invokes UB). Code's a bit duplicated. I tried making the struct a template, but it's just too much of a fuss (needs a variable template, which we can't use in Qt 5), so I decided to use cut'n'paste. Task-number: QTBUG-137069 Pick-to: 6.9 6.8 6.5 5.15 Change-Id: I8b55718eaf3c6ad9a4d89d4fc9d64f0c41bb21fa Reviewed-by: Ahmad Samir <[email protected]>
-rw-r--r--tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
index 3468c97f429..97ce0271634 100644
--- a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
+++ b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
@@ -4,6 +4,8 @@
#include <QTest>
#include <QtCore/QScopedPointer>
+#include <QtCore/qstdlibdetection.h>
+
/*!
\class tst_QScopedPointer
\internal
@@ -22,6 +24,7 @@ private Q_SLOTS:
void dataOnValue();
void dataSignature();
void reset();
+ void resetDeleteOrdering();
void dereferenceOperator();
void dereferenceOperatorSignature();
void pointerOperator();
@@ -127,6 +130,85 @@ void tst_QScopedPointer::reset()
}
}
+void tst_QScopedPointer::resetDeleteOrdering()
+{
+ {
+ struct CheckingDeleter;
+ using SP = QScopedPointer<int, CheckingDeleter>;
+ static const SP *instance = nullptr; // QScopedPointer does not handle stateful deleters
+ static const int *expected = nullptr;
+
+ struct CheckingDeleter {
+ static void cleanup(int *p)
+ {
+ const auto *value = instance->get();
+ std::unique_ptr<int> deleter(p);
+ QT_TRY { QCOMPARE(value, expected); } QT_CATCH(...) {} // eat QTest failure exception, if any
+ }
+ void operator()(int *p) { cleanup(p); }
+ };
+
+ // reset()
+ {
+ SP p(new int{42});
+ instance = &p;
+ expected = nullptr;
+ p.reset();
+ }
+ if (QTest::currentTestFailed())
+ return;
+ // destructor
+ {
+ SP p(new int{48});
+ instance = &p;
+ expected = p.get(); // inconsistent with reset(), but consistent with unique_ptr
+ }
+ if (QTest::currentTestFailed())
+ return;
+ }
+
+ // comparison with unique_ptr:
+ {
+ struct CheckingDeleter;
+ using UP = std::unique_ptr<int, CheckingDeleter>;
+ // unique_ptr handles stateful deleters, but be consistent with QScopedPointer test
+ static const UP *instance = nullptr;
+ static const int *expected = nullptr;
+
+ struct CheckingDeleter {
+ void operator()(int *p) const
+ {
+ const auto *value = instance->get();
+ std::unique_ptr<int> deleter(p);
+ QT_TRY { QCOMPARE(value, expected); } QT_CATCH(...) {} // eat QTest failure exception, if any
+ }
+ };
+
+ // reset()
+ {
+ UP p(new int{42});
+ instance = &p;
+ expected = nullptr; // https://eel.is/c++draft/unique.ptr#single.modifiers-3 ... 5
+ p.reset();
+ }
+ if (QTest::currentTestFailed())
+ return;
+ // destructor
+#ifdef Q_STL_LIBCPP
+ // This would fail on libc++ https://github.com/llvm/llvm-project/issues/108149
+ if (false)
+#endif
+ {
+ UP p(new int{48});
+ instance = &p;
+ expected = p.get(); // https://eel.is/c++draft/unique.ptr#single.dtor
+ }
+ if (QTest::currentTestFailed())
+ return;
+
+ }
+}
+
class AbstractClass
{
public: