mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-03 15:55:27 +08:00
6.5.3 clean
This commit is contained in:
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -1,3 +0,0 @@
|
||||
[unexpectedDisconnection]
|
||||
windows ci
|
||||
|
@ -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);
|
||||
|
||||
|
@ -14,6 +14,7 @@ qt_internal_add_test(tst_qtimer
|
||||
tst_qtimer.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Qt::TestPrivate
|
||||
)
|
||||
|
||||
## Scopes:
|
||||
|
@ -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
|
||||
|
@ -5,7 +5,7 @@
|
||||
## tst_qtranslator Test:
|
||||
#####################################################################
|
||||
|
||||
if (NOT QT_CONFIG_thread)
|
||||
if (NOT QT_FEATURE_thread)
|
||||
return()
|
||||
endif()
|
||||
|
||||
|
@ -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()
|
||||
|
Reference in New Issue
Block a user