| Flutter Windows Embedder |

cursor_handler_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 #include "flutter/shell/platform/windows/cursor_handler.h"
5
6 #include <memory>
7 #include <vector>
8
9 #include "flutter/fml/macros.h"
10 #include "flutter/shell/platform/common/client_wrapper/include/flutter/method_result_functions.h"
11 #include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_message_codec.h"
12 #include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_method_codec.h"
13 #include "flutter/shell/platform/windows/flutter_windows_view.h"
14 #include "flutter/shell/platform/windows/testing/engine_modifier.h"
15 #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h"
16 #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
17 #include "flutter/shell/platform/windows/testing/mock_windows_proc_table.h"
18 #include "flutter/shell/platform/windows/testing/test_binary_messenger.h"
19 #include "flutter/shell/platform/windows/testing/windows_test.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22
23 namespace flutter {
24 namespace testing {
25
26 namespace {
27 using ::testing::_;
28 using ::testing::IsNull;
29 using ::testing::NotNull;
30 using ::testing::Return;
31
32 static constexpr char kChannelName[] = "flutter/mousecursor";
33
34 static constexpr char kActivateSystemCursorMethod[] = "activateSystemCursor";
35 static constexpr char kCreateCustomCursorMethod[] =
36 "createCustomCursor/windows";
37 static constexpr char kSetCustomCursorMethod[] = "setCustomCursor/windows";
38 static constexpr char kDeleteCustomCursorMethod[] =
39 "deleteCustomCursor/windows";
40
41 void SimulateCursorMessage(TestBinaryMessenger* messenger,
42 const std::string& method_name,
43 std::unique_ptr<EncodableValue> arguments,
44 MethodResult<EncodableValue>* result_handler) {
45 MethodCall<> call(method_name, std::move(arguments));
46
47 auto message = StandardMethodCodec::GetInstance().EncodeMethodCall(call);
48
49 EXPECT_TRUE(messenger->SimulateEngineMessage(
50 kChannelName, message->data(), message->size(),
51 [&result_handler](const uint8_t* reply, size_t reply_size) {
52 StandardMethodCodec::GetInstance().DecodeAndProcessResponseEnvelope(
53 reply, reply_size, result_handler);
54 }));
55 }
56
57 } // namespace
58
59 class CursorHandlerTest : public WindowsTest {
60 public:
61 CursorHandlerTest() = default;
62 virtual ~CursorHandlerTest() = default;
63
64 protected:
65 FlutterWindowsEngine* engine() { return engine_.get(); }
66 FlutterWindowsView* view() { return view_.get(); }
67 MockWindowBindingHandler* window() { return window_; }
68 MockWindowsProcTable* proc_table() { return windows_proc_table_.get(); }
69
70 void UseHeadlessEngine() {
71 FlutterWindowsEngineBuilder builder{GetContext()};
72
73 engine_ = builder.Build();
74 }
75
76 void UseEngineWithView() {
77 windows_proc_table_ = std::make_shared<MockWindowsProcTable>();
78
79 FlutterWindowsEngineBuilder builder{GetContext()};
80 builder.SetWindowsProcTable(windows_proc_table_);
81
82 auto window = std::make_unique<MockWindowBindingHandler>();
83 EXPECT_CALL(*window.get(), SetView).Times(1);
84 EXPECT_CALL(*window.get(), GetWindowHandle).WillRepeatedly(Return(nullptr));
85
86 window_ = window.get();
87 engine_ = builder.Build();
88 view_ =
89 engine_->CreateView(std::move(window),
90 /*is_sized_to_content=*/false, BoxConstraints());
91 }
92
93 private:
94 std::unique_ptr<FlutterWindowsEngine> engine_;
95 std::unique_ptr<FlutterWindowsView> view_;
96 MockWindowBindingHandler* window_;
97 std::shared_ptr<MockWindowsProcTable> windows_proc_table_;
98
99 FML_DISALLOW_COPY_AND_ASSIGN(CursorHandlerTest);
100 };
101
102 TEST_F(CursorHandlerTest, ActivateSystemCursor) {
103 UseEngineWithView();
104
105 TestBinaryMessenger messenger;
106 CursorHandler cursor_handler(&messenger, engine());
107
108 EXPECT_CALL(*proc_table(), LoadCursor(IsNull(), IDC_HAND)).Times(1);
109 EXPECT_CALL(*proc_table(), SetCursor).Times(1);
110
111 bool success = false;
112 MethodResultFunctions<> result_handler(
113 [&success](const EncodableValue* result) {
114 success = true;
115 EXPECT_EQ(result, nullptr);
116 },
117 nullptr, nullptr);
118
119 SimulateCursorMessage(&messenger, kActivateSystemCursorMethod,
120 std::make_unique<EncodableValue>(EncodableMap{
121 {EncodableValue("device"), EncodableValue(0)},
122 {EncodableValue("kind"), EncodableValue("click")},
123 }),
124 &result_handler);
125
126 EXPECT_TRUE(success);
127 }
128
129 TEST_F(CursorHandlerTest, CreateCustomCursor) {
130 UseEngineWithView();
131
132 TestBinaryMessenger messenger;
133 CursorHandler cursor_handler(&messenger, engine());
134
135 // Create a 4x4 raw BGRA test cursor buffer.
136 std::vector<uint8_t> buffer(4 * 4 * 4, 0);
137
138 bool success = false;
139 MethodResultFunctions<> result_handler(
140 [&success](const EncodableValue* result) {
141 success = true;
142 EXPECT_EQ(std::get<std::string>(*result), "hello");
143 },
144 nullptr, nullptr);
145
146 SimulateCursorMessage(&messenger, kCreateCustomCursorMethod,
147 std::make_unique<EncodableValue>(EncodableMap{
148 {EncodableValue("name"), EncodableValue("hello")},
149 {EncodableValue("buffer"), EncodableValue(buffer)},
150 {EncodableValue("width"), EncodableValue(4)},
151 {EncodableValue("height"), EncodableValue(4)},
152 {EncodableValue("hotX"), EncodableValue(0.0)},
153 {EncodableValue("hotY"), EncodableValue(0.0)},
154 }),
155 &result_handler);
156
157 EXPECT_TRUE(success);
158 }
159
160 TEST_F(CursorHandlerTest, SetCustomCursor) {
161 UseEngineWithView();
162
163 TestBinaryMessenger messenger;
164 CursorHandler cursor_handler(&messenger, engine());
165
166 // Create a 4x4 raw BGRA test cursor buffer.
167 std::vector<uint8_t> buffer(4 * 4 * 4, 0);
168
169 bool success = false;
170 MethodResultFunctions<> create_result_handler(nullptr, nullptr, nullptr);
171 MethodResultFunctions<> set_result_handler(
172 [&success](const EncodableValue* result) {
173 success = true;
174 EXPECT_EQ(result, nullptr);
175 },
176 nullptr, nullptr);
177
178 EXPECT_CALL(*proc_table(), LoadCursor).Times(0);
179 EXPECT_CALL(*proc_table(), SetCursor(NotNull())).Times(1);
180
181 SimulateCursorMessage(&messenger, kCreateCustomCursorMethod,
182 std::make_unique<EncodableValue>(EncodableMap{
183 {EncodableValue("name"), EncodableValue("hello")},
184 {EncodableValue("buffer"), EncodableValue(buffer)},
185 {EncodableValue("width"), EncodableValue(4)},
186 {EncodableValue("height"), EncodableValue(4)},
187 {EncodableValue("hotX"), EncodableValue(0.0)},
188 {EncodableValue("hotY"), EncodableValue(0.0)},
189 }),
190 &create_result_handler);
191
192 SimulateCursorMessage(&messenger, kSetCustomCursorMethod,
193 std::make_unique<EncodableValue>(EncodableMap{
194 {EncodableValue("name"), EncodableValue("hello")},
195 }),
196 &set_result_handler);
197
198 EXPECT_TRUE(success);
199 }
200
201 TEST_F(CursorHandlerTest, SetNonexistentCustomCursor) {
202 UseEngineWithView();
203
204 TestBinaryMessenger messenger;
205 CursorHandler cursor_handler(&messenger, engine());
206
207 bool error = false;
208 MethodResultFunctions<> result_handler(
209 nullptr,
210 [&error](const std::string& error_code, const std::string& error_message,
211 const EncodableValue* value) {
212 error = true;
213 EXPECT_EQ(
214 error_message,
215 "The custom cursor identified by the argument key cannot be found");
216 },
217 nullptr);
218
219 EXPECT_CALL(*proc_table(), LoadCursor).Times(0);
220 EXPECT_CALL(*proc_table(), SetCursor).Times(0);
221
222 SimulateCursorMessage(&messenger, kSetCustomCursorMethod,
223 std::make_unique<EncodableValue>(EncodableMap{
224 {EncodableValue("name"), EncodableValue("hello")},
225 }),
226 &result_handler);
227
228 EXPECT_TRUE(error);
229 }
230
231 TEST_F(CursorHandlerTest, DeleteCustomCursor) {
232 UseEngineWithView();
233
234 TestBinaryMessenger messenger;
235 CursorHandler cursor_handler(&messenger, engine());
236
237 // Create a 4x4 raw BGRA test cursor buffer.
238 std::vector<uint8_t> buffer(4 * 4 * 4, 0);
239
240 bool success = false;
241 MethodResultFunctions<> create_result_handler(nullptr, nullptr, nullptr);
242 MethodResultFunctions<> delete_result_handler(
243 [&success](const EncodableValue* result) {
244 success = true;
245 EXPECT_EQ(result, nullptr);
246 },
247 nullptr, nullptr);
248
249 SimulateCursorMessage(&messenger, kCreateCustomCursorMethod,
250 std::make_unique<EncodableValue>(EncodableMap{
251 {EncodableValue("name"), EncodableValue("hello")},
252 {EncodableValue("buffer"), EncodableValue(buffer)},
253 {EncodableValue("width"), EncodableValue(4)},
254 {EncodableValue("height"), EncodableValue(4)},
255 {EncodableValue("hotX"), EncodableValue(0.0)},
256 {EncodableValue("hotY"), EncodableValue(0.0)},
257 }),
258 &create_result_handler);
259
260 SimulateCursorMessage(&messenger, kDeleteCustomCursorMethod,
261 std::make_unique<EncodableValue>(EncodableMap{
262 {EncodableValue("name"), EncodableValue("hello")},
263 }),
264 &delete_result_handler);
265
266 EXPECT_TRUE(success);
267 }
268
269 TEST_F(CursorHandlerTest, DeleteNonexistentCustomCursor) {
270 UseEngineWithView();
271
272 TestBinaryMessenger messenger;
273 CursorHandler cursor_handler(&messenger, engine());
274
275 bool success = false;
276 MethodResultFunctions<> result_handler(
277 [&success](const EncodableValue* result) {
278 success = true;
279 EXPECT_EQ(result, nullptr);
280 },
281 nullptr, nullptr);
282
283 SimulateCursorMessage(&messenger, kDeleteCustomCursorMethod,
284 std::make_unique<EncodableValue>(EncodableMap{
285 {EncodableValue("name"), EncodableValue("fake")},
286 }),
287 &result_handler);
288
289 EXPECT_TRUE(success);
290 }
291
292 } // namespace testing
293 } // namespace flutter
flutter::CursorHandler
Definition: cursor_handler.h:22
flutter::EncodableValue
Definition: encodable_value.h:166
flutter::FlutterWindowsEngine
Definition: flutter_windows_engine.h:92
flutter::FlutterWindowsView
Definition: flutter_windows_view.h:47
flutter::MethodCodec::EncodeMethodCall
std::unique_ptr< std::vector< uint8_t > > EncodeMethodCall(const MethodCall< T > &method_call) const
Definition: method_codec.h:48
flutter::MethodResultFunctions
Definition: method_result_functions.h:31
flutter::StandardMethodCodec::GetInstance
static const StandardMethodCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
Definition: standard_codec.cc:341
flutter::testing::CursorHandlerTest
Definition: cursor_handler_unittests.cc:59
flutter::testing::CursorHandlerTest::UseHeadlessEngine
void UseHeadlessEngine()
Definition: cursor_handler_unittests.cc:70
flutter::testing::CursorHandlerTest::UseEngineWithView
void UseEngineWithView()
Definition: cursor_handler_unittests.cc:76
flutter::testing::CursorHandlerTest::CursorHandlerTest
CursorHandlerTest()=default
flutter::testing::CursorHandlerTest::window
MockWindowBindingHandler * window()
Definition: cursor_handler_unittests.cc:67
flutter::testing::CursorHandlerTest::view
FlutterWindowsView * view()
Definition: cursor_handler_unittests.cc:66
flutter::testing::CursorHandlerTest::engine
FlutterWindowsEngine * engine()
Definition: cursor_handler_unittests.cc:65
flutter::testing::CursorHandlerTest::~CursorHandlerTest
virtual ~CursorHandlerTest()=default
flutter::testing::CursorHandlerTest::proc_table
MockWindowsProcTable * proc_table()
Definition: cursor_handler_unittests.cc:68
kDeleteCustomCursorMethod
static constexpr char kDeleteCustomCursorMethod[]
Definition: cursor_handler.cc:41
kActivateSystemCursorMethod
static constexpr char kActivateSystemCursorMethod[]
Definition: cursor_handler.cc:14
kChannelName
static constexpr char kChannelName[]
Definition: cursor_handler.cc:12
kCreateCustomCursorMethod
static constexpr char kCreateCustomCursorMethod[]
Definition: cursor_handler.cc:19
kSetCustomCursorMethod
static constexpr char kSetCustomCursorMethod[]
Definition: cursor_handler.cc:37
cursor_handler.h
flutter_windows_view.h
message
Win32Message message
Definition: keyboard_unittests.cc:137
method_result_functions.h
flutter::testing::TEST_F
TEST_F(AccessibilityPluginTest, DirectAnnounceCall)
Definition: accessibility_plugin_unittests.cc:102
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::EncodableMap
std::map< EncodableValue, EncodableValue > EncodableMap
Definition: encodable_value.h:96
standard_message_codec.h
standard_method_codec.h