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