Add a simple test for keyboard events generation.

Check that the events generated by wxUIActionSimulator result in the same
wxKeyEvents being generated under all platforms. This is not the same as
checking the event generation for the actual keys pressed by the user as there
are some small differences between the two but better than nothing.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65519 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2010-09-11 10:18:31 +00:00
parent 2dcbc4615b
commit 042ddf5def
11 changed files with 443 additions and 0 deletions

View File

@ -195,6 +195,7 @@ TEST_GUI_OBJECTS = \
test_gui_windowtest.o \
test_gui_clone.o \
test_gui_propagation.o \
test_gui_keyboard.o \
test_gui_fonttest.o \
test_gui_image.o \
test_gui_rawbmp.o \
@ -803,6 +804,9 @@ test_gui_clone.o: $(srcdir)/events/clone.cpp $(TEST_GUI_ODEP)
test_gui_propagation.o: $(srcdir)/events/propagation.cpp $(TEST_GUI_ODEP)
$(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/events/propagation.cpp
test_gui_keyboard.o: $(srcdir)/events/keyboard.cpp $(TEST_GUI_ODEP)
$(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/events/keyboard.cpp
test_gui_fonttest.o: $(srcdir)/font/fonttest.cpp $(TEST_GUI_ODEP)
$(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/font/fonttest.cpp

407
tests/events/keyboard.cpp Normal file
View File

@ -0,0 +1,407 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/events/keyboard.cpp
// Purpose: Test keyboard events
// Author: Vadim Zeitlin
// Created: 2010-09-05
// RCS-ID: $Id$
// Copyright: (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_UIACTIONSIMULATOR
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/event.h"
#include "wx/window.h"
#endif // WX_PRECOMP
#include "wx/uiaction.h"
#include "wx/vector.h"
namespace
{
// ----------------------------------------------------------------------------
// test window verifying the event generation
// ----------------------------------------------------------------------------
class KeyboardTestWindow : public wxWindow
{
public:
KeyboardTestWindow(wxWindow *parent)
: wxWindow(parent, wxID_ANY)
{
Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(KeyboardTestWindow::OnKeyDown));
Connect(wxEVT_CHAR, wxKeyEventHandler(KeyboardTestWindow::OnChar));
Connect(wxEVT_KEY_UP, wxKeyEventHandler(KeyboardTestWindow::OnKeyUp));
}
unsigned GetKeyDownCount() const { return m_keyDownEvents.size(); }
unsigned GetCharCount() const { return m_charEvents.size(); }
unsigned GetKeyUpCount() const { return m_keyUpEvents.size(); }
const wxKeyEvent& GetKeyDownEvent(unsigned n = 0) const
{
return m_keyDownEvents[n];
}
const wxKeyEvent& GetCharEvent(unsigned n = 0) const
{
return m_charEvents[n];
}
const wxKeyEvent& GetKeyUpEvent(unsigned n = 0) const
{
return m_keyUpEvents[n];
}
void ClearEvents()
{
m_keyDownEvents =
m_charEvents =
m_keyUpEvents = wxVector<wxKeyEvent>();
}
private:
void OnKeyDown(wxKeyEvent& event)
{
m_keyDownEvents.push_back(event);
event.Skip();
}
void OnChar(wxKeyEvent& event)
{
m_charEvents.push_back(event);
event.Skip();
}
void OnKeyUp(wxKeyEvent& event)
{
m_keyUpEvents.push_back(event);
event.Skip();
}
wxVector<wxKeyEvent> m_keyDownEvents,
m_charEvents,
m_keyUpEvents;
wxDECLARE_NO_COPY_CLASS(KeyboardTestWindow);
};
// Object describing the (main fields of) keyboard event.
struct KeyDesc
{
KeyDesc(int keycode, int mods = 0)
: m_keycode(keycode),
m_mods(mods)
{
}
int m_keycode;
int m_mods;
};
// These functions are only needed because of wx bug: currently, modifiers key
// events are inconsistent between platforms and wxMSW generates key down event
// for e.g. WXK_CONTROL with wxMOD_CONTROL set and key up event with it unset
// while wxGTK does exactly vice versa. So we provide these helpers to make it
// possible to make the tests pass under all platforms for now but ideally they
// should all be made to behave the same and this should become unnecessary.
int GetModForKey(int keycode)
{
switch ( keycode )
{
case WXK_CONTROL: return wxMOD_CONTROL;
case WXK_SHIFT: return wxMOD_SHIFT;
case WXK_ALT: return wxMOD_ALT;
default:
wxFAIL_MSG( "Unknown modifier key" );
}
return wxMOD_NONE;
}
#ifdef __WXGTK__
KeyDesc ModKeyDown(int keycode)
{
// Second level bug: currently wxUIActionSimulator produces different
// modifiers than actually pressing the key. So while the above comment is
// true for keys pressed by user, when simulating them we do get the
// corresponding bit set for the modifier press events.
//
// Again, this is a bug and wxUIActionSimulator should be fixed to behave
// as the real events do but until this happens just work around this here.
return KeyDesc(keycode, GetModForKey(keycode));
}
KeyDesc ModKeyUp(int keycode)
{
return KeyDesc(keycode, GetModForKey(keycode));
}
#else // Assume MSW-like behaviour for all the other platforms.
KeyDesc ModKeyDown(int keycode)
{
return KeyDesc(keycode, GetModForKey(keycode));
}
KeyDesc ModKeyUp(int keycode)
{
return KeyDesc(keycode);
}
#endif // Platforms.
// Verify that the event object corresponds to our idea of what it should be.
void TestEvent(int line, const wxKeyEvent& ev, const KeyDesc& desc)
{
// Construct the message we'll display if an assert fails.
std::string msg;
const wxEventType t = ev.GetEventType();
if ( t == wxEVT_KEY_DOWN )
msg = "key down";
else if ( t == wxEVT_CHAR )
msg = "char";
else if ( t == wxEVT_KEY_UP )
msg = "key up";
else
CPPUNIT_FAIL( "unknown event type" );
msg += " event at line ";
msg += wxString::Format("%d", line).mb_str();
CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong key code in " + msg,
desc.m_keycode,
ev.GetKeyCode() );
#if wxUSE_UNICODE
if ( desc.m_keycode < 0x80 )
{
// FIXME: Currently wxMSW generates 'A' key code for key down/up events
// for the 'a' physical key while wxGTK and wxOSX/Cocoa generate them
// with 'a' and it's not clear which behaviour is more correct so don't
// test this for those events, only test it for EVT_CHAR where the
// correct behaviour is clear.
if ( t == wxEVT_CHAR )
{
// For 7-bit ASCII Unicode keys are the same as normal key codes.
CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong Unicode key in " + msg,
(char)desc.m_keycode,
(char)ev.GetUnicodeKey() );
}
}
else
{
// In this test we don't use any really Unicode characters so far so
// anything above 0x80 must be special keys (e.g. WXK_CONTROL &c) which
// don't have any Unicode equivalent.
CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong non-zero Unicode key in " + msg,
0,
(int)ev.GetUnicodeKey() );
}
#endif // wxUSE_UNICODE
CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong modifiers in " + msg,
desc.m_mods,
ev.GetModifiers() );
}
// Call TestEvent() passing it the line number from where it was called: this
// is useful for interpreting the assert failure messages.
#define ASSERT_KEY_EVENT_IS( ev, desc ) TestEvent(__LINE__, ev, desc)
} // anonymous namespace
// --------------------------------------------------------------------------
// test class
// --------------------------------------------------------------------------
class KeyboardEventTestCase : public CppUnit::TestCase
{
public:
KeyboardEventTestCase() {}
virtual void setUp();
virtual void tearDown();
private:
CPPUNIT_TEST_SUITE( KeyboardEventTestCase );
CPPUNIT_TEST( NormalLetter );
CPPUNIT_TEST( NormalSpecial );
CPPUNIT_TEST( CtrlLetter );
CPPUNIT_TEST( CtrlSpecial );
CPPUNIT_TEST( ShiftLetter );
CPPUNIT_TEST( ShiftSpecial );
CPPUNIT_TEST_SUITE_END();
void NormalLetter();
void NormalSpecial();
void CtrlLetter();
void CtrlSpecial();
void ShiftLetter();
void ShiftSpecial();
KeyboardTestWindow *m_win;
wxDECLARE_NO_COPY_CLASS(KeyboardEventTestCase);
};
wxREGISTER_UNIT_TEST(KeyboardEvent);
void KeyboardEventTestCase::setUp()
{
m_win = new KeyboardTestWindow(wxTheApp->GetTopWindow());
m_win->SetFocus();
wxYield(); // 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
// was shown, e.g. this does happen in practice when launching the test
// from command line. Simply discard all the spurious events so far.
m_win->ClearEvents();
}
void KeyboardEventTestCase::tearDown()
{
m_win->Destroy();
}
void KeyboardEventTestCase::NormalLetter()
{
wxUIActionSimulator sim;
sim.Char('a');
wxYield();
CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyDownCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(), 'A' );
CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(), 'a' );
CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyUpCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(), 'A' );
}
void KeyboardEventTestCase::NormalSpecial()
{
wxUIActionSimulator sim;
sim.Char(WXK_END);
wxYield();
CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyDownCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(), WXK_END );
CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(), WXK_END );
CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyUpCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(), WXK_END );
}
void KeyboardEventTestCase::CtrlLetter()
{
wxUIActionSimulator sim;
sim.Char('z', wxMOD_CONTROL);
wxYield();
CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
ModKeyDown(WXK_CONTROL) );
ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
KeyDesc('Z', wxMOD_CONTROL) );
CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
KeyDesc('\x1a', wxMOD_CONTROL) );
CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
KeyDesc('Z', wxMOD_CONTROL) );
ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
ModKeyUp(WXK_CONTROL) );
}
void KeyboardEventTestCase::CtrlSpecial()
{
wxUIActionSimulator sim;
sim.Char(WXK_PAGEUP, wxMOD_CONTROL);
wxYield();
CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
ModKeyDown(WXK_CONTROL) );
ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
KeyDesc(WXK_PAGEUP, wxMOD_CONTROL) );
CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
KeyDesc(WXK_PAGEUP, wxMOD_CONTROL) );
CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
KeyDesc(WXK_PAGEUP, wxMOD_CONTROL) );
ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
ModKeyUp(WXK_CONTROL) );
}
void KeyboardEventTestCase::ShiftLetter()
{
wxUIActionSimulator sim;
sim.Char('Q', wxMOD_SHIFT);
wxYield();
CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
ModKeyDown(WXK_SHIFT) );
ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
KeyDesc('Q', wxMOD_SHIFT) );
CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
KeyDesc('Q', wxMOD_SHIFT) );
CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
KeyDesc('Q', wxMOD_SHIFT) );
ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
ModKeyUp(WXK_SHIFT) );
}
void KeyboardEventTestCase::ShiftSpecial()
{
wxUIActionSimulator sim;
sim.Char(WXK_TAB, wxMOD_SHIFT);
wxYield();
CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
ModKeyDown(WXK_SHIFT) );
ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
KeyDesc(WXK_TAB, wxMOD_SHIFT) );
CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
KeyDesc(WXK_TAB, wxMOD_SHIFT) );
CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
KeyDesc(WXK_TAB, wxMOD_SHIFT) );
ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
ModKeyUp(WXK_SHIFT) );
}
#endif // wxUSE_UIACTIONSIMULATOR

View File

@ -180,6 +180,7 @@ TEST_GUI_OBJECTS = \
$(OBJS)\test_gui_windowtest.obj \
$(OBJS)\test_gui_clone.obj \
$(OBJS)\test_gui_propagation.obj \
$(OBJS)\test_gui_keyboard.obj \
$(OBJS)\test_gui_fonttest.obj \
$(OBJS)\test_gui_image.obj \
$(OBJS)\test_gui_rawbmp.obj \
@ -849,6 +850,9 @@ $(OBJS)\test_gui_clone.obj: .\events\clone.cpp
$(OBJS)\test_gui_propagation.obj: .\events\propagation.cpp
$(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\events\propagation.cpp
$(OBJS)\test_gui_keyboard.obj: .\events\keyboard.cpp
$(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\events\keyboard.cpp
$(OBJS)\test_gui_fonttest.obj: .\font\fonttest.cpp
$(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\font\fonttest.cpp

View File

@ -173,6 +173,7 @@ TEST_GUI_OBJECTS = \
$(OBJS)\test_gui_windowtest.o \
$(OBJS)\test_gui_clone.o \
$(OBJS)\test_gui_propagation.o \
$(OBJS)\test_gui_keyboard.o \
$(OBJS)\test_gui_fonttest.o \
$(OBJS)\test_gui_image.o \
$(OBJS)\test_gui_rawbmp.o \
@ -830,6 +831,9 @@ $(OBJS)\test_gui_clone.o: ./events/clone.cpp
$(OBJS)\test_gui_propagation.o: ./events/propagation.cpp
$(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\test_gui_keyboard.o: ./events/keyboard.cpp
$(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\test_gui_fonttest.o: ./font/fonttest.cpp
$(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<

View File

@ -175,6 +175,7 @@ TEST_GUI_OBJECTS = \
$(OBJS)\test_gui_windowtest.obj \
$(OBJS)\test_gui_clone.obj \
$(OBJS)\test_gui_propagation.obj \
$(OBJS)\test_gui_keyboard.obj \
$(OBJS)\test_gui_fonttest.obj \
$(OBJS)\test_gui_image.obj \
$(OBJS)\test_gui_rawbmp.obj \
@ -975,6 +976,9 @@ $(OBJS)\test_gui_clone.obj: .\events\clone.cpp
$(OBJS)\test_gui_propagation.obj: .\events\propagation.cpp
$(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\events\propagation.cpp
$(OBJS)\test_gui_keyboard.obj: .\events\keyboard.cpp
$(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\events\keyboard.cpp
$(OBJS)\test_gui_fonttest.obj: .\font\fonttest.cpp
$(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\font\fonttest.cpp

View File

@ -415,6 +415,7 @@ TEST_GUI_OBJECTS = &
$(OBJS)\test_gui_windowtest.obj &
$(OBJS)\test_gui_clone.obj &
$(OBJS)\test_gui_propagation.obj &
$(OBJS)\test_gui_keyboard.obj &
$(OBJS)\test_gui_fonttest.obj &
$(OBJS)\test_gui_image.obj &
$(OBJS)\test_gui_rawbmp.obj &
@ -888,6 +889,9 @@ $(OBJS)\test_gui_clone.obj : .AUTODEPEND .\events\clone.cpp
$(OBJS)\test_gui_propagation.obj : .AUTODEPEND .\events\propagation.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<
$(OBJS)\test_gui_keyboard.obj : .AUTODEPEND .\events\keyboard.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<
$(OBJS)\test_gui_fonttest.obj : .AUTODEPEND .\font\fonttest.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<

View File

@ -176,6 +176,7 @@
controls/windowtest.cpp
events/clone.cpp
events/propagation.cpp
events/keyboard.cpp
font/fonttest.cpp
image/image.cpp
image/rawbmp.cpp

View File

@ -353,6 +353,10 @@ SOURCE=.\controls\itemcontainertest.cpp
# End Source File
# Begin Source File
SOURCE=.\events\keyboard.cpp
# End Source File
# Begin Source File
SOURCE=.\controls\label.cpp
# End Source File
# Begin Source File

View File

@ -700,6 +700,9 @@
<File
RelativePath=".\controls\itemcontainertest.cpp">
</File>
<File
RelativePath=".\events\keyboard.cpp">
</File>
<File
RelativePath=".\controls\label.cpp">
</File>

View File

@ -1007,6 +1007,10 @@
RelativePath=".\controls\itemcontainertest.cpp"
>
</File>
<File
RelativePath=".\events\keyboard.cpp"
>
</File>
<File
RelativePath=".\controls\label.cpp"
>

View File

@ -979,6 +979,10 @@
RelativePath=".\controls\itemcontainertest.cpp"
>
</File>
<File
RelativePath=".\events\keyboard.cpp"
>
</File>
<File
RelativePath=".\controls\label.cpp"
>