Stabilize tst_QWidget::optimizedResizeMove and optimizedResize_topLevel

The test functions tst_QWidget::optimizedResizeMove and
tst_QWidget::optimizedResize_topLevel use a custom widget to record
paint events in a boolean.
Using QTRY_* or qWait() to wait for the boolean to become true stops
event processing upon consumption of the first paint event.
In case of multiple paint events, the next paint event will be recorded
in the next check and may lead to a wrong result.
This leads to flakiness on platforms generating multiple paint events,
openSuSE Leap 15.4 / XCB being one of them.

This patch replaces the boolean with a counter. It adds a
waitForPaintEvents method to the custom class, which processes events,
until the counter stops increasing. It returns true when paint events
have been recorded and false otherwise. It resets the counter after
each call.

It also removes the QSKIP on wayland, as the failure results from the
same reason.

Fixes: QTBUG-109093
Change-Id: I59ee8bb4efeaf5417d5749d21e384bee89301ae0
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 2ec7a6322f465ad7cce3c48096d8912903196ab2)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Axel Spoerl 2022-12-01 11:03:31 +01:00 committed by Qt Cherry-pick Bot
parent d95b21706f
commit 761bd30d7d

View File

@ -4490,22 +4490,20 @@ class StaticWidget : public QWidget
Q_OBJECT
public:
bool partial = false;
bool gotPaintEvent = false;
QRegion paintedRegion;
explicit StaticWidget(QWidget *parent = nullptr) : QWidget(parent)
explicit StaticWidget(const QPalette &palette, QWidget *parent = nullptr) : QWidget(parent)
{
setAttribute(Qt::WA_StaticContents);
setAttribute(Qt::WA_OpaquePaintEvent);
setPalette(Qt::red); // Make sure we have an opaque palette.
setPalette(palette);
setAutoFillBackground(true);
}
void paintEvent(QPaintEvent *e) override
{
paintedRegion += e->region();
gotPaintEvent = true;
// qDebug() << "paint" << e->region();
++paintEvents;
// Look for a full update, set partial to false if found.
for (QRect r : e->region()) {
partial = (r != rect());
@ -4513,6 +4511,28 @@ public:
break;
}
}
// Wait timeout ms until at least one paint event has been consumed
// and the counter is no longer increasing.
// => making sure to consume multiple paint events relating to one operation
// before returning true.
bool waitForPaintEvent(int timeout = 100)
{
QDeadlineTimer deadline(timeout);
int count = -1;
while (!deadline.hasExpired() && count != paintEvents) {
count = paintEvents;
QCoreApplication::processEvents();
if (count == paintEvents && count > 0) {
paintEvents = 0;
return true;
}
}
paintEvents = 0;
return false;
}
private:
int paintEvents = 0;
};
/*
@ -4521,102 +4541,75 @@ public:
*/
void tst_QWidget::optimizedResizeMove()
{
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
QWidget parent;
parent.setPalette(simplePalette());
parent.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
parent.setWindowTitle(QTest::currentTestFunction());
parent.resize(400, 400);
StaticWidget staticWidget(&parent);
staticWidget.setPalette(simplePalette());
staticWidget.gotPaintEvent = false;
StaticWidget staticWidget(simplePalette(), &parent);
staticWidget.move(150, 150);
staticWidget.resize(150, 150);
parent.show();
QVERIFY(QTest::qWaitForWindowExposed(&parent));
QTRY_VERIFY(staticWidget.gotPaintEvent);
QVERIFY(staticWidget.waitForPaintEvent());
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(10, 10));
QTest::qWait(20);
QCOMPARE(staticWidget.gotPaintEvent, false);
QVERIFY(!staticWidget.waitForPaintEvent());
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
QTest::qWait(20);
QCOMPARE(staticWidget.gotPaintEvent, false);
QVERIFY(!staticWidget.waitForPaintEvent());
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(-10, 10));
QTest::qWait(20);
QCOMPARE(staticWidget.gotPaintEvent, false);
QVERIFY(!staticWidget.waitForPaintEvent());
staticWidget.gotPaintEvent = false;
staticWidget.resize(staticWidget.size() + QSize(10, 10));
QTRY_VERIFY(staticWidget.gotPaintEvent);
QVERIFY(staticWidget.waitForPaintEvent());
QCOMPARE(staticWidget.partial, true);
staticWidget.gotPaintEvent = false;
staticWidget.resize(staticWidget.size() + QSize(-10, -10));
QTest::qWait(20);
QCOMPARE(staticWidget.gotPaintEvent, false);
QVERIFY(!staticWidget.waitForPaintEvent());
staticWidget.gotPaintEvent = false;
staticWidget.resize(staticWidget.size() + QSize(10, -10));
QTRY_VERIFY(staticWidget.gotPaintEvent);
QVERIFY(staticWidget.waitForPaintEvent());
QCOMPARE(staticWidget.partial, true);
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(10, 10));
staticWidget.resize(staticWidget.size() + QSize(-10, -10));
QTest::qWait(20);
QCOMPARE(staticWidget.gotPaintEvent, false);
QVERIFY(!staticWidget.waitForPaintEvent());
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(10, 10));
staticWidget.resize(staticWidget.size() + QSize(10, 10));
QTRY_VERIFY(staticWidget.gotPaintEvent);
QVERIFY(staticWidget.waitForPaintEvent());
QCOMPARE(staticWidget.partial, true);
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
staticWidget.resize(staticWidget.size() + QSize(-10, -10));
QTest::qWait(20);
QCOMPARE(staticWidget.gotPaintEvent, false);
QVERIFY(!staticWidget.waitForPaintEvent());
staticWidget.setAttribute(Qt::WA_StaticContents, false);
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
staticWidget.resize(staticWidget.size() + QSize(-10, -10));
QTRY_VERIFY(staticWidget.gotPaintEvent);
QVERIFY(staticWidget.waitForPaintEvent());
QCOMPARE(staticWidget.partial, false);
staticWidget.setAttribute(Qt::WA_StaticContents, true);
staticWidget.setAttribute(Qt::WA_StaticContents, false);
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(10, 10));
QTest::qWait(20);
QCOMPARE(staticWidget.gotPaintEvent, false);
QVERIFY(!staticWidget.waitForPaintEvent());
staticWidget.setAttribute(Qt::WA_StaticContents, true);
}
void tst_QWidget::optimizedResize_topLevel()
{
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
QSKIP("Wayland: This fails. Figure out why.");
if (QHighDpiScaling::isActive())
QSKIP("Skip due to rounding errors in the regions.");
StaticWidget topLevel;
StaticWidget topLevel(simplePalette());
topLevel.setPalette(simplePalette());
topLevel.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
topLevel.gotPaintEvent = false;
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
QTRY_VERIFY(topLevel.gotPaintEvent);
QVERIFY(topLevel.waitForPaintEvent());
topLevel.gotPaintEvent = false;
topLevel.partial = false;
topLevel.paintedRegion = QRegion();
@ -4641,7 +4634,7 @@ void tst_QWidget::optimizedResize_topLevel()
QRegion expectedUpdateRegion(topLevel.rect());
expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
QTRY_VERIFY(topLevel.gotPaintEvent);
QVERIFY(topLevel.waitForPaintEvent());
if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("offscreen"))
QSKIP("QTBUG-26424");
QCOMPARE(topLevel.partial, true);