Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: remoting/host/linux/x11_character_injector_unittest.cc

Issue 2346643003: [Remoting Host] Handle text event characters that are not presented on the keyboard (Closed)
Patch Set: Remove mock keyboard reference Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "remoting/host/linux/x11_character_injector.h"
6
7 #include <stdarg.h>
8
9 #include <map>
10
11 #include "base/memory/ptr_util.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "remoting/host/linux/x11_keyboard.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace {
19
20 const int kMappingExpireMs = 200;
21
22 base::TimeDelta TimeDeltaMs(int ms) {
23 return base::TimeDelta::FromMilliseconds(ms);
24 }
25
26 } // namespace
27
28 namespace remoting {
29
30 class FakeX11Keyboard : public X11Keyboard {
31 public:
32 struct KeyPressExpectation {
33 base::TimeDelta min_delay; // To the last key press.
34 base::TimeDelta max_delay;
35 uint32_t keycode;
36 };
37
38 struct ChangeKeyMappingExpectation {
39 uint32_t keycode;
40 uint32_t code_point;
41 };
42
43 explicit FakeX11Keyboard(const std::vector<uint32_t>& available_keycodes);
44 ~FakeX11Keyboard() override;
45
46 std::vector<uint32_t> GetUnusedKeycodes() override;
47
48 void PressKey(uint32_t keycode, uint32_t modifiers) override;
49 bool FindKeycode(uint32_t code_point,
50 uint32_t* keycode,
51 uint32_t* modifiers) override;
52 bool ChangeKeyMapping(uint32_t keycode, uint32_t code_point) override;
53 void Flush() override;
54 void Sync() override;
55
56 void ExpectKeyPress(const std::vector<KeyPressExpectation>& sequence);
57 void ExpectChangeKeyMapping(
58 const std::vector<ChangeKeyMappingExpectation>& sequence);
59 void InjectorAboutToDestruct();
60
61 // Sets a callback to be called when the keypress expectation queue becomes
62 // empty.
63 void SetKeyPressFinishedCallback(const base::Closure& callback) {
64 keypress_finished_callback_ = callback;
65 }
66
67 private:
68 static const int kSyncDelayMs = 1;
69
70 std::map<uint32_t, uint32_t> keycode_mapping_;
71 std::queue<KeyPressExpectation> keypress_expectations_;
72 std::queue<ChangeKeyMappingExpectation> change_key_mapping_expectations_;
73 bool injector_about_to_destruct_ = false;
74 base::TimeTicks last_keypress_time_;
75 base::Closure keypress_finished_callback_;
76 };
77
78 FakeX11Keyboard::FakeX11Keyboard(
79 const std::vector<uint32_t>& available_keycodes) {
80 for (uint32_t keycode : available_keycodes) {
81 keycode_mapping_.insert({keycode, 0});
82 }
83 }
84
85 FakeX11Keyboard::~FakeX11Keyboard() {
86 DCHECK(keypress_expectations_.empty());
87 DCHECK(change_key_mapping_expectations_.empty());
88 for (const auto& pair : keycode_mapping_) {
89 EXPECT_EQ(0u, pair.second);
90 }
91 }
92
93 std::vector<uint32_t> FakeX11Keyboard::GetUnusedKeycodes() {
94 std::vector<uint32_t> keycodes;
95 for (const auto& pair : keycode_mapping_) {
96 if (!pair.second) {
97 keycodes.push_back(pair.first);
98 }
99 }
100 return keycodes;
101 }
102
103 void FakeX11Keyboard::PressKey(uint32_t keycode, uint32_t modifiers) {
104 ASSERT_FALSE(keypress_expectations_.empty());
105 KeyPressExpectation& expectation = keypress_expectations_.front();
106 ASSERT_EQ(expectation.keycode, keycode);
107 base::TimeTicks now = base::TimeTicks::Now();
108 base::TimeDelta delay = now - last_keypress_time_;
109 ASSERT_GE(delay, expectation.min_delay);
110 ASSERT_LE(delay, expectation.max_delay);
111 last_keypress_time_ = now;
112 keypress_expectations_.pop();
113 if (keypress_expectations_.empty() && keypress_finished_callback_) {
114 keypress_finished_callback_.Run();
115 }
116 }
117
118 bool FakeX11Keyboard::FindKeycode(uint32_t code_point,
119 uint32_t* keycode,
120 uint32_t* modifiers) {
121 auto position = std::find_if(keycode_mapping_.begin(), keycode_mapping_.end(),
122 [code_point](const std::pair<uint32_t, uint32_t>& pair) {
123 return pair.second == code_point;
124 });
125 if (position == keycode_mapping_.end()) {
126 return false;
127 }
128 *keycode = position->first;
129 *modifiers = 0;
130 return true;
131 }
132
133 bool FakeX11Keyboard::ChangeKeyMapping(uint32_t keycode, uint32_t code_point) {
134 if (injector_about_to_destruct_) {
135 EXPECT_EQ(0u, code_point);
136 } else {
137 EXPECT_FALSE(change_key_mapping_expectations_.empty())
138 << "Unexpected change key request. Key Code: " << keycode
139 << " Code Point: " << code_point;
140 ChangeKeyMappingExpectation& expectation =
141 change_key_mapping_expectations_.front();
142 EXPECT_EQ(expectation.keycode, keycode);
143 EXPECT_EQ(expectation.code_point, code_point);
144 change_key_mapping_expectations_.pop();
145 }
146
147 keycode_mapping_[keycode] = code_point;
148 return true;
149 }
150
151 void FakeX11Keyboard::Flush() {}
152
153 void FakeX11Keyboard::Sync() {
154 usleep(kSyncDelayMs * 1000);
155 }
156
157 void FakeX11Keyboard::ExpectKeyPress(
158 const std::vector<KeyPressExpectation>& sequence) {
159 for (const auto& expectation : sequence) {
160 keypress_expectations_.push(expectation);
161 }
162 }
163
164 void FakeX11Keyboard::ExpectChangeKeyMapping(
165 const std::vector<ChangeKeyMappingExpectation>& sequence) {
166 for (const auto& expectation : sequence) {
167 change_key_mapping_expectations_.push(expectation);
168 }
169 }
170
171 void FakeX11Keyboard::InjectorAboutToDestruct() {
172 injector_about_to_destruct_ = true;
173 }
174
175 class X11CharacterInjectorTest : public testing::Test {
176 public:
177 void SetUp() override;
178 void TearDown() override;
179
180 protected:
181 void ResetRunLoop();
182 void FillUntilFull(bool immediately_run);
183
184 std::unique_ptr<X11CharacterInjector> injector_;
185 FakeX11Keyboard* keyboard_; // Owned by |injector_|.
186
187 base::MessageLoop message_loop_;
188 std::unique_ptr<base::RunLoop> run_loop_;
189 };
190
191 void X11CharacterInjectorTest::SetUp() {
192 keyboard_ = new FakeX11Keyboard({55, 54, 53, 52, 51});
193 injector_.reset(new X11CharacterInjector(base::WrapUnique(keyboard_)));
194 ResetRunLoop();
195 }
196
197 void X11CharacterInjectorTest::TearDown() {
198 run_loop_->Run();
199 keyboard_->InjectorAboutToDestruct();
200 injector_.reset();
201 }
202
203 void X11CharacterInjectorTest::ResetRunLoop() {
204 run_loop_.reset(new base::RunLoop());
205 keyboard_->SetKeyPressFinishedCallback(run_loop_->QuitClosure());
206 }
207
208 void X11CharacterInjectorTest::FillUntilFull(bool immediately_run) {
209 injector_->Inject(1);
210 injector_->Inject(2);
211 injector_->Inject(3);
212 injector_->Inject(4);
213 injector_->Inject(5);
214
215 keyboard_->ExpectChangeKeyMapping(
216 {{55, 1}, {54, 2}, {53, 3}, {52, 4}, {51, 5}});
217
218 keyboard_->ExpectKeyPress(
219 {{base::TimeDelta(), base::TimeDelta::Max(), 55},
220 {base::TimeDelta(), TimeDeltaMs(10), 54},
221 {base::TimeDelta(), TimeDeltaMs(10), 53},
222 {base::TimeDelta(), TimeDeltaMs(10), 52},
223 {base::TimeDelta(), TimeDeltaMs(10), 51}});
224 if (immediately_run) {
225 run_loop_->Run();
226 ResetRunLoop();
227 }
228 }
229
230 TEST_F(X11CharacterInjectorTest, TestNoMappingNoExpectation) {
231 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
232 run_loop_->QuitClosure());
233 }
234
235 TEST_F(X11CharacterInjectorTest, TestTypeOneCharacter) {
236 injector_->Inject(123);
237
238 keyboard_->ExpectChangeKeyMapping({{55, 123}});
239 keyboard_->ExpectKeyPress({{base::TimeDelta(), base::TimeDelta::Max(), 55}});
240 }
241
242 TEST_F(X11CharacterInjectorTest, TestMapCharactersUntilFull) {
243 FillUntilFull(false);
244 }
245
246 TEST_F(X11CharacterInjectorTest, TestMapOneCharacterWhenFull) {
247 FillUntilFull(false);
248 injector_->Inject(6);
249
250 keyboard_->ExpectChangeKeyMapping({{55, 6}});
251
252 keyboard_->ExpectKeyPress({{TimeDeltaMs(kMappingExpireMs - 50),
253 TimeDeltaMs(kMappingExpireMs + 50), 55}});
254 }
255
256 TEST_F(X11CharacterInjectorTest, TestImmediatelyReuseOldKeycodeAfterExpired) {
257 FillUntilFull(true);
258
259 usleep((kMappingExpireMs + 50) * 1000);
260
261 injector_->Inject(6);
262
263 keyboard_->ExpectChangeKeyMapping({{55, 6}});
264
265 keyboard_->ExpectKeyPress(
266 {{base::TimeDelta(), base::TimeDelta::Max(), 55}});
267 }
268
269 TEST_F(X11CharacterInjectorTest, TestReusingMappedCharacterLowersPriority) {
270 FillUntilFull(true);
271
272 usleep((kMappingExpireMs + 50) * 1000);
273
274 injector_->Inject(1);
275 injector_->Inject(6);
276
277 keyboard_->ExpectChangeKeyMapping({{54, 6}});
278
279 keyboard_->ExpectKeyPress(
280 {{base::TimeDelta(), base::TimeDelta::Max(), 55},
281 {base::TimeDelta(), TimeDeltaMs(10), 54}});
282 }
283
284 TEST_F(X11CharacterInjectorTest, TestOrderAfterReusingCharacters) {
285 FillUntilFull(true);
286
287 injector_->Inject(2);
288 injector_->Inject(4);
289 injector_->Inject(5);
290 injector_->Inject(1);
291 injector_->Inject(3);
292
293 keyboard_->ExpectKeyPress(
294 {{base::TimeDelta(), base::TimeDelta::Max(), 54},
295 {base::TimeDelta(), TimeDeltaMs(10), 52},
296 {base::TimeDelta(), TimeDeltaMs(10), 51},
297 {base::TimeDelta(), TimeDeltaMs(10), 55},
298 {base::TimeDelta(), TimeDeltaMs(10), 53}});
299
300 run_loop_->Run();
301 ResetRunLoop();
302
303 usleep((kMappingExpireMs + 50) * 1000);
304
305 injector_->Inject(31);
306 injector_->Inject(32);
307 injector_->Inject(33);
308 injector_->Inject(34);
309 injector_->Inject(35);
310
311 keyboard_->ExpectChangeKeyMapping({
312 {54, 31}, {52, 32}, {51, 33}, {55, 34}, {53, 35}});
313
314 keyboard_->ExpectKeyPress(
315 {{base::TimeDelta(), base::TimeDelta::Max(), 54},
316 {base::TimeDelta(), TimeDeltaMs(10), 52},
317 {base::TimeDelta(), TimeDeltaMs(10), 51},
318 {base::TimeDelta(), TimeDeltaMs(10), 55},
319 {base::TimeDelta(), TimeDeltaMs(10), 53}});
320 }
321
322 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698