xref: /aosp_15_r20/external/cronet/ipc/ipc_channel_proxy_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2014 The Chromium Authors
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 "base/memory/raw_ptr.h"
6 #include "base/memory/raw_ptr_exclusion.h"
7 #include "build/build_config.h"
8 
9 #include <stddef.h>
10 #include <stdint.h>
11 
12 #include <memory>
13 
14 #include "base/message_loop/message_pump_type.h"
15 #include "base/pickle.h"
16 #include "base/run_loop.h"
17 #include "base/task/single_thread_task_runner.h"
18 #include "base/threading/thread.h"
19 #include "ipc/ipc_message.h"
20 #include "ipc/ipc_test_base.h"
21 #include "ipc/message_filter.h"
22 
23 // Get basic type definitions.
24 #define IPC_MESSAGE_IMPL
25 #include "ipc/ipc_channel_proxy_unittest_messages.h"
26 
27 // Generate constructors.
28 #include "ipc/struct_constructor_macros.h"
29 #include "ipc/ipc_channel_proxy_unittest_messages.h"
30 
31 // Generate param traits write methods.
32 #include "ipc/param_traits_write_macros.h"
33 namespace IPC {
34 #include "ipc/ipc_channel_proxy_unittest_messages.h"
35 }  // namespace IPC
36 
37 // Generate param traits read methods.
38 #include "ipc/param_traits_read_macros.h"
39 namespace IPC {
40 #include "ipc/ipc_channel_proxy_unittest_messages.h"
41 }  // namespace IPC
42 
43 // Generate param traits log methods.
44 #include "ipc/param_traits_log_macros.h"
45 namespace IPC {
46 #include "ipc/ipc_channel_proxy_unittest_messages.h"
47 }  // namespace IPC
48 
49 
50 namespace {
51 
CreateRunLoopAndRun(base::RunLoop ** run_loop_ptr)52 void CreateRunLoopAndRun(base::RunLoop** run_loop_ptr) {
53   base::RunLoop run_loop;
54   *run_loop_ptr = &run_loop;
55   run_loop.Run();
56   *run_loop_ptr = nullptr;
57 }
58 
59 class QuitListener : public IPC::Listener {
60  public:
61   QuitListener() = default;
62 
OnMessageReceived(const IPC::Message & message)63   bool OnMessageReceived(const IPC::Message& message) override {
64     IPC_BEGIN_MESSAGE_MAP(QuitListener, message)
65       IPC_MESSAGE_HANDLER(WorkerMsg_Quit, OnQuit)
66       IPC_MESSAGE_HANDLER(TestMsg_BadMessage, OnBadMessage)
67     IPC_END_MESSAGE_MAP()
68     return true;
69   }
70 
OnBadMessageReceived(const IPC::Message & message)71   void OnBadMessageReceived(const IPC::Message& message) override {
72     bad_message_received_ = true;
73   }
74 
OnChannelError()75   void OnChannelError() override { CHECK(quit_message_received_); }
76 
OnQuit()77   void OnQuit() {
78     quit_message_received_ = true;
79     run_loop_->QuitWhenIdle();
80   }
81 
OnBadMessage(const BadType & bad_type)82   void OnBadMessage(const BadType& bad_type) {
83     // Should never be called since IPC wouldn't be deserialized correctly.
84     CHECK(false);
85   }
86 
87   bool bad_message_received_ = false;
88   bool quit_message_received_ = false;
89   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
90   // #constexpr-ctor-field-initializer, #addr-of
91   RAW_PTR_EXCLUSION base::RunLoop* run_loop_ = nullptr;
92 };
93 
94 class ChannelReflectorListener : public IPC::Listener {
95  public:
96   ChannelReflectorListener() = default;
97 
Init(IPC::Channel * channel)98   void Init(IPC::Channel* channel) {
99     DCHECK(!channel_);
100     channel_ = channel;
101   }
102 
OnMessageReceived(const IPC::Message & message)103   bool OnMessageReceived(const IPC::Message& message) override {
104     IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener, message)
105       IPC_MESSAGE_HANDLER(TestMsg_Bounce, OnTestBounce)
106       IPC_MESSAGE_HANDLER(TestMsg_SendBadMessage, OnSendBadMessage)
107       IPC_MESSAGE_HANDLER(AutomationMsg_Bounce, OnAutomationBounce)
108       IPC_MESSAGE_HANDLER(WorkerMsg_Bounce, OnBounce)
109       IPC_MESSAGE_HANDLER(WorkerMsg_Quit, OnQuit)
110     IPC_END_MESSAGE_MAP()
111     return true;
112   }
113 
OnTestBounce()114   void OnTestBounce() {
115     channel_->Send(new TestMsg_Bounce());
116   }
117 
OnSendBadMessage()118   void OnSendBadMessage() {
119     channel_->Send(new TestMsg_BadMessage(BadType()));
120   }
121 
OnAutomationBounce()122   void OnAutomationBounce() { channel_->Send(new AutomationMsg_Bounce()); }
123 
OnBounce()124   void OnBounce() {
125     channel_->Send(new WorkerMsg_Bounce());
126   }
127 
OnQuit()128   void OnQuit() {
129     channel_->Send(new WorkerMsg_Quit());
130     run_loop_->QuitWhenIdle();
131   }
132 
133   // This field is not a raw_ptr<> because it was filtered by the rewriter for:
134   // #constexpr-ctor-field-initializer, #addr-of
135   RAW_PTR_EXCLUSION base::RunLoop* run_loop_ = nullptr;
136 
137  private:
138   raw_ptr<IPC::Channel> channel_ = nullptr;
139 };
140 
141 class MessageCountFilter : public IPC::MessageFilter {
142  public:
143   enum FilterEvent {
144     NONE,
145     FILTER_ADDED,
146     CHANNEL_CONNECTED,
147     CHANNEL_ERROR,
148     CHANNEL_CLOSING,
149     FILTER_REMOVED
150   };
151 
152   MessageCountFilter() = default;
MessageCountFilter(uint32_t supported_message_class)153   MessageCountFilter(uint32_t supported_message_class)
154       : supported_message_class_(supported_message_class),
155         is_global_filter_(false) {}
156 
OnFilterAdded(IPC::Channel * channel)157   void OnFilterAdded(IPC::Channel* channel) override {
158     EXPECT_TRUE(channel);
159     EXPECT_EQ(NONE, last_filter_event_);
160     last_filter_event_ = FILTER_ADDED;
161   }
162 
OnChannelConnected(int32_t peer_pid)163   void OnChannelConnected(int32_t peer_pid) override {
164     EXPECT_EQ(FILTER_ADDED, last_filter_event_);
165     EXPECT_NE(static_cast<int32_t>(base::kNullProcessId), peer_pid);
166     last_filter_event_ = CHANNEL_CONNECTED;
167   }
168 
OnChannelError()169   void OnChannelError() override {
170     EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
171     last_filter_event_ = CHANNEL_ERROR;
172   }
173 
OnChannelClosing()174   void OnChannelClosing() override {
175     // We may or may not have gotten OnChannelError; if not, the last event has
176     // to be OnChannelConnected.
177     EXPECT_NE(FILTER_REMOVED, last_filter_event_);
178     if (last_filter_event_ != CHANNEL_ERROR)
179       EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
180     last_filter_event_ = CHANNEL_CLOSING;
181   }
182 
OnFilterRemoved()183   void OnFilterRemoved() override {
184     // A filter may be removed at any time, even before the channel is connected
185     // (and thus before OnFilterAdded is ever able to dispatch.) The only time
186     // we won't see OnFilterRemoved is immediately after OnFilterAdded, because
187     // OnChannelConnected is always the next event to fire after that.
188     EXPECT_NE(FILTER_ADDED, last_filter_event_);
189     last_filter_event_ = FILTER_REMOVED;
190   }
191 
OnMessageReceived(const IPC::Message & message)192   bool OnMessageReceived(const IPC::Message& message) override {
193     // We should always get the OnFilterAdded and OnChannelConnected events
194     // prior to any messages.
195     EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
196 
197     if (!is_global_filter_) {
198       EXPECT_EQ(supported_message_class_, IPC_MESSAGE_CLASS(message));
199     }
200     ++messages_received_;
201 
202     if (!message_filtering_enabled_)
203       return false;
204 
205     bool handled = true;
206     IPC_BEGIN_MESSAGE_MAP(MessageCountFilter, message)
207       IPC_MESSAGE_HANDLER(TestMsg_BadMessage, OnBadMessage)
208       IPC_MESSAGE_UNHANDLED(handled = false)
209     IPC_END_MESSAGE_MAP()
210     return handled;
211   }
212 
OnBadMessage(const BadType & bad_type)213   void OnBadMessage(const BadType& bad_type) {
214     // Should never be called since IPC wouldn't be deserialized correctly.
215     CHECK(false);
216   }
217 
GetSupportedMessageClasses(std::vector<uint32_t> * supported_message_classes) const218   bool GetSupportedMessageClasses(
219       std::vector<uint32_t>* supported_message_classes) const override {
220     if (is_global_filter_)
221       return false;
222     supported_message_classes->push_back(supported_message_class_);
223     return true;
224   }
225 
set_message_filtering_enabled(bool enabled)226   void set_message_filtering_enabled(bool enabled) {
227     message_filtering_enabled_ = enabled;
228   }
229 
messages_received() const230   size_t messages_received() const { return messages_received_; }
last_filter_event() const231   FilterEvent last_filter_event() const { return last_filter_event_; }
232 
233  private:
234   ~MessageCountFilter() override = default;
235 
236   size_t messages_received_ = 0;
237   uint32_t supported_message_class_ = 0;
238   bool is_global_filter_ = true;
239 
240   FilterEvent last_filter_event_ = NONE;
241   bool message_filtering_enabled_ = false;
242 };
243 
244 class IPCChannelProxyTest : public IPCChannelMojoTestBase {
245  public:
246   IPCChannelProxyTest() = default;
247   ~IPCChannelProxyTest() override = default;
248 
SetUp()249   void SetUp() override {
250     IPCChannelMojoTestBase::SetUp();
251 
252     Init("ChannelProxyClient");
253 
254     thread_ = std::make_unique<base::Thread>("ChannelProxyTestServerThread");
255     base::Thread::Options options;
256     options.message_pump_type = base::MessagePumpType::IO;
257     thread_->StartWithOptions(std::move(options));
258 
259     listener_ = std::make_unique<QuitListener>();
260     channel_proxy_ = IPC::ChannelProxy::Create(
261         TakeHandle().release(), IPC::Channel::MODE_SERVER, listener_.get(),
262         thread_->task_runner(),
263         base::SingleThreadTaskRunner::GetCurrentDefault());
264   }
265 
TearDown()266   void TearDown() override {
267     channel_proxy_.reset();
268     thread_.reset();
269     listener_.reset();
270     IPCChannelMojoTestBase::TearDown();
271   }
272 
SendQuitMessageAndWaitForIdle()273   void SendQuitMessageAndWaitForIdle() {
274     sender()->Send(new WorkerMsg_Quit);
275     CreateRunLoopAndRun(&listener_->run_loop_);
276     EXPECT_TRUE(WaitForClientShutdown());
277   }
278 
DidListenerGetBadMessage()279   bool DidListenerGetBadMessage() {
280     return listener_->bad_message_received_;
281   }
282 
channel_proxy()283   IPC::ChannelProxy* channel_proxy() { return channel_proxy_.get(); }
sender()284   IPC::Sender* sender() { return channel_proxy_.get(); }
285 
286  private:
287   std::unique_ptr<base::Thread> thread_;
288   std::unique_ptr<QuitListener> listener_;
289   std::unique_ptr<IPC::ChannelProxy> channel_proxy_;
290 };
291 
TEST_F(IPCChannelProxyTest,MessageClassFilters)292 TEST_F(IPCChannelProxyTest, MessageClassFilters) {
293   // Construct a filter per message class.
294   std::vector<scoped_refptr<MessageCountFilter>> class_filters;
295   class_filters.push_back(
296       base::MakeRefCounted<MessageCountFilter>(TestMsgStart));
297   class_filters.push_back(
298       base::MakeRefCounted<MessageCountFilter>(AutomationMsgStart));
299   for (size_t i = 0; i < class_filters.size(); ++i)
300     channel_proxy()->AddFilter(class_filters[i].get());
301 
302   // Send a message for each class; each filter should receive just one message.
303   sender()->Send(new TestMsg_Bounce);
304   sender()->Send(new AutomationMsg_Bounce);
305 
306   // Send some messages not assigned to a specific or valid message class.
307   sender()->Send(new WorkerMsg_Bounce);
308 
309   // Each filter should have received just the one sent message of the
310   // corresponding class.
311   SendQuitMessageAndWaitForIdle();
312   for (size_t i = 0; i < class_filters.size(); ++i)
313     EXPECT_EQ(1U, class_filters[i]->messages_received());
314 }
315 
TEST_F(IPCChannelProxyTest,GlobalAndMessageClassFilters)316 TEST_F(IPCChannelProxyTest, GlobalAndMessageClassFilters) {
317   // Add a class and global filter.
318   scoped_refptr<MessageCountFilter> class_filter(
319       new MessageCountFilter(TestMsgStart));
320   class_filter->set_message_filtering_enabled(false);
321   channel_proxy()->AddFilter(class_filter.get());
322 
323   scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
324   global_filter->set_message_filtering_enabled(false);
325   channel_proxy()->AddFilter(global_filter.get());
326 
327   // A message  of class Test should be seen by both the global filter and
328   // Test-specific filter.
329   sender()->Send(new TestMsg_Bounce);
330 
331   // A message of a different class should be seen only by the global filter.
332   sender()->Send(new AutomationMsg_Bounce);
333 
334   // Flush all messages.
335   SendQuitMessageAndWaitForIdle();
336 
337   // The class filter should have received only the class-specific message.
338   EXPECT_EQ(1U, class_filter->messages_received());
339 
340   // The global filter should have received both messages, as well as the final
341   // QUIT message.
342   EXPECT_EQ(3U, global_filter->messages_received());
343 }
344 
TEST_F(IPCChannelProxyTest,FilterRemoval)345 TEST_F(IPCChannelProxyTest, FilterRemoval) {
346   // Add a class and global filter.
347   scoped_refptr<MessageCountFilter> class_filter(
348       new MessageCountFilter(TestMsgStart));
349   scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
350 
351   // Add and remove both types of filters.
352   channel_proxy()->AddFilter(class_filter.get());
353   channel_proxy()->AddFilter(global_filter.get());
354   channel_proxy()->RemoveFilter(global_filter.get());
355   channel_proxy()->RemoveFilter(class_filter.get());
356 
357   // Send some messages; they should not be seen by either filter.
358   sender()->Send(new TestMsg_Bounce);
359   sender()->Send(new AutomationMsg_Bounce);
360 
361   // Ensure that the filters were removed and did not receive any messages.
362   SendQuitMessageAndWaitForIdle();
363   EXPECT_EQ(MessageCountFilter::FILTER_REMOVED,
364             global_filter->last_filter_event());
365   EXPECT_EQ(MessageCountFilter::FILTER_REMOVED,
366             class_filter->last_filter_event());
367   EXPECT_EQ(0U, class_filter->messages_received());
368   EXPECT_EQ(0U, global_filter->messages_received());
369 }
370 
TEST_F(IPCChannelProxyTest,BadMessageOnListenerThread)371 TEST_F(IPCChannelProxyTest, BadMessageOnListenerThread) {
372   scoped_refptr<MessageCountFilter> class_filter(
373       new MessageCountFilter(TestMsgStart));
374   class_filter->set_message_filtering_enabled(false);
375   channel_proxy()->AddFilter(class_filter.get());
376 
377   sender()->Send(new TestMsg_SendBadMessage());
378 
379   SendQuitMessageAndWaitForIdle();
380   EXPECT_TRUE(DidListenerGetBadMessage());
381 }
382 
TEST_F(IPCChannelProxyTest,BadMessageOnIPCThread)383 TEST_F(IPCChannelProxyTest, BadMessageOnIPCThread) {
384   scoped_refptr<MessageCountFilter> class_filter(
385       new MessageCountFilter(TestMsgStart));
386   class_filter->set_message_filtering_enabled(true);
387   channel_proxy()->AddFilter(class_filter.get());
388 
389   sender()->Send(new TestMsg_SendBadMessage());
390 
391   SendQuitMessageAndWaitForIdle();
392   EXPECT_TRUE(DidListenerGetBadMessage());
393 }
394 
395 class IPCChannelBadMessageTest : public IPCChannelMojoTestBase {
396  public:
SetUp()397   void SetUp() override {
398     IPCChannelMojoTestBase::SetUp();
399 
400     Init("ChannelProxyClient");
401 
402     listener_ = std::make_unique<QuitListener>();
403     CreateChannel(listener_.get());
404     ASSERT_TRUE(ConnectChannel());
405   }
406 
TearDown()407   void TearDown() override {
408     IPCChannelMojoTestBase::TearDown();
409     listener_.reset();
410   }
411 
SendQuitMessageAndWaitForIdle()412   void SendQuitMessageAndWaitForIdle() {
413     sender()->Send(new WorkerMsg_Quit);
414     CreateRunLoopAndRun(&listener_->run_loop_);
415     EXPECT_TRUE(WaitForClientShutdown());
416   }
417 
DidListenerGetBadMessage()418   bool DidListenerGetBadMessage() {
419     return listener_->bad_message_received_;
420   }
421 
422  private:
423   std::unique_ptr<QuitListener> listener_;
424 };
425 
TEST_F(IPCChannelBadMessageTest,BadMessage)426 TEST_F(IPCChannelBadMessageTest, BadMessage) {
427   sender()->Send(new TestMsg_SendBadMessage());
428   SendQuitMessageAndWaitForIdle();
429   EXPECT_TRUE(DidListenerGetBadMessage());
430 }
431 
DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ChannelProxyClient)432 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ChannelProxyClient) {
433   ChannelReflectorListener listener;
434   Connect(&listener);
435   listener.Init(channel());
436 
437   CreateRunLoopAndRun(&listener.run_loop_);
438 
439   Close();
440 }
441 
442 }  // namespace
443