6.5.3 clean

This commit is contained in:
kleuter
2023-11-01 18:02:52 +01:00
parent bbe896803b
commit 7018d9e6c8
2170 changed files with 57471 additions and 43550 deletions

View File

@ -556,6 +556,7 @@ void tst_QDeadlineTimer::expire()
void tst_QDeadlineTimer::stdchrono()
{
using namespace std::chrono;
using namespace std::chrono_literals;
QFETCH_GLOBAL(Qt::TimerType, timerType);
// create some forevers
@ -668,82 +669,82 @@ void tst_QDeadlineTimer::stdchrono()
// make it regular
now = QDeadlineTimer::current(timerType);
deadline.setRemainingTime(milliseconds(4 * minResolution), timerType);
deadline.setRemainingTime(4ms * minResolution, timerType);
QVERIFY(!deadline.hasExpired());
QVERIFY(!deadline.isForever());
QCOMPARE(deadline.timerType(), timerType);
QCOMPARE_GT(deadline.remainingTimeAsDuration(), milliseconds(3 * minResolution));
QCOMPARE_LT(deadline.remainingTimeAsDuration(), milliseconds(5 * minResolution));
QCOMPARE_GT(deadline.remainingTimeAsDuration(), nanoseconds(3000000 * minResolution));
QCOMPARE_LT(deadline.remainingTimeAsDuration(), nanoseconds(5000000 * minResolution));
QCOMPARE_GT(deadline.deadline<steady_clock>(), (steady_clock::now() + milliseconds(3 * minResolution)));
QCOMPARE_LT(deadline.deadline<steady_clock>(), (steady_clock::now() + milliseconds(5 * minResolution)));
QCOMPARE_GT(deadline.deadline<system_clock>(), (system_clock::now() + milliseconds(3 * minResolution)));
QCOMPARE_LT(deadline.deadline<system_clock>(), (system_clock::now() + milliseconds(5 * minResolution)));
QCOMPARE_GT(deadline.remainingTimeAsDuration(), 3ms * minResolution);
QCOMPARE_LT(deadline.remainingTimeAsDuration(), 5ms * minResolution);
QCOMPARE_GT(deadline.remainingTimeAsDuration(), 3'000'000ns * minResolution);
QCOMPARE_LT(deadline.remainingTimeAsDuration(), 5'000'000ns * minResolution);
QCOMPARE_GT(deadline.deadline<steady_clock>(), (steady_clock::now() + 3ms * minResolution));
QCOMPARE_LT(deadline.deadline<steady_clock>(), (steady_clock::now() + 5ms * minResolution));
QCOMPARE_GT(deadline.deadline<system_clock>(), (system_clock::now() + 3ms * minResolution));
QCOMPARE_LT(deadline.deadline<system_clock>(), (system_clock::now() + 5ms * minResolution));
if (timerType == Qt::CoarseTimer) {
QCOMPARE_GT(deadline, (now + milliseconds(3 * minResolution)));
QCOMPARE_LT(deadline, (now + milliseconds(5 * minResolution)));
QCOMPARE_GT(deadline, (now + nanoseconds(3000000 * minResolution)));
QCOMPARE_LT(deadline, (now + nanoseconds(5000000 * minResolution)));
QCOMPARE_GT(deadline, milliseconds(3 * minResolution));
QCOMPARE_LT(deadline, milliseconds(5 * minResolution));
QCOMPARE_GT(deadline, nanoseconds(3000000 * minResolution));
QCOMPARE_LT(deadline, nanoseconds(5000000 * minResolution));
QCOMPARE_GT(deadline, now + 3ms * minResolution);
QCOMPARE_LT(deadline, now + 5ms * minResolution);
QCOMPARE_GT(deadline, now + 3000000ns * minResolution);
QCOMPARE_LT(deadline, now + 5000000ns * minResolution);
QCOMPARE_GT(deadline, 3ms * minResolution);
QCOMPARE_LT(deadline, 5ms * minResolution);
QCOMPARE_GT(deadline, 3000000ns * minResolution);
QCOMPARE_LT(deadline, 5000000ns * minResolution);
QCOMPARE_GE(deadline, steady_clock::now());
QCOMPARE_GE(deadline, system_clock::now());
}
now = QDeadlineTimer::current(timerType);
deadline = QDeadlineTimer(seconds(1), timerType);
deadline = QDeadlineTimer(1s, timerType);
QVERIFY(!deadline.hasExpired());
QVERIFY(!deadline.isForever());
QCOMPARE(deadline.timerType(), timerType);
QCOMPARE_GT(deadline.remainingTimeAsDuration(), (seconds(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.remainingTimeAsDuration(), seconds(1));
QCOMPARE_GT(deadline.deadline<steady_clock>(), (steady_clock::now() + seconds(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.deadline<steady_clock>(), (steady_clock::now() + seconds(1) + milliseconds(minResolution)));
QCOMPARE_GT(deadline.deadline<system_clock>(), (system_clock::now() + seconds(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.deadline<system_clock>(), (system_clock::now() + seconds(1) + milliseconds(minResolution)));
QCOMPARE_GT(deadline.remainingTimeAsDuration(), 1s - 1ms * minResolution);
QCOMPARE_LE(deadline.remainingTimeAsDuration(), 1s);
QCOMPARE_GT(deadline.deadline<steady_clock>(), steady_clock::now() + 1s - 1ms * minResolution);
QCOMPARE_LE(deadline.deadline<steady_clock>(), steady_clock::now() + 1s + 1ms * minResolution);
QCOMPARE_GT(deadline.deadline<system_clock>(), system_clock::now() + 1s - 1ms * minResolution);
QCOMPARE_LE(deadline.deadline<system_clock>(), system_clock::now() + 1s + 1ms * minResolution);
if (timerType == Qt::CoarseTimer) {
QCOMPARE_GT(deadline, (seconds(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline, seconds(1));
QCOMPARE_GT(deadline, 1s - 1ms * minResolution);
QCOMPARE_LE(deadline, 1s);
}
now = QDeadlineTimer::current(timerType);
deadline.setRemainingTime(hours(1), timerType);
deadline.setRemainingTime(1h, timerType);
QVERIFY(!deadline.hasExpired());
QVERIFY(!deadline.isForever());
QCOMPARE(deadline.timerType(), timerType);
QCOMPARE_GT(deadline.remainingTimeAsDuration(), (hours(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.remainingTimeAsDuration(), hours(1));
QCOMPARE_GT(deadline.deadline<steady_clock>(), (steady_clock::now() + hours(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.deadline<steady_clock>(), (steady_clock::now() + hours(1) + milliseconds(minResolution)));
QCOMPARE_GT(deadline.deadline<system_clock>(), (system_clock::now() + hours(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.deadline<system_clock>(), (system_clock::now() + hours(1) + milliseconds(minResolution)));
QCOMPARE_GT(deadline.remainingTimeAsDuration(), 1h - 1ms * minResolution);
QCOMPARE_LE(deadline.remainingTimeAsDuration(), 1h);
QCOMPARE_GT(deadline.deadline<steady_clock>(), steady_clock::now() + 1h - 1ms * minResolution);
QCOMPARE_LE(deadline.deadline<steady_clock>(), steady_clock::now() + 1h + 1ms * minResolution);
QCOMPARE_GT(deadline.deadline<system_clock>(), system_clock::now() + 1h - 1ms * minResolution);
QCOMPARE_LE(deadline.deadline<system_clock>(), system_clock::now() + 1h + 1ms * minResolution);
now = QDeadlineTimer::current(timerType);
deadline.setDeadline(system_clock::now() + seconds(1), timerType);
deadline.setDeadline(system_clock::now() + 1s, timerType);
QVERIFY(!deadline.hasExpired());
QVERIFY(!deadline.isForever());
QCOMPARE(deadline.timerType(), timerType);
QCOMPARE_GT(deadline.remainingTimeAsDuration(), (seconds(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.remainingTimeAsDuration(), seconds(1));
QCOMPARE_GT(deadline.deadline<steady_clock>(), (steady_clock::now() + seconds(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.deadline<steady_clock>(), (steady_clock::now() + seconds(1) + milliseconds(minResolution)));
QCOMPARE_GT(deadline.deadline<system_clock>(), (system_clock::now() + seconds(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.deadline<system_clock>(), (system_clock::now() + seconds(1) + milliseconds(minResolution)));
QCOMPARE_GT(deadline.remainingTimeAsDuration(), 1s - 1ms * minResolution);
QCOMPARE_LE(deadline.remainingTimeAsDuration(), 1s);
QCOMPARE_GT(deadline.deadline<steady_clock>(), steady_clock::now() + 1s - 1ms * minResolution);
QCOMPARE_LE(deadline.deadline<steady_clock>(), steady_clock::now() + 1s + 1ms * minResolution);
QCOMPARE_GT(deadline.deadline<system_clock>(), system_clock::now() + 1s - 1ms * minResolution);
QCOMPARE_LE(deadline.deadline<system_clock>(), system_clock::now() + 1s + 1ms * minResolution);
now = QDeadlineTimer::current(timerType);
deadline.setDeadline(steady_clock::now() + seconds(1), timerType);
deadline.setDeadline(steady_clock::now() + 1s, timerType);
QVERIFY(!deadline.hasExpired());
QVERIFY(!deadline.isForever());
QCOMPARE(deadline.timerType(), timerType);
QCOMPARE_GT(deadline.remainingTimeAsDuration(), (seconds(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.remainingTimeAsDuration(), seconds(1));
QCOMPARE_GT(deadline.deadline<steady_clock>(), (steady_clock::now() + seconds(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.deadline<steady_clock>(), (steady_clock::now() + seconds(1) + milliseconds(minResolution)));
QCOMPARE_GT(deadline.deadline<system_clock>(), (system_clock::now() + seconds(1) - milliseconds(minResolution)));
QCOMPARE_LE(deadline.deadline<system_clock>(), (system_clock::now() + seconds(1) + milliseconds(minResolution)));
QCOMPARE_GT(deadline.remainingTimeAsDuration(), 1s - 1ms * minResolution);
QCOMPARE_LE(deadline.remainingTimeAsDuration(), 1s);
QCOMPARE_GT(deadline.deadline<steady_clock>(), steady_clock::now() + 1s - 1ms * minResolution);
QCOMPARE_LE(deadline.deadline<steady_clock>(), steady_clock::now() + 1s + 1ms * minResolution);
QCOMPARE_GT(deadline.deadline<system_clock>(), system_clock::now() + 1s - 1ms * minResolution);
QCOMPARE_LE(deadline.deadline<system_clock>(), system_clock::now() + 1s + 1ms * minResolution);
}
QTEST_MAIN(tst_QDeadlineTimer)

View File

@ -121,6 +121,26 @@ static_assert(!QTypeTraits::has_operator_less_than_v<std::tuple<int, Nested2>>);
static_assert(QTypeTraits::has_operator_equal_v<std::tuple<int, Nested2>>);
static_assert(!QTypeTraits::has_operator_less_than_v<std::tuple<int, Nested2>>);
// optionals of nesteds
static_assert(QTypeTraits::has_operator_equal_v<std::optional<std::variant<QString>>>);
static_assert(QTypeTraits::has_operator_less_than_v<std::optional<std::variant<QString>>>);
static_assert(!QTypeTraits::has_operator_equal_v<std::optional<std::variant<NoOperators>>>);
static_assert(!QTypeTraits::has_operator_less_than_v<std::optional<std::variant<NoOperators>>>);
static_assert(QTypeTraits::has_operator_equal_v<std::optional<Nested>>);
static_assert(!QTypeTraits::has_operator_less_than_v<std::optional<Nested>>);
static_assert(QTypeTraits::has_operator_equal_v<std::optional<std::tuple<int, Nested>>>);
static_assert(!QTypeTraits::has_operator_less_than_v<std::optional<std::tuple<int, Nested>>>);
static_assert(QTypeTraits::has_operator_equal_v<std::optional<std::tuple<int, Nested>>>);
static_assert(!QTypeTraits::has_operator_less_than_v<std::optional<std::tuple<int, Nested>>>);
static_assert(QTypeTraits::has_operator_equal_v<std::optional<Nested2>>);
static_assert(!QTypeTraits::has_operator_less_than_v<std::optional<Nested2>>);
static_assert(QTypeTraits::has_operator_equal_v<std::optional<std::tuple<int, Nested2>>>);
static_assert(!QTypeTraits::has_operator_less_than_v<std::optional<std::tuple<int, Nested2>>>);
static_assert(QTypeTraits::has_operator_equal_v<std::optional<std::tuple<int, Nested2>>>);
static_assert(!QTypeTraits::has_operator_less_than_v<std::optional<std::tuple<int, Nested2>>>);
}
struct BaseGenericType

View File

@ -8191,6 +8191,16 @@ void tst_QObject::objectNameBinding()
QObject obj;
QTestPrivate::testReadWritePropertyBasics<QObject, QString>(obj, "test1", "test2",
"objectName");
const QPropertyBinding<QString> binding([]() {
QObject obj2;
obj2.setObjectName(QLatin1String("no loop"));
return obj2.objectName();
}, {});
obj.bindableObjectName().setBinding(binding);
QCOMPARE(obj.objectName(), QLatin1String("no loop"));
QVERIFY2(!binding.error().hasError(), qPrintable(binding.error().description()));
}
namespace EmitToDestroyedClass {

View File

@ -76,6 +76,7 @@ private slots:
void metaProperty();
void modifyObserverListWhileIterating();
void noDoubleCapture();
void compatPropertyNoDobuleNotification();
void compatPropertySignals();
@ -1493,6 +1494,22 @@ void tst_QProperty::modifyObserverListWhileIterating()
}
}
void tst_QProperty::noDoubleCapture()
{
QProperty<long long> size;
size = 3;
QProperty<int> max;
max.setBinding([&size]() -> int {
// each loop run attempts to capture size
for (int i = 0; i < size; ++i) {}
return size.value();
});
auto bindingPriv = QPropertyBindingPrivate::get(max.binding());
QCOMPARE(bindingPriv->dependencyObserverCount, 1U);
size = 4; // should not crash
QCOMPARE(max.value(), 4);
}
class CompatPropertyTester : public QObject
{
Q_OBJECT
@ -1694,6 +1711,14 @@ class PropertyAdaptorTester : public QObject
Q_PROPERTY(int foo1 READ foo WRITE setFoo)
signals:
void dummySignal1();
void dummySignal2();
void dummySignal3();
void dummySignal4();
void dummySignal5();
void dummySignal6();
void dummySignal7();
void dummySignal8();
void fooChanged(int newFoo);
public slots:
@ -1722,9 +1747,11 @@ void tst_QProperty::propertyAdaptorBinding()
// Check binding of non BINDABLE property
PropertyAdaptorTester object;
// set up a dummy connection (needed to verify that the QBindable avoids an out-of-bounds read)
QObject::connect(&object, &PropertyAdaptorTester::dummySignal1, [](){});
QBindable<int> binding(&object, "foo");
QObject::connect(&object, &PropertyAdaptorTester::fooChanged, &object,
&PropertyAdaptorTester::fooHasChanged);
QBindable<int> binding(&object, "foo");
binding.setBinding([&]() { return source + 1; });
QCOMPARE(object.foo(), 6);
QCOMPARE(object.fooChangedCount, 1);

View File

@ -1,3 +0,0 @@
[unexpectedDisconnection]
windows ci

View File

@ -131,11 +131,11 @@ public slots:
++sequence;
if (sequence == 1) {
// read from both ends
(void) readEnd1->read(data1, sizeof(data1));
(void) readEnd2->read(data2, sizeof(data2));
QCOMPARE(readEnd1->read(data1, sizeof(data1)), 1);
QCOMPARE(readEnd2->read(data2, sizeof(data2)), 1);
emit finished();
} else if (sequence == 2) {
// we should never get here
// check that we can't read now because we've read our byte
QCOMPARE(readEnd2->read(data2, sizeof(data2)), qint64(-2));
QVERIFY(readEnd2->isValid());
}
@ -151,7 +151,7 @@ void tst_QSocketNotifier::unexpectedDisconnection()
Given two sockets and two QSocketNotifiers registered on each
their socket. If both sockets receive data, and the first slot
invoked by one of the socket notifiers empties both sockets, the
other notifier will also emit activated(). This results in
other notifier will also emit activated(). This was causing an
unexpected disconnection in QAbstractSocket.
The use case is that somebody calls one of the
@ -187,8 +187,9 @@ void tst_QSocketNotifier::unexpectedDisconnection()
writeEnd1->waitForBytesWritten();
writeEnd2->waitForBytesWritten();
writeEnd1->flush();
writeEnd2->flush();
// ensure both read ends are ready for reading, before the event loop
QVERIFY(readEnd1.waitForRead(5000));
QVERIFY(readEnd2.waitForRead(5000));
UnexpectedDisconnectTester tester(&readEnd1, &readEnd2);

View File

@ -14,6 +14,7 @@ qt_internal_add_test(tst_qtimer
tst_qtimer.cpp
LIBRARIES
Qt::CorePrivate
Qt::TestPrivate
)
## Scopes:

View File

@ -11,6 +11,7 @@
#include <QtCore/private/qglobal_p.h>
#include <QTest>
#include <QSignalSpy>
#include <QtTest/private/qpropertytesthelper_p.h>
#include <qtimer.h>
#include <qthread.h>
@ -32,6 +33,12 @@ private slots:
void zeroTimer();
void singleShotTimeout();
void timeout();
void singleShotNormalizes_data();
void singleShotNormalizes();
void sequentialTimers_data();
void sequentialTimers();
void singleShotSequentialTimers_data();
void singleShotSequentialTimers();
void remainingTime();
void remainingTimeInitial_data();
void remainingTimeInitial();
@ -69,6 +76,7 @@ private slots:
void bindToTimer();
void bindTimer();
void automatedBindingTests();
};
void tst_QTimer::zeroTimer()
@ -120,6 +128,142 @@ void tst_QTimer::timeout()
QTRY_VERIFY_WITH_TIMEOUT(timeoutSpy.size() > oldCount, TIMEOUT_TIMEOUT);
}
void tst_QTimer::singleShotNormalizes_data()
{
QTest::addColumn<QByteArray>("slotName");
QTest::newRow("normalized") << QByteArray(SLOT(exitLoop()));
QTest::newRow("space-before") << QByteArray(SLOT( exitLoop()));
QTest::newRow("space-after") << QByteArray(SLOT(exitLoop ()));
QTest::newRow("space-around") << QByteArray(SLOT( exitLoop ()));
QTest::newRow("spaces-before") << QByteArray(SLOT( exitLoop()));
QTest::newRow("spaces-after") << QByteArray(SLOT(exitLoop ()));
QTest::newRow("spaces-around") << QByteArray(SLOT( exitLoop ()));
QTest::newRow("space-in-parens") << QByteArray(SLOT(exitLoop( )));
QTest::newRow("spaces-in-parens") << QByteArray(SLOT(exitLoop( )));
QTest::newRow("space-after-parens") << QByteArray(SLOT(exitLoop() ));
QTest::newRow("spaces-after-parens") << QByteArray(SLOT(exitLoop() ));
}
void tst_QTimer::singleShotNormalizes()
{
using namespace std::chrono_literals;
static constexpr int TestTimeout = 250 * 1000;
QFETCH(QByteArray, slotName);
QEventLoop loop;
// control test: regular connection
{
QTimer timer;
QVERIFY(QObject::connect(&timer, SIGNAL(timeout()), &QTestEventLoop::instance(), slotName.constData()));
timer.setSingleShot(true);
timer.start(1);
QTestEventLoop::instance().enterLoop(TestTimeout);
QVERIFY(!QTestEventLoop::instance().timeout());
}
// non-zero time
QTimer::singleShot(1, &QTestEventLoop::instance(), slotName.constData());
QTestEventLoop::instance().enterLoop(TestTimeout);
QVERIFY(!QTestEventLoop::instance().timeout());
QTimer::singleShot(1ms, &QTestEventLoop::instance(), slotName.constData());
QTestEventLoop::instance().enterLoop(TestTimeout);
QVERIFY(!QTestEventLoop::instance().timeout());
// zero time
QTimer::singleShot(0, &QTestEventLoop::instance(), slotName.constData());
QTestEventLoop::instance().enterLoop(TestTimeout);
QVERIFY(!QTestEventLoop::instance().timeout());
QTimer::singleShot(0ms, &QTestEventLoop::instance(), slotName.constData());
QTestEventLoop::instance().enterLoop(TestTimeout);
QVERIFY(!QTestEventLoop::instance().timeout());
}
void tst_QTimer::sequentialTimers_data()
{
#ifdef Q_OS_WIN
QSKIP("The API used by QEventDispatcherWin32 doesn't respect the order");
#endif
QTest::addColumn<QList<int>>("timeouts");
auto addRow = [](const QList<int> &l) {
QByteArray name;
int last = -1;
for (int i = 0; i < l.size(); ++i) {
Q_ASSERT_X(l[i] >= last, "tst_QTimer", "input list must be sorted");
name += QByteArray::number(l[i]) + ',';
}
name.chop(1);
QTest::addRow("%s", name.constData()) << l;
};
// PreciseTimers
addRow({0, 0, 0, 0, 0, 0});
addRow({0, 1, 2});
addRow({1, 1, 1, 2, 2, 2, 2});
addRow({1, 2, 3});
addRow({19, 19, 19});
// CoarseTimer for setInterval
addRow({20, 20, 20, 20, 20});
addRow({25, 25, 25, 25, 25, 25, 50});
}
void tst_QTimer::sequentialTimers()
{
QFETCH(const QList<int>, timeouts);
QByteArray result, expected;
std::vector<std::unique_ptr<QTimer>> timers;
expected.resize(timeouts.size());
result.reserve(timeouts.size());
timers.reserve(timeouts.size());
for (int i = 0; i < timeouts.size(); ++i) {
auto timer = std::make_unique<QTimer>();
timer->setSingleShot(true);
timer->setInterval(timeouts[i]);
char c = 'A' + i;
expected[i] = c;
QObject::connect(timer.get(), &QTimer::timeout, this, [&result, c = c]() {
result.append(c);
});
timers.push_back(std::move(timer));
}
// start the timers
for (auto &timer : timers)
timer->start();
QTestEventLoop::instance().enterLoopMSecs(timeouts.last() * 2 + 10);
QCOMPARE(result, expected);
}
void tst_QTimer::singleShotSequentialTimers_data()
{
sequentialTimers_data();
}
void tst_QTimer::singleShotSequentialTimers()
{
QFETCH(const QList<int>, timeouts);
QByteArray result, expected;
expected.resize(timeouts.size());
result.reserve(timeouts.size());
for (int i = 0; i < timeouts.size(); ++i) {
char c = 'A' + i;
expected[i] = c;
QTimer::singleShot(timeouts[i], this, [&result, c = c]() {
result.append(c);
});
}
QTestEventLoop::instance().enterLoopMSecs(timeouts.last() * 2 + 10);
QCOMPARE(result, expected);
}
void tst_QTimer::remainingTime()
{
QTimer tested;
@ -1159,6 +1303,42 @@ void tst_QTimer::bindTimer()
QCOMPARE(timer.timerType(), Qt::VeryCoarseTimer);
}
void tst_QTimer::automatedBindingTests()
{
QTimer timer;
QVERIFY(!timer.isSingleShot());
QTestPrivate::testReadWritePropertyBasics(timer, true, false, "singleShot");
if (QTest::currentTestFailed()) {
qDebug("Failed property test for QTimer::singleShot");
return;
}
QCOMPARE_NE(timer.interval(), 10);
QTestPrivate::testReadWritePropertyBasics(timer, 10, 20, "interval");
if (QTest::currentTestFailed()) {
qDebug("Failed property test for QTimer::interval");
return;
}
QCOMPARE_NE(timer.timerType(), Qt::PreciseTimer);
QTestPrivate::testReadWritePropertyBasics(timer, Qt::PreciseTimer, Qt::CoarseTimer,
"timerType");
if (QTest::currentTestFailed()) {
qDebug("Failed property test for QTimer::timerType");
return;
}
timer.start(1000);
QVERIFY(timer.isActive());
QTestPrivate::testReadOnlyPropertyBasics(timer, true, false, "active",
[&timer]() { timer.stop(); });
if (QTest::currentTestFailed()) {
qDebug("Failed property test for QTimer::active");
return;
}
}
class OrderHelper : public QObject
{
Q_OBJECT

View File

@ -5,7 +5,7 @@
## tst_qtranslator Test:
#####################################################################
if (NOT QT_CONFIG_thread)
if (NOT QT_FEATURE_thread)
return()
endif()

View File

@ -129,6 +129,12 @@ private slots:
void canConvert_data();
void canConvert();
void canConvertAndConvert_ReturnFalse_WhenConvertingBetweenPointerAndValue_data();
void canConvertAndConvert_ReturnFalse_WhenConvertingBetweenPointerAndValue();
void canConvertAndConvert_ReturnFalse_WhenConvertingQObjectBetweenPointerAndValue();
void convert();
void toSize_data();
@ -326,6 +332,8 @@ private slots:
void preferDirectConversionOverInterfaces();
void mutableView();
void canViewAndView_ReturnFalseAndDefault_WhenConvertingBetweenPointerAndValue();
void moveOperations();
void equalsWithoutMetaObject();
@ -335,6 +343,8 @@ private slots:
void copyNonDefaultConstructible();
private:
template<typename T>
void canViewAndView_ReturnFalseAndDefault_WhenConvertingBetweenPointerAndValue_impl(const QByteArray &typeName);
void dataStream_data(QDataStream::Version version);
void loadQVariantFromDataStream(QDataStream::Version version);
void saveQVariantFromDataStream(QDataStream::Version version);
@ -623,6 +633,100 @@ QT_WARNING_POP
#endif // QT_DEPRECATED_SINCE(6, 0)
}
namespace {
// Used for testing canConvert/convert of QObject derived types
struct QObjectDerived : QObject
{
Q_OBJECT
};
// Adds a test table row for checking value <-> pointer conversion
// If type is a pointer, the target type is value type and vice versa.
template<typename T>
void addRowForPointerValueConversion()
{
using ValueType = std::remove_pointer_t<T>;
if constexpr (!std::is_same_v<ValueType, std::nullptr_t>) {
static ValueType instance{}; // static since we may need a pointer to a valid object
QVariant variant;
if constexpr (std::is_pointer_v<T>)
variant = QVariant::fromValue(&instance);
else
variant = QVariant::fromValue(instance);
// Toggle pointer/value type
using TargetType = std::conditional_t<std::is_pointer_v<T>, ValueType, T *>;
const QMetaType fromType = QMetaType::fromType<T>();
const QMetaType toType = QMetaType::fromType<TargetType>();
QTest::addRow("%s->%s", fromType.name(), toType.name())
<< variant << QMetaType::fromType<TargetType>();
}
}
} // namespace
void tst_QVariant::canConvertAndConvert_ReturnFalse_WhenConvertingBetweenPointerAndValue_data()
{
QTest::addColumn<QVariant>("variant");
QTest::addColumn<QMetaType>("targetType");
#define ADD_ROW(typeName, typeNameId, realType) \
addRowForPointerValueConversion<realType>(); \
addRowForPointerValueConversion<realType *>();
// Add rows for static primitive types
QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(ADD_ROW)
// Add rows for static core types
QT_FOR_EACH_STATIC_CORE_CLASS(ADD_ROW)
#undef ADD_ROW
}
void tst_QVariant::canConvertAndConvert_ReturnFalse_WhenConvertingBetweenPointerAndValue()
{
QFETCH(QVariant, variant);
QFETCH(QMetaType, targetType);
QVERIFY(!variant.canConvert(targetType));
QVERIFY(!variant.convert(targetType));
// As per the documentation, when QVariant::convert fails, the
// QVariant is cleared and changed to the requested type.
QVERIFY(variant.isNull());
QCOMPARE(variant.metaType(), targetType);
}
void tst_QVariant::canConvertAndConvert_ReturnFalse_WhenConvertingQObjectBetweenPointerAndValue()
{
// Types derived from QObject are non-copyable and require their own test.
// We only test pointer -> value conversion, because constructing a QVariant
// from a non-copyable object will just set the QVariant to null.
QObjectDerived object;
QVariant variant = QVariant::fromValue(&object);
constexpr QMetaType targetType = QMetaType::fromType<QObjectDerived>();
QVERIFY(!variant.canConvert(targetType));
QTest::ignoreMessage(
QtWarningMsg,
QRegularExpression(".*does not support destruction and copy construction"));
QVERIFY(!variant.convert(targetType));
// When the QVariant::convert fails, the QVariant is cleared, and since the target type is
// invalid for QVariant, the QVariant's type is also cleared to an unknown type.
QVERIFY(variant.isNull());
QCOMPARE(variant.metaType(), QMetaType());
}
void tst_QVariant::convert()
{
// verify that after convert(), the variant's type has been changed
@ -632,7 +736,6 @@ void tst_QVariant::convert()
QCOMPARE(var.toInt(), 0);
}
void tst_QVariant::toInt_data()
{
QTest::addColumn<QVariant>("value");
@ -5506,6 +5609,38 @@ void tst_QVariant::mutableView()
QCOMPARE(extracted.text, nullptr);
}
template<typename T>
void tst_QVariant::canViewAndView_ReturnFalseAndDefault_WhenConvertingBetweenPointerAndValue_impl(
const QByteArray &typeName)
{
T instance{};
// Value -> Pointer
QVariant value = QVariant::fromValue(instance);
QVERIFY2(!value.canView<T *>(), typeName);
QCOMPARE(value.view<T *>(), nullptr); // Expect default constructed pointer
// Pointer -> Value
QVariant pointer = QVariant::fromValue(&instance);
QVERIFY2(!pointer.canView<T>(), typeName);
QCOMPARE(pointer.view<T>(), T{}); // Expect default constructed. Note: Weak test since instance
// is default constructed, but we detect data corruption
}
void tst_QVariant::canViewAndView_ReturnFalseAndDefault_WhenConvertingBetweenPointerAndValue()
{
#define ADD_TEST_IMPL(typeName, typeNameId, realType) \
canViewAndView_ReturnFalseAndDefault_WhenConvertingBetweenPointerAndValue_impl<realType>( \
#typeName);
// Add tests for static primitive types
QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(ADD_TEST_IMPL)
// Add tests for static core types
QT_FOR_EACH_STATIC_CORE_CLASS(ADD_TEST_IMPL)
#undef ADD_TEST_IMPL
}
void tst_QVariant::moveOperations()
{
{
@ -5597,6 +5732,13 @@ private:
~Indestructible() {}
};
struct NotCopyable
{
NotCopyable() = default;
NotCopyable(const NotCopyable&) = delete;
NotCopyable &operator=(const NotCopyable &) = delete;
};
void tst_QVariant::constructFromIncompatibleMetaType_data()
{
QTest::addColumn<QMetaType>("type");
@ -5607,6 +5749,7 @@ void tst_QVariant::constructFromIncompatibleMetaType_data()
addRow(QMetaType::fromType<NonDefaultConstructible>());
addRow(QMetaType::fromType<QObject>());
addRow(QMetaType::fromType<Indestructible>());
addRow(QMetaType::fromType<NotCopyable>());
}
void tst_QVariant::constructFromIncompatibleMetaType()