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