1 // Copyright (c) 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.
5 #include "dbus/object_manager.h"
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/threading/thread.h"
14 #include "base/threading/thread_restrictions.h"
16 #include "dbus/object_path.h"
17 #include "dbus/object_proxy.h"
18 #include "dbus/property.h"
19 #include "dbus/test_service.h"
20 #include "testing/gtest/include/gtest/gtest.h"
24 // The object manager test exercises the asynchronous APIs in ObjectManager,
25 // and by extension PropertySet and Property<>.
26 class ObjectManagerTest
27 : public testing::Test
,
28 public ObjectManager::Interface
{
33 struct Properties
: public PropertySet
{
34 Property
<std::string
> name
;
35 Property
<int16
> version
;
36 Property
<std::vector
<std::string
> > methods
;
37 Property
<std::vector
<ObjectPath
> > objects
;
39 Properties(ObjectProxy
* object_proxy
,
40 const std::string
& interface_name
,
41 PropertyChangedCallback property_changed_callback
)
42 : PropertySet(object_proxy
, interface_name
, property_changed_callback
) {
43 RegisterProperty("Name", &name
);
44 RegisterProperty("Version", &version
);
45 RegisterProperty("Methods", &methods
);
46 RegisterProperty("Objects", &objects
);
50 virtual PropertySet
* CreateProperties(
51 ObjectProxy
* object_proxy
,
52 const ObjectPath
& object_path
,
53 const std::string
& interface_name
) OVERRIDE
{
54 Properties
* properties
= new Properties(
55 object_proxy
, interface_name
,
56 base::Bind(&ObjectManagerTest::OnPropertyChanged
,
57 base::Unretained(this), object_path
));
58 return static_cast<PropertySet
*>(properties
);
61 virtual void SetUp() {
62 // Make the main thread not to allow IO.
63 base::ThreadRestrictions::SetIOAllowed(false);
65 // Start the D-Bus thread.
66 dbus_thread_
.reset(new base::Thread("D-Bus Thread"));
67 base::Thread::Options thread_options
;
68 thread_options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
69 ASSERT_TRUE(dbus_thread_
->StartWithOptions(thread_options
));
71 // Start the test service, using the D-Bus thread.
72 TestService::Options options
;
73 options
.dbus_task_runner
= dbus_thread_
->message_loop_proxy();
74 test_service_
.reset(new TestService(options
));
75 ASSERT_TRUE(test_service_
->StartService());
76 ASSERT_TRUE(test_service_
->WaitUntilServiceIsStarted());
77 ASSERT_TRUE(test_service_
->HasDBusThread());
79 // Create the client, using the D-Bus thread.
80 Bus::Options bus_options
;
81 bus_options
.bus_type
= Bus::SESSION
;
82 bus_options
.connection_type
= Bus::PRIVATE
;
83 bus_options
.dbus_task_runner
= dbus_thread_
->message_loop_proxy();
84 bus_
= new Bus(bus_options
);
85 ASSERT_TRUE(bus_
->HasDBusThread());
87 object_manager_
= bus_
->GetObjectManager(
88 "org.chromium.TestService",
89 ObjectPath("/org/chromium/TestService"));
90 object_manager_
->RegisterInterface("org.chromium.TestInterface", this);
92 object_manager_
->GetManagedObjects();
96 virtual void TearDown() {
97 bus_
->ShutdownOnDBusThreadAndBlock();
99 // Shut down the service.
100 test_service_
->ShutdownAndBlock();
102 // Reset to the default.
103 base::ThreadRestrictions::SetIOAllowed(true);
105 // Stopping a thread is considered an IO operation, so do this after
107 test_service_
->Stop();
110 void MethodCallback(Response
* response
) {
111 method_callback_called_
= true;
112 message_loop_
.Quit();
116 // Called when an object is added.
117 virtual void ObjectAdded(const ObjectPath
& object_path
,
118 const std::string
& interface_name
) OVERRIDE
{
119 added_objects_
.push_back(std::make_pair(object_path
, interface_name
));
120 message_loop_
.Quit();
123 // Called when an object is removed.
124 virtual void ObjectRemoved(const ObjectPath
& object_path
,
125 const std::string
& interface_name
) OVERRIDE
{
126 removed_objects_
.push_back(std::make_pair(object_path
, interface_name
));
127 message_loop_
.Quit();
130 // Called when a property value is updated.
131 void OnPropertyChanged(const ObjectPath
& object_path
,
132 const std::string
& name
) {
133 updated_properties_
.push_back(name
);
134 message_loop_
.Quit();
137 static const size_t kExpectedObjects
= 1;
138 static const size_t kExpectedProperties
= 4;
140 void WaitForObject() {
141 while (added_objects_
.size() < kExpectedObjects
||
142 updated_properties_
.size() < kExpectedProperties
)
144 for (size_t i
= 0; i
< kExpectedObjects
; ++i
)
145 added_objects_
.erase(added_objects_
.begin());
146 for (size_t i
= 0; i
< kExpectedProperties
; ++i
)
147 updated_properties_
.erase(updated_properties_
.begin());
150 void WaitForRemoveObject() {
151 while (removed_objects_
.size() < kExpectedObjects
)
153 for (size_t i
= 0; i
< kExpectedObjects
; ++i
)
154 removed_objects_
.erase(removed_objects_
.begin());
157 void WaitForMethodCallback() {
159 method_callback_called_
= false;
162 void PerformAction(const std::string
& action
, const ObjectPath
& object_path
) {
163 ObjectProxy
* object_proxy
= bus_
->GetObjectProxy(
164 "org.chromium.TestService",
165 ObjectPath("/org/chromium/TestObject"));
167 MethodCall
method_call("org.chromium.TestInterface", "PerformAction");
168 MessageWriter
writer(&method_call
);
169 writer
.AppendString(action
);
170 writer
.AppendObjectPath(object_path
);
172 object_proxy
->CallMethod(&method_call
,
173 ObjectProxy::TIMEOUT_USE_DEFAULT
,
174 base::Bind(&ObjectManagerTest::MethodCallback
,
175 base::Unretained(this)));
176 WaitForMethodCallback();
179 base::MessageLoop message_loop_
;
180 scoped_ptr
<base::Thread
> dbus_thread_
;
181 scoped_refptr
<Bus
> bus_
;
182 ObjectManager
* object_manager_
;
183 scoped_ptr
<TestService
> test_service_
;
185 std::vector
<std::pair
<ObjectPath
, std::string
> > added_objects_
;
186 std::vector
<std::pair
<ObjectPath
, std::string
> > removed_objects_
;
187 std::vector
<std::string
> updated_properties_
;
189 bool method_callback_called_
;
193 TEST_F(ObjectManagerTest
, InitialObject
) {
194 ObjectProxy
* object_proxy
= object_manager_
->GetObjectProxy(
195 ObjectPath("/org/chromium/TestObject"));
196 EXPECT_TRUE(object_proxy
!= NULL
);
198 Properties
* properties
= static_cast<Properties
*>(
199 object_manager_
->GetProperties(ObjectPath("/org/chromium/TestObject"),
200 "org.chromium.TestInterface"));
201 EXPECT_TRUE(properties
!= NULL
);
203 EXPECT_EQ("TestService", properties
->name
.value());
204 EXPECT_EQ(10, properties
->version
.value());
206 std::vector
<std::string
> methods
= properties
->methods
.value();
207 ASSERT_EQ(4U, methods
.size());
208 EXPECT_EQ("Echo", methods
[0]);
209 EXPECT_EQ("SlowEcho", methods
[1]);
210 EXPECT_EQ("AsyncEcho", methods
[2]);
211 EXPECT_EQ("BrokenMethod", methods
[3]);
213 std::vector
<ObjectPath
> objects
= properties
->objects
.value();
214 ASSERT_EQ(1U, objects
.size());
215 EXPECT_EQ(ObjectPath("/TestObjectPath"), objects
[0]);
218 TEST_F(ObjectManagerTest
, UnknownObjectProxy
) {
219 ObjectProxy
* object_proxy
= object_manager_
->GetObjectProxy(
220 ObjectPath("/org/chromium/UnknownObject"));
221 EXPECT_TRUE(object_proxy
== NULL
);
224 TEST_F(ObjectManagerTest
, UnknownObjectProperties
) {
225 Properties
* properties
= static_cast<Properties
*>(
226 object_manager_
->GetProperties(ObjectPath("/org/chromium/UnknownObject"),
227 "org.chromium.TestInterface"));
228 EXPECT_TRUE(properties
== NULL
);
231 TEST_F(ObjectManagerTest
, UnknownInterfaceProperties
) {
232 Properties
* properties
= static_cast<Properties
*>(
233 object_manager_
->GetProperties(ObjectPath("/org/chromium/TestObject"),
234 "org.chromium.UnknownService"));
235 EXPECT_TRUE(properties
== NULL
);
238 TEST_F(ObjectManagerTest
, GetObjects
) {
239 std::vector
<ObjectPath
> object_paths
= object_manager_
->GetObjects();
240 ASSERT_EQ(1U, object_paths
.size());
241 EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths
[0]);
244 TEST_F(ObjectManagerTest
, GetObjectsWithInterface
) {
245 std::vector
<ObjectPath
> object_paths
=
246 object_manager_
->GetObjectsWithInterface("org.chromium.TestInterface");
247 ASSERT_EQ(1U, object_paths
.size());
248 EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths
[0]);
251 TEST_F(ObjectManagerTest
, GetObjectsWithUnknownInterface
) {
252 std::vector
<ObjectPath
> object_paths
=
253 object_manager_
->GetObjectsWithInterface("org.chromium.UnknownService");
254 EXPECT_EQ(0U, object_paths
.size());
257 TEST_F(ObjectManagerTest
, SameObject
) {
258 ObjectManager
* object_manager
= bus_
->GetObjectManager(
259 "org.chromium.TestService",
260 ObjectPath("/org/chromium/TestService"));
261 EXPECT_EQ(object_manager_
, object_manager
);
264 TEST_F(ObjectManagerTest
, DifferentObjectForService
) {
265 ObjectManager
* object_manager
= bus_
->GetObjectManager(
266 "org.chromium.DifferentService",
267 ObjectPath("/org/chromium/TestService"));
268 EXPECT_NE(object_manager_
, object_manager
);
271 TEST_F(ObjectManagerTest
, DifferentObjectForPath
) {
272 ObjectManager
* object_manager
= bus_
->GetObjectManager(
273 "org.chromium.TestService",
274 ObjectPath("/org/chromium/DifferentService"));
275 EXPECT_NE(object_manager_
, object_manager
);
278 TEST_F(ObjectManagerTest
, SecondObject
) {
279 PerformAction("AddObject", ObjectPath("/org/chromium/SecondObject"));
282 ObjectProxy
* object_proxy
= object_manager_
->GetObjectProxy(
283 ObjectPath("/org/chromium/SecondObject"));
284 EXPECT_TRUE(object_proxy
!= NULL
);
286 Properties
* properties
= static_cast<Properties
*>(
287 object_manager_
->GetProperties(ObjectPath("/org/chromium/SecondObject"),
288 "org.chromium.TestInterface"));
289 EXPECT_TRUE(properties
!= NULL
);
291 std::vector
<ObjectPath
> object_paths
= object_manager_
->GetObjects();
292 ASSERT_EQ(2U, object_paths
.size());
294 std::sort(object_paths
.begin(), object_paths
.end());
295 EXPECT_EQ(ObjectPath("/org/chromium/SecondObject"), object_paths
[0]);
296 EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths
[1]);
299 object_manager_
->GetObjectsWithInterface("org.chromium.TestInterface");
300 ASSERT_EQ(2U, object_paths
.size());
302 std::sort(object_paths
.begin(), object_paths
.end());
303 EXPECT_EQ(ObjectPath("/org/chromium/SecondObject"), object_paths
[0]);
304 EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths
[1]);
307 TEST_F(ObjectManagerTest
, RemoveSecondObject
) {
308 PerformAction("AddObject", ObjectPath("/org/chromium/SecondObject"));
311 std::vector
<ObjectPath
> object_paths
= object_manager_
->GetObjects();
312 ASSERT_EQ(2U, object_paths
.size());
314 PerformAction("RemoveObject", ObjectPath("/org/chromium/SecondObject"));
315 WaitForRemoveObject();
317 ObjectProxy
* object_proxy
= object_manager_
->GetObjectProxy(
318 ObjectPath("/org/chromium/SecondObject"));
319 EXPECT_TRUE(object_proxy
== NULL
);
321 Properties
* properties
= static_cast<Properties
*>(
322 object_manager_
->GetProperties(ObjectPath("/org/chromium/SecondObject"),
323 "org.chromium.TestInterface"));
324 EXPECT_TRUE(properties
== NULL
);
326 object_paths
= object_manager_
->GetObjects();
327 ASSERT_EQ(1U, object_paths
.size());
328 EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths
[0]);
331 object_manager_
->GetObjectsWithInterface("org.chromium.TestInterface");
332 ASSERT_EQ(1U, object_paths
.size());
333 EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths
[0]);
336 TEST_F(ObjectManagerTest
, OwnershipLost
) {
337 PerformAction("ReleaseOwnership", ObjectPath("/org/chromium/TestService"));
338 WaitForRemoveObject();
340 std::vector
<ObjectPath
> object_paths
= object_manager_
->GetObjects();
341 ASSERT_EQ(0U, object_paths
.size());
344 TEST_F(ObjectManagerTest
, OwnershipLostAndRegained
) {
345 PerformAction("Ownership", ObjectPath("/org/chromium/TestService"));
346 WaitForRemoveObject();
349 std::vector
<ObjectPath
> object_paths
= object_manager_
->GetObjects();
350 ASSERT_EQ(1U, object_paths
.size());