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, Signal* signal) {
    124     MessageReader reader(signal);
    125     std::string name, old_owner, new_owner;
    126     ASSERT_TRUE(reader.PopString(&name));
    127     ASSERT_TRUE(reader.PopString(&old_owner));
    128     ASSERT_TRUE(reader.PopString(&new_owner));
    129     latest_name_owner_ = new_owner;
    130     *called_flag = true;
    131     message_loop_.Quit();
    132   }
    133 
    134   // Called when the "Test" signal is received, in the main thread.
    135   // Copy the string payload to |test_signal_string_|.
    136   void OnTestSignal(Signal* signal) {
    137     MessageReader reader(signal);
    138     ASSERT_TRUE(reader.PopString(&test_signal_string_));
    139     message_loop_.Quit();
    140   }
    141 
    142   // Called when connected to the signal.
    143   void OnConnected(const std::string& interface_name,
    144                    const std::string& signal_name,
    145                    bool success) {
    146     ASSERT_TRUE(success);
    147     message_loop_.Quit();
    148   }
    149 
    150  protected:
    151   // Wait for the hey signal to be received.
    152   void WaitForTestSignal() {
    153     // OnTestSignal() will quit the message loop.
    154     message_loop_.Run();
    155   }
    156 
    157   // Stopping a thread is considered an IO operation, so we need to fiddle with
    158   // thread restrictions before and after calling Stop() on a TestService.
    159   void SafeServiceStop(TestService* test_service) {
    160     base::ThreadRestrictions::SetIOAllowed(true);
    161     test_service->Stop();
    162     base::ThreadRestrictions::SetIOAllowed(false);
    163   }
    164 
    165   base::MessageLoop message_loop_;
    166   scoped_ptr<base::Thread> dbus_thread_;
    167   scoped_refptr<Bus> bus_;
    168   ObjectProxy* object_proxy_;
    169   scoped_ptr<TestService> test_service_;
    170   scoped_ptr<TestService> test_service2_;
    171   // Text message from "Test" signal.
    172   std::string test_signal_string_;
    173 
    174   // The known latest name owner of TestService. Updated in OnNameOwnerChanged.
    175   std::string latest_name_owner_;
    176 
    177   // Boolean flags to record callback calls.
    178   bool on_name_owner_changed_called_;
    179   bool on_ownership_called_;
    180 };
    181 
    182 TEST_F(SignalSenderVerificationTest, TestSignalAccepted) {
    183   const char kMessage[] = "hello, world";
    184   // Send the test signal from the exported object.
    185   test_service_->SendTestSignal(kMessage);
    186   // Receive the signal with the object proxy. The signal is handled in
    187   // SignalSenderVerificationTest::OnTestSignal() in the main thread.
    188   WaitForTestSignal();
    189   ASSERT_EQ(kMessage, test_signal_string_);
    190 }
    191 
    192 TEST_F(SignalSenderVerificationTest, TestSignalRejected) {
    193   // To make sure the histogram instance is created.
    194   UMA_HISTOGRAM_COUNTS("DBus.RejectedSignalCount", 0);
    195   base::HistogramBase* reject_signal_histogram =
    196         base::StatisticsRecorder::FindHistogram("DBus.RejectedSignalCount");
    197   scoped_ptr<base::HistogramSamples> samples1(
    198       reject_signal_histogram->SnapshotSamples());
    199 
    200   const char kNewMessage[] = "hello, new world";
    201   test_service2_->SendTestSignal(kNewMessage);
    202 
    203   // This test tests that our callback is NOT called by the ObjectProxy.
    204   // Sleep to have message delivered to the client via the D-Bus service.
    205   base::PlatformThread::Sleep(TestTimeouts::action_timeout());
    206 
    207   scoped_ptr<base::HistogramSamples> samples2(
    208       reject_signal_histogram->SnapshotSamples());
    209 
    210   ASSERT_EQ("", test_signal_string_);
    211   EXPECT_EQ(samples1->TotalCount() + 1, samples2->TotalCount());
    212 }
    213 
    214 TEST_F(SignalSenderVerificationTest, TestOwnerChanged) {
    215   const char kMessage[] = "hello, world";
    216 
    217   // Send the test signal from the exported object.
    218   test_service_->SendTestSignal(kMessage);
    219   // Receive the signal with the object proxy. The signal is handled in
    220   // SignalSenderVerificationTest::OnTestSignal() in the main thread.
    221   WaitForTestSignal();
    222   ASSERT_EQ(kMessage, test_signal_string_);
    223 
    224   // Release and acquire the name ownership.
    225   // latest_name_owner_ should be non empty as |test_service_| owns the name.
    226   ASSERT_FALSE(latest_name_owner_.empty());
    227   test_service_->ShutdownAndBlock();
    228   // OnNameOwnerChanged will PostTask to quit the message loop.
    229   message_loop_.Run();
    230   // latest_name_owner_ should be empty as the owner is gone.
    231   ASSERT_TRUE(latest_name_owner_.empty());
    232 
    233   // Reset the flag as NameOwnerChanged is already received in setup.
    234   on_name_owner_changed_called_ = false;
    235   on_ownership_called_ = false;
    236   test_service2_->RequestOwnership(
    237       base::Bind(&SignalSenderVerificationTest::OnOwnership,
    238                  base::Unretained(this), true));
    239   // Both of OnNameOwnerChanged() and OnOwnership() should quit the MessageLoop,
    240   // but there's no expected order of those 2 event.
    241   message_loop_.Run();
    242   if (!on_name_owner_changed_called_ || !on_ownership_called_)
    243     message_loop_.Run();
    244   ASSERT_TRUE(on_name_owner_changed_called_);
    245   ASSERT_TRUE(on_ownership_called_);
    246 
    247   // latest_name_owner_ becomes non empty as the new owner appears.
    248   ASSERT_FALSE(latest_name_owner_.empty());
    249 
    250   // Now the second service owns the name.
    251   const char kNewMessage[] = "hello, new world";
    252 
    253   test_service2_->SendTestSignal(kNewMessage);
    254   WaitForTestSignal();
    255   ASSERT_EQ(kNewMessage, test_signal_string_);
    256 }
    257 
    258 TEST_F(SignalSenderVerificationTest, 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   message_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_->message_loop_proxy();
    273   options.request_ownership_options = Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT;
    274   TestService stealable_test_service(options);
    275   ASSERT_TRUE(stealable_test_service.StartService());
    276   ASSERT_TRUE(stealable_test_service.WaitUntilServiceIsStarted());
    277   ASSERT_TRUE(stealable_test_service.HasDBusThread());
    278   ASSERT_TRUE(stealable_test_service.has_ownership());
    279 
    280   // OnNameOwnerChanged will PostTask to quit the message loop.
    281   message_loop_.Run();
    282 
    283   // Send a signal to check that the service is correctly owned.
    284   const char kMessage[] = "hello, world";
    285 
    286   // Send the test signal from the exported object.
    287   stealable_test_service.SendTestSignal(kMessage);
    288   // Receive the signal with the object proxy. The signal is handled in
    289   // SignalSenderVerificationTest::OnTestSignal() in the main thread.
    290   WaitForTestSignal();
    291   ASSERT_EQ(kMessage, test_signal_string_);
    292 
    293   // Reset the flag as NameOwnerChanged was called above.
    294   on_name_owner_changed_called_ = false;
    295   test_service2_->RequestOwnership(
    296       base::Bind(&SignalSenderVerificationTest::OnOwnership,
    297                  base::Unretained(this), true));
    298   // Both of OnNameOwnerChanged() and OnOwnership() should quit the MessageLoop,
    299   // but there's no expected order of those 2 event.
    300   message_loop_.Run();
    301   if (!on_name_owner_changed_called_ || !on_ownership_called_)
    302     message_loop_.Run();
    303   ASSERT_TRUE(on_name_owner_changed_called_);
    304   ASSERT_TRUE(on_ownership_called_);
    305 
    306   // Now the second service owns the name.
    307   const char kNewMessage[] = "hello, new world";
    308 
    309   test_service2_->SendTestSignal(kNewMessage);
    310   WaitForTestSignal();
    311   ASSERT_EQ(kNewMessage, test_signal_string_);
    312 
    313   SafeServiceStop(&stealable_test_service);
    314 }
    315 
    316 // Fails on Linux ChromiumOS Tests
    317 TEST_F(SignalSenderVerificationTest, DISABLED_TestMultipleObjects) {
    318   const char kMessage[] = "hello, world";
    319 
    320   ObjectProxy* object_proxy2 = bus_->GetObjectProxy(
    321       "org.chromium.TestService",
    322       ObjectPath("/org/chromium/DifferentObject"));
    323 
    324   bool second_name_owner_changed_called = false;
    325   object_proxy2->SetNameOwnerChangedCallback(
    326       base::Bind(&SignalSenderVerificationTest::OnNameOwnerChanged,
    327                  base::Unretained(this),
    328                  &second_name_owner_changed_called));
    329 
    330   // Connect to a signal on the additional remote object to trigger the
    331   // name owner matching.
    332   object_proxy2->ConnectToSignal(
    333       "org.chromium.DifferentTestInterface",
    334       "Test",
    335       base::Bind(&SignalSenderVerificationTest::OnTestSignal,
    336                  base::Unretained(this)),
    337       base::Bind(&SignalSenderVerificationTest::OnConnected,
    338                  base::Unretained(this)));
    339   // Wait until the object proxy is connected to the signal.
    340   message_loop_.Run();
    341 
    342   // Send the test signal from the exported object.
    343   test_service_->SendTestSignal(kMessage);
    344   // Receive the signal with the object proxy. The signal is handled in
    345   // SignalSenderVerificationTest::OnTestSignal() in the main thread.
    346   WaitForTestSignal();
    347   ASSERT_EQ(kMessage, test_signal_string_);
    348 
    349   // Release and acquire the name ownership.
    350   // latest_name_owner_ should be non empty as |test_service_| owns the name.
    351   ASSERT_FALSE(latest_name_owner_.empty());
    352   test_service_->ShutdownAndBlock();
    353   // OnNameOwnerChanged will PostTask to quit the message loop.
    354   message_loop_.Run();
    355   // latest_name_owner_ should be empty as the owner is gone.
    356   ASSERT_TRUE(latest_name_owner_.empty());
    357 
    358   // Reset the flag as NameOwnerChanged is already received in setup.
    359   on_name_owner_changed_called_ = false;
    360   second_name_owner_changed_called = false;
    361   test_service2_->RequestOwnership(
    362       base::Bind(&SignalSenderVerificationTest::OnOwnership,
    363                  base::Unretained(this), true));
    364   // Both of OnNameOwnerChanged() and OnOwnership() should quit the MessageLoop,
    365   // but there's no expected order of those 2 event.
    366   while (!on_name_owner_changed_called_ || !second_name_owner_changed_called ||
    367          !on_ownership_called_)
    368     message_loop_.Run();
    369   ASSERT_TRUE(on_name_owner_changed_called_);
    370   ASSERT_TRUE(second_name_owner_changed_called);
    371   ASSERT_TRUE(on_ownership_called_);
    372 
    373   // latest_name_owner_ becomes non empty as the new owner appears.
    374   ASSERT_FALSE(latest_name_owner_.empty());
    375 
    376   // Now the second service owns the name.
    377   const char kNewMessage[] = "hello, new world";
    378 
    379   test_service2_->SendTestSignal(kNewMessage);
    380   WaitForTestSignal();
    381   ASSERT_EQ(kNewMessage, test_signal_string_);
    382 }
    383 
    384 }  // namespace dbus
    385