Flutter Engine
plugin_registrar_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 "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h"
6 
7 #include <memory>
8 #include <vector>
9 
10 #include "flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h"
11 #include "gtest/gtest.h"
12 
13 namespace flutter {
14 
15 namespace {
16 
17 // Stub implementation to validate calls to the API.
18 class TestApi : public testing::StubFlutterApi {
19  public:
20  // |flutter::testing::StubFlutterApi|
21  bool MessengerSend(const char* channel,
22  const uint8_t* message,
23  const size_t message_size) override {
24  last_data_sent_ = message;
25  return message_engine_result;
26  }
27 
28  bool MessengerSendWithReply(const char* channel,
29  const uint8_t* message,
30  const size_t message_size,
31  const FlutterDesktopBinaryReply reply,
32  void* user_data) override {
33  last_data_sent_ = message;
34  return message_engine_result;
35  }
36 
37  void MessengerSetCallback(const char* channel,
39  void* user_data) override {
40  last_message_callback_set_ = callback;
41  }
42 
43  void PluginRegistrarSetDestructionHandler(
44  FlutterDesktopOnPluginRegistrarDestroyed callback) override {
45  last_destruction_callback_set_ = callback;
46  }
47 
48  const uint8_t* last_data_sent() { return last_data_sent_; }
49  FlutterDesktopMessageCallback last_message_callback_set() {
50  return last_message_callback_set_;
51  }
52  FlutterDesktopOnPluginRegistrarDestroyed last_destruction_callback_set() {
53  return last_destruction_callback_set_;
54  }
55 
56  private:
57  const uint8_t* last_data_sent_ = nullptr;
58  FlutterDesktopMessageCallback last_message_callback_set_ = nullptr;
59  FlutterDesktopOnPluginRegistrarDestroyed last_destruction_callback_set_ =
60  nullptr;
61 };
62 
63 // A PluginRegistrar whose destruction can be watched for by tests.
64 class TestPluginRegistrar : public PluginRegistrar {
65  public:
66  explicit TestPluginRegistrar(FlutterDesktopPluginRegistrarRef core_registrar)
67  : PluginRegistrar(core_registrar) {}
68 
69  virtual ~TestPluginRegistrar() {
70  if (destruction_callback_) {
71  destruction_callback_();
72  }
73  }
74 
75  void SetDestructionCallback(std::function<void()> callback) {
76  destruction_callback_ = std::move(callback);
77  }
78 
79  private:
80  std::function<void()> destruction_callback_;
81 };
82 
83 // A test plugin that tries to access registrar state during destruction and
84 // reports it out via a flag provided at construction.
85 class TestPlugin : public Plugin {
86  public:
87  // registrar_valid_at_destruction will be set at destruction to indicate
88  // whether or not |registrar->messenger()| was non-null.
89  TestPlugin(PluginRegistrar* registrar, bool* registrar_valid_at_destruction)
90  : registrar_(registrar),
91  registrar_valid_at_destruction_(registrar_valid_at_destruction) {}
92  virtual ~TestPlugin() {
93  *registrar_valid_at_destruction_ = registrar_->messenger() != nullptr;
94  }
95 
96  private:
97  PluginRegistrar* registrar_;
98  bool* registrar_valid_at_destruction_;
99 };
100 
101 } // namespace
102 
103 // Tests that the registrar runs plugin destructors before its own teardown.
104 TEST(PluginRegistrarTest, PluginDestroyedBeforeRegistrar) {
105  auto dummy_registrar_handle =
106  reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1);
107  bool registrar_valid_at_destruction = false;
108  {
109  PluginRegistrar registrar(dummy_registrar_handle);
110 
111  auto plugin = std::make_unique<TestPlugin>(&registrar,
112  &registrar_valid_at_destruction);
113  registrar.AddPlugin(std::move(plugin));
114  }
115  EXPECT_TRUE(registrar_valid_at_destruction);
116 }
117 
118 // Tests that the registrar returns a messenger that passes Send through to the
119 // C API.
120 TEST(PluginRegistrarTest, MessengerSend) {
121  testing::ScopedStubFlutterApi scoped_api_stub(std::make_unique<TestApi>());
122  auto test_api = static_cast<TestApi*>(scoped_api_stub.stub());
123 
124  auto dummy_registrar_handle =
125  reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1);
126  PluginRegistrar registrar(dummy_registrar_handle);
127  BinaryMessenger* messenger = registrar.messenger();
128 
129  std::vector<uint8_t> message = {1, 2, 3, 4};
130  messenger->Send("some_channel", &message[0], message.size());
131  EXPECT_EQ(test_api->last_data_sent(), &message[0]);
132 }
133 
134 // Tests that the registrar returns a messenger that passes callback
135 // registration and unregistration through to the C API.
136 TEST(PluginRegistrarTest, MessengerSetMessageHandler) {
137  testing::ScopedStubFlutterApi scoped_api_stub(std::make_unique<TestApi>());
138  auto test_api = static_cast<TestApi*>(scoped_api_stub.stub());
139 
140  auto dummy_registrar_handle =
141  reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1);
142  PluginRegistrar registrar(dummy_registrar_handle);
143  BinaryMessenger* messenger = registrar.messenger();
144  const std::string channel_name("foo");
145 
146  // Register.
147  BinaryMessageHandler binary_handler = [](const uint8_t* message,
148  const size_t message_size,
149  BinaryReply reply) {};
150  messenger->SetMessageHandler(channel_name, std::move(binary_handler));
151  EXPECT_NE(test_api->last_message_callback_set(), nullptr);
152 
153  // Unregister.
154  messenger->SetMessageHandler(channel_name, nullptr);
155  EXPECT_EQ(test_api->last_message_callback_set(), nullptr);
156 }
157 
158 // Tests that the registrar manager returns the same instance when getting
159 // the wrapper for the same reference.
160 TEST(PluginRegistrarTest, ManagerSameInstance) {
162  manager->Reset();
163 
164  testing::ScopedStubFlutterApi scoped_api_stub(std::make_unique<TestApi>());
165 
166  auto dummy_registrar_handle =
167  reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1);
168 
169  EXPECT_EQ(manager->GetRegistrar<PluginRegistrar>(dummy_registrar_handle),
170  manager->GetRegistrar<PluginRegistrar>(dummy_registrar_handle));
171 }
172 
173 // Tests that the registrar manager returns different objects for different
174 // references.
175 TEST(PluginRegistrarTest, ManagerDifferentInstances) {
177  manager->Reset();
178 
179  testing::ScopedStubFlutterApi scoped_api_stub(std::make_unique<TestApi>());
180 
181  auto dummy_registrar_handle_a =
182  reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1);
183  auto dummy_registrar_handle_b =
184  reinterpret_cast<FlutterDesktopPluginRegistrarRef>(2);
185 
186  EXPECT_NE(manager->GetRegistrar<PluginRegistrar>(dummy_registrar_handle_a),
187  manager->GetRegistrar<PluginRegistrar>(dummy_registrar_handle_b));
188 }
189 
190 // Tests that the registrar manager deletes wrappers when the underlying
191 // reference is destroyed.
192 TEST(PluginRegistrarTest, ManagerRemovesOnDestruction) {
194  manager->Reset();
195 
196  testing::ScopedStubFlutterApi scoped_api_stub(std::make_unique<TestApi>());
197  auto test_api = static_cast<TestApi*>(scoped_api_stub.stub());
198 
199  auto dummy_registrar_handle =
200  reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1);
201  auto* wrapper =
202  manager->GetRegistrar<TestPluginRegistrar>(dummy_registrar_handle);
203 
204  // Simulate destruction of the reference, and ensure that the wrapper
205  // is destroyed.
206  EXPECT_NE(test_api->last_destruction_callback_set(), nullptr);
207  bool destroyed = false;
208  wrapper->SetDestructionCallback([&destroyed]() { destroyed = true; });
209  test_api->last_destruction_callback_set()(dummy_registrar_handle);
210  EXPECT_EQ(destroyed, true);
211 
212  // Requesting the wrapper should now create a new object.
213  EXPECT_NE(manager->GetRegistrar<TestPluginRegistrar>(dummy_registrar_handle),
214  nullptr);
215 }
216 
217 } // namespace flutter
T * GetRegistrar(FlutterDesktopPluginRegistrarRef registrar_ref)
Dart_NativeFunction function
Definition: fuchsia.cc:51
BinaryMessenger * messenger()
std::function< void(const uint8_t *reply, size_t reply_size)> BinaryReply
G_BEGIN_DECLS FlValue gpointer user_data
static PluginRegistrarManager * GetInstance()
virtual void SetMessageHandler(const std::string &channel, BinaryMessageHandler handler)=0
void(* FlutterDesktopBinaryReply)(const uint8_t *data, size_t data_size, void *user_data)
TEST(DartServiceIsolateTest, CanAddAndRemoveHandles)
void(* FlutterDesktopOnPluginRegistrarDestroyed)(FlutterDesktopPluginRegistrarRef)
virtual void Send(const std::string &channel, const uint8_t *message, size_t message_size, BinaryReply reply=nullptr) const =0
void(* FlutterDesktopMessageCallback)(FlutterDesktopMessengerRef, const FlutterDesktopMessage *, void *)
std::function< void(const uint8_t *message, size_t message_size, BinaryReply reply)> BinaryMessageHandler