xref: /aosp_15_r20/external/libchrome/dbus/signal_sender_verification_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1 // Copyright (c) 2012 The Chromium 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 
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/metrics/histogram_macros.h"
10 #include "base/metrics/histogram_samples.h"
11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/test/test_timeouts.h"
14 #include "base/threading/platform_thread.h"
15 #include "base/threading/thread_restrictions.h"
16 #include "dbus/bus.h"
17 #include "dbus/message.h"
18 #include "dbus/object_proxy.h"
19 #include "dbus/test_service.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace dbus {
23 
24 // The test for sender verification in ObjectProxy.
25 class SignalSenderVerificationTest : public testing::Test {
26  public:
SignalSenderVerificationTest()27   SignalSenderVerificationTest()
28       : on_name_owner_changed_called_(false),
29         on_ownership_called_(false) {
30   }
31 
SetUp()32   void SetUp() override {
33     // Make the main thread not to allow IO.
34     base::ThreadRestrictions::SetIOAllowed(false);
35 
36     // Start the D-Bus thread.
37     dbus_thread_.reset(new base::Thread("D-Bus Thread"));
38     base::Thread::Options thread_options;
39     thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
40     ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options));
41 
42     // Create the test service, using the D-Bus thread.
43     TestService::Options options;
44     options.dbus_task_runner = dbus_thread_->task_runner();
45     test_service_.reset(new TestService(options));
46 
47     // Create the client, using the D-Bus thread.
48     Bus::Options bus_options;
49     bus_options.bus_type = Bus::SESSION;
50     bus_options.connection_type = Bus::PRIVATE;
51     bus_options.dbus_task_runner = dbus_thread_->task_runner();
52     bus_ = new Bus(bus_options);
53     object_proxy_ = bus_->GetObjectProxy(
54         test_service_->service_name(),
55         ObjectPath("/org/chromium/TestObject"));
56     ASSERT_TRUE(bus_->HasDBusThread());
57 
58     object_proxy_->SetNameOwnerChangedCallback(
59         base::Bind(&SignalSenderVerificationTest::OnNameOwnerChanged,
60                    base::Unretained(this),
61                    &on_name_owner_changed_called_));
62 
63     // Connect to the "Test" signal of "org.chromium.TestInterface" from
64     // the remote object.
65     object_proxy_->ConnectToSignal(
66         "org.chromium.TestInterface",
67         "Test",
68         base::Bind(&SignalSenderVerificationTest::OnTestSignal,
69                    base::Unretained(this)),
70         base::Bind(&SignalSenderVerificationTest::OnConnected,
71                    base::Unretained(this)));
72     // Wait until the object proxy is connected to the signal.
73     run_loop_.reset(new base::RunLoop);
74     run_loop_->Run();
75 
76     // Start the test service.
77     ASSERT_TRUE(test_service_->StartService());
78     ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
79     ASSERT_TRUE(test_service_->HasDBusThread());
80     ASSERT_TRUE(test_service_->has_ownership());
81 
82     // Same setup for the second TestService. This service should not have the
83     // ownership of the name at this point.
84     options.service_name = test_service_->service_name();
85     test_service2_.reset(new TestService(options));
86     ASSERT_TRUE(test_service2_->StartService());
87     ASSERT_TRUE(test_service2_->WaitUntilServiceIsStarted());
88     ASSERT_TRUE(test_service2_->HasDBusThread());
89     ASSERT_FALSE(test_service2_->has_ownership());
90 
91     // The name should be owned and known at this point.
92     if (!on_name_owner_changed_called_) {
93       run_loop_.reset(new base::RunLoop);
94       run_loop_->Run();
95     }
96     ASSERT_FALSE(latest_name_owner_.empty());
97   }
98 
TearDown()99   void TearDown() override {
100     bus_->ShutdownOnDBusThreadAndBlock();
101 
102     // Shut down the service.
103     test_service_->ShutdownAndBlock();
104     test_service2_->ShutdownAndBlock();
105 
106     // Reset to the default.
107     base::ThreadRestrictions::SetIOAllowed(true);
108 
109     // Stopping a thread is considered an IO operation, so do this after
110     // allowing IO.
111     test_service_->Stop();
112     test_service2_->Stop();
113   }
114 
OnOwnership(bool expected,bool success)115   void OnOwnership(bool expected, bool success) {
116     ASSERT_EQ(expected, success);
117     // PostTask to quit the MessageLoop as this is called from D-Bus thread.
118     message_loop_.task_runner()->PostTask(
119         FROM_HERE,
120         base::Bind(&SignalSenderVerificationTest::OnOwnershipInternal,
121                    base::Unretained(this)));
122   }
123 
OnOwnershipInternal()124   void OnOwnershipInternal() {
125     on_ownership_called_ = true;
126     run_loop_->Quit();
127   }
128 
OnNameOwnerChanged(bool * called_flag,const std::string & old_owner,const std::string & new_owner)129   void OnNameOwnerChanged(bool* called_flag,
130                           const std::string& old_owner,
131                           const std::string& new_owner) {
132     latest_name_owner_ = new_owner;
133     *called_flag = true;
134     run_loop_->Quit();
135   }
136 
137   // Called when the "Test" signal is received, in the main thread.
138   // Copy the string payload to |test_signal_string_|.
OnTestSignal(Signal * signal)139   void OnTestSignal(Signal* signal) {
140     MessageReader reader(signal);
141     ASSERT_TRUE(reader.PopString(&test_signal_string_));
142     run_loop_->Quit();
143   }
144 
145   // Called when connected to the signal.
OnConnected(const std::string & interface_name,const std::string & signal_name,bool success)146   void OnConnected(const std::string& interface_name,
147                    const std::string& signal_name,
148                    bool success) {
149     ASSERT_TRUE(success);
150     run_loop_->Quit();
151   }
152 
153  protected:
154   // Wait for the hey signal to be received.
WaitForTestSignal()155   void WaitForTestSignal() {
156     // OnTestSignal() will quit the message loop.
157     run_loop_.reset(new base::RunLoop);
158     run_loop_->Run();
159   }
160 
161   // Stopping a thread is considered an IO operation, so we need to fiddle with
162   // thread restrictions before and after calling Stop() on a TestService.
SafeServiceStop(TestService * test_service)163   void SafeServiceStop(TestService* test_service) {
164     base::ThreadRestrictions::SetIOAllowed(true);
165     test_service->Stop();
166     base::ThreadRestrictions::SetIOAllowed(false);
167   }
168 
169   base::MessageLoop message_loop_;
170   std::unique_ptr<base::RunLoop> run_loop_;
171   std::unique_ptr<base::Thread> dbus_thread_;
172   scoped_refptr<Bus> bus_;
173   ObjectProxy* object_proxy_;
174   std::unique_ptr<TestService> test_service_;
175   std::unique_ptr<TestService> test_service2_;
176   // Text message from "Test" signal.
177   std::string test_signal_string_;
178 
179   // The known latest name owner of TestService. Updated in OnNameOwnerChanged.
180   std::string latest_name_owner_;
181 
182   // Boolean flags to record callback calls.
183   bool on_name_owner_changed_called_;
184   bool on_ownership_called_;
185 };
186 
TEST_F(SignalSenderVerificationTest,TestSignalAccepted)187 TEST_F(SignalSenderVerificationTest, TestSignalAccepted) {
188   const char kMessage[] = "hello, world";
189   // Send the test signal from the exported object.
190   test_service_->SendTestSignal(kMessage);
191   // Receive the signal with the object proxy. The signal is handled in
192   // SignalSenderVerificationTest::OnTestSignal() in the main thread.
193   WaitForTestSignal();
194   ASSERT_EQ(kMessage, test_signal_string_);
195 }
196 
TEST_F(SignalSenderVerificationTest,TestSignalRejected)197 TEST_F(SignalSenderVerificationTest, TestSignalRejected) {
198   const char kNewMessage[] = "hello, new world";
199   test_service2_->SendTestSignal(kNewMessage);
200 
201   // This test tests that our callback is NOT called by the ObjectProxy.
202   // Sleep to have message delivered to the client via the D-Bus service.
203   base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
204 
205   ASSERT_EQ("", test_signal_string_);
206 }
207 
208 // Flaky. https://crbug.com/785555
TEST_F(SignalSenderVerificationTest,DISABLED_TestOwnerChanged)209 TEST_F(SignalSenderVerificationTest, DISABLED_TestOwnerChanged) {
210   const char kMessage[] = "hello, world";
211 
212   // Send the test signal from the exported object.
213   test_service_->SendTestSignal(kMessage);
214   // Receive the signal with the object proxy. The signal is handled in
215   // SignalSenderVerificationTest::OnTestSignal() in the main thread.
216   WaitForTestSignal();
217   ASSERT_EQ(kMessage, test_signal_string_);
218 
219   // Release and acquire the name ownership.
220   // latest_name_owner_ should be non empty as |test_service_| owns the name.
221   ASSERT_FALSE(latest_name_owner_.empty());
222   test_service_->ShutdownAndBlock();
223   // OnNameOwnerChanged will PostTask to quit the message loop.
224   run_loop_.reset(new base::RunLoop);
225   run_loop_->Run();
226   // latest_name_owner_ should be empty as the owner is gone.
227   ASSERT_TRUE(latest_name_owner_.empty());
228 
229   // Reset the flag as NameOwnerChanged is already received in setup.
230   on_name_owner_changed_called_ = false;
231   on_ownership_called_ = false;
232   test_service2_->RequestOwnership(
233       base::Bind(&SignalSenderVerificationTest::OnOwnership,
234                  base::Unretained(this), true));
235   // Both of OnNameOwnerChanged() and OnOwnership() should quit the MessageLoop,
236   // but there's no expected order of those 2 event.
237   run_loop_.reset(new base::RunLoop);
238   run_loop_->Run();
239   if (!on_name_owner_changed_called_ || !on_ownership_called_) {
240     run_loop_.reset(new base::RunLoop);
241     run_loop_->Run();
242   }
243   ASSERT_TRUE(on_name_owner_changed_called_);
244   ASSERT_TRUE(on_ownership_called_);
245 
246   // latest_name_owner_ becomes non empty as the new owner appears.
247   ASSERT_FALSE(latest_name_owner_.empty());
248 
249   // Now the second service owns the name.
250   const char kNewMessage[] = "hello, new world";
251 
252   test_service2_->SendTestSignal(kNewMessage);
253   WaitForTestSignal();
254   ASSERT_EQ(kNewMessage, test_signal_string_);
255 }
256 
257 // Flaky. https://crbug.com/785555
TEST_F(SignalSenderVerificationTest,DISABLED_TestOwnerStealing)258 TEST_F(SignalSenderVerificationTest, DISABLED_TestOwnerStealing) {
259   // Release and acquire the name ownership.
260   // latest_name_owner_ should be non empty as |test_service_| owns the name.
261   ASSERT_FALSE(latest_name_owner_.empty());
262   test_service_->ShutdownAndBlock();
263   // OnNameOwnerChanged will PostTask to quit the message loop.
264   run_loop_.reset(new base::RunLoop);
265   run_loop_->Run();
266   // latest_name_owner_ should be empty as the owner is gone.
267   ASSERT_TRUE(latest_name_owner_.empty());
268   // Reset the flag as NameOwnerChanged is already received in setup.
269   on_name_owner_changed_called_ = false;
270 
271   // Start a test service that allows theft, using the D-Bus thread.
272   TestService::Options options;
273   options.dbus_task_runner = dbus_thread_->task_runner();
274   options.request_ownership_options = Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT;
275   options.service_name = test_service_->service_name();
276   TestService stealable_test_service(options);
277   ASSERT_TRUE(stealable_test_service.StartService());
278   ASSERT_TRUE(stealable_test_service.WaitUntilServiceIsStarted());
279   ASSERT_TRUE(stealable_test_service.HasDBusThread());
280   ASSERT_TRUE(stealable_test_service.has_ownership());
281 
282   // OnNameOwnerChanged will PostTask to quit the message loop.
283   run_loop_.reset(new base::RunLoop);
284   run_loop_->Run();
285 
286   // Send a signal to check that the service is correctly owned.
287   const char kMessage[] = "hello, world";
288 
289   // Send the test signal from the exported object.
290   stealable_test_service.SendTestSignal(kMessage);
291   // Receive the signal with the object proxy. The signal is handled in
292   // SignalSenderVerificationTest::OnTestSignal() in the main thread.
293   WaitForTestSignal();
294   ASSERT_EQ(kMessage, test_signal_string_);
295 
296   // Reset the flag as NameOwnerChanged was called above.
297   on_name_owner_changed_called_ = false;
298   test_service2_->RequestOwnership(
299       base::Bind(&SignalSenderVerificationTest::OnOwnership,
300                  base::Unretained(this), true));
301   // Both of OnNameOwnerChanged() and OnOwnership() should quit the MessageLoop,
302   // but there's no expected order of those 2 event.
303   run_loop_.reset(new base::RunLoop);
304   run_loop_->Run();
305   if (!on_name_owner_changed_called_ || !on_ownership_called_) {
306     run_loop_.reset(new base::RunLoop);
307     run_loop_->Run();
308   }
309   ASSERT_TRUE(on_name_owner_changed_called_);
310   ASSERT_TRUE(on_ownership_called_);
311 
312   // Now the second service owns the name.
313   const char kNewMessage[] = "hello, new world";
314 
315   test_service2_->SendTestSignal(kNewMessage);
316   WaitForTestSignal();
317   ASSERT_EQ(kNewMessage, test_signal_string_);
318 
319   SafeServiceStop(&stealable_test_service);
320 }
321 
322 // Fails on Linux ChromiumOS Tests
TEST_F(SignalSenderVerificationTest,DISABLED_TestMultipleObjects)323 TEST_F(SignalSenderVerificationTest, DISABLED_TestMultipleObjects) {
324   const char kMessage[] = "hello, world";
325 
326   ObjectProxy* object_proxy2 = bus_->GetObjectProxy(
327       test_service_->service_name(),
328       ObjectPath("/org/chromium/DifferentObject"));
329 
330   bool second_name_owner_changed_called = false;
331   object_proxy2->SetNameOwnerChangedCallback(
332       base::Bind(&SignalSenderVerificationTest::OnNameOwnerChanged,
333                  base::Unretained(this),
334                  &second_name_owner_changed_called));
335 
336   // Connect to a signal on the additional remote object to trigger the
337   // name owner matching.
338   object_proxy2->ConnectToSignal(
339       "org.chromium.DifferentTestInterface",
340       "Test",
341       base::Bind(&SignalSenderVerificationTest::OnTestSignal,
342                  base::Unretained(this)),
343       base::Bind(&SignalSenderVerificationTest::OnConnected,
344                  base::Unretained(this)));
345   // Wait until the object proxy is connected to the signal.
346   run_loop_.reset(new base::RunLoop);
347   run_loop_->Run();
348 
349   // Send the test signal from the exported object.
350   test_service_->SendTestSignal(kMessage);
351   // Receive the signal with the object proxy. The signal is handled in
352   // SignalSenderVerificationTest::OnTestSignal() in the main thread.
353   WaitForTestSignal();
354   ASSERT_EQ(kMessage, test_signal_string_);
355 
356   // Release and acquire the name ownership.
357   // latest_name_owner_ should be non empty as |test_service_| owns the name.
358   ASSERT_FALSE(latest_name_owner_.empty());
359   test_service_->ShutdownAndBlock();
360   // OnNameOwnerChanged will PostTask to quit the message loop.
361   run_loop_.reset(new base::RunLoop);
362   run_loop_->Run();
363   // latest_name_owner_ should be empty as the owner is gone.
364   ASSERT_TRUE(latest_name_owner_.empty());
365 
366   // Reset the flag as NameOwnerChanged is already received in setup.
367   on_name_owner_changed_called_ = false;
368   second_name_owner_changed_called = false;
369   test_service2_->RequestOwnership(
370       base::Bind(&SignalSenderVerificationTest::OnOwnership,
371                  base::Unretained(this), true));
372   // Both of OnNameOwnerChanged() and OnOwnership() should quit the MessageLoop,
373   // but there's no expected order of those 2 event.
374   while (!on_name_owner_changed_called_ || !second_name_owner_changed_called ||
375          !on_ownership_called_) {
376     run_loop_.reset(new base::RunLoop);
377     run_loop_->Run();
378   }
379   ASSERT_TRUE(on_name_owner_changed_called_);
380   ASSERT_TRUE(second_name_owner_changed_called);
381   ASSERT_TRUE(on_ownership_called_);
382 
383   // latest_name_owner_ becomes non empty as the new owner appears.
384   ASSERT_FALSE(latest_name_owner_.empty());
385 
386   // Now the second service owns the name.
387   const char kNewMessage[] = "hello, new world";
388 
389   test_service2_->SendTestSignal(kNewMessage);
390   WaitForTestSignal();
391   ASSERT_EQ(kNewMessage, test_signal_string_);
392 }
393 
394 }  // namespace dbus
395