Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
plugin_registrar_windows_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
5#include <memory>
6#include <string>
7
10#include "gmock/gmock.h"
11#include "gtest/gtest.h"
12
13namespace flutter {
14
15namespace {
16
17using ::testing::Return;
18
19// Stub implementation to validate calls to the API.
20class TestWindowsApi : public testing::StubFlutterWindowsApi {
21 public:
22 void PluginRegistrarRegisterTopLevelWindowProcDelegate(
24 void* user_data) override {
25 ++registered_delegate_count_;
26 last_registered_delegate_ = delegate;
27 last_registered_user_data_ = user_data;
28 }
29
30 MOCK_METHOD(FlutterDesktopViewRef, PluginRegistrarGetView, (), (override));
31 MOCK_METHOD(FlutterDesktopViewRef,
32 PluginRegistrarGetViewById,
34 (override));
35
36 void PluginRegistrarUnregisterTopLevelWindowProcDelegate(
37 FlutterDesktopWindowProcCallback delegate) override {
38 --registered_delegate_count_;
39 }
40
41 int registered_delegate_count() { return registered_delegate_count_; }
42
43 FlutterDesktopWindowProcCallback last_registered_delegate() {
44 return last_registered_delegate_;
45 }
46
47 void* last_registered_user_data() { return last_registered_user_data_; }
48
49 bool PluginRegistrarGetGraphicsAdapter(IDXGIAdapter** adapter_out) override {
50 *adapter_out = reinterpret_cast<IDXGIAdapter*>(10);
51 return true;
52 }
53
54 private:
55 int registered_delegate_count_ = 0;
56 FlutterDesktopWindowProcCallback last_registered_delegate_ = nullptr;
57 void* last_registered_user_data_ = nullptr;
58};
59
60// A test plugin that tries to access registrar state during destruction and
61// reports it out via a flag provided at construction.
62class TestPlugin : public Plugin {
63 public:
64 // registrar_valid_at_destruction will be set at destruction to indicate
65 // whether or not |registrar->GetView()| was non-null.
66 TestPlugin(PluginRegistrarWindows* registrar,
67 bool* registrar_valid_at_destruction)
68 : registrar_(registrar),
69 registrar_valid_at_destruction_(registrar_valid_at_destruction) {}
70 virtual ~TestPlugin() {
71 *registrar_valid_at_destruction_ = registrar_->GetView() != nullptr;
72 }
73
74 private:
75 PluginRegistrarWindows* registrar_;
76 bool* registrar_valid_at_destruction_;
77};
78
79} // namespace
80
81TEST(PluginRegistrarWindowsTest, GetView) {
82 auto windows_api = std::make_unique<TestWindowsApi>();
83 EXPECT_CALL(*windows_api, PluginRegistrarGetView)
84 .WillOnce(Return(reinterpret_cast<FlutterDesktopViewRef>(1)));
85
86 testing::ScopedStubFlutterWindowsApi scoped_api_stub(std::move(windows_api));
87 auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
88 PluginRegistrarWindows registrar(
89 reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1));
90
91 EXPECT_NE(registrar.GetView(), nullptr);
92}
93
94TEST(PluginRegistrarWindowsTest, GetViewById) {
95 auto windows_api = std::make_unique<TestWindowsApi>();
96 EXPECT_CALL(*windows_api, PluginRegistrarGetView)
97 .WillRepeatedly(Return(nullptr));
98 EXPECT_CALL(*windows_api, PluginRegistrarGetViewById(123))
99 .WillOnce(Return(reinterpret_cast<FlutterDesktopViewRef>(1)));
100 EXPECT_CALL(*windows_api, PluginRegistrarGetViewById(456))
101 .WillOnce(Return(nullptr));
102
103 testing::ScopedStubFlutterWindowsApi scoped_api_stub(std::move(windows_api));
104 auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
105 PluginRegistrarWindows registrar(
106 reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1));
107
108 EXPECT_EQ(registrar.GetView(), nullptr);
109 EXPECT_NE(registrar.GetViewById(123).get(), nullptr);
110 EXPECT_EQ(registrar.GetViewById(456).get(), nullptr);
111}
112
113TEST(PluginRegistrarWindowsTest, GetGraphicsAdapter) {
114 auto windows_api = std::make_unique<TestWindowsApi>();
115 EXPECT_CALL(*windows_api, PluginRegistrarGetView)
116 .WillRepeatedly(Return(nullptr));
117 testing::ScopedStubFlutterWindowsApi scoped_api_stub(std::move(windows_api));
118 auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
119 PluginRegistrarWindows registrar(
120 reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1));
121 IDXGIAdapter* adapter = nullptr;
122 EXPECT_TRUE(registrar.GetGraphicsAdapter(&adapter));
123 EXPECT_EQ(adapter, reinterpret_cast<IDXGIAdapter*>(10));
124}
125
126// Tests that the registrar runs plugin destructors before its own teardown.
127TEST(PluginRegistrarWindowsTest, PluginDestroyedBeforeRegistrar) {
128 auto windows_api = std::make_unique<TestWindowsApi>();
129 EXPECT_CALL(*windows_api, PluginRegistrarGetView)
130 .WillRepeatedly(Return(reinterpret_cast<FlutterDesktopViewRef>(1)));
131 testing::ScopedStubFlutterWindowsApi scoped_api_stub(std::move(windows_api));
132 auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
133 PluginRegistrarWindows registrar(
134 reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1));
135
136 auto dummy_registrar_handle =
137 reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1);
138 bool registrar_valid_at_destruction = false;
139 {
140 PluginRegistrarWindows registrar(dummy_registrar_handle);
141
142 auto plugin = std::make_unique<TestPlugin>(&registrar,
143 &registrar_valid_at_destruction);
144 registrar.AddPlugin(std::move(plugin));
145 }
146 EXPECT_TRUE(registrar_valid_at_destruction);
147}
148
149TEST(PluginRegistrarWindowsTest, RegisterUnregister) {
150 auto windows_api = std::make_unique<TestWindowsApi>();
151 EXPECT_CALL(*windows_api, PluginRegistrarGetView).WillOnce(Return(nullptr));
152 testing::ScopedStubFlutterWindowsApi scoped_api_stub(std::move(windows_api));
153 auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
154 PluginRegistrarWindows registrar(
155 reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1));
156
157 WindowProcDelegate delegate = [](HWND hwnd, UINT message, WPARAM wparam,
158 LPARAM lparam) {
159 return std::optional<LRESULT>();
160 };
161 int id_a = registrar.RegisterTopLevelWindowProcDelegate(delegate);
162 EXPECT_EQ(test_api->registered_delegate_count(), 1);
163 int id_b = registrar.RegisterTopLevelWindowProcDelegate(delegate);
164 // All the C++-level delegates are driven by a since C callback, so the
165 // registration count should stay the same.
166 EXPECT_EQ(test_api->registered_delegate_count(), 1);
167
168 // Unregistering one of the two delegates shouldn't cause the underlying C
169 // callback to be unregistered.
171 EXPECT_EQ(test_api->registered_delegate_count(), 1);
172 // Unregistering both should unregister it.
174 EXPECT_EQ(test_api->registered_delegate_count(), 0);
175
176 EXPECT_NE(id_a, id_b);
177}
178
179TEST(PluginRegistrarWindowsTest, CallsRegisteredDelegates) {
180 auto windows_api = std::make_unique<TestWindowsApi>();
181 EXPECT_CALL(*windows_api, PluginRegistrarGetView).WillOnce(Return(nullptr));
182 testing::ScopedStubFlutterWindowsApi scoped_api_stub(std::move(windows_api));
183 auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
184 PluginRegistrarWindows registrar(
185 reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1));
186
187 HWND dummy_hwnd;
188 bool called_a = false;
189 WindowProcDelegate delegate_a = [&called_a, &dummy_hwnd](
190 HWND hwnd, UINT message, WPARAM wparam,
191 LPARAM lparam) {
192 called_a = true;
193 EXPECT_EQ(hwnd, dummy_hwnd);
194 EXPECT_EQ(message, 2);
195 EXPECT_EQ(wparam, 3);
196 EXPECT_EQ(lparam, 4);
197 return std::optional<LRESULT>();
198 };
199 bool called_b = false;
200 WindowProcDelegate delegate_b = [&called_b](HWND hwnd, UINT message,
201 WPARAM wparam, LPARAM lparam) {
202 called_b = true;
203 return std::optional<LRESULT>();
204 };
205 int id_a = registrar.RegisterTopLevelWindowProcDelegate(delegate_a);
206 int id_b = registrar.RegisterTopLevelWindowProcDelegate(delegate_b);
207
208 LRESULT result = 0;
209 bool handled = test_api->last_registered_delegate()(
210 dummy_hwnd, 2, 3, 4, test_api->last_registered_user_data(), &result);
211 EXPECT_TRUE(called_a);
212 EXPECT_TRUE(called_b);
213 EXPECT_FALSE(handled);
214}
215
216TEST(PluginRegistrarWindowsTest, StopsOnceHandled) {
217 auto windows_api = std::make_unique<TestWindowsApi>();
218 EXPECT_CALL(*windows_api, PluginRegistrarGetView).WillOnce(Return(nullptr));
219 testing::ScopedStubFlutterWindowsApi scoped_api_stub(std::move(windows_api));
220 auto test_api = static_cast<TestWindowsApi*>(scoped_api_stub.stub());
221 PluginRegistrarWindows registrar(
222 reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1));
223
224 bool called_a = false;
225 WindowProcDelegate delegate_a = [&called_a](HWND hwnd, UINT message,
226 WPARAM wparam, LPARAM lparam) {
227 called_a = true;
228 return std::optional<LRESULT>(7);
229 };
230 bool called_b = false;
231 WindowProcDelegate delegate_b = [&called_b](HWND hwnd, UINT message,
232 WPARAM wparam, LPARAM lparam) {
233 called_b = true;
234 return std::optional<LRESULT>(7);
235 };
236 int id_a = registrar.RegisterTopLevelWindowProcDelegate(delegate_a);
237 int id_b = registrar.RegisterTopLevelWindowProcDelegate(delegate_b);
238
239 HWND dummy_hwnd;
240 LRESULT result = 0;
241 bool handled = test_api->last_registered_delegate()(
242 dummy_hwnd, 2, 3, 4, test_api->last_registered_user_data(), &result);
243 // Only one of the delegates should have been called, since each claims to
244 // have fully handled the message.
245 EXPECT_TRUE(called_a || called_b);
246 EXPECT_NE(called_a, called_b);
247 // The return value should propagate through.
248 EXPECT_TRUE(handled);
249 EXPECT_EQ(result, 7);
250}
251
252} // namespace flutter
void AddPlugin(std::unique_ptr< Plugin > plugin)
bool GetGraphicsAdapter(IDXGIAdapter **adapter_out)
int RegisterTopLevelWindowProcDelegate(WindowProcDelegate delegate)
std::shared_ptr< FlutterView > GetViewById(FlutterViewId view_id) const
const char * message
bool(* FlutterDesktopWindowProcCallback)(HWND, UINT, WPARAM, LPARAM, void *, LRESULT *result)
int64_t FlutterDesktopViewId
struct FlutterDesktopView * FlutterDesktopViewRef
TEST(FrameTimingsRecorderTest, RecordVsync)
std::function< std::optional< LRESULT >(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)> WindowProcDelegate
LONG_PTR LRESULT
unsigned int UINT
LONG_PTR LPARAM
UINT_PTR WPARAM