tst_QScopedPointer: add a test for reset/delete ordering
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.8 6.5 5.15 Change-Id: I8b55718eaf3c6ad9a4d89d4fc9d64f0c41bb21fa Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> (cherry picked from commit 82015992c853b50dac167da26b8b858ac4794c66) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
8f6a286fff
commit
8d81da76be
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user