15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/bus.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/run_loop.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/exported_object.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_proxy.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/scoped_dbus_error.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "dbus/test_service.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)namespace dbus {
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used to test AddFilterFunction().
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DBusHandlerResult DummyHandler(DBusConnection* connection,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               DBusMessage* raw_message,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               void* user_data) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Test helper for BusTest.ListenForServiceOwnerChange that wraps a
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// base::RunLoop. At Run() time, the caller pass in the expected number of
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// quit calls, and at QuitIfConditionIsSatisified() time, only quit the RunLoop
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// if the expected number of quit calls have been reached.
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class RunLoopWithExpectedCount {
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RunLoopWithExpectedCount() : expected_quit_calls_(0), actual_quit_calls_(0) {}
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ~RunLoopWithExpectedCount() {}
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void Run(int expected_quit_calls) {
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_EQ(0, expected_quit_calls_);
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_EQ(0, actual_quit_calls_);
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    expected_quit_calls_ = expected_quit_calls;
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    run_loop_.reset(new base::RunLoop());
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    run_loop_->Run();
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void QuitIfConditionIsSatisified() {
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (++actual_quit_calls_ != expected_quit_calls_)
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    run_loop_->Quit();
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    expected_quit_calls_ = 0;
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    actual_quit_calls_ = 0;
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<base::RunLoop> run_loop_;
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int expected_quit_calls_;
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int actual_quit_calls_;
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(RunLoopWithExpectedCount);
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Test helper for BusTest.ListenForServiceOwnerChange.
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void OnServiceOwnerChanged(RunLoopWithExpectedCount* run_loop_state,
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           std::string* service_owner,
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           int* num_of_owner_changes,
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           const std::string& new_service_owner) {
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *service_owner = new_service_owner;
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ++(*num_of_owner_changes);
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  run_loop_state->QuitIfConditionIsSatisified();
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(BusTest, GetObjectProxy) {
777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::Options options;
787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Bus> bus = new Bus(options);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ObjectProxy* object_proxy1 =
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bus->GetObjectProxy("org.chromium.TestService",
827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                          ObjectPath("/org/chromium/TestObject"));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy1);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should return the same object.
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ObjectProxy* object_proxy2 =
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bus->GetObjectProxy("org.chromium.TestService",
887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                          ObjectPath("/org/chromium/TestObject"));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy2);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(object_proxy1, object_proxy2);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should not.
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ObjectProxy* object_proxy3 =
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bus->GetObjectProxy(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "org.chromium.TestService",
967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          ObjectPath("/org/chromium/DifferentTestObject"));
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy3);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(object_proxy1, object_proxy3);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->ShutdownAndBlock();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(BusTest, GetObjectProxyIgnoreUnknownService) {
1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::Options options;
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Bus> bus = new Bus(options);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ObjectProxy* object_proxy1 =
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bus->GetObjectProxyWithOptions(
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "org.chromium.TestService",
1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          ObjectPath("/org/chromium/TestObject"),
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy1);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should return the same object.
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ObjectProxy* object_proxy2 =
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bus->GetObjectProxyWithOptions(
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "org.chromium.TestService",
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          ObjectPath("/org/chromium/TestObject"),
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy2);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(object_proxy1, object_proxy2);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should not.
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ObjectProxy* object_proxy3 =
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bus->GetObjectProxyWithOptions(
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "org.chromium.TestService",
1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          ObjectPath("/org/chromium/DifferentTestObject"),
1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy3);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(object_proxy1, object_proxy3);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->ShutdownAndBlock();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BusTest, RemoveObjectProxy) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Setup the current thread's MessageLoop.
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop message_loop;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start the D-Bus thread.
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Thread::Options thread_options;
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Thread dbus_thread("D-Bus thread");
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dbus_thread.StartWithOptions(thread_options);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create the bus.
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::Options options;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  options.dbus_task_runner = dbus_thread.message_loop_proxy();
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Bus> bus = new Bus(options);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(bus->shutdown_completed());
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Try to remove a non existant object proxy should return false.
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bus->RemoveObjectProxy("org.chromium.TestService",
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                             ObjectPath("/org/chromium/TestObject"),
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             base::Bind(&base::DoNothing)));
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ObjectProxy* object_proxy1 =
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bus->GetObjectProxy("org.chromium.TestService",
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                          ObjectPath("/org/chromium/TestObject"));
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(object_proxy1);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Increment the reference count to the object proxy to avoid destroying it
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // while removing the object.
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  object_proxy1->AddRef();
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Remove the object from the bus. This will invalidate any other usage of
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // object_proxy1 other than destroy it. We keep this object for a comparison
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // at a later time.
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bus->RemoveObjectProxy("org.chromium.TestService",
1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                             ObjectPath("/org/chromium/TestObject"),
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             base::Bind(&base::DoNothing)));
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should return a different object because the first object was removed
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // from the bus, but not deleted from memory.
1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ObjectProxy* object_proxy2 =
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bus->GetObjectProxy("org.chromium.TestService",
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                          ObjectPath("/org/chromium/TestObject"));
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(object_proxy2);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compare the new object with the first object. The first object still exists
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // thanks to the increased reference.
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_NE(object_proxy1, object_proxy2);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Release object_proxy1.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  object_proxy1->Release();
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Shut down synchronously.
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bus->ShutdownOnDBusThreadAndBlock();
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(bus->shutdown_completed());
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dbus_thread.Stop();
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(BusTest, GetExportedObject) {
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::Options options;
1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Bus> bus = new Bus(options);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ExportedObject* object_proxy1 =
1997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy1);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should return the same object.
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ExportedObject* object_proxy2 =
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy2);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(object_proxy1, object_proxy2);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should not.
2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ExportedObject* object_proxy3 =
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bus->GetExportedObject(
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          ObjectPath("/org/chromium/DifferentTestObject"));
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy3);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(object_proxy1, object_proxy3);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->ShutdownAndBlock();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BusTest, UnregisterExportedObject) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the D-Bus thread.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread::Options thread_options;
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread dbus_thread("D-Bus thread");
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_thread.StartWithOptions(thread_options);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the bus.
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::Options options;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  options.dbus_task_runner = dbus_thread.message_loop_proxy();
2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Bus> bus = new Bus(options);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bus->shutdown_completed());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ExportedObject* object_proxy1 =
2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy1);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Increment the reference count to the object proxy to avoid destroying it
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // calling UnregisterExportedObject. This ensures the dbus::ExportedObject is
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // not freed from memory. See http://crbug.com/137846 for details.
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  object_proxy1->AddRef();
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bus->UnregisterExportedObject(ObjectPath("/org/chromium/TestObject"));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This should return a new object because the object_proxy1 is still in
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // alloc'ed memory.
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ExportedObject* object_proxy2 =
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(object_proxy2);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(object_proxy1, object_proxy2);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Release the incremented reference.
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  object_proxy1->Release();
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shut down synchronously.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->ShutdownOnDBusThreadAndBlock();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(bus->shutdown_completed());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_thread.Stop();
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(BusTest, ShutdownAndBlock) {
2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::Options options;
2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Bus> bus = new Bus(options);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bus->shutdown_completed());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shut down synchronously.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->ShutdownAndBlock();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(bus->shutdown_completed());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(BusTest, ShutdownAndBlockWithDBusThread) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the D-Bus thread.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread::Options thread_options;
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread dbus_thread("D-Bus thread");
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_thread.StartWithOptions(thread_options);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the bus.
2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::Options options;
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  options.dbus_task_runner = dbus_thread.message_loop_proxy();
2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Bus> bus = new Bus(options);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bus->shutdown_completed());
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shut down synchronously.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->ShutdownOnDBusThreadAndBlock();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(bus->shutdown_completed());
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_thread.Stop();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(BusTest, AddFilterFunction) {
2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::Options options;
2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Bus> bus = new Bus(options);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should connect before calling AddFilterFunction().
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->Connect();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int data1 = 100;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int data2 = 200;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(bus->AddFilterFunction(&DummyHandler, &data1));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cannot add the same function with the same data.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bus->AddFilterFunction(&DummyHandler, &data1));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Can add the same function with different data.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(bus->AddFilterFunction(&DummyHandler, &data2));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(bus->RemoveFilterFunction(&DummyHandler, &data1));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bus->RemoveFilterFunction(&DummyHandler, &data1));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(bus->RemoveFilterFunction(&DummyHandler, &data2));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->ShutdownAndBlock();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(BusTest, DoubleAddAndRemoveMatch) {
3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::Options options;
3107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Bus> bus = new Bus(options);
3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ScopedDBusError error;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bus->Connect();
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adds the same rule twice.
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bus->AddMatch(
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "type='signal',interface='org.chromium.TestService',path='/'",
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error.get());
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(error.is_set());
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bus->AddMatch(
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "type='signal',interface='org.chromium.TestService',path='/'",
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error.get());
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(error.is_set());
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Removes the same rule twice.
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(bus->RemoveMatch(
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "type='signal',interface='org.chromium.TestService',path='/'",
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error.get()));
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(error.is_set());
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The rule should be still in the bus since it was removed only once.
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A second removal shouldn't give an error.
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(bus->RemoveMatch(
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "type='signal',interface='org.chromium.TestService',path='/'",
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error.get()));
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(error.is_set());
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A third attemp to remove the same rule should fail.
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(bus->RemoveMatch(
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "type='signal',interface='org.chromium.TestService',path='/'",
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error.get()));
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bus->ShutdownAndBlock();
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST(BusTest, ListenForServiceOwnerChange) {
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Setup the current thread's MessageLoop. Must be of TYPE_IO for the
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // listeners to work.
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RunLoopWithExpectedCount run_loop_state;
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Create the bus.
3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::Options bus_options;
3557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Bus> bus = new Bus(bus_options);
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Add a listener.
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string service_owner1;
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int num_of_owner_changes1 = 0;
3607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::GetServiceOwnerCallback callback1 =
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&OnServiceOwnerChanged,
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 &run_loop_state,
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 &service_owner1,
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 &num_of_owner_changes1);
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bus->ListenForServiceOwnerChange("org.chromium.TestService", callback1);
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This should be a no-op.
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bus->ListenForServiceOwnerChange("org.chromium.TestService", callback1);
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Nothing has happened yet. Check initial state.
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(service_owner1.empty());
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(0, num_of_owner_changes1);
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Make an ownership change.
375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_TRUE(bus->RequestOwnershipAndBlock("org.chromium.TestService",
376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            Bus::REQUIRE_PRIMARY));
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  run_loop_state.Run(1);
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  {
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Get the current service owner and check to make sure the listener got
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // the right value.
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::string current_service_owner =
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bus->GetServiceOwnerAndBlock("org.chromium.TestService",
3847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                     Bus::REPORT_ERRORS);
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ASSERT_FALSE(current_service_owner.empty());
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Make sure the listener heard about the new owner.
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_EQ(current_service_owner, service_owner1);
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Test the second ListenForServiceOwnerChange() above is indeed a no-op.
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_EQ(1, num_of_owner_changes1);
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Add a second listener.
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string service_owner2;
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int num_of_owner_changes2 = 0;
3977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  Bus::GetServiceOwnerCallback callback2 =
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&OnServiceOwnerChanged,
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 &run_loop_state,
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 &service_owner2,
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 &num_of_owner_changes2);
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bus->ListenForServiceOwnerChange("org.chromium.TestService", callback2);
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Release the ownership and make sure the service owner listeners fire with
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // the right values and the right number of times.
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(bus->ReleaseOwnership("org.chromium.TestService"));
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  run_loop_state.Run(2);
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(service_owner1.empty());
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(service_owner2.empty());
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(2, num_of_owner_changes1);
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(1, num_of_owner_changes2);
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Unlisten so shutdown can proceed correctly.
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bus->UnlistenForServiceOwnerChange("org.chromium.TestService", callback1);
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bus->UnlistenForServiceOwnerChange("org.chromium.TestService", callback2);
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Shut down synchronously.
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bus->ShutdownAndBlock();
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(bus->shutdown_completed());
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
4247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}  // namespace dbus
426