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