Merge lp:~andreas-pokorny/mir/add-key-repeat-utility into lp:mir
- add-key-repeat-utility
- Merge into development-branch
Status: | Work in progress |
---|---|
Proposed branch: | lp:~andreas-pokorny/mir/add-key-repeat-utility |
Merge into: | lp:mir |
Prerequisite: | lp:~andreas-pokorny/mir/add-dispatchable-alarm-factory |
Diff against target: |
407 lines (+340/-11) 6 files modified
include/test/mir/test/doubles/mock_alarm_factory.h (+18/-11) src/platforms/evdev/CMakeLists.txt (+1/-0) src/platforms/evdev/key_repeater.cpp (+97/-0) src/platforms/evdev/key_repeater.h (+64/-0) tests/unit-tests/input/CMakeLists.txt (+1/-0) tests/unit-tests/input/test_key_repeater.cpp (+159/-0) |
To merge this branch: | bzr merge lp:~andreas-pokorny/mir/add-key-repeat-utility |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Needs Fixing | |
Kevin DuBois (community) | Approve | ||
Review via email: mp+289961@code.launchpad.net |
Commit message
Add Key repeat utility
Similar to the key press tracking in KeyRepeatDispat
Description of the change
A split out of an upcoming branch that moves repeat handling into the input platforms and makes it configureable. In this MP an implementation of the necessary key code tracking is added.
Kevin DuBois (kdub) wrote : | # |
> + mtd::MockAlarm * alarm = new mtd::MockAlarm;
> needs delete/unique_ptr?
Ah, reading through the mock factory, it seems this gets wrapped with a unique_ptr on invocation.... Still not threadsafe, and will leak if the test fails to call the function.
mir/test/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3417
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Andreas Pokorny (andreas-pokorny) wrote : | # |
> > + mtd::MockAlarm * alarm = new mtd::MockAlarm;
> > needs delete/unique_ptr?
> Ah, reading through the mock factory, it seems this gets wrapped with a
> unique_ptr on invocation.... Still not threadsafe, and will leak if the test
> fails to call the function.
In some of the tests I want to define call expectations.. but when the unique_ptr is created inside the method I dont get access to the object. But I guess in those cases I could still create the Alarm object in advance with make_unique.
> mir/test/
> })) is the best way I've found to work around gmock's difficulty with move-
> only types.
Andreas Pokorny (andreas-pokorny) wrote : | # |
> + // destructor cancels the alarm
> + ~MockAlarm()
> + {
> + cancel();
> + }
> Seems specific to a test
But thats the behavior of Alarm objects..
> + if (existing_timer == repeat_
> + existing_timer = repeat_
> + std::make_pair(
> + code,
> + alarm_factory-
> + [this, code]()
> + {
> + this->handle_
> + })
> + )
> + ).first;
>
> braces around multi-line if statement
>
> + mtd::MockAlarm * alarm = new mtd::MockAlarm;
> needs delete/unique_ptr?
ack
Andreas Pokorny (andreas-pokorny) wrote : | # |
> > > + mtd::MockAlarm * alarm = new mtd::MockAlarm;
> > > needs delete/unique_ptr?
> > Ah, reading through the mock factory, it seems this gets wrapped with a
> > unique_ptr on invocation.... Still not threadsafe, and will leak if the test
> > fails to call the function.
>
> In some of the tests I want to define call expectations.. but when the
> unique_ptr is created inside the method I dont get access to the object. But I
> guess in those cases I could still create the Alarm object in advance with
> make_unique.
>
> > mir/test/
> std::make_
> > })) is the best way I've found to work around gmock's difficulty with move-
> > only types.
It does not work here. I had to reorder the expectations to still have a valid Alarm ptr in the test case. But to get the unique_ptr to the caller .. I cannot use Return() with a move only type, and an Invoke action with a mutable lambda.
- 3418. By Andreas Pokorny
-
fixed indenting
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3418
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
ABORTED: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3418
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Kevin DuBois (kdub) wrote : | # |
> It does not work here. I had to reorder the expectations to still have a valid
> Alarm ptr in the test case. But to get the unique_ptr to the caller .. I
> cannot use Return() with a move only type, and an Invoke action with a mutable
> lambda.
can merge this branch in, makes things a bit more raii in the test: lp:~kdub/mir/key-repeat-gmock-fixes
Andreas Pokorny (andreas-pokorny) wrote : | # |
wow.. for some reason I always tried binding the alarm object by value to lambda.
Works fine. Thanks!
- 3419. By Andreas Pokorny
-
merge prereq
- 3420. By Andreas Pokorny
-
Merge improvement from kdub..
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3420
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 3421. By Andreas Pokorny
-
merge prereq to resolve conflict
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3421
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unmerged revisions
- 3421. By Andreas Pokorny
-
merge prereq to resolve conflict
- 3420. By Andreas Pokorny
-
Merge improvement from kdub..
- 3419. By Andreas Pokorny
-
merge prereq
- 3418. By Andreas Pokorny
-
fixed indenting
- 3417. By Andreas Pokorny
-
merge prereq
- 3416. By Andreas Pokorny
-
Add accessors
- 3415. By Andreas Pokorny
-
Add Key repeat utility
Similar to the key press tracking in KeyRepeatDispat
cher, this class will support the evdev platform and fake input devices in implementing repeat handling. - 3414. By Andreas Pokorny
-
Add mir::dispatch:
:AlarmFactory Implementation of mir::time:
:AlarmFactory that works with mir::dispatch: :Dispatchable and supports all the state transitions required by the test suite accumulated in test_glib_ main_loop. cpp. With this change several GPL interfaces defined inside the mirserver API have been moved to mircommon and LGPL.
Preview Diff
1 | === modified file 'include/test/mir/test/doubles/mock_alarm_factory.h' |
2 | --- include/test/mir/test/doubles/mock_alarm_factory.h 2016-03-31 18:14:16 +0000 |
3 | +++ include/test/mir/test/doubles/mock_alarm_factory.h 2016-03-31 18:14:16 +0000 |
4 | @@ -20,6 +20,8 @@ |
5 | #define MIR_TEST_DOUBLES_MOCK_ALARM_FACTORY_H |
6 | |
7 | #include "mir/time/alarm_factory.h" |
8 | +#include "mir/time/alarm.h" |
9 | +#include "mir/test/gmock_fixes.h" |
10 | |
11 | namespace mir |
12 | { |
13 | @@ -28,19 +30,24 @@ |
14 | namespace doubles |
15 | { |
16 | |
17 | +struct MockAlarm : public mir::time::Alarm |
18 | +{ |
19 | + MOCK_METHOD0(cancel, bool()); |
20 | + MOCK_CONST_METHOD0(state, mir::time::Alarm::State()); |
21 | + MOCK_METHOD1(reschedule_in, bool(std::chrono::milliseconds)); |
22 | + MOCK_METHOD1(reschedule_for, bool(mir::time::Timestamp)); |
23 | + |
24 | + // destructor cancels the alarm |
25 | + ~MockAlarm() |
26 | + { |
27 | + cancel(); |
28 | + } |
29 | +}; |
30 | + |
31 | struct MockAlarmFactory : public mir::time::AlarmFactory |
32 | { |
33 | - MOCK_METHOD1(create_alarm_adapter, mir::time::Alarm*(std::function<void()> const&)); |
34 | - MOCK_METHOD1(create_lockable_alarm_adapter, mir::time::Alarm*(std::shared_ptr<mir::LockableCallback> const&)); |
35 | - std::unique_ptr<mir::time::Alarm> create_alarm(std::function<void()> const& cb) |
36 | - { |
37 | - return std::unique_ptr<mir::time::Alarm>(create_alarm_adapter(cb)); |
38 | - } |
39 | - |
40 | - std::unique_ptr<mir::time::Alarm> create_alarm(std::shared_ptr<mir::LockableCallback> const& lcb) |
41 | - { |
42 | - return std::unique_ptr<mir::time::Alarm>(create_lockable_alarm_adapter(lcb)); |
43 | - } |
44 | + MOCK_METHOD1(create_alarm, std::unique_ptr<time::Alarm>(std::function<void()> const&)); |
45 | + MOCK_METHOD1(create_alarm, std::unique_ptr<time::Alarm>(std::shared_ptr<mir::LockableCallback> const&)); |
46 | }; |
47 | |
48 | } |
49 | |
50 | === modified file 'src/platforms/evdev/CMakeLists.txt' |
51 | --- src/platforms/evdev/CMakeLists.txt 2016-03-23 06:39:56 +0000 |
52 | +++ src/platforms/evdev/CMakeLists.txt 2016-03-31 18:14:16 +0000 |
53 | @@ -18,6 +18,7 @@ |
54 | add_library(mirevdevutilsobjects OBJECT |
55 | evdev_device_detection.cpp |
56 | button_utils.cpp |
57 | + key_repeater.cpp |
58 | ) |
59 | |
60 | add_library(mirplatforminputevdevobjects OBJECT |
61 | |
62 | === added file 'src/platforms/evdev/key_repeater.cpp' |
63 | --- src/platforms/evdev/key_repeater.cpp 1970-01-01 00:00:00 +0000 |
64 | +++ src/platforms/evdev/key_repeater.cpp 2016-03-31 18:14:16 +0000 |
65 | @@ -0,0 +1,97 @@ |
66 | +/* |
67 | + * Copyright © 2016 Canonical Ltd. |
68 | + * |
69 | + * This program is free software: you can redistribute it and/or modify it |
70 | + * under the terms of the GNU General Public License version 3, |
71 | + * as published by the Free Software Foundation. |
72 | + * |
73 | + * This program is distributed in the hope that it will be useful, |
74 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
75 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
76 | + * GNU General Public License for more details. |
77 | + * |
78 | + * You should have received a copy of the GNU General Public License |
79 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
80 | + * |
81 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
82 | + */ |
83 | + |
84 | +#include "key_repeater.h" |
85 | + |
86 | +#include "mir/time/alarm_factory.h" |
87 | +#include "mir/time/alarm.h" |
88 | + |
89 | +namespace mie = mir::input::evdev; |
90 | +namespace mt = mir::time; |
91 | + |
92 | +mie::KeyRepeater::KeyRepeater(std::shared_ptr<mir::time::AlarmFactory> const& alarm_factory, std::function<void(int32_t keycode)> const& send_repeat_key) |
93 | + : send_repeat{send_repeat_key}, alarm_factory{alarm_factory} |
94 | +{ |
95 | +} |
96 | + |
97 | +void mie::KeyRepeater::enable(std::chrono::milliseconds repeat_delay, std::chrono::milliseconds repeat_interval) |
98 | +{ |
99 | + enabled_ = true; |
100 | + this->repeat_delay = repeat_delay; |
101 | + this->repeat_interval = repeat_interval; |
102 | +} |
103 | + |
104 | +void mie::KeyRepeater::disable() |
105 | +{ |
106 | + enabled_ = false; |
107 | + repeat_alarms_by_scancode.clear(); |
108 | +} |
109 | + |
110 | +void mie::KeyRepeater::press(int32_t code) |
111 | +{ |
112 | + if (enabled_) |
113 | + { |
114 | + auto existing_timer = repeat_alarms_by_scancode.find(code); |
115 | + if (existing_timer == repeat_alarms_by_scancode.end()) |
116 | + { |
117 | + existing_timer = repeat_alarms_by_scancode.emplace( |
118 | + std::make_pair( |
119 | + code, |
120 | + alarm_factory->create_alarm( |
121 | + [this, code]() |
122 | + { |
123 | + this->handle_timeout(code); |
124 | + }) |
125 | + ) |
126 | + ).first; |
127 | + } |
128 | + existing_timer->second->reschedule_in(repeat_delay); |
129 | + } |
130 | +} |
131 | + |
132 | +void mie::KeyRepeater::release(int32_t code) |
133 | +{ |
134 | + repeat_alarms_by_scancode.erase(code); |
135 | +} |
136 | + |
137 | +void mie::KeyRepeater::handle_timeout(int32_t code) |
138 | +{ |
139 | + if (enabled_) |
140 | + { |
141 | + auto existing_timer = repeat_alarms_by_scancode.find(code); |
142 | + if (existing_timer != repeat_alarms_by_scancode.end()) |
143 | + existing_timer->second->reschedule_in(repeat_interval); |
144 | + |
145 | + send_repeat(code); |
146 | + } |
147 | +} |
148 | + |
149 | +bool mie::KeyRepeater::enabled() const |
150 | +{ |
151 | + return enabled_; |
152 | +} |
153 | + |
154 | +std::chrono::milliseconds mie::KeyRepeater::delay() const |
155 | +{ |
156 | + return repeat_delay; |
157 | +} |
158 | + |
159 | +std::chrono::milliseconds mie::KeyRepeater::interval() const |
160 | +{ |
161 | + return repeat_interval; |
162 | +} |
163 | |
164 | === added file 'src/platforms/evdev/key_repeater.h' |
165 | --- src/platforms/evdev/key_repeater.h 1970-01-01 00:00:00 +0000 |
166 | +++ src/platforms/evdev/key_repeater.h 2016-03-31 18:14:16 +0000 |
167 | @@ -0,0 +1,64 @@ |
168 | +/* |
169 | + * Copyright © 2016 Canonical Ltd. |
170 | + * |
171 | + * This program is free software: you can redistribute it and/or modify it |
172 | + * under the terms of the GNU General Public License version 3, |
173 | + * as published by the Free Software Foundation. |
174 | + * |
175 | + * This program is distributed in the hope that it will be useful, |
176 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
177 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
178 | + * GNU General Public License for more details. |
179 | + * |
180 | + * You should have received a copy of the GNU General Public License |
181 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
182 | + * |
183 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
184 | + */ |
185 | + |
186 | +#ifndef MIR_INPUT_EVDEV_KEY_REPEATER_H_ |
187 | +#define MIR_INPUT_EVDEV_KEY_REPEATER_H_ |
188 | + |
189 | +#include <memory> |
190 | +#include <chrono> |
191 | +#include <unordered_map> |
192 | +#include <functional> |
193 | + |
194 | +namespace mir |
195 | +{ |
196 | +namespace time |
197 | +{ |
198 | +class Alarm; |
199 | +class AlarmFactory; |
200 | +} |
201 | +namespace input |
202 | +{ |
203 | +namespace evdev |
204 | +{ |
205 | + |
206 | +struct KeyRepeater |
207 | +{ |
208 | + KeyRepeater(std::shared_ptr<mir::time::AlarmFactory> const& alarm_factory, std::function<void(int32_t keycode)> const& send_repeat_key); |
209 | + void enable(std::chrono::milliseconds repeat_delay, std::chrono::milliseconds repeat_interval); |
210 | + void disable(); |
211 | + bool enabled() const; |
212 | + std::chrono::milliseconds delay() const; |
213 | + std::chrono::milliseconds interval() const; |
214 | + void press(int32_t code); |
215 | + void release(int32_t code); |
216 | + |
217 | +private: |
218 | + void handle_timeout(int32_t code); |
219 | + bool enabled_{true}; |
220 | + |
221 | + std::chrono::milliseconds repeat_delay{500}; |
222 | + std::chrono::milliseconds repeat_interval{50}; |
223 | + |
224 | + std::function<void(int32_t)> send_repeat; |
225 | + std::unordered_map<int32_t, std::unique_ptr<mir::time::Alarm>> repeat_alarms_by_scancode; |
226 | + std::shared_ptr<mir::time::AlarmFactory> const alarm_factory; |
227 | +}; |
228 | +} |
229 | +} |
230 | +} |
231 | +#endif |
232 | |
233 | === modified file 'tests/unit-tests/input/CMakeLists.txt' |
234 | --- tests/unit-tests/input/CMakeLists.txt 2016-03-23 06:39:56 +0000 |
235 | +++ tests/unit-tests/input/CMakeLists.txt 2016-03-31 18:14:16 +0000 |
236 | @@ -15,6 +15,7 @@ |
237 | ${CMAKE_CURRENT_SOURCE_DIR}/test_surface_input_dispatcher.cpp |
238 | ${CMAKE_CURRENT_SOURCE_DIR}/test_seat_input_device_tracker.cpp |
239 | ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeat_dispatcher.cpp |
240 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_key_repeater.cpp |
241 | ${CMAKE_CURRENT_SOURCE_DIR}/test_validator.cpp |
242 | ) |
243 | |
244 | |
245 | === added file 'tests/unit-tests/input/test_key_repeater.cpp' |
246 | --- tests/unit-tests/input/test_key_repeater.cpp 1970-01-01 00:00:00 +0000 |
247 | +++ tests/unit-tests/input/test_key_repeater.cpp 2016-03-31 18:14:16 +0000 |
248 | @@ -0,0 +1,159 @@ |
249 | +/* |
250 | + * Copyright © 2016 Canonical Ltd. |
251 | + * |
252 | + * This program is free software: you can redistribute it and/or modify |
253 | + * it under the terms of the GNU General Public License version 3 as |
254 | + * published by the Free Software Foundation. |
255 | + * |
256 | + * This program is distributed in the hope that it will be useful, |
257 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
258 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
259 | + * GNU General Public License for more details. |
260 | + * |
261 | + * You should have received a copy of the GNU General Public License |
262 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
263 | + * |
264 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
265 | + */ |
266 | + |
267 | +#include "src/platforms/evdev/key_repeater.h" |
268 | +#include "mir/test/doubles/mock_alarm_factory.h" |
269 | +#include "mir/test/fake_shared.h" |
270 | + |
271 | +#include <gtest/gtest.h> |
272 | +#include <gmock/gmock.h> |
273 | + |
274 | +namespace mt = mir::test; |
275 | +namespace mtd = mt::doubles; |
276 | +namespace mie = mir::input::evdev; |
277 | + |
278 | +using namespace ::testing; |
279 | +using namespace std::chrono_literals; |
280 | + |
281 | +namespace |
282 | +{ |
283 | +struct KeyRepeater : Test |
284 | +{ |
285 | + MOCK_METHOD1(repeat_called, void(int32_t)); |
286 | + |
287 | + NiceMock<mtd::MockAlarmFactory> mock_factory; |
288 | + mie::KeyRepeater repeater{ |
289 | + mt::fake_shared(mock_factory), |
290 | + [this](int32_t code) |
291 | + { |
292 | + repeat_called(code); |
293 | + }}; |
294 | + |
295 | + const int32_t a_key = 32; |
296 | + const int32_t another_key = 33; |
297 | +}; |
298 | +} |
299 | + |
300 | +TEST_F(KeyRepeater, no_repeat_alarm_when_disabled) |
301 | +{ |
302 | + repeater.disable(); |
303 | + EXPECT_CALL(mock_factory, create_alarm(An<std::function<void()> const&>())).Times(0); |
304 | + |
305 | + repeater.press(a_key); |
306 | + repeater.release(a_key); |
307 | +} |
308 | + |
309 | +TEST_F(KeyRepeater, repeat_enabled_by_default) |
310 | +{ |
311 | + auto alarm = std::make_unique<mtd::MockAlarm>(); |
312 | + EXPECT_CALL(*alarm, reschedule_in(_)).Times(1); |
313 | + EXPECT_CALL(mock_factory, create_alarm(An<std::function<void()> const&>())) |
314 | + .Times(1) |
315 | + .WillOnce(Invoke([&](std::function<void()> const&){ return std::move(alarm); })); |
316 | + |
317 | + repeater.press(a_key); |
318 | +} |
319 | + |
320 | +TEST_F(KeyRepeater, alarm_canceled_on_disable) |
321 | +{ |
322 | + auto alarm = std::make_unique<mtd::MockAlarm>(); |
323 | + EXPECT_CALL(*alarm, cancel()).Times(1); |
324 | + EXPECT_CALL(mock_factory, create_alarm(An<std::function<void()> const&>())) |
325 | + .Times(1) |
326 | + .WillOnce(Invoke([&](std::function<void()> const&){ return std::move(alarm); })); |
327 | + |
328 | + repeater.press(a_key); |
329 | + repeater.disable(); |
330 | +} |
331 | + |
332 | +TEST_F(KeyRepeater, alarm_canceled_on_release) |
333 | +{ |
334 | + auto alarm = std::make_unique<mtd::MockAlarm>(); |
335 | + EXPECT_CALL(*alarm, reschedule_in(_)).Times(1); |
336 | + EXPECT_CALL(*alarm, cancel()).Times(1); |
337 | + EXPECT_CALL(mock_factory, create_alarm(An<std::function<void()> const&>())) |
338 | + .Times(1) |
339 | + .WillOnce(Invoke([&](std::function<void()> const&){ return std::move(alarm); })); |
340 | + |
341 | + repeater.press(a_key); |
342 | + repeater.release(a_key); |
343 | +} |
344 | + |
345 | +TEST_F(KeyRepeater, tracks_key_code) |
346 | +{ |
347 | + auto alarm = std::make_unique<mtd::MockAlarm>(); |
348 | + auto second_alarm = std::make_unique<mtd::MockAlarm>(); |
349 | + |
350 | + Sequence seq1; |
351 | + Sequence seq2; |
352 | + EXPECT_CALL(mock_factory, create_alarm(An<std::function<void()> const&>())) |
353 | + .InSequence(seq1) |
354 | + .WillOnce(Invoke([&](std::function<void()> const&){ return std::move(alarm); })); |
355 | + EXPECT_CALL(*alarm, reschedule_in(_)) |
356 | + .InSequence(seq2); |
357 | + |
358 | + EXPECT_CALL(mock_factory, create_alarm(An<std::function<void()> const&>())) |
359 | + .InSequence(seq1) |
360 | + .WillOnce(Invoke([&](std::function<void()> const&){ return std::move(second_alarm); })); |
361 | + EXPECT_CALL(*second_alarm, reschedule_in(_)) |
362 | + .InSequence(seq2); |
363 | + EXPECT_CALL(*second_alarm, cancel()) |
364 | + .InSequence(seq2); |
365 | + |
366 | + EXPECT_CALL(*alarm, cancel()) |
367 | + .InSequence(seq2); |
368 | + |
369 | + repeater.press(a_key); |
370 | + repeater.press(another_key); |
371 | + repeater.release(another_key); |
372 | + repeater.release(a_key); |
373 | +} |
374 | + |
375 | +TEST_F(KeyRepeater, alarm_rescheduled_on_timeout) |
376 | +{ |
377 | + auto alarm = std::make_unique<mtd::MockAlarm>(); |
378 | + std::function<void()> timer_callback; |
379 | + EXPECT_CALL(*this, repeat_called(a_key)).Times(1); |
380 | + EXPECT_CALL(*alarm, reschedule_in(50ms)).Times(1); |
381 | + EXPECT_CALL(*alarm, reschedule_in(10ms)).Times(1); |
382 | + |
383 | + EXPECT_CALL(mock_factory, create_alarm(An<std::function<void()> const&>())) |
384 | + .Times(1) |
385 | + .WillOnce(Invoke([&](std::function<void()> const& callback){ |
386 | + timer_callback = callback; |
387 | + return std::move(alarm); })); |
388 | + |
389 | + repeater.enable(50ms, 10ms); |
390 | + repeater.press(a_key); |
391 | + timer_callback(); |
392 | +} |
393 | + |
394 | +TEST_F(KeyRepeater, repeat_called_on_timeout) |
395 | +{ |
396 | + auto alarm = std::make_unique<mtd::MockAlarm>(); |
397 | + std::function<void()> timer_callback; |
398 | + EXPECT_CALL(*this, repeat_called(a_key)).Times(1); |
399 | + EXPECT_CALL(mock_factory, create_alarm(An<std::function<void()> const&>())) |
400 | + .Times(1) |
401 | + .WillOnce(Invoke([&](std::function<void()> const& callback){ |
402 | + timer_callback = callback; |
403 | + return std::move(alarm); })); |
404 | + |
405 | + repeater.press(a_key); |
406 | + timer_callback(); |
407 | +} |
+ // destructor cancels the alarm
+ ~MockAlarm()
+ {
+ cancel();
+ }
Seems specific to a test
+ if (existing_timer == repeat_ alarms_ by_scancode. end()) alarms_ by_scancode. emplace( >create_ alarm( timeout( code);
+ existing_timer = repeat_
+ std::make_pair(
+ code,
+ alarm_factory-
+ [this, code]()
+ {
+ this->handle_
+ })
+ )
+ ).first;
braces around multi-line if statement
+ mtd::MockAlarm * alarm = new mtd::MockAlarm;
needs delete/unique_ptr?