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