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