Home | History | Annotate | Download | only in dbus
      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:
     25   SignalSenderVerificationTest()
     26       : on_name_owner_changed_called_(false),
     27         on_ownership_called_(false) {
     28   }
     29 
     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 
     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 
    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 
    118   void OnOwnershipInternal() {
    119     on_ownership_called_ = true;
    120     message_loop_.Quit();
    121   }
    122 
    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_|.
    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.
    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.
    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.
    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 
    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 
    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 
    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 
    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
    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