OXYGENHUB
◆ main openmsx / src / unittest / BooleanInput_test.cc
11.0 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "catch.hpp"
2
#include "BooleanInput.hh"
3
4
#include <SDL.h>
5
6
using namespace openmsx;
7
8
TEST_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::Direction::UP),    "joy1 hat1 up");
43
		compare(BooleanJoystickHat(ID(3), 5, BooleanJoystickHat::Direction::DOWN),  "joy4 hat5 down");
44
		compare(BooleanJoystickHat(ID(2), 4, BooleanJoystickHat::Direction::LEFT),  "joy3 hat4 left");
45
		compare(BooleanJoystickHat(ID(1), 2, BooleanJoystickHat::Direction::RIGHT), "joy2 hat2 right");
46
	}
47
	SECTION("joystick axis") {
48
		compare(BooleanJoystickAxis(ID(0), 1, BooleanJoystickAxis::Direction::POS), "joy1 +axis1");
49
		compare(BooleanJoystickAxis(ID(3), 2, BooleanJoystickAxis::Direction::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
87
TEST_CASE("BooleanInput: capture")
88
{
89
	auto getJoyDeadThreshold = [](JoystickId /*joystick*/) { return 8192; };
90
	auto check = [&](const Event& event, std::string_view expected) {
91
		auto input = captureBooleanInput(event, getJoyDeadThreshold);
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
169
TEST_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 getJoyDeadThreshold = [](JoystickId /*joystick*/) { return 8192; };
283
	auto check = [&](const std::optional<BooleanInput>& binding, const Event& event, std::optional<bool> expected) {
284
		REQUIRE(binding);
285
		CHECK(match(*binding, event, getJoyDeadThreshold) == 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
}