Stabilize flakiness in tst_QOpenGLWidget

qWaitForWindowActive was called in two test functions without
activating the relevant widget.
This patch adds widget activation before calling
qWaitForWindowActive.

Helper function verifyColor:
A loop made six comparison attempts of widget size, pixel color and
image with a 200ms waiting time after each unsuccessful attempt.
The widget size was tested at the beginning of the loop.
The test was failed on the first size mismatch, which occurred when
verifyColor was called before the widget was rendered.
That has lead to flakiness (e.g. on openSuSE).

This patch encapsules each check in a lambda and calls qWaitFor to
ensure event processing until each condition has become true.

Change-Id: Ic98f93c8acf41459bc728f2969fe8b01768048dd
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Axel Spoerl 2022-11-08 09:47:15 +01:00
parent fe67c69643
commit ca254a0937

View File

@ -423,6 +423,7 @@ void tst_QOpenGLWidget::asViewport()
// repainted when going from Inactive to Active. So wait for the window to be // repainted when going from Inactive to Active. So wait for the window to be
// active before we continue, so the activation doesn't happen at a random // active before we continue, so the activation doesn't happen at a random
// time below. And call processEvents to have the paint events delivered right away. // time below. And call processEvents to have the paint events delivered right away.
widget.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&widget)); QVERIFY(QTest::qWaitForWindowActive(&widget));
qApp->processEvents(); qApp->processEvents();
} }
@ -599,50 +600,59 @@ static QPixmap grabWidgetWithoutRepaint(const QWidget *widget, QRect clipArea)
bool verifyColor(const QWidget *widget, const QRect &clipArea, const QColor &color, int callerLine) bool verifyColor(const QWidget *widget, const QRect &clipArea, const QColor &color, int callerLine)
{ {
for (int t = 0; t < 6; t++) { // Create a comparison target image
const QPixmap pixmap = grabWidgetWithoutRepaint(widget, clipArea); QPixmap expectedPixmap(grabWidgetWithoutRepaint(widget, clipArea)); /* ensure equal formats */
if (!QTest::qCompare(pixmap.size(), expectedPixmap.detach();
clipArea.size(), expectedPixmap.fill(color);
"pixmap.size()", const QImage expectedImage = expectedPixmap.toImage();
"rect.size()",
__FILE__,
callerLine))
return false;
// test image size
QPixmap pixmap;
auto testSize = [&](){
pixmap = grabWidgetWithoutRepaint(widget, clipArea);
return pixmap.size() == clipArea.size();
};
const QImage image = pixmap.toImage(); // test the first pixel's color
QPixmap expectedPixmap(pixmap); /* ensure equal formats */ uint firstPixel;
expectedPixmap.detach(); auto testPixel = [&](){
expectedPixmap.fill(color); const QImage image = grabWidgetWithoutRepaint(widget, clipArea).toImage();
uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0;
uint firstPixel = image.pixel(0,0) | alphaCorrection; firstPixel = image.pixel(0,0) | alphaCorrection;
return firstPixel == QColor(color).rgb();
};
// Retry a couple of times. Some window managers have transparency animation, or are // test the rendered image
// just slow to render. QImage image;
if (t < 5) { auto testImage = [&](){
if (firstPixel == QColor(color).rgb() image = grabWidgetWithoutRepaint(widget, clipArea).toImage();
&& image == expectedPixmap.toImage()) return image == expectedImage;
return true; };
else
QTest::qWait(200); // Perform checks and make test case fail if unsuccessful
} else { if (!QTest::qWaitFor(testSize))
if (!QTest::qVerify(firstPixel == QColor(color).rgb(), return QTest::qCompare(pixmap.size(),
"firstPixel == QColor(color).rgb()", clipArea.size(),
qPrintable(msgRgbMismatch(firstPixel, QColor(color).rgb())), "pixmap.size()",
__FILE__, callerLine)) { "rect.size()",
return false; __FILE__,
} callerLine);
if (!QTest::qVerify(image == expectedPixmap.toImage(),
"image == expectedPixmap.toImage()", if (!QTest::qWaitFor(testPixel)) {
"grabbed pixmap differs from expected pixmap", return QTest::qVerify(firstPixel == QColor(color).rgb(),
__FILE__, callerLine)) { "firstPixel == QColor(color).rgb()",
return false; qPrintable(msgRgbMismatch(firstPixel, QColor(color).rgb())),
} __FILE__, callerLine);
}
} }
return false; if (!QTest::qWaitFor(testImage)) {
return QTest::qVerify(image == expectedImage,
"image == expectedPixmap.toImage()",
"grabbed pixmap differs from expected pixmap",
__FILE__, callerLine);
}
return true;
} }
void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible() void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible()
@ -675,6 +685,7 @@ void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible()
stack.resize(dimensionSize, dimensionSize); stack.resize(dimensionSize, dimensionSize);
stack.show(); stack.show();
QVERIFY(QTest::qWaitForWindowExposed(&stack)); QVERIFY(QTest::qWaitForWindowExposed(&stack));
stack.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&stack)); QVERIFY(QTest::qWaitForWindowActive(&stack));
// Switch to the QOpenGLWidget. // Switch to the QOpenGLWidget.