openMSX
BooleanInput_test.cc
Go to the documentation of this file.
1#include "catch.hpp"
2#include "BooleanInput.hh"
3
4#include "SDL.h"
5
6using namespace openmsx;
7
8TEST_CASE("BooleanInput: toString, parse")
9{
10 auto compare = [](const BooleanInput& input, const std::string& str) {
11 auto str2 = toString(input);
12 CHECK(str2 == str);
13
14 auto input2 = parseBooleanInput(str);
15 CHECK(input2);
16 CHECK(*input2 == input);
17 };
18 using ID = JoystickId;
19
20 SECTION("keyboard") {
21 compare(BooleanKeyboard(SDLK_a), "keyb A");
22 compare(BooleanKeyboard(SDLK_LALT), "keyb Left Alt");
23
24 // old key names
25 auto k1 = parseBooleanInput("keyb PrintSCreen");
26 REQUIRE(k1);
27 auto k2 = parseBooleanInput("keyb PRINT");
28 REQUIRE(k2);
29 CHECK(*k1 == *k2);
30 CHECK(*k2 == BooleanKeyboard(SDLK_PRINTSCREEN));
31 CHECK(toString(*k2) == "keyb PrintScreen");
32 }
33 SECTION("mouse button") {
34 compare(BooleanMouseButton( 2), "mouse button2");
35 compare(BooleanMouseButton(11), "mouse button11");
36 }
37 SECTION("joystick button") {
38 compare(BooleanJoystickButton(ID(0), 2), "joy1 button2");
39 compare(BooleanJoystickButton(ID(1), 4), "joy2 button4");
40 }
41 SECTION("joystick hat") {
42 compare(BooleanJoystickHat(ID(0), 1, BooleanJoystickHat::UP), "joy1 hat1 up");
43 compare(BooleanJoystickHat(ID(3), 5, BooleanJoystickHat::DOWN), "joy4 hat5 down");
44 compare(BooleanJoystickHat(ID(2), 4, BooleanJoystickHat::LEFT), "joy3 hat4 left");
45 compare(BooleanJoystickHat(ID(1), 2, BooleanJoystickHat::RIGHT), "joy2 hat2 right");
46 }
47 SECTION("joystick axis") {
48 compare(BooleanJoystickAxis(ID(0), 1, BooleanJoystickAxis::POS), "joy1 +axis1");
49 compare(BooleanJoystickAxis(ID(3), 2, BooleanJoystickAxis::NEG), "joy4 -axis2");
50 }
51 SECTION("parse error") {
52 CHECK(!parseBooleanInput("")); // no type
53 CHECK(!parseBooleanInput("bla")); // invalid type
54
55 CHECK(!parseBooleanInput("keyb")); // missing name
56 CHECK(!parseBooleanInput("keyb invalid-key"));
57 CHECK(!parseBooleanInput("keyb A too-many-args"));
58 CHECK( parseBooleanInput("keyb B")); // OK
59
60 CHECK(!parseBooleanInput("mouse")); // missing button
61 CHECK(!parseBooleanInput("mouse buttonA")); // invalid number
62 CHECK(!parseBooleanInput("mouse button1 too-many-args"));
63 CHECK( parseBooleanInput("mouse button1")); // OK
64
65 CHECK(!parseBooleanInput("joy")); // missing joystick-number
66 CHECK(!parseBooleanInput("joyZ")); // invalid number
67 CHECK(!parseBooleanInput("joy1")); // missing subtype
68 CHECK(!parseBooleanInput("joy2 button")); // missing button number
69 CHECK(!parseBooleanInput("joy3 buttonA")); // invalid number
70 CHECK(!parseBooleanInput("joy4 button2 too-many-args"));
71 CHECK( parseBooleanInput("joy4 button2")); // OK
72
73 CHECK(!parseBooleanInput("joy2 hat")); // missing hat number
74 CHECK(!parseBooleanInput("joy2 hatA")); // invalid number
75 CHECK(!parseBooleanInput("joy2 hat3")); // missing value
76 CHECK(!parseBooleanInput("joy2 hat3 bla")); // invalid value
77 CHECK(!parseBooleanInput("joy2 hat3 up too-many-args"));
78 CHECK( parseBooleanInput("joy2 hat3 up")); // OK
79
80 CHECK(!parseBooleanInput("joy2 axis3")); // missing +/-
81 CHECK(!parseBooleanInput("joy2 +axis")); // missing number
82 CHECK(!parseBooleanInput("joy2 +axis@")); // invalid number
83 CHECK( parseBooleanInput("joy2 +axis2")); // OK
84 }
85}
86
87TEST_CASE("BooleanInput: capture")
88{
89 auto getJoyDeadZone = [](JoystickId /*joystick*/) { return 25; };
90 auto check = [&](const Event& event, const std::string& expected) {
91 auto input = captureBooleanInput(event, getJoyDeadZone);
92 if (expected.empty()) {
93 CHECK(!input);
94 } else {
95 CHECK(toString(*input) == expected);
96 }
97 };
98
99 SDL_Event sdl = {};
100
101 SECTION("keyboard") {
102 check(KeyDownEvent::create(SDLK_h), "keyb H");
103 check(KeyUpEvent ::create(SDLK_h), "");
104 }
105 SECTION("mouse") {
106 sdl.button = SDL_MouseButtonEvent{};
107 sdl.button.type = SDL_MOUSEBUTTONDOWN;
108 sdl.button.button = 2;
109 check(MouseButtonDownEvent(sdl), "mouse button2");
110 sdl.button.type = SDL_MOUSEBUTTONUP;
111 check(MouseButtonUpEvent(sdl), "");
112
113 sdl.motion = SDL_MouseMotionEvent{};
114 sdl.motion.type = SDL_MOUSEMOTION;
115 sdl.motion.xrel = 10;
116 sdl.motion.yrel = 20;
117 sdl.motion.x = 30;
118 sdl.motion.y = 40;
119 check(MouseMotionEvent(sdl), "");
120
121 sdl.wheel = SDL_MouseWheelEvent{};
122 sdl.wheel.type = SDL_MOUSEWHEEL;
123 sdl.wheel.x = 2;
124 sdl.wheel.y = 4;
125 check(MouseWheelEvent(sdl), "");
126 }
127 SECTION("joystick") {
128 sdl.jbutton = SDL_JoyButtonEvent{};
129 sdl.jbutton.type = SDL_JOYBUTTONDOWN;
130 sdl.jbutton.which = 0;
131 sdl.jbutton.button = 3;
132 check(JoystickButtonDownEvent(sdl), "joy1 button3");
133 sdl.jbutton.type = SDL_JOYBUTTONUP;
134 check(JoystickButtonUpEvent(sdl), "");
135
136 sdl.jhat = SDL_JoyHatEvent{};
137 sdl.jhat.type = SDL_JOYHATMOTION;
138 sdl.jhat.which = 1;
139 sdl.jhat.hat = 1;
140 sdl.jhat.value = SDL_HAT_LEFT;
141 check(JoystickHatEvent(sdl), "joy2 hat1 left");
142 sdl.jhat.value = SDL_HAT_CENTERED;
143 check(JoystickHatEvent(sdl), "");
144 sdl.jhat.value = SDL_HAT_LEFTDOWN;
145 check(JoystickHatEvent(sdl), "");
146
147 sdl.jaxis = SDL_JoyAxisEvent{};
148 sdl.jaxis.type = SDL_JOYAXISMOTION;
149 sdl.jaxis.which = 2;
150 sdl.jaxis.axis = 1;
151 sdl.jaxis.value = 32000;
152 check(JoystickAxisMotionEvent(sdl), "joy3 +axis1");
153 sdl.jaxis.value = -32000;
154 check(JoystickAxisMotionEvent(sdl), "joy3 -axis1");
155 sdl.jaxis.value = 2000; // close to center
156 check(JoystickAxisMotionEvent(sdl), "");
157 }
158 SECTION("other SDL") {
159 sdl.window = SDL_WindowEvent{};
160 sdl.window.type = SDL_WINDOWEVENT;
161 check(WindowEvent(sdl), "");
162 }
163 SECTION("other") {
164 check(FileDropEvent("file.ext"), "");
165 check(BootEvent{}, "");
166 }
167}
168
169TEST_CASE("BooleanInput: match")
170{
171 // define various events
172 auto keyDownA = KeyDownEvent::create(SDLK_a);
173 auto keyDownB = KeyDownEvent::create(SDLK_b);
174 auto keyUpA = KeyUpEvent::create(SDLK_a);
175 auto keyUpB = KeyUpEvent::create(SDLK_b);
176
177 SDL_Event sdl;
178 sdl.button = SDL_MouseButtonEvent{};
179 sdl.button.type = SDL_MOUSEBUTTONDOWN;
180 sdl.button.button = 1;
181 auto mouseDown1 = MouseButtonDownEvent(sdl);
182 sdl.button.button = 2;
183 auto mouseDown2 = MouseButtonDownEvent(sdl);
184
185 sdl.button.type = SDL_MOUSEBUTTONUP;
186 sdl.button.button = 1;
187 auto mouseUp1 = MouseButtonUpEvent(sdl);
188 sdl.button.button = 2;
189 auto mouseUp2 = MouseButtonUpEvent(sdl);
190
191 sdl.wheel = SDL_MouseWheelEvent{};
192 sdl.wheel.type = SDL_MOUSEWHEEL;
193 sdl.wheel.x = 2;
194 sdl.wheel.y = 4;
195 auto mouseWheel = MouseWheelEvent(sdl);
196
197 sdl.jbutton = SDL_JoyButtonEvent{};
198 sdl.jbutton.type = SDL_JOYBUTTONDOWN;
199 sdl.jbutton.which = 0;
200 sdl.jbutton.button = 2;
201 auto joy1button2Down = JoystickButtonDownEvent(sdl);
202 sdl.jbutton.type = SDL_JOYBUTTONUP;
203 auto joy1button2Up = JoystickButtonUpEvent(sdl);
204
205 sdl.jbutton.type = SDL_JOYBUTTONDOWN;
206 sdl.jbutton.which = 0;
207 sdl.jbutton.button = 3;
208 auto joy1button3Down = JoystickButtonDownEvent(sdl);
209 sdl.jbutton.type = SDL_JOYBUTTONUP;
210 auto joy1button3Up = JoystickButtonUpEvent(sdl);
211
212 sdl.jbutton.type = SDL_JOYBUTTONDOWN;
213 sdl.jbutton.which = 1;
214 sdl.jbutton.button = 2;
215 auto joy2button2Down = JoystickButtonDownEvent(sdl);
216 sdl.type = SDL_JOYBUTTONUP;
217 auto joy2button2Up = JoystickButtonUpEvent(sdl);
218
219 sdl.jhat = SDL_JoyHatEvent{};
220 sdl.jhat.type = SDL_JOYHATMOTION;
221 sdl.jhat.which = 0;
222 sdl.jhat.hat = 1;
223 sdl.jhat.value = SDL_HAT_LEFT;
224 auto joy1hat1left = JoystickHatEvent(sdl);
225 sdl.jhat.value = SDL_HAT_LEFTDOWN;
226 auto joy1hat1leftDown = JoystickHatEvent(sdl);
227 sdl.jhat.value = SDL_HAT_DOWN;
228 auto joy1hat1down = JoystickHatEvent(sdl);
229
230 sdl.jhat.type = SDL_JOYHATMOTION;
231 sdl.jhat.which = 0;
232 sdl.jhat.hat = 2;
233 sdl.jhat.value = SDL_HAT_LEFT;
234 auto joy1hat2left = JoystickHatEvent(sdl);
235 sdl.jhat.value = SDL_HAT_LEFTDOWN;
236 auto joy1hat2leftDown = JoystickHatEvent(sdl);
237 sdl.jhat.value = SDL_HAT_DOWN;
238 auto joy1hat2down = JoystickHatEvent(sdl);
239
240 sdl.jhat.type = SDL_JOYHATMOTION;
241 sdl.jhat.which = 1;
242 sdl.jhat.hat = 1;
243 sdl.jhat.value = SDL_HAT_LEFT;
244 auto joy2hat1left = JoystickHatEvent(sdl);
245 sdl.jhat.value = SDL_HAT_LEFTDOWN;
246 auto joy2hat1leftDown = JoystickHatEvent(sdl);
247 sdl.jhat.value = SDL_HAT_DOWN;
248 auto joy2hat1down = JoystickHatEvent(sdl);
249
250 sdl.jaxis = SDL_JoyAxisEvent{};
251 sdl.jaxis.type = SDL_JOYAXISMOTION;
252 sdl.jaxis.which = 0;
253 sdl.jaxis.axis = 1;
254 sdl.jaxis.value = 32000;
255 auto joy1axis1P32000 = JoystickAxisMotionEvent(sdl);
256 sdl.jaxis.value = 123;
257 auto joy1axis1P123 = JoystickAxisMotionEvent(sdl);
258 sdl.jaxis.value = -27000;
259 auto joy1axis1M27000 = JoystickAxisMotionEvent(sdl);
260
261 sdl.jaxis.type = SDL_JOYAXISMOTION;
262 sdl.jaxis.which = 0;
263 sdl.jaxis.axis = 2;
264 sdl.jaxis.value = 32000;
265 auto joy1axis2P32000 = JoystickAxisMotionEvent(sdl);
266 sdl.jaxis.value = 123;
267 auto joy1axis2P123 = JoystickAxisMotionEvent(sdl);
268 sdl.jaxis.value = -27000;
269 auto joy1axis2M27000 = JoystickAxisMotionEvent(sdl);
270
271 sdl.jaxis.type = SDL_JOYAXISMOTION;
272 sdl.jaxis.which = 1;
273 sdl.jaxis.axis = 1;
274 sdl.jaxis.value = 32000;
275 auto joy2axis1P32000 = JoystickAxisMotionEvent(sdl);
276 sdl.jaxis.value = 123;
277 auto joy2axis1P123 = JoystickAxisMotionEvent(sdl);
278 sdl.jaxis.value = -27000;
279 auto joy2axis1M27000 = JoystickAxisMotionEvent(sdl);
280
281 // check against various BooleanInputs
282 auto getJoyDeadZone = [](JoystickId /*joystick*/) { return 25; };
283 auto check = [&](const std::optional<BooleanInput>& binding, const Event& event, std::optional<bool> expected) {
284 REQUIRE(binding);
285 CHECK(match(*binding, event, getJoyDeadZone) == expected);
286 };
287
288 auto bKeyA = parseBooleanInput("keyb A");
289 check(bKeyA, keyDownA, true);
290 check(bKeyA, keyUpA, false);
291 check(bKeyA, keyDownB, {});
292 check(bKeyA, keyUpB, {});
293 check(bKeyA, joy1button2Down, {});
294 check(bKeyA, mouseWheel, {});
295
296 auto bMouseButton1 = parseBooleanInput("mouse button1");
297 check(bMouseButton1, mouseDown1, true);
298 check(bMouseButton1, mouseUp1, false);
299 check(bMouseButton1, mouseDown2, {});
300 check(bMouseButton1, mouseUp2, {});
301 check(bMouseButton1, keyDownA, {});
302 check(bMouseButton1, mouseWheel, {});
303
304 auto bJoy1Button2 = parseBooleanInput("joy1 button2");
305 check(bJoy1Button2, joy1button2Down, true);
306 check(bJoy1Button2, joy1button2Up, false);
307 check(bJoy1Button2, joy1button3Down, {});
308 check(bJoy1Button2, joy1button3Up, {});
309 check(bJoy1Button2, joy2button2Down, {});
310 check(bJoy1Button2, joy2button2Up, {});
311 check(bJoy1Button2, mouseUp2, {});
312 check(bJoy1Button2, mouseWheel, {});
313
314 auto bJoy1Hat1Left = parseBooleanInput("joy1 hat1 left");
315 check(bJoy1Hat1Left, joy1hat1left, true);
316 check(bJoy1Hat1Left, joy1hat1leftDown, true);
317 check(bJoy1Hat1Left, joy1hat1down, false);
318 check(bJoy1Hat1Left, joy1hat2left, {});
319 check(bJoy1Hat1Left, joy1hat2leftDown, {});
320 check(bJoy1Hat1Left, joy1hat2down, {});
321 check(bJoy1Hat1Left, joy2hat1left, {});
322 check(bJoy1Hat1Left, joy2hat1leftDown, {});
323 check(bJoy1Hat1Left, joy2hat1down, {});
324 check(bJoy1Hat1Left, joy1button2Down, {});
325 check(bJoy1Hat1Left, mouseWheel, {});
326
327 auto bJoy1Axis1P = parseBooleanInput("joy1 +axis1");
328 check(bJoy1Axis1P, joy1axis1P32000, true);
329 check(bJoy1Axis1P, joy1axis1P123, false);
330 check(bJoy1Axis1P, joy1axis1M27000, false);
331 check(bJoy1Axis1P, joy1axis2P32000, {});
332 check(bJoy1Axis1P, joy1axis2P123, {});
333 check(bJoy1Axis1P, joy1axis2M27000, {});
334 check(bJoy1Axis1P, joy2axis1P32000, {});
335 check(bJoy1Axis1P, joy2axis1P123, {});
336 check(bJoy1Axis1P, joy2axis1M27000, {});
337 check(bJoy1Axis1P, joy1hat1left, {});
338 check(bJoy1Axis1P, mouseWheel, {});
339}
TEST_CASE("BooleanInput: toString, parse")
Sent when the MSX resets or powers up.
Definition Event.hh:369
static KeyDownEvent create(SDL_Keycode code, SDL_Keymod mod=KMOD_NONE)
Definition Event.hh:81
static KeyUpEvent create(SDL_Keycode code, SDL_Keymod mod=KMOD_NONE)
Definition Event.hh:62
CHECK(m3==m3)
This file implemented 3 utility functions:
Definition Autofire.cc:11
std::optional< BooleanInput > captureBooleanInput(const Event &event, function_ref< int(JoystickId)> getJoyDeadZone)
std::optional< bool > match(const BooleanInput &binding, const Event &event, function_ref< int(JoystickId)> getJoyDeadZone)
std::optional< BooleanInput > parseBooleanInput(std::string_view text)
std::variant< BooleanKeyboard, BooleanMouseButton, BooleanJoystickButton, BooleanJoystickHat, BooleanJoystickAxis > BooleanInput
std::string toString(const BooleanInput &input)
std::variant< KeyUpEvent, KeyDownEvent, MouseMotionEvent, MouseButtonUpEvent, MouseButtonDownEvent, MouseWheelEvent, JoystickAxisMotionEvent, JoystickHatEvent, JoystickButtonUpEvent, JoystickButtonDownEvent, OsdControlReleaseEvent, OsdControlPressEvent, WindowEvent, TextEvent, FileDropEvent, QuitEvent, FinishFrameEvent, CliCommandEvent, GroupEvent, BootEvent, FrameDrawnEvent, BreakEvent, SwitchRendererEvent, TakeReverseSnapshotEvent, AfterTimedEvent, MachineLoadedEvent, MachineActivatedEvent, MachineDeactivatedEvent, MidiInReaderEvent, MidiInWindowsEvent, MidiInCoreMidiEvent, MidiInCoreMidiVirtualEvent, MidiInALSAEvent, Rs232TesterEvent, Rs232NetEvent, ImGuiDelayedActionEvent, ImGuiActiveEvent > Event
Definition Event.hh:444