1 /*
2 * barrier -- mouse and keyboard sharing utility
3 * Copyright (C) 2012-2016 Symless Ltd.
4 * Copyright (C) 2011 Nick Bolton
5 *
6 * This package is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * found in the file LICENSE that should have accompanied this file.
9 *
10 * This package is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #define TEST_ENV
20
21 #include "test/mock/barrier/MockKeyMap.h"
22 #include "test/mock/barrier/MockEventQueue.h"
23 #include "platform/XWindowsKeyState.h"
24 #include "base/Log.h"
25
26 #define XK_LATIN1
27 #define XK_MISCELLANY
28 #include <X11/keysymdef.h>
29
30 #if HAVE_XKB_EXTENSION
31 # include <X11/XKBlib.h>
32 #endif
33
34 #include "test/global/gtest.h"
35 #include "test/global/gmock.h"
36 #include <errno.h>
37
38 class XWindowsKeyStateTests : public ::testing::Test
39 {
40 protected:
XWindowsKeyStateTests()41 XWindowsKeyStateTests() :
42 m_display(NULL)
43 {
44 }
45
~XWindowsKeyStateTests()46 ~XWindowsKeyStateTests()
47 {
48 if (m_display != NULL) {
49 LOG((CLOG_DEBUG "closing display"));
50 XCloseDisplay(m_display);
51 }
52 }
53
54 virtual void
SetUp()55 SetUp()
56 {
57 // open the display only once for the entire test suite
58 if (this->m_display == NULL) {
59 LOG((CLOG_DEBUG "opening display"));
60 this->m_display = XOpenDisplay(NULL);
61
62 ASSERT_TRUE(this->m_display != NULL)
63 << "unable to open display: " << errno;
64 }
65 }
66
67 virtual void
TearDown()68 TearDown()
69 {
70 }
71
72 Display* m_display;
73 };
74
TEST_F(XWindowsKeyStateTests,setActiveGroup_pollAndSet_groupIsZero)75 TEST_F(XWindowsKeyStateTests, setActiveGroup_pollAndSet_groupIsZero)
76 {
77 MockKeyMap keyMap;
78 MockEventQueue eventQueue;
79 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
80
81 keyState.setActiveGroup(XWindowsKeyState::kGroupPollAndSet);
82
83 ASSERT_EQ(0, keyState.group());
84 }
85
TEST_F(XWindowsKeyStateTests,setActiveGroup_poll_groupIsNotSet)86 TEST_F(XWindowsKeyStateTests, setActiveGroup_poll_groupIsNotSet)
87 {
88 MockKeyMap keyMap;
89 MockEventQueue eventQueue;
90 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
91
92 keyState.setActiveGroup(XWindowsKeyState::kGroupPoll);
93
94 ASSERT_LE(-1, keyState.group());
95 }
96
TEST_F(XWindowsKeyStateTests,setActiveGroup_customGroup_groupWasSet)97 TEST_F(XWindowsKeyStateTests, setActiveGroup_customGroup_groupWasSet)
98 {
99 MockKeyMap keyMap;
100 MockEventQueue eventQueue;
101 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
102
103 keyState.setActiveGroup(1);
104
105 ASSERT_EQ(1, keyState.group());
106 }
107
TEST_F(XWindowsKeyStateTests,mapModifiersFromX_zeroState_zeroMask)108 TEST_F(XWindowsKeyStateTests, mapModifiersFromX_zeroState_zeroMask)
109 {
110 MockKeyMap keyMap;
111 MockEventQueue eventQueue;
112 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
113
114 int mask = keyState.mapModifiersFromX(0);
115
116 ASSERT_EQ(0, mask);
117 }
118
TEST_F(XWindowsKeyStateTests,mapModifiersToX_zeroMask_resultIsTrue)119 TEST_F(XWindowsKeyStateTests, mapModifiersToX_zeroMask_resultIsTrue)
120 {
121 MockKeyMap keyMap;
122 MockEventQueue eventQueue;
123 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
124
125 unsigned int modifiers = 0;
126 bool result = keyState.mapModifiersToX(0, modifiers);
127
128 ASSERT_TRUE(result);
129 }
130
TEST_F(XWindowsKeyStateTests,fakeCtrlAltDel_default_returnsFalse)131 TEST_F(XWindowsKeyStateTests, fakeCtrlAltDel_default_returnsFalse)
132 {
133 MockKeyMap keyMap;
134 MockEventQueue eventQueue;
135 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
136
137 bool result = keyState.fakeCtrlAltDel();
138
139 ASSERT_FALSE(result);
140 }
141
TEST_F(XWindowsKeyStateTests,pollActiveModifiers_defaultState_returnsZero)142 TEST_F(XWindowsKeyStateTests, pollActiveModifiers_defaultState_returnsZero)
143 {
144 MockKeyMap keyMap;
145 MockEventQueue eventQueue;
146 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
147
148 KeyModifierMask actual = keyState.pollActiveModifiers();
149
150 ASSERT_EQ(0, actual);
151 }
152
TEST_F(XWindowsKeyStateTests,pollActiveModifiers_shiftKeyDownThenUp_masksAreCorrect)153 TEST_F(XWindowsKeyStateTests, pollActiveModifiers_shiftKeyDownThenUp_masksAreCorrect)
154 {
155 MockKeyMap keyMap;
156 MockEventQueue eventQueue;
157 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
158
159 // set mock modifier mapping
160 std::fill(keyState.modifierFromX().begin(), keyState.modifierFromX().end(), 0);
161 keyState.modifierFromX()[ShiftMapIndex] = KeyModifierShift;
162
163 KeyCode key = XKeysymToKeycode(m_display, XK_Shift_L);
164
165 // fake shift key down (without using barrier)
166 XTestFakeKeyEvent(m_display, key, true, CurrentTime);
167
168 // function under test (1st call)
169 KeyModifierMask modDown = keyState.pollActiveModifiers();
170
171 // fake shift key up (without using barrier)
172 XTestFakeKeyEvent(m_display, key, false, CurrentTime);
173
174 // function under test (2nd call)
175 KeyModifierMask modUp = keyState.pollActiveModifiers();
176
177 EXPECT_TRUE((modDown & KeyModifierShift) == KeyModifierShift)
178 << "shift key not in mask - key was not pressed";
179
180 EXPECT_TRUE((modUp & KeyModifierShift) == 0)
181 << "shift key still in mask - make sure no keys are being held down";
182 }
183
TEST_F(XWindowsKeyStateTests,pollActiveGroup_defaultState_returnsZero)184 TEST_F(XWindowsKeyStateTests, pollActiveGroup_defaultState_returnsZero)
185 {
186 MockKeyMap keyMap;
187 MockEventQueue eventQueue;
188 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
189
190 SInt32 actual = keyState.pollActiveGroup();
191
192 ASSERT_EQ(0, actual);
193 }
194
TEST_F(XWindowsKeyStateTests,pollActiveGroup_positiveGroup_returnsGroup)195 TEST_F(XWindowsKeyStateTests, pollActiveGroup_positiveGroup_returnsGroup)
196 {
197 MockKeyMap keyMap;
198 MockEventQueue eventQueue;
199 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
200
201 keyState.group(3);
202
203 SInt32 actual = keyState.pollActiveGroup();
204
205 ASSERT_EQ(3, actual);
206 }
207
TEST_F(XWindowsKeyStateTests,pollActiveGroup_xkb_areEqual)208 TEST_F(XWindowsKeyStateTests, pollActiveGroup_xkb_areEqual)
209 {
210 #if HAVE_XKB_EXTENSION
211 MockKeyMap keyMap;
212 MockEventQueue eventQueue;
213 XWindowsKeyState keyState(new XWindowsImpl(), m_display, true, &eventQueue, keyMap);
214
215 // reset the group
216 keyState.group(-1);
217
218 XkbStateRec state;
219
220 // compare pollActiveGroup() with XkbGetState()
221 if (XkbGetState(m_display, XkbUseCoreKbd, &state) == Success) {
222 SInt32 actual = keyState.pollActiveGroup();
223
224 ASSERT_EQ(state.group, actual);
225 }
226 else {
227 FAIL() << "XkbGetState() returned error " << errno;
228 }
229 #else
230 SUCCEED() << "Xkb extension not installed";
231 #endif
232 }
233
234