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