Merge branch 'msw-uitests'

Attempt to fix wxMSW UI tests under AppVeyor and other improvements.

See #23926.
This commit is contained in:
Vadim Zeitlin 2023-10-02 19:32:52 +02:00
commit 0741b09a92
17 changed files with 118 additions and 162 deletions

View file

@ -74,8 +74,10 @@ void BitmapToggleButtonTestCase::Click()
wxUIActionSimulator sim;
const wxPoint pos = m_button->GetScreenPosition();
//We move in slightly to account for window decorations
sim.MouseMove(m_button->GetScreenPosition() + wxPoint(10, 10));
sim.MouseMove(pos + wxPoint(10, 10));
wxYield();
sim.MouseClick();
@ -86,9 +88,10 @@ void BitmapToggleButtonTestCase::Click()
clicked.Clear();
#ifdef __WXMSW__
wxMilliSleep(1000);
#endif
// Change the mouse position to prevent the second click from being
// recognized as double click.
sim.MouseMove(pos + wxPoint(20, 20));
wxYield();
sim.MouseClick();
wxYield();

View file

@ -23,6 +23,7 @@
// Get operator<<(wxSize) so that wxSize values are shown correctly in case of
// a failure of a CHECK() involving them.
#include "asserthelper.h"
#include "waitfor.h"
class ButtonTestCase
{
@ -64,7 +65,10 @@ TEST_CASE_METHOD(ButtonTestCase, "Button::Click", "[button]")
wxYield();
sim.MouseClick();
wxYield();
// At least under wxMSW calling wxYield() just once doesn't always work, so
// try for a while.
WaitFor("button to be clicked", [&]() { return clicked.GetCount() != 0; });
CHECK( clicked.GetCount() == 1 );
}

View file

@ -20,7 +20,7 @@
#include "wx/uiaction.h"
#ifdef __WXGTK__
#include "wx/stopwatch.h"
#include "waitfor.h"
#endif // __WXGTK__
#include "testableframe.h"
@ -366,31 +366,23 @@ protected:
#ifdef __WXGTK__
// Unfortunately it's not enough to call wxYield() once, so wait up to
// 0.5 sec.
wxStopWatch sw;
while ( true )
{
wxYield();
WaitFor("wxDataViewCtrl upder", [this, item, existence]() {
const bool isItemRectEmpty = m_dvc->GetItemRect(item).IsEmpty();
switch ( existence )
{
case wxITEM_APPEAR:
if ( !isItemRectEmpty )
return;
return true;
break;
case wxITEM_DISAPPEAR:
if ( isItemRectEmpty )
return;
return true;
break;
}
if ( sw.Time() > 500 )
{
WARN("Timed out waiting for wxDataViewCtrl");
break;
}
}
return false;
});
#else // !__WXGTK__
wxUnusedVar(item);
wxUnusedVar(existence);
@ -810,16 +802,9 @@ TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
#ifdef __WXGTK__
// Wait for the list control to be relaid out.
wxStopWatch sw;
while ( m_dvc->GetTopItem() == m_root )
{
if ( sw.Time() > 500 )
{
WARN("Timed out waiting for wxDataViewCtrl layout");
break;
}
wxYield();
}
WaitFor("wxDataViewCtrl layout", [this]() {
return m_dvc->GetTopItem() != m_root;
});
#endif // __WXGTK__
// Check that this was indeed the case.
@ -858,16 +843,9 @@ TEST_CASE_METHOD(MultiColumnsDataViewCtrlTestCase,
{
#ifdef __WXGTK__
// Wait for the list control to be realized.
wxStopWatch sw;
while ( m_firstColumn->GetWidth() == 0 )
{
if ( sw.Time() > 500 )
{
WARN("Timed out waiting for wxDataViewListCtrl to be realized");
break;
}
wxYield();
}
WaitFor("wxDataViewCtrl to be realized", [this]() {
return m_firstColumn->GetWidth() != 0;
});
#endif
// Check the width of the first column.

View file

@ -26,7 +26,7 @@
#include "wx/stopwatch.h"
#endif // __WXGTK__
#include "waitforpaint.h"
#include "waitfor.h"
// To disable tests which work locally, but not when run on GitHub CI.
#if defined(__WXGTK__) && !defined(__WXGTK3__)

View file

@ -16,12 +16,13 @@
#if wxUSE_DATEPICKCTRL
#include "wx/datectrl.h"
#endif
#include "wx/stopwatch.h"
#include "wx/propgrid/propgrid.h"
#include "wx/propgrid/manager.h"
#include "wx/propgrid/advprops.h"
#include "waitfor.h"
#include <random>
#include <vector>
@ -450,11 +451,7 @@ static wxPropertyGridManager* CreateGrid(int style, int extraStyle)
pgManager->Refresh();
pgManager->Update();
// Wait for update to be done
wxStopWatch sw;
while ( sw.Time() < 100 )
{
wxYield();
}
YieldForAWhile(100);
return pgManager;
}
@ -722,11 +719,7 @@ TEST_CASE("PropertyGridTestCase", "[propgrid]")
pgManager->Refresh();
pgManager->Update();
// Wait for update to be done
wxStopWatch sw;
while ( sw.Time() < 100 )
{
wxYield();
}
YieldForAWhile(100);
}
SECTION("Default_Values")

View file

@ -29,7 +29,7 @@
#endif // wxUSE_CLIPBOARD
#ifdef __WXGTK__
#include "wx/stopwatch.h"
#include "waitfor.h"
#endif
#include "wx/private/localeset.h"
@ -397,8 +397,7 @@ void TextCtrlTestCase::HitTestSingleLine()
#ifdef __WXGTK__
// wxGTK must be given an opportunity to lay the text out.
for ( wxStopWatch sw; sw.Time() < 50; )
wxYield();
YieldForAWhile();
#endif
REQUIRE( m_text->HitTest(wxPoint(2*sizeChar.x, yMid), &pos) == wxTE_HT_ON_TEXT );
@ -757,18 +756,10 @@ void TextCtrlTestCase::DoPositionToCoordsTestWithStyle(long style)
// wxGTK needs to yield here to update the text control.
#ifdef __WXGTK__
wxStopWatch sw;
while ( m_text->PositionToCoords(0).y == 0 ||
m_text->PositionToCoords(pos).y > TEXT_HEIGHT )
{
if ( sw.Time() > 1000 )
{
FAIL("Timed out waiting for wxTextCtrl update.");
break;
}
wxYield();
}
WaitFor("wxTextCtrl update", [this, pos]() {
return m_text->PositionToCoords(0).y != 0 &&
m_text->PositionToCoords(pos).y <= TEXT_HEIGHT;
}, 1000);
#endif // __WXGTK__
wxPoint coords = m_text->PositionToCoords(0);

View file

@ -22,7 +22,7 @@
#include "wx/msw/webview_ie.h"
#endif
#if wxUSE_WEBVIEW_WEBKIT2
#include "wx/stopwatch.h"
#include "waitfor.h"
#endif
//Convenience macro
@ -235,8 +235,7 @@ TEST_CASE_METHOD(WebViewTestCase, "WebView", "[wxWebView]")
// bit before giving up. Avoid calling HasSelection() right away
// without wxYielding a bit because this seems to cause the extension
// to hang with webkit 2.40.0+.
for ( wxStopWatch sw; sw.Time() < 50; )
wxYield();
YieldForAWhile();
#endif // wxUSE_WEBVIEW_WEBKIT2
CHECK(m_browser->HasSelection());

View file

@ -19,12 +19,12 @@
#include "asserthelper.h"
#include "testableframe.h"
#include "testwindow.h"
#include "waitfor.h"
#include "wx/uiaction.h"
#include "wx/caret.h"
#include "wx/cshelp.h"
#include "wx/dcclient.h"
#include "wx/stopwatch.h"
#include "wx/tooltip.h"
#include "wx/wupdlock.h"
@ -40,8 +40,7 @@ public:
// Without this, when running this test suite solo it succeeds,
// but not when running it together with the other tests !!
// Not needed when run under Xvfb display.
for ( wxStopWatch sw; sw.Time() < 50; )
wxYield();
YieldForAWhile();
#endif
}
@ -510,13 +509,7 @@ TEST_CASE_METHOD(WindowTestCase, "Window::Refresh", "[window]")
parent->RefreshRect(wxRect(150, 10, 300, 80));
for ( wxStopWatch sw; sw.Time() < 100; )
{
if ( isParentPainted )
break;
wxYield();
}
WaitFor("parent repaint", [&]() { return isParentPainted; }, 100);
// child1 should be the only window not to receive the wxEVT_PAINT event
// because it does not intersect with the refreshed rectangle.

View file

@ -24,9 +24,7 @@
#include "wx/uiaction.h"
#include "wx/vector.h"
#ifdef __WXGTK__
#include "wx/stopwatch.h"
#endif
#include "waitfor.h"
namespace
{
@ -229,10 +227,7 @@ void KeyboardEventTestCase::setUp()
wxYield();
m_win->SetFocus();
#ifdef __WXGTK__
for ( wxStopWatch sw; sw.Time() < 10; )
#endif
wxYield(); // needed to show the new window
YieldForAWhile(10); // needed to show the new window
// The window might get some key up events when it's being shown if the key
// was pressed when the program was started and released after the window

View file

@ -26,10 +26,13 @@
#include "wx/scopeguard.h"
#include "wx/toolbar.h"
#include "wx/uiaction.h"
#include "wx/stopwatch.h"
#include <memory>
#ifdef __WXGTK__
#include "waitfor.h"
#endif
// FIXME: Currently under OS X testing paint event doesn't work because neither
// calling Refresh()+Update() nor even sending wxPaintEvent directly to
// the window doesn't result in calls to its event handlers, so disable
@ -174,8 +177,7 @@ public:
#ifdef __WXGTK__
// We need to map the window, otherwise we're not going to get any
// paint events for it.
for ( wxStopWatch sw; sw.Time() < 50; )
wxYield();
YieldForAWhile();
// Ignore events generated during the initial mapping.
g_str.clear();

View file

@ -23,7 +23,7 @@
#include "wx/window.h"
#include "testfile.h"
#include "waitforpaint.h"
#include "waitfor.h"
static const wxSize s_dcSize(260, 300);
@ -751,11 +751,7 @@ TEST_CASE("ClipperTestCase::wxPaintDC", "[clipper][dc][paintdc]")
testWin->Refresh();
testWin->Update();
// Wait for update to be done
wxStopWatch sw;
while( sw.Time() < 50 )
{
wxYield();
}
YieldForAWhile();
CHECK(paintExecuted == true);
}

View file

@ -22,7 +22,7 @@
#include "wx/dcclient.h"
#include "testfile.h"
#include "waitforpaint.h"
#include "waitfor.h"
#include <memory>
@ -4322,11 +4322,7 @@ TEST_CASE("ClippingBoxTestCase::wxPaintDC", "[clip][dc][paintdc]")
testWin->Refresh();
testWin->Update();
// Wait for update to be done
wxStopWatch sw;
while( sw.Time() < 50 )
{
wxYield();
}
YieldForAWhile();
CHECK(paintExecuted == true);
}

View file

@ -19,14 +19,14 @@
#ifndef WX_PRECOMP
#include "wx/dataview.h"
#ifdef __WXGTK__
#include "wx/stopwatch.h"
#endif // __WXGTK__
#endif // WX_PRECOMP
#include "wx/persist/dataview.h"
#ifdef __WXGTK__
#include "waitfor.h"
#endif // __WXGTK__
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
@ -90,17 +90,9 @@ static wxDataViewCtrl* CreatePersistenceTestDVC()
void GTKWaitRealized(wxDataViewCtrl* list)
{
#ifdef __WXGTK__
wxStopWatch sw;
while ( list->GetColumn(0)->GetWidth() == 0 )
{
if ( sw.Time() > 500 )
{
WARN("Timed out waiting for wxDataViewCtrl to be realized");
break;
}
wxYield();
}
WaitFor("wxDataViewCtrl to be realized", [list]() {
return list->GetColumn(0)->GetWidth() != 0;
});
#else // !__WXGTK__
wxUnusedVar(list);
#endif // __WXGTK__/!__WXGTK__

View file

@ -17,14 +17,14 @@
#ifndef WX_PRECOMP
#include "wx/frame.h"
#ifdef __WXGTK__
#include "wx/stopwatch.h"
#endif // __WXGTK__
#endif // WX_PRECOMP
#include "wx/persist/toplevel.h"
#ifdef __WXGTK__
#include "waitfor.h"
#endif // __WXGTK__
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
@ -117,17 +117,11 @@ TEST_CASE_METHOD(PersistenceTests, "wxPersistTLW", "[persist][tlw]")
}
else
{
wxStopWatch sw;
while ( !frame->IsIconized() )
if ( !WaitFor("frame to be iconized", [frame]() {
return frame->IsIconized();
}) )
{
wxYield();
if ( sw.Time() > 500 )
{
// 500ms should be enough for the window to end up iconized.
WARN("Frame wasn't iconized as expected");
checkIconized = false;
break;
}
checkIconized = false;
}
}
#endif // __WXGTK__
@ -148,16 +142,9 @@ TEST_CASE_METHOD(PersistenceTests, "wxPersistTLW", "[persist][tlw]")
if ( checkIconized )
{
#ifdef __WXGTK__
wxStopWatch sw;
while ( !frame->IsIconized() )
{
wxYield();
if ( sw.Time() > 500 )
{
INFO("Abandoning wait after " << sw.Time() << "ms");
break;
}
}
WaitFor("frame to be iconized", [frame]() {
return frame->IsIconized();
});
#endif // __WXGTK__
CHECK(frame->IsIconized());

View file

@ -1,17 +1,57 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/waitforpaint.h
// Name: tests/waitfor.h
// Purpose: Helper WaitForPaint class
// Author: Vadim Zeitlin
// Created: 2019-10-17 (extracted from tests/window/setsize.cpp)
// Copyright: (c) 2019 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_TESTS_WAITFORPAINT_H_
#define _WX_TESTS_WAITFORPAINT_H_
#ifndef _WX_TESTS_WAITFOR_H_
#define _WX_TESTS_WAITFOR_H_
#include "wx/stopwatch.h"
#include "wx/window.h"
#include <functional>
// Function used to wait until the given predicate becomes true or timeout
// expires.
inline bool
WaitFor(const char* what, const std::function<bool ()>& pred, int timeout = 500)
{
wxStopWatch sw;
for ( ;; )
{
wxYield();
if ( pred() )
break;
if ( sw.Time() > timeout )
{
WARN("Timed out waiting for " << what);
return false;
}
}
return true;
}
// An even simpler version which doesn't wait for anything but just calls
// wxYield() until the given timeout expires.
inline void
YieldForAWhile(int timeout = 50)
{
wxStopWatch sw;
for ( ;; )
{
wxYield();
if ( sw.Time() > timeout )
break;
}
}
// Class used to check if we received the (first) paint event: this is
// currently used under GTK only, as MSW doesn't seem to need to wait for the
// things to work, while under Mac nothing works anyhow.
@ -32,23 +72,10 @@ public:
// event to come and logs a warning if we didn't get it.
void YieldUntilPainted(int timeoutInMS = 250)
{
wxStopWatch sw;
for ( ;; )
if ( WaitFor("repaint", [this]() { return m_painted; }, timeoutInMS) )
{
wxYield();
if ( m_painted )
{
// Reset it in case YieldUntilPainted() is called again.
m_painted = false;
break;
}
if ( sw.Time() > timeoutInMS )
{
WARN("Didn't get a paint event until timeout expiration");
break;
}
// Reset it in case YieldUntilPainted() is called again.
m_painted = false;
}
}
@ -99,4 +126,4 @@ public:
#endif // __WXGTK__/!__WXGTK__
#endif // _WX_TESTS_WAITFORPAINT_H_
#endif // _WX_TESTS_WAITFOR_H_

View file

@ -21,7 +21,7 @@
#include <memory>
#include "asserthelper.h"
#include "waitforpaint.h"
#include "waitfor.h"
// ----------------------------------------------------------------------------
// tests themselves

View file

@ -22,7 +22,7 @@
#include <memory>
#include "asserthelper.h"
#include "waitforpaint.h"
#include "waitfor.h"
// ----------------------------------------------------------------------------
// tests helpers