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/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 
     21 namespace dbus {
     22 
     23 // The test for sender verification in ObjectProxy.
     24 class 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 
    185 TEST_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 .
    196 TEST_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 
    218 TEST_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 
    266 TEST_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
    330 TEST_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