| 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_ = engine_->CreateView(std::move(window));
89 }
90
91 private:
92 std::unique_ptr<FlutterWindowsEngine> engine_;
93 std::unique_ptr<FlutterWindowsView> view_;
94 MockWindowBindingHandler* window_;
95 std::shared_ptr<MockWindowsProcTable> windows_proc_table_;
96
97 FML_DISALLOW_COPY_AND_ASSIGN(CursorHandlerTest);
98 };
99
100 TEST_F(CursorHandlerTest, ActivateSystemCursor) {
101 UseEngineWithView();
102
103 TestBinaryMessenger messenger;
104 CursorHandler cursor_handler(&messenger, engine());
105
106 EXPECT_CALL(*proc_table(), LoadCursor(IsNull(), IDC_HAND)).Times(1);
107 EXPECT_CALL(*proc_table(), SetCursor).Times(1);
108
109 bool success = false;
110 MethodResultFunctions<> result_handler(
111 [&success](const EncodableValue* result) {
112 success = true;
113 EXPECT_EQ(result, nullptr);
114 },
115 nullptr, nullptr);
116
117 SimulateCursorMessage(&messenger, kActivateSystemCursorMethod,
118 std::make_unique<EncodableValue>(EncodableMap{
119 {EncodableValue("device"), EncodableValue(0)},
120 {EncodableValue("kind"), EncodableValue("click")},
121 }),
122 &result_handler);
123
124 EXPECT_TRUE(success);
125 }
126
127 TEST_F(CursorHandlerTest, CreateCustomCursor) {
128 UseEngineWithView();
129
130 TestBinaryMessenger messenger;
131 CursorHandler cursor_handler(&messenger, engine());
132
133 // Create a 4x4 raw BGRA test cursor buffer.
134 std::vector<uint8_t> buffer(4 * 4 * 4, 0);
135
136 bool success = false;
137 MethodResultFunctions<> result_handler(
138 [&success](const EncodableValue* result) {
139 success = true;
140 EXPECT_EQ(std::get<std::string>(*result), "hello");
141 },
142 nullptr, nullptr);
143
144 SimulateCursorMessage(&messenger, kCreateCustomCursorMethod,
145 std::make_unique<EncodableValue>(EncodableMap{
146 {EncodableValue("name"), EncodableValue("hello")},
147 {EncodableValue("buffer"), EncodableValue(buffer)},
148 {EncodableValue("width"), EncodableValue(4)},
149 {EncodableValue("height"), EncodableValue(4)},
150 {EncodableValue("hotX"), EncodableValue(0.0)},
151 {EncodableValue("hotY"), EncodableValue(0.0)},
152 }),
153 &result_handler);
154
155 EXPECT_TRUE(success);
156 }
157
158 TEST_F(CursorHandlerTest, SetCustomCursor) {
159 UseEngineWithView();
160
161 TestBinaryMessenger messenger;
162 CursorHandler cursor_handler(&messenger, engine());
163
164 // Create a 4x4 raw BGRA test cursor buffer.
165 std::vector<uint8_t> buffer(4 * 4 * 4, 0);
166
167 bool success = false;
168 MethodResultFunctions<> create_result_handler(nullptr, nullptr, nullptr);
169 MethodResultFunctions<> set_result_handler(
170 [&success](const EncodableValue* result) {
171 success = true;
172 EXPECT_EQ(result, nullptr);
173 },
174 nullptr, nullptr);
175
176 EXPECT_CALL(*proc_table(), LoadCursor).Times(0);
177 EXPECT_CALL(*proc_table(), SetCursor(NotNull())).Times(1);
178
179 SimulateCursorMessage(&messenger, kCreateCustomCursorMethod,
180 std::make_unique<EncodableValue>(EncodableMap{
181 {EncodableValue("name"), EncodableValue("hello")},
182 {EncodableValue("buffer"), EncodableValue(buffer)},
183 {EncodableValue("width"), EncodableValue(4)},
184 {EncodableValue("height"), EncodableValue(4)},
185 {EncodableValue("hotX"), EncodableValue(0.0)},
186 {EncodableValue("hotY"), EncodableValue(0.0)},
187 }),
188 &create_result_handler);
189
190 SimulateCursorMessage(&messenger, kSetCustomCursorMethod,
191 std::make_unique<EncodableValue>(EncodableMap{
192 {EncodableValue("name"), EncodableValue("hello")},
193 }),
194 &set_result_handler);
195
196 EXPECT_TRUE(success);
197 }
198
199 TEST_F(CursorHandlerTest, SetNonexistentCustomCursor) {
200 UseEngineWithView();
201
202 TestBinaryMessenger messenger;
203 CursorHandler cursor_handler(&messenger, engine());
204
205 bool error = false;
206 MethodResultFunctions<> result_handler(
207 nullptr,
208 [&error](const std::string& error_code, const std::string& error_message,
209 const EncodableValue* value) {
210 error = true;
211 EXPECT_EQ(
212 error_message,
213 "The custom cursor identified by the argument key cannot be found");
214 },
215 nullptr);
216
217 EXPECT_CALL(*proc_table(), LoadCursor).Times(0);
218 EXPECT_CALL(*proc_table(), SetCursor).Times(0);
219
220 SimulateCursorMessage(&messenger, kSetCustomCursorMethod,
221 std::make_unique<EncodableValue>(EncodableMap{
222 {EncodableValue("name"), EncodableValue("hello")},
223 }),
224 &result_handler);
225
226 EXPECT_TRUE(error);
227 }
228
229 TEST_F(CursorHandlerTest, DeleteCustomCursor) {
230 UseEngineWithView();
231
232 TestBinaryMessenger messenger;
233 CursorHandler cursor_handler(&messenger, engine());
234
235 // Create a 4x4 raw BGRA test cursor buffer.
236 std::vector<uint8_t> buffer(4 * 4 * 4, 0);
237
238 bool success = false;
239 MethodResultFunctions<> create_result_handler(nullptr, nullptr, nullptr);
240 MethodResultFunctions<> delete_result_handler(
241 [&success](const EncodableValue* result) {
242 success = true;
243 EXPECT_EQ(result, nullptr);
244 },
245 nullptr, nullptr);
246
247 SimulateCursorMessage(&messenger, kCreateCustomCursorMethod,
248 std::make_unique<EncodableValue>(EncodableMap{
249 {EncodableValue("name"), EncodableValue("hello")},
250 {EncodableValue("buffer"), EncodableValue(buffer)},
251 {EncodableValue("width"), EncodableValue(4)},
252 {EncodableValue("height"), EncodableValue(4)},
253 {EncodableValue("hotX"), EncodableValue(0.0)},
254 {EncodableValue("hotY"), EncodableValue(0.0)},
255 }),
256 &create_result_handler);
257
258 SimulateCursorMessage(&messenger, kDeleteCustomCursorMethod,
259 std::make_unique<EncodableValue>(EncodableMap{
260 {EncodableValue("name"), EncodableValue("hello")},
261 }),
262 &delete_result_handler);
263
264 EXPECT_TRUE(success);
265 }
266
267 TEST_F(CursorHandlerTest, DeleteNonexistentCustomCursor) {
268 UseEngineWithView();
269
270 TestBinaryMessenger messenger;
271 CursorHandler cursor_handler(&messenger, engine());
272
273 bool success = false;
274 MethodResultFunctions<> result_handler(
275 [&success](const EncodableValue* result) {
276 success = true;
277 EXPECT_EQ(result, nullptr);
278 },
279 nullptr, nullptr);
280
281 SimulateCursorMessage(&messenger, kDeleteCustomCursorMethod,
282 std::make_unique<EncodableValue>(EncodableMap{
283 {EncodableValue("name"), EncodableValue("fake")},
284 }),
285 &result_handler);
286
287 EXPECT_TRUE(success);
288 }
289
290 } // namespace testing
291 } // 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:34
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:98
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