Use WaitFor() and new YieldForAWhile() helpers in the tests
Reuse the existing function (and another new one, which is even simpler) instead of duplicating its code in many places in the tests. No real changes.
This commit is contained in:
parent
dc6085a808
commit
fa5964c100
12 changed files with 69 additions and 132 deletions
|
|
@ -20,7 +20,7 @@
|
||||||
#include "wx/uiaction.h"
|
#include "wx/uiaction.h"
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
#include "wx/stopwatch.h"
|
#include "waitfor.h"
|
||||||
#endif // __WXGTK__
|
#endif // __WXGTK__
|
||||||
|
|
||||||
#include "testableframe.h"
|
#include "testableframe.h"
|
||||||
|
|
@ -366,31 +366,23 @@ protected:
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
// Unfortunately it's not enough to call wxYield() once, so wait up to
|
// Unfortunately it's not enough to call wxYield() once, so wait up to
|
||||||
// 0.5 sec.
|
// 0.5 sec.
|
||||||
wxStopWatch sw;
|
WaitFor("wxDataViewCtrl upder", [this, item, existence]() {
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
wxYield();
|
|
||||||
|
|
||||||
const bool isItemRectEmpty = m_dvc->GetItemRect(item).IsEmpty();
|
const bool isItemRectEmpty = m_dvc->GetItemRect(item).IsEmpty();
|
||||||
switch ( existence )
|
switch ( existence )
|
||||||
{
|
{
|
||||||
case wxITEM_APPEAR:
|
case wxITEM_APPEAR:
|
||||||
if ( !isItemRectEmpty )
|
if ( !isItemRectEmpty )
|
||||||
return;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case wxITEM_DISAPPEAR:
|
case wxITEM_DISAPPEAR:
|
||||||
if ( isItemRectEmpty )
|
if ( isItemRectEmpty )
|
||||||
return;
|
return true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( sw.Time() > 500 )
|
return false;
|
||||||
{
|
});
|
||||||
WARN("Timed out waiting for wxDataViewCtrl");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else // !__WXGTK__
|
#else // !__WXGTK__
|
||||||
wxUnusedVar(item);
|
wxUnusedVar(item);
|
||||||
wxUnusedVar(existence);
|
wxUnusedVar(existence);
|
||||||
|
|
@ -810,16 +802,9 @@ TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
// Wait for the list control to be relaid out.
|
// Wait for the list control to be relaid out.
|
||||||
wxStopWatch sw;
|
WaitFor("wxDataViewCtrl layout", [this]() {
|
||||||
while ( m_dvc->GetTopItem() == m_root )
|
return m_dvc->GetTopItem() != m_root;
|
||||||
{
|
});
|
||||||
if ( sw.Time() > 500 )
|
|
||||||
{
|
|
||||||
WARN("Timed out waiting for wxDataViewCtrl layout");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wxYield();
|
|
||||||
}
|
|
||||||
#endif // __WXGTK__
|
#endif // __WXGTK__
|
||||||
|
|
||||||
// Check that this was indeed the case.
|
// Check that this was indeed the case.
|
||||||
|
|
@ -858,16 +843,9 @@ TEST_CASE_METHOD(MultiColumnsDataViewCtrlTestCase,
|
||||||
{
|
{
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
// Wait for the list control to be realized.
|
// Wait for the list control to be realized.
|
||||||
wxStopWatch sw;
|
WaitFor("wxDataViewCtrl to be realized", [this]() {
|
||||||
while ( m_firstColumn->GetWidth() == 0 )
|
return m_firstColumn->GetWidth() != 0;
|
||||||
{
|
});
|
||||||
if ( sw.Time() > 500 )
|
|
||||||
{
|
|
||||||
WARN("Timed out waiting for wxDataViewListCtrl to be realized");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wxYield();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check the width of the first column.
|
// Check the width of the first column.
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,13 @@
|
||||||
#if wxUSE_DATEPICKCTRL
|
#if wxUSE_DATEPICKCTRL
|
||||||
#include "wx/datectrl.h"
|
#include "wx/datectrl.h"
|
||||||
#endif
|
#endif
|
||||||
#include "wx/stopwatch.h"
|
|
||||||
|
|
||||||
#include "wx/propgrid/propgrid.h"
|
#include "wx/propgrid/propgrid.h"
|
||||||
#include "wx/propgrid/manager.h"
|
#include "wx/propgrid/manager.h"
|
||||||
#include "wx/propgrid/advprops.h"
|
#include "wx/propgrid/advprops.h"
|
||||||
|
|
||||||
|
#include "waitfor.h"
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -450,11 +451,7 @@ static wxPropertyGridManager* CreateGrid(int style, int extraStyle)
|
||||||
pgManager->Refresh();
|
pgManager->Refresh();
|
||||||
pgManager->Update();
|
pgManager->Update();
|
||||||
// Wait for update to be done
|
// Wait for update to be done
|
||||||
wxStopWatch sw;
|
YieldForAWhile(100);
|
||||||
while ( sw.Time() < 100 )
|
|
||||||
{
|
|
||||||
wxYield();
|
|
||||||
}
|
|
||||||
|
|
||||||
return pgManager;
|
return pgManager;
|
||||||
}
|
}
|
||||||
|
|
@ -722,11 +719,7 @@ TEST_CASE("PropertyGridTestCase", "[propgrid]")
|
||||||
pgManager->Refresh();
|
pgManager->Refresh();
|
||||||
pgManager->Update();
|
pgManager->Update();
|
||||||
// Wait for update to be done
|
// Wait for update to be done
|
||||||
wxStopWatch sw;
|
YieldForAWhile(100);
|
||||||
while ( sw.Time() < 100 )
|
|
||||||
{
|
|
||||||
wxYield();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Default_Values")
|
SECTION("Default_Values")
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
#endif // wxUSE_CLIPBOARD
|
#endif // wxUSE_CLIPBOARD
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
#include "wx/stopwatch.h"
|
#include "waitfor.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "wx/private/localeset.h"
|
#include "wx/private/localeset.h"
|
||||||
|
|
@ -397,8 +397,7 @@ void TextCtrlTestCase::HitTestSingleLine()
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
// wxGTK must be given an opportunity to lay the text out.
|
// wxGTK must be given an opportunity to lay the text out.
|
||||||
for ( wxStopWatch sw; sw.Time() < 50; )
|
YieldForAWhile();
|
||||||
wxYield();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
REQUIRE( m_text->HitTest(wxPoint(2*sizeChar.x, yMid), &pos) == wxTE_HT_ON_TEXT );
|
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.
|
// wxGTK needs to yield here to update the text control.
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
wxStopWatch sw;
|
WaitFor("wxTextCtrl update", [this, pos]() {
|
||||||
while ( m_text->PositionToCoords(0).y == 0 ||
|
return m_text->PositionToCoords(0).y != 0 &&
|
||||||
m_text->PositionToCoords(pos).y > TEXT_HEIGHT )
|
m_text->PositionToCoords(pos).y <= TEXT_HEIGHT;
|
||||||
{
|
}, 1000);
|
||||||
if ( sw.Time() > 1000 )
|
|
||||||
{
|
|
||||||
FAIL("Timed out waiting for wxTextCtrl update.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxYield();
|
|
||||||
}
|
|
||||||
#endif // __WXGTK__
|
#endif // __WXGTK__
|
||||||
|
|
||||||
wxPoint coords = m_text->PositionToCoords(0);
|
wxPoint coords = m_text->PositionToCoords(0);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
#include "wx/msw/webview_ie.h"
|
#include "wx/msw/webview_ie.h"
|
||||||
#endif
|
#endif
|
||||||
#if wxUSE_WEBVIEW_WEBKIT2
|
#if wxUSE_WEBVIEW_WEBKIT2
|
||||||
#include "wx/stopwatch.h"
|
#include "waitfor.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Convenience macro
|
//Convenience macro
|
||||||
|
|
@ -235,8 +235,7 @@ TEST_CASE_METHOD(WebViewTestCase, "WebView", "[wxWebView]")
|
||||||
// bit before giving up. Avoid calling HasSelection() right away
|
// bit before giving up. Avoid calling HasSelection() right away
|
||||||
// without wxYielding a bit because this seems to cause the extension
|
// without wxYielding a bit because this seems to cause the extension
|
||||||
// to hang with webkit 2.40.0+.
|
// to hang with webkit 2.40.0+.
|
||||||
for ( wxStopWatch sw; sw.Time() < 50; )
|
YieldForAWhile();
|
||||||
wxYield();
|
|
||||||
#endif // wxUSE_WEBVIEW_WEBKIT2
|
#endif // wxUSE_WEBVIEW_WEBKIT2
|
||||||
|
|
||||||
CHECK(m_browser->HasSelection());
|
CHECK(m_browser->HasSelection());
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,12 @@
|
||||||
#include "asserthelper.h"
|
#include "asserthelper.h"
|
||||||
#include "testableframe.h"
|
#include "testableframe.h"
|
||||||
#include "testwindow.h"
|
#include "testwindow.h"
|
||||||
|
#include "waitfor.h"
|
||||||
|
|
||||||
#include "wx/uiaction.h"
|
#include "wx/uiaction.h"
|
||||||
#include "wx/caret.h"
|
#include "wx/caret.h"
|
||||||
#include "wx/cshelp.h"
|
#include "wx/cshelp.h"
|
||||||
#include "wx/dcclient.h"
|
#include "wx/dcclient.h"
|
||||||
#include "wx/stopwatch.h"
|
|
||||||
#include "wx/tooltip.h"
|
#include "wx/tooltip.h"
|
||||||
#include "wx/wupdlock.h"
|
#include "wx/wupdlock.h"
|
||||||
|
|
||||||
|
|
@ -40,8 +40,7 @@ public:
|
||||||
// Without this, when running this test suite solo it succeeds,
|
// Without this, when running this test suite solo it succeeds,
|
||||||
// but not when running it together with the other tests !!
|
// but not when running it together with the other tests !!
|
||||||
// Not needed when run under Xvfb display.
|
// Not needed when run under Xvfb display.
|
||||||
for ( wxStopWatch sw; sw.Time() < 50; )
|
YieldForAWhile();
|
||||||
wxYield();
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -510,13 +509,7 @@ TEST_CASE_METHOD(WindowTestCase, "Window::Refresh", "[window]")
|
||||||
|
|
||||||
parent->RefreshRect(wxRect(150, 10, 300, 80));
|
parent->RefreshRect(wxRect(150, 10, 300, 80));
|
||||||
|
|
||||||
for ( wxStopWatch sw; sw.Time() < 100; )
|
WaitFor("parent repaint", [&]() { return isParentPainted; }, 100);
|
||||||
{
|
|
||||||
if ( isParentPainted )
|
|
||||||
break;
|
|
||||||
|
|
||||||
wxYield();
|
|
||||||
}
|
|
||||||
|
|
||||||
// child1 should be the only window not to receive the wxEVT_PAINT event
|
// child1 should be the only window not to receive the wxEVT_PAINT event
|
||||||
// because it does not intersect with the refreshed rectangle.
|
// because it does not intersect with the refreshed rectangle.
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,7 @@
|
||||||
#include "wx/uiaction.h"
|
#include "wx/uiaction.h"
|
||||||
#include "wx/vector.h"
|
#include "wx/vector.h"
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
#include "waitfor.h"
|
||||||
#include "wx/stopwatch.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
@ -229,10 +227,7 @@ void KeyboardEventTestCase::setUp()
|
||||||
wxYield();
|
wxYield();
|
||||||
m_win->SetFocus();
|
m_win->SetFocus();
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
YieldForAWhile(10); // needed to show the new window
|
||||||
for ( wxStopWatch sw; sw.Time() < 10; )
|
|
||||||
#endif
|
|
||||||
wxYield(); // needed to show the new window
|
|
||||||
|
|
||||||
// The window might get some key up events when it's being shown if the key
|
// 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
|
// was pressed when the program was started and released after the window
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,13 @@
|
||||||
#include "wx/scopeguard.h"
|
#include "wx/scopeguard.h"
|
||||||
#include "wx/toolbar.h"
|
#include "wx/toolbar.h"
|
||||||
#include "wx/uiaction.h"
|
#include "wx/uiaction.h"
|
||||||
#include "wx/stopwatch.h"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#ifdef __WXGTK__
|
||||||
|
#include "waitfor.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// FIXME: Currently under OS X testing paint event doesn't work because neither
|
// FIXME: Currently under OS X testing paint event doesn't work because neither
|
||||||
// calling Refresh()+Update() nor even sending wxPaintEvent directly to
|
// calling Refresh()+Update() nor even sending wxPaintEvent directly to
|
||||||
// the window doesn't result in calls to its event handlers, so disable
|
// the window doesn't result in calls to its event handlers, so disable
|
||||||
|
|
@ -174,8 +177,7 @@ public:
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
// We need to map the window, otherwise we're not going to get any
|
// We need to map the window, otherwise we're not going to get any
|
||||||
// paint events for it.
|
// paint events for it.
|
||||||
for ( wxStopWatch sw; sw.Time() < 50; )
|
YieldForAWhile();
|
||||||
wxYield();
|
|
||||||
|
|
||||||
// Ignore events generated during the initial mapping.
|
// Ignore events generated during the initial mapping.
|
||||||
g_str.clear();
|
g_str.clear();
|
||||||
|
|
|
||||||
|
|
@ -751,11 +751,7 @@ TEST_CASE("ClipperTestCase::wxPaintDC", "[clipper][dc][paintdc]")
|
||||||
testWin->Refresh();
|
testWin->Refresh();
|
||||||
testWin->Update();
|
testWin->Update();
|
||||||
// Wait for update to be done
|
// Wait for update to be done
|
||||||
wxStopWatch sw;
|
YieldForAWhile();
|
||||||
while( sw.Time() < 50 )
|
|
||||||
{
|
|
||||||
wxYield();
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(paintExecuted == true);
|
CHECK(paintExecuted == true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4322,11 +4322,7 @@ TEST_CASE("ClippingBoxTestCase::wxPaintDC", "[clip][dc][paintdc]")
|
||||||
testWin->Refresh();
|
testWin->Refresh();
|
||||||
testWin->Update();
|
testWin->Update();
|
||||||
// Wait for update to be done
|
// Wait for update to be done
|
||||||
wxStopWatch sw;
|
YieldForAWhile();
|
||||||
while( sw.Time() < 50 )
|
|
||||||
{
|
|
||||||
wxYield();
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(paintExecuted == true);
|
CHECK(paintExecuted == true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,14 @@
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include "wx/dataview.h"
|
#include "wx/dataview.h"
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
|
||||||
#include "wx/stopwatch.h"
|
|
||||||
#endif // __WXGTK__
|
|
||||||
#endif // WX_PRECOMP
|
#endif // WX_PRECOMP
|
||||||
|
|
||||||
#include "wx/persist/dataview.h"
|
#include "wx/persist/dataview.h"
|
||||||
|
|
||||||
|
#ifdef __WXGTK__
|
||||||
|
#include "waitfor.h"
|
||||||
|
#endif // __WXGTK__
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// constants
|
// constants
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
@ -90,17 +90,9 @@ static wxDataViewCtrl* CreatePersistenceTestDVC()
|
||||||
void GTKWaitRealized(wxDataViewCtrl* list)
|
void GTKWaitRealized(wxDataViewCtrl* list)
|
||||||
{
|
{
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
wxStopWatch sw;
|
WaitFor("wxDataViewCtrl to be realized", [list]() {
|
||||||
while ( list->GetColumn(0)->GetWidth() == 0 )
|
return list->GetColumn(0)->GetWidth() != 0;
|
||||||
{
|
});
|
||||||
if ( sw.Time() > 500 )
|
|
||||||
{
|
|
||||||
WARN("Timed out waiting for wxDataViewCtrl to be realized");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxYield();
|
|
||||||
}
|
|
||||||
#else // !__WXGTK__
|
#else // !__WXGTK__
|
||||||
wxUnusedVar(list);
|
wxUnusedVar(list);
|
||||||
#endif // __WXGTK__/!__WXGTK__
|
#endif // __WXGTK__/!__WXGTK__
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,14 @@
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include "wx/frame.h"
|
#include "wx/frame.h"
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
|
||||||
#include "wx/stopwatch.h"
|
|
||||||
#endif // __WXGTK__
|
|
||||||
#endif // WX_PRECOMP
|
#endif // WX_PRECOMP
|
||||||
|
|
||||||
#include "wx/persist/toplevel.h"
|
#include "wx/persist/toplevel.h"
|
||||||
|
|
||||||
|
#ifdef __WXGTK__
|
||||||
|
#include "waitfor.h"
|
||||||
|
#endif // __WXGTK__
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// constants
|
// constants
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
@ -117,17 +117,11 @@ TEST_CASE_METHOD(PersistenceTests, "wxPersistTLW", "[persist][tlw]")
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wxStopWatch sw;
|
if ( !WaitFor("frame to be iconized", [frame]() {
|
||||||
while ( !frame->IsIconized() )
|
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;
|
checkIconized = false;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // __WXGTK__
|
#endif // __WXGTK__
|
||||||
|
|
@ -148,16 +142,9 @@ TEST_CASE_METHOD(PersistenceTests, "wxPersistTLW", "[persist][tlw]")
|
||||||
if ( checkIconized )
|
if ( checkIconized )
|
||||||
{
|
{
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
wxStopWatch sw;
|
WaitFor("frame to be iconized", [frame]() {
|
||||||
while ( !frame->IsIconized() )
|
return frame->IsIconized();
|
||||||
{
|
});
|
||||||
wxYield();
|
|
||||||
if ( sw.Time() > 500 )
|
|
||||||
{
|
|
||||||
INFO("Abandoning wait after " << sw.Time() << "ms");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // __WXGTK__
|
#endif // __WXGTK__
|
||||||
|
|
||||||
CHECK(frame->IsIconized());
|
CHECK(frame->IsIconized());
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,21 @@ WaitFor(const char* what, const std::function<bool ()>& pred, int timeout = 500)
|
||||||
return true;
|
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
|
// 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
|
// 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.
|
// things to work, while under Mac nothing works anyhow.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue