test_one_shot_keys.cpp
10501 bytes
1/* Copyright 2021 Stefan Kerkmann
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "action_util.h"
18#include "keyboard_report_util.hpp"
19#include "test_common.hpp"
20
21using testing::_;
22using testing::InSequence;
23
24class OneShot : public TestFixture {};
25class OneShotParametrizedTestFixture : public ::testing::WithParamInterface<std::pair<KeymapKey, KeymapKey>>, public OneShot {};
26
27TEST_F(OneShot, OSMWithoutAdditionalKeypressDoesNothing) {
28 TestDriver driver;
29 auto osm_key = KeymapKey(0, 0, 0, OSM(MOD_LSFT), KC_LSFT);
30
31 set_keymap({osm_key});
32
33 /* Press and release OSM key*/
34 EXPECT_NO_REPORT(driver);
35 tap_key(osm_key);
36 VERIFY_AND_CLEAR(driver);
37
38 /* OSM are added when an actual report is send */
39 EXPECT_REPORT(driver, (osm_key.report_code));
40 send_keyboard_report();
41 VERIFY_AND_CLEAR(driver);
42
43 /* Make unit-test pass */
44 clear_oneshot_mods();
45}
46
47#if defined(ONESHOT_TIMEOUT)
48
49TEST_P(OneShotParametrizedTestFixture, OSMExpiredDoesNothing) {
50 TestDriver driver;
51 KeymapKey osm_key = GetParam().first;
52 KeymapKey regular_key = GetParam().second;
53
54 set_keymap({osm_key, regular_key});
55
56 /* Press and release OSM */
57 EXPECT_NO_REPORT(driver);
58 osm_key.press();
59 run_one_scan_loop();
60 osm_key.release();
61 idle_for(ONESHOT_TIMEOUT);
62 VERIFY_AND_CLEAR(driver);
63
64 /* Press regular key */
65 EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
66 regular_key.press();
67 run_one_scan_loop();
68 VERIFY_AND_CLEAR(driver);
69
70 /* Release regular key */
71 EXPECT_EMPTY_REPORT(driver);
72 regular_key.release();
73 run_one_scan_loop();
74 VERIFY_AND_CLEAR(driver);
75}
76
77#endif
78
79TEST_P(OneShotParametrizedTestFixture, OSMWithAdditionalKeypress) {
80 TestDriver driver;
81 KeymapKey osm_key = GetParam().first;
82 KeymapKey regular_key = GetParam().second;
83
84 set_keymap({osm_key, regular_key});
85
86 /* Press and release OSM */
87 EXPECT_NO_REPORT(driver);
88 tap_key(osm_key);
89 VERIFY_AND_CLEAR(driver);
90
91 /* Press regular key */
92 EXPECT_REPORT(driver, (osm_key.report_code, regular_key.report_code)).Times(1);
93 regular_key.press();
94 run_one_scan_loop();
95 VERIFY_AND_CLEAR(driver);
96
97 /* Release regular key */
98 EXPECT_EMPTY_REPORT(driver);
99 regular_key.release();
100 run_one_scan_loop();
101 VERIFY_AND_CLEAR(driver);
102}
103
104TEST_P(OneShotParametrizedTestFixture, OSMAsRegularModifierWithAdditionalKeypress) {
105 TestDriver driver;
106 testing::InSequence s;
107
108 KeymapKey osm_key = GetParam().first;
109 KeymapKey regular_key = GetParam().second;
110
111 set_keymap({osm_key, regular_key});
112
113 /* Press OSM */
114 EXPECT_NO_REPORT(driver);
115 osm_key.press();
116 run_one_scan_loop();
117 VERIFY_AND_CLEAR(driver);
118
119 /* Press regular key */
120 EXPECT_NO_REPORT(driver);
121 regular_key.press();
122 run_one_scan_loop();
123 VERIFY_AND_CLEAR(driver);
124
125 /* Release regular key */
126 EXPECT_NO_REPORT(driver);
127 regular_key.release();
128 run_one_scan_loop();
129 VERIFY_AND_CLEAR(driver);
130
131 /* Release OSM */
132 EXPECT_REPORT(driver, (regular_key.report_code, osm_key.report_code)).Times(1);
133 EXPECT_EMPTY_REPORT(driver);
134 osm_key.release();
135 run_one_scan_loop();
136 VERIFY_AND_CLEAR(driver);
137}
138
139// clang-format off
140
141INSTANTIATE_TEST_CASE_P(
142 OneShotModifierTests,
143 OneShotParametrizedTestFixture,
144 ::testing::Values(
145 /* first is osm key, second is regular key. */
146 std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}, KeymapKey{0, 1, 1, KC_A}),
147 std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LCTL), KC_LCTL}, KeymapKey{0, 1, 1, KC_A}),
148 std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LALT), KC_LALT}, KeymapKey{0, 1, 1, KC_A}),
149 std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LGUI), KC_LGUI}, KeymapKey{0, 1, 1, KC_A}),
150 std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RCTL), KC_RCTL}, KeymapKey{0, 1, 1, KC_A}),
151 std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RSFT), KC_RSFT}, KeymapKey{0, 1, 1, KC_A}),
152 std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RALT), KC_RALT}, KeymapKey{0, 1, 1, KC_A}),
153 std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RGUI), KC_RGUI}, KeymapKey{0, 1, 1, KC_A})
154 ));
155// clang-format on
156
157TEST_F(OneShot, OSMChainingTwoOSMs) {
158 TestDriver driver;
159 InSequence s;
160 KeymapKey osm_key1 = KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT};
161 KeymapKey osm_key2 = KeymapKey{0, 0, 1, OSM(MOD_LCTL), KC_LCTL};
162 KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A};
163
164 set_keymap({osm_key1, osm_key2, regular_key});
165
166 /* Press and release OSM1 */
167 EXPECT_NO_REPORT(driver);
168 tap_key(osm_key1);
169 VERIFY_AND_CLEAR(driver);
170
171 /* Press and relesea OSM2 */
172 EXPECT_NO_REPORT(driver);
173 tap_key(osm_key2);
174 VERIFY_AND_CLEAR(driver);
175
176 /* Press regular key */
177 EXPECT_REPORT(driver, (osm_key1.report_code, osm_key2.report_code, regular_key.report_code)).Times(1);
178 regular_key.press();
179 run_one_scan_loop();
180 VERIFY_AND_CLEAR(driver);
181
182 /* Release regular key */
183 EXPECT_EMPTY_REPORT(driver);
184 regular_key.release();
185 run_one_scan_loop();
186 VERIFY_AND_CLEAR(driver);
187}
188
189TEST_F(OneShot, OSMDoubleTapNotLockingOSMs) {
190 TestDriver driver;
191 InSequence s;
192 KeymapKey osm_key1 = KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT};
193 KeymapKey osm_key2 = KeymapKey{0, 0, 1, OSM(MOD_LCTL), KC_LCTL};
194 KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A};
195
196 set_keymap({osm_key1, osm_key2, regular_key});
197
198 /* Press and release OSM1 */
199 EXPECT_NO_REPORT(driver);
200 tap_key(osm_key1);
201 VERIFY_AND_CLEAR(driver);
202
203 /* Press and release OSM2 twice */
204 EXPECT_NO_REPORT(driver);
205 tap_key(osm_key2);
206 tap_key(osm_key2);
207 VERIFY_AND_CLEAR(driver);
208
209 /* Press regular key */
210 EXPECT_REPORT(driver, (osm_key1.report_code, osm_key2.report_code, regular_key.report_code)).Times(1);
211 regular_key.press();
212 run_one_scan_loop();
213 VERIFY_AND_CLEAR(driver);
214
215 /* Release regular key */
216 EXPECT_EMPTY_REPORT(driver);
217 regular_key.release();
218 run_one_scan_loop();
219 VERIFY_AND_CLEAR(driver);
220
221 /* Press regular key */
222 EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
223 regular_key.press();
224 run_one_scan_loop();
225 VERIFY_AND_CLEAR(driver);
226
227 /* Release regular key */
228 EXPECT_EMPTY_REPORT(driver);
229 regular_key.release();
230 run_one_scan_loop();
231 VERIFY_AND_CLEAR(driver);
232}
233
234TEST_F(OneShot, OSMHoldNotLockingOSMs) {
235 TestDriver driver;
236 InSequence s;
237 KeymapKey osm_key1 = KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT};
238 KeymapKey osm_key2 = KeymapKey{0, 0, 1, OSM(MOD_LCTL), KC_LCTL};
239 KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A};
240
241 set_keymap({osm_key1, osm_key2, regular_key});
242
243 /* Press and release OSM1 */
244 EXPECT_NO_REPORT(driver);
245 tap_key(osm_key1);
246 VERIFY_AND_CLEAR(driver);
247
248 /* Press and hold OSM2 */
249 EXPECT_REPORT(driver, (osm_key1.report_code, osm_key2.report_code)).Times(1);
250 osm_key2.press();
251 run_one_scan_loop();
252 idle_for(TAPPING_TERM);
253 VERIFY_AND_CLEAR(driver);
254
255 /* Press and release regular key */
256 EXPECT_REPORT(driver, (osm_key1.report_code, osm_key2.report_code, regular_key.report_code)).Times(1);
257 EXPECT_REPORT(driver, (osm_key2.report_code)).Times(1);
258 tap_key(regular_key);
259 VERIFY_AND_CLEAR(driver);
260
261 /* Release OSM2 */
262 EXPECT_EMPTY_REPORT(driver);
263 osm_key2.release();
264 run_one_scan_loop();
265 VERIFY_AND_CLEAR(driver);
266
267 /* Press regular key */
268 EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
269 regular_key.press();
270 run_one_scan_loop();
271 VERIFY_AND_CLEAR(driver);
272
273 /* Release regular key */
274 EXPECT_EMPTY_REPORT(driver);
275 regular_key.release();
276 run_one_scan_loop();
277 VERIFY_AND_CLEAR(driver);
278}
279
280TEST_F(OneShot, OSLWithAdditionalKeypress) {
281 TestDriver driver;
282 InSequence s;
283 KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
284 KeymapKey regular_key = KeymapKey{1, 1, 0, KC_A};
285
286 set_keymap({osl_key, regular_key});
287
288 /* Press OSL key */
289 EXPECT_NO_REPORT(driver);
290 osl_key.press();
291 run_one_scan_loop();
292 VERIFY_AND_CLEAR(driver);
293
294 /* Release OSL key */
295 EXPECT_NO_REPORT(driver);
296 osl_key.release();
297 run_one_scan_loop();
298 VERIFY_AND_CLEAR(driver);
299
300 /* Press regular key */
301 EXPECT_REPORT(driver, (regular_key.report_code)).Times(1);
302 EXPECT_EMPTY_REPORT(driver);
303 regular_key.press();
304 run_one_scan_loop();
305 VERIFY_AND_CLEAR(driver);
306
307 /* Release regular key */
308 EXPECT_NO_REPORT(driver);
309 regular_key.release();
310 run_one_scan_loop();
311 VERIFY_AND_CLEAR(driver);
312}
313
314TEST_F(OneShot, OSLWithOsmAndAdditionalKeypress) {
315 TestDriver driver;
316 InSequence s;
317 KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)};
318 KeymapKey osm_key = KeymapKey{1, 1, 0, OSM(MOD_LSFT), KC_LSFT};
319 KeymapKey regular_key = KeymapKey{1, 1, 1, KC_A};
320
321 set_keymap({osl_key, osm_key, regular_key});
322
323 /* Press OSL key */
324 EXPECT_NO_REPORT(driver);
325 osl_key.press();
326 run_one_scan_loop();
327 VERIFY_AND_CLEAR(driver);
328
329 /* Release OSL key */
330 EXPECT_NO_REPORT(driver);
331 osl_key.release();
332 run_one_scan_loop();
333 EXPECT_TRUE(layer_state_is(1));
334 VERIFY_AND_CLEAR(driver);
335
336 /* Press and release OSM */
337 EXPECT_NO_REPORT(driver);
338 tap_key(osm_key);
339 EXPECT_TRUE(layer_state_is(1));
340 VERIFY_AND_CLEAR(driver);
341
342 /* Press regular key */
343 EXPECT_REPORT(driver, (osm_key.report_code, regular_key.report_code)).Times(1);
344 EXPECT_EMPTY_REPORT(driver);
345 regular_key.press();
346 run_one_scan_loop();
347 EXPECT_FALSE(layer_state_is(1));
348 VERIFY_AND_CLEAR(driver);
349
350 /* Release regular key */
351 EXPECT_NO_REPORT(driver);
352 regular_key.release();
353 run_one_scan_loop();
354 VERIFY_AND_CLEAR(driver);
355}