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

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: Reviewer's Feedback 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
« no previous file with comments | « remoting/host/linux/x11_character_injector.cc ('k') | remoting/host/linux/x11_keyboard.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <unordered_map>
8
9 #include "base/memory/ptr_util.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "remoting/host/linux/x11_keyboard.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace {
17 const base::TimeDelta kKeycodeReuseDuration =
Sergey Ulanov 2016/10/03 17:41:56 Please use constexpr for TimeDelta consts. indenta
Yuwei 2016/10/03 21:17:47 Done.
18 base::TimeDelta::FromMilliseconds(100);
19 }
20
21 namespace remoting {
22
23 // This class acts as a simulated keyboard interface for testing that
24 // * Maintains a changeable simulated keyboard layout.
25 // * Verifies the correct sequence of characters are being typed.
26 // * Ensures that a key mapping can't be changed if the time elapsed since
27 // last used is less than |kKeycodeReuseDuration|.
28 class FakeX11Keyboard : public X11Keyboard {
29 public:
30 struct MappingInfo {
31 uint32_t code_point;
32 base::TimeTicks reusable_at;
33 };
34
35 explicit FakeX11Keyboard(const std::vector<uint32_t>& available_keycodes);
36 ~FakeX11Keyboard() override;
37
38 // X11Keyboard overrides.
39 std::vector<uint32_t> GetUnusedKeycodes() override;
40
41 void PressKey(uint32_t keycode, uint32_t modifiers) override;
42 bool FindKeycode(uint32_t code_point,
43 uint32_t* keycode,
44 uint32_t* modifiers) override;
45 bool ChangeKeyMapping(uint32_t keycode, uint32_t code_point) override;
46 void Flush() override;
47 void Sync() override;
48
49 void ExpectEnterCodePoints(const std::vector<uint32_t>& sequence);
50
51 // Sets a callback to be called when the keypress expectation queue becomes
52 // empty.
53 void SetKeyPressFinishedCallback(const base::Closure& callback) {
54 keypress_finished_callback_ = callback;
55 }
56
57 private:
58 std::unordered_map<uint32_t, MappingInfo> keycode_mapping_;
59 std::deque<uint32_t> expected_code_point_sequence_;
60 base::Closure keypress_finished_callback_;
61 };
62
63 FakeX11Keyboard::FakeX11Keyboard(
64 const std::vector<uint32_t>& available_keycodes) {
65 for (uint32_t keycode : available_keycodes) {
66 keycode_mapping_.insert({keycode, {0, base::TimeTicks()}});
67 }
68 }
69
70 FakeX11Keyboard::~FakeX11Keyboard() {
71 DCHECK(expected_code_point_sequence_.empty());
Sergey Ulanov 2016/10/03 17:41:56 EXPECT_TRUE()
Yuwei 2016/10/03 21:17:47 Done.
72 for (const auto& pair : keycode_mapping_) {
73 EXPECT_EQ(0u, pair.second.code_point);
74 }
75 }
76
77 std::vector<uint32_t> FakeX11Keyboard::GetUnusedKeycodes() {
78 std::vector<uint32_t> keycodes;
79 for (const auto& pair : keycode_mapping_) {
80 if (!pair.second.code_point) {
81 keycodes.push_back(pair.first);
82 }
83 }
84 return keycodes;
85 }
86
87 void FakeX11Keyboard::PressKey(uint32_t keycode, uint32_t modifiers) {
88 ASSERT_FALSE(expected_code_point_sequence_.empty());
89 uint32_t expected_code_point = expected_code_point_sequence_.front();
90 auto position = keycode_mapping_.find(keycode);
91 ASSERT_NE(position, keycode_mapping_.end());
92 MappingInfo& info = position->second;
93 EXPECT_EQ(expected_code_point, info.code_point);
94 info.reusable_at = base::TimeTicks::Now() + kKeycodeReuseDuration;
95 expected_code_point_sequence_.pop_front();
96 if (expected_code_point_sequence_.empty() && keypress_finished_callback_) {
97 keypress_finished_callback_.Run();
98 }
99 }
100
101 bool FakeX11Keyboard::FindKeycode(uint32_t code_point,
102 uint32_t* keycode,
103 uint32_t* modifiers) {
104 auto position = std::find_if(keycode_mapping_.begin(), keycode_mapping_.end(),
105 [code_point](const std::pair<uint32_t, MappingInfo>& pair) {
106 return pair.second.code_point == code_point;
107 });
108 if (position == keycode_mapping_.end()) {
109 return false;
110 }
111 *keycode = position->first;
112 *modifiers = 0;
113 return true;
114 }
115
116 bool FakeX11Keyboard::ChangeKeyMapping(uint32_t keycode, uint32_t code_point) {
117 MappingInfo& info = keycode_mapping_[keycode];
118 info.code_point = code_point;
119 if (code_point) {
120 base::TimeTicks now = base::TimeTicks::Now();
121 EXPECT_LE(info.reusable_at, now)
122 << "Attempted to reuse a keycode in less than "
123 << kKeycodeReuseDuration;
124 info.reusable_at = now + kKeycodeReuseDuration;
125 } else {
126 info.reusable_at = base::TimeTicks();
127 }
128 return true;
129 }
130
131 void FakeX11Keyboard::Flush() {}
132
133 void FakeX11Keyboard::Sync() {}
134
135 void FakeX11Keyboard::ExpectEnterCodePoints(
136 const std::vector<uint32_t>& sequence) {
137 expected_code_point_sequence_.insert(expected_code_point_sequence_.end(),
138 sequence.begin(), sequence.end());
139 }
140
141 class X11CharacterInjectorTest : public testing::Test {
142 public:
143 void SetUp() override;
144 void TearDown() override;
145
146 protected:
147 // Injects the characters sequentially, verifies the sequence of characters
148 // being injected are correct, and runs the message loop until all
149 // characters are injected.
150 void InjectAndRun(const std::vector<uint32_t>& code_points);
151
152 std::unique_ptr<X11CharacterInjector> injector_;
153 FakeX11Keyboard* keyboard_; // Owned by |injector_|.
154
155 base::MessageLoop message_loop_;
156 };
157
158 void X11CharacterInjectorTest::SetUp() {
159 keyboard_ = new FakeX11Keyboard({55, 54, 53, 52, 51});
160 injector_.reset(new X11CharacterInjector(base::WrapUnique(keyboard_)));
161 }
162
163 void X11CharacterInjectorTest::TearDown() {
164 injector_.reset();
165 }
166
167 void X11CharacterInjectorTest::InjectAndRun(
168 const std::vector<uint32_t>& code_points) {
169 base::RunLoop run_loop;
170 keyboard_->SetKeyPressFinishedCallback(run_loop.QuitClosure());
171 std::for_each(code_points.begin(), code_points.end(),
172 std::bind(&X11CharacterInjector::Inject, injector_.get(),
173 std::placeholders::_1));
174 keyboard_->ExpectEnterCodePoints(code_points);
175 run_loop.Run();
176 }
177
178 TEST_F(X11CharacterInjectorTest, TestNoMappingNoExpectation) {
179 }
180
181 TEST_F(X11CharacterInjectorTest, TestTypeOneCharacter) {
182 InjectAndRun({123});
183 }
184
185 TEST_F(X11CharacterInjectorTest, TestMapCharactersUntilFull) {
186 InjectAndRun({1, 2, 3, 4, 5});
187 }
188
189 TEST_F(X11CharacterInjectorTest, TestMapOneCharacterWhenFull) {
190 InjectAndRun({1, 2, 3, 4, 5, 6});
191 }
192
193 TEST_F(X11CharacterInjectorTest, TestReuseMappedCharacterOnce) {
194 InjectAndRun({1, 2, 3, 4, 5});
195 InjectAndRun({1, 6});
196 }
197
198 TEST_F(X11CharacterInjectorTest, TestReuseAllMappedCharactersInChangedOrder) {
199 InjectAndRun({1, 2, 3, 4, 5});
200 InjectAndRun({2, 4, 5, 1, 3});
201 InjectAndRun({31, 32, 33, 34, 35});
202 }
203
204 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/linux/x11_character_injector.cc ('k') | remoting/host/linux/x11_keyboard.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698