1 // Copyright 2013 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 "dbus/object_proxy.h"
6 #include "base/bind.h"
7 #include "base/files/file_descriptor_watcher_posix.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "dbus/bus.h"
12 #include "dbus/test_service.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace dbus {
16 namespace {
17
18 class ObjectProxyTest : public testing::Test {
19 protected:
ObjectProxyTest()20 ObjectProxyTest() : file_descriptor_watcher_(&message_loop_) {}
21
SetUp()22 void SetUp() override {
23 Bus::Options bus_options;
24 bus_options.bus_type = Bus::SESSION;
25 bus_options.connection_type = Bus::PRIVATE;
26 bus_ = new Bus(bus_options);
27 }
28
TearDown()29 void TearDown() override { bus_->ShutdownAndBlock(); }
30
31 base::MessageLoopForIO message_loop_;
32
33 // This enables FileDescriptorWatcher, which is required by dbus::Watch.
34 base::FileDescriptorWatcher file_descriptor_watcher_;
35
36 scoped_refptr<Bus> bus_;
37 };
38
39 // Used as a WaitForServiceToBeAvailableCallback.
OnServiceIsAvailable(bool * dest_service_is_available,int * num_calls,bool src_service_is_available)40 void OnServiceIsAvailable(bool* dest_service_is_available,
41 int* num_calls,
42 bool src_service_is_available) {
43 *dest_service_is_available = src_service_is_available;
44 (*num_calls)++;
45 }
46
47 // Used as a callback for TestService::RequestOwnership().
OnOwnershipRequestDone(bool success)48 void OnOwnershipRequestDone(bool success) {
49 ASSERT_TRUE(success);
50 }
51
52 // Used as a callback for TestService::ReleaseOwnership().
OnOwnershipReleased()53 void OnOwnershipReleased() {}
54
TEST_F(ObjectProxyTest,WaitForServiceToBeAvailableRunOnce)55 TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableRunOnce) {
56 TestService::Options options;
57 TestService test_service(options);
58 ObjectProxy* object_proxy = bus_->GetObjectProxy(
59 test_service.service_name(), ObjectPath("/org/chromium/TestObject"));
60
61 // The callback is not yet called because the service is not available.
62 int num_calls = 0;
63 bool service_is_available = false;
64 object_proxy->WaitForServiceToBeAvailable(
65 base::Bind(&OnServiceIsAvailable, &service_is_available, &num_calls));
66 base::RunLoop().RunUntilIdle();
67 EXPECT_EQ(0, num_calls);
68
69 // Start the service. The callback should be called asynchronously.
70 ASSERT_TRUE(test_service.StartService());
71 ASSERT_TRUE(test_service.WaitUntilServiceIsStarted());
72 ASSERT_TRUE(test_service.has_ownership());
73 num_calls = 0;
74 base::RunLoop().RunUntilIdle();
75 EXPECT_EQ(1, num_calls);
76 EXPECT_TRUE(service_is_available);
77
78 // Release the service's ownership of its name. The callback should not be
79 // invoked again.
80 test_service.ReleaseOwnership(base::Bind(&OnOwnershipReleased));
81 num_calls = 0;
82 base::RunLoop().RunUntilIdle();
83 EXPECT_EQ(0, num_calls);
84
85 // Take ownership of the name and check that the callback is not called.
86 test_service.RequestOwnership(base::Bind(&OnOwnershipRequestDone));
87 num_calls = 0;
88 base::RunLoop().RunUntilIdle();
89 EXPECT_EQ(0, num_calls);
90 }
91
TEST_F(ObjectProxyTest,WaitForServiceToBeAvailableAlreadyRunning)92 TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableAlreadyRunning) {
93 TestService::Options options;
94 TestService test_service(options);
95 ObjectProxy* object_proxy = bus_->GetObjectProxy(
96 test_service.service_name(), ObjectPath("/org/chromium/TestObject"));
97
98 ASSERT_TRUE(test_service.StartService());
99 ASSERT_TRUE(test_service.WaitUntilServiceIsStarted());
100 ASSERT_TRUE(test_service.has_ownership());
101
102 // Since the service is already running, the callback should be invoked
103 // immediately (but asynchronously, rather than the callback being invoked
104 // directly within WaitForServiceToBeAvailable()).
105 int num_calls = 0;
106 bool service_is_available = false;
107 object_proxy->WaitForServiceToBeAvailable(
108 base::Bind(&OnServiceIsAvailable, &service_is_available, &num_calls));
109 EXPECT_EQ(0, num_calls);
110
111 base::RunLoop().RunUntilIdle();
112 EXPECT_EQ(1, num_calls);
113 EXPECT_TRUE(service_is_available);
114 }
115
TEST_F(ObjectProxyTest,WaitForServiceToBeAvailableMultipleCallbacks)116 TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableMultipleCallbacks) {
117 TestService::Options options;
118 TestService test_service(options);
119 ObjectProxy* object_proxy = bus_->GetObjectProxy(
120 test_service.service_name(), ObjectPath("/org/chromium/TestObject"));
121
122 // Register two callbacks.
123 int num_calls_1 = 0, num_calls_2 = 0;
124 bool service_is_available_1 = false, service_is_available_2 = false;
125 object_proxy->WaitForServiceToBeAvailable(
126 base::Bind(&OnServiceIsAvailable, &service_is_available_1, &num_calls_1));
127 object_proxy->WaitForServiceToBeAvailable(
128 base::Bind(&OnServiceIsAvailable, &service_is_available_2, &num_calls_2));
129 base::RunLoop().RunUntilIdle();
130 EXPECT_EQ(0, num_calls_1);
131 EXPECT_EQ(0, num_calls_2);
132
133 // Start the service and confirm that both callbacks are invoked.
134 ASSERT_TRUE(test_service.StartService());
135 ASSERT_TRUE(test_service.WaitUntilServiceIsStarted());
136 ASSERT_TRUE(test_service.has_ownership());
137 num_calls_1 = 0;
138 num_calls_2 = 0;
139 base::RunLoop().RunUntilIdle();
140 EXPECT_EQ(1, num_calls_1);
141 EXPECT_EQ(1, num_calls_2);
142 EXPECT_TRUE(service_is_available_1);
143 EXPECT_TRUE(service_is_available_2);
144 }
145
146 } // namespace
147 } // namespace dbus
148