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();
expectedPixmap.fill(color);
const QImage expectedImage = expectedPixmap.toImage();
// test image size
QPixmap pixmap;
auto testSize = [&](){
pixmap = grabWidgetWithoutRepaint(widget, clipArea);
return pixmap.size() == clipArea.size();
};
// test the first pixel's color
uint firstPixel;
auto testPixel = [&](){
const QImage image = grabWidgetWithoutRepaint(widget, clipArea).toImage();
uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0;
firstPixel = image.pixel(0,0) | alphaCorrection;
return firstPixel == QColor(color).rgb();
};
// test the rendered image
QImage image;
auto testImage = [&](){
image = grabWidgetWithoutRepaint(widget, clipArea).toImage();
return image == expectedImage;
};
// Perform checks and make test case fail if unsuccessful
if (!QTest::qWaitFor(testSize))
return QTest::qCompare(pixmap.size(),
clipArea.size(), clipArea.size(),
"pixmap.size()", "pixmap.size()",
"rect.size()", "rect.size()",
__FILE__, __FILE__,
callerLine)) callerLine);
return false;
if (!QTest::qWaitFor(testPixel)) {
const QImage image = pixmap.toImage(); return QTest::qVerify(firstPixel == QColor(color).rgb(),
QPixmap expectedPixmap(pixmap); /* ensure equal formats */
expectedPixmap.detach();
expectedPixmap.fill(color);
uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0;
uint firstPixel = image.pixel(0,0) | alphaCorrection;
// Retry a couple of times. Some window managers have transparency animation, or are
// just slow to render.
if (t < 5) {
if (firstPixel == QColor(color).rgb()
&& image == expectedPixmap.toImage())
return true;
else
QTest::qWait(200);
} else {
if (!QTest::qVerify(firstPixel == QColor(color).rgb(),
"firstPixel == QColor(color).rgb()", "firstPixel == QColor(color).rgb()",
qPrintable(msgRgbMismatch(firstPixel, QColor(color).rgb())), qPrintable(msgRgbMismatch(firstPixel, QColor(color).rgb())),
__FILE__, callerLine)) { __FILE__, callerLine);
return false;
}
if (!QTest::qVerify(image == expectedPixmap.toImage(),
"image == expectedPixmap.toImage()",
"grabbed pixmap differs from expected pixmap",
__FILE__, callerLine)) {
return false;
}
}
} }
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.