blob: 82949d3e0e8f0abd60d03a717eab521ddc0482bc [file] [log] [blame]
[email protected]20bed012012-02-10 21:45:231// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]2ef498f2011-08-23 19:25:202// 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/bus.h"
6
[email protected]e20d39fe2011-09-02 06:56:237#include "base/bind.h"
8#include "base/message_loop.h"
[email protected]2ef498f2011-08-23 19:25:209#include "base/memory/ref_counted.h"
[email protected]e20d39fe2011-09-02 06:56:2310#include "base/threading/thread.h"
[email protected]2ef498f2011-08-23 19:25:2011#include "dbus/exported_object.h"
[email protected]216ed0b2012-02-14 21:29:0612#include "dbus/object_path.h"
[email protected]2ef498f2011-08-23 19:25:2013#include "dbus/object_proxy.h"
[email protected]bae0f882013-01-31 06:08:0214#include "dbus/scoped_dbus_error.h"
[email protected]2ef498f2011-08-23 19:25:2015
16#include "testing/gtest/include/gtest/gtest.h"
17
[email protected]12e25992011-10-06 00:20:5318namespace {
19
20// Used to test AddFilterFunction().
21DBusHandlerResult DummyHandler(DBusConnection* connection,
22 DBusMessage* raw_message,
23 void* user_data) {
24 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
25}
26
27} // namespace
28
[email protected]2ef498f2011-08-23 19:25:2029TEST(BusTest, GetObjectProxy) {
30 dbus::Bus::Options options;
31 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
32
33 dbus::ObjectProxy* object_proxy1 =
34 bus->GetObjectProxy("org.chromium.TestService",
[email protected]216ed0b2012-02-14 21:29:0635 dbus::ObjectPath("/org/chromium/TestObject"));
[email protected]2ef498f2011-08-23 19:25:2036 ASSERT_TRUE(object_proxy1);
37
38 // This should return the same object.
39 dbus::ObjectProxy* object_proxy2 =
40 bus->GetObjectProxy("org.chromium.TestService",
[email protected]216ed0b2012-02-14 21:29:0641 dbus::ObjectPath("/org/chromium/TestObject"));
[email protected]2ef498f2011-08-23 19:25:2042 ASSERT_TRUE(object_proxy2);
43 EXPECT_EQ(object_proxy1, object_proxy2);
44
45 // This should not.
46 dbus::ObjectProxy* object_proxy3 =
[email protected]216ed0b2012-02-14 21:29:0647 bus->GetObjectProxy(
48 "org.chromium.TestService",
49 dbus::ObjectPath("/org/chromium/DifferentTestObject"));
[email protected]2ef498f2011-08-23 19:25:2050 ASSERT_TRUE(object_proxy3);
51 EXPECT_NE(object_proxy1, object_proxy3);
[email protected]6477a412011-10-13 00:45:2652
53 bus->ShutdownAndBlock();
[email protected]2ef498f2011-08-23 19:25:2054}
55
[email protected]20bed012012-02-10 21:45:2356TEST(BusTest, GetObjectProxyIgnoreUnknownService) {
57 dbus::Bus::Options options;
58 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
59
60 dbus::ObjectProxy* object_proxy1 =
61 bus->GetObjectProxyWithOptions(
62 "org.chromium.TestService",
[email protected]216ed0b2012-02-14 21:29:0663 dbus::ObjectPath("/org/chromium/TestObject"),
[email protected]20bed012012-02-10 21:45:2364 dbus::ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
65 ASSERT_TRUE(object_proxy1);
66
67 // This should return the same object.
68 dbus::ObjectProxy* object_proxy2 =
69 bus->GetObjectProxyWithOptions(
70 "org.chromium.TestService",
[email protected]216ed0b2012-02-14 21:29:0671 dbus::ObjectPath("/org/chromium/TestObject"),
[email protected]20bed012012-02-10 21:45:2372 dbus::ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
73 ASSERT_TRUE(object_proxy2);
74 EXPECT_EQ(object_proxy1, object_proxy2);
75
76 // This should not.
77 dbus::ObjectProxy* object_proxy3 =
78 bus->GetObjectProxyWithOptions(
79 "org.chromium.TestService",
[email protected]216ed0b2012-02-14 21:29:0680 dbus::ObjectPath("/org/chromium/DifferentTestObject"),
[email protected]20bed012012-02-10 21:45:2381 dbus::ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
82 ASSERT_TRUE(object_proxy3);
83 EXPECT_NE(object_proxy1, object_proxy3);
84
85 bus->ShutdownAndBlock();
86}
87
[email protected]38ecdc82013-01-29 20:29:1288TEST(BusTest, RemoveObjectProxy) {
89 // Setup the current thread's MessageLoop.
[email protected]ff33b18e2013-05-01 16:10:3090 base::MessageLoop message_loop;
[email protected]38ecdc82013-01-29 20:29:1291
92 // Start the D-Bus thread.
93 base::Thread::Options thread_options;
[email protected]ff33b18e2013-05-01 16:10:3094 thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
[email protected]38ecdc82013-01-29 20:29:1295 base::Thread dbus_thread("D-Bus thread");
96 dbus_thread.StartWithOptions(thread_options);
97
98 // Create the bus.
99 dbus::Bus::Options options;
[email protected]200328a2013-02-20 01:36:53100 options.dbus_task_runner = dbus_thread.message_loop_proxy();
[email protected]38ecdc82013-01-29 20:29:12101 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
102 ASSERT_FALSE(bus->shutdown_completed());
103
104 // Try to remove a non existant object proxy should return false.
105 ASSERT_FALSE(
106 bus->RemoveObjectProxy("org.chromium.TestService",
107 dbus::ObjectPath("/org/chromium/TestObject"),
108 base::Bind(&base::DoNothing)));
109
110 dbus::ObjectProxy* object_proxy1 =
111 bus->GetObjectProxy("org.chromium.TestService",
112 dbus::ObjectPath("/org/chromium/TestObject"));
113 ASSERT_TRUE(object_proxy1);
114
115 // Increment the reference count to the object proxy to avoid destroying it
116 // while removing the object.
117 object_proxy1->AddRef();
118
119 // Remove the object from the bus. This will invalidate any other usage of
120 // object_proxy1 other than destroy it. We keep this object for a comparison
121 // at a later time.
122 ASSERT_TRUE(
123 bus->RemoveObjectProxy("org.chromium.TestService",
124 dbus::ObjectPath("/org/chromium/TestObject"),
125 base::Bind(&base::DoNothing)));
126
127 // This should return a different object because the first object was removed
128 // from the bus, but not deleted from memory.
129 dbus::ObjectProxy* object_proxy2 =
130 bus->GetObjectProxy("org.chromium.TestService",
131 dbus::ObjectPath("/org/chromium/TestObject"));
132 ASSERT_TRUE(object_proxy2);
133
134 // Compare the new object with the first object. The first object still exists
135 // thanks to the increased reference.
136 EXPECT_NE(object_proxy1, object_proxy2);
137
138 // Release object_proxy1.
139 object_proxy1->Release();
140
141 // Shut down synchronously.
142 bus->ShutdownOnDBusThreadAndBlock();
143 EXPECT_TRUE(bus->shutdown_completed());
144 dbus_thread.Stop();
145}
146
[email protected]2ef498f2011-08-23 19:25:20147TEST(BusTest, GetExportedObject) {
148 dbus::Bus::Options options;
149 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
150
151 dbus::ExportedObject* object_proxy1 =
[email protected]15e7b162012-03-10 01:12:52152 bus->GetExportedObject(dbus::ObjectPath("/org/chromium/TestObject"));
[email protected]2ef498f2011-08-23 19:25:20153 ASSERT_TRUE(object_proxy1);
154
155 // This should return the same object.
156 dbus::ExportedObject* object_proxy2 =
[email protected]15e7b162012-03-10 01:12:52157 bus->GetExportedObject(dbus::ObjectPath("/org/chromium/TestObject"));
[email protected]2ef498f2011-08-23 19:25:20158 ASSERT_TRUE(object_proxy2);
159 EXPECT_EQ(object_proxy1, object_proxy2);
160
161 // This should not.
162 dbus::ExportedObject* object_proxy3 =
[email protected]216ed0b2012-02-14 21:29:06163 bus->GetExportedObject(
[email protected]216ed0b2012-02-14 21:29:06164 dbus::ObjectPath("/org/chromium/DifferentTestObject"));
[email protected]2ef498f2011-08-23 19:25:20165 ASSERT_TRUE(object_proxy3);
166 EXPECT_NE(object_proxy1, object_proxy3);
[email protected]6477a412011-10-13 00:45:26167
168 bus->ShutdownAndBlock();
[email protected]2ef498f2011-08-23 19:25:20169}
[email protected]e20d39fe2011-09-02 06:56:23170
[email protected]bda57352013-01-24 00:58:35171TEST(BusTest, UnregisterExportedObject) {
[email protected]d7361fdc2012-03-14 01:18:35172 // Start the D-Bus thread.
173 base::Thread::Options thread_options;
[email protected]ff33b18e2013-05-01 16:10:30174 thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
[email protected]d7361fdc2012-03-14 01:18:35175 base::Thread dbus_thread("D-Bus thread");
176 dbus_thread.StartWithOptions(thread_options);
177
178 // Create the bus.
179 dbus::Bus::Options options;
[email protected]200328a2013-02-20 01:36:53180 options.dbus_task_runner = dbus_thread.message_loop_proxy();
[email protected]d7361fdc2012-03-14 01:18:35181 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
182 ASSERT_FALSE(bus->shutdown_completed());
183
184 dbus::ExportedObject* object_proxy1 =
185 bus->GetExportedObject(dbus::ObjectPath("/org/chromium/TestObject"));
186 ASSERT_TRUE(object_proxy1);
187
[email protected]bda57352013-01-24 00:58:35188 // Increment the reference count to the object proxy to avoid destroying it
189 // calling UnregisterExportedObject. This ensures the dbus::ExportedObject is
190 // not freed from memory. See http://crbug.com/137846 for details.
191 object_proxy1->AddRef();
192
[email protected]d7361fdc2012-03-14 01:18:35193 bus->UnregisterExportedObject(dbus::ObjectPath("/org/chromium/TestObject"));
194
[email protected]bda57352013-01-24 00:58:35195 // This should return a new object because the object_proxy1 is still in
196 // alloc'ed memory.
[email protected]d7361fdc2012-03-14 01:18:35197 dbus::ExportedObject* object_proxy2 =
198 bus->GetExportedObject(dbus::ObjectPath("/org/chromium/TestObject"));
199 ASSERT_TRUE(object_proxy2);
200 EXPECT_NE(object_proxy1, object_proxy2);
201
[email protected]bda57352013-01-24 00:58:35202 // Release the incremented reference.
203 object_proxy1->Release();
204
[email protected]d7361fdc2012-03-14 01:18:35205 // Shut down synchronously.
206 bus->ShutdownOnDBusThreadAndBlock();
207 EXPECT_TRUE(bus->shutdown_completed());
208 dbus_thread.Stop();
209}
210
[email protected]e20d39fe2011-09-02 06:56:23211TEST(BusTest, ShutdownAndBlock) {
212 dbus::Bus::Options options;
213 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
214 ASSERT_FALSE(bus->shutdown_completed());
215
216 // Shut down synchronously.
217 bus->ShutdownAndBlock();
218 EXPECT_TRUE(bus->shutdown_completed());
219}
220
221TEST(BusTest, ShutdownAndBlockWithDBusThread) {
222 // Start the D-Bus thread.
223 base::Thread::Options thread_options;
[email protected]ff33b18e2013-05-01 16:10:30224 thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
[email protected]e20d39fe2011-09-02 06:56:23225 base::Thread dbus_thread("D-Bus thread");
226 dbus_thread.StartWithOptions(thread_options);
227
228 // Create the bus.
229 dbus::Bus::Options options;
[email protected]200328a2013-02-20 01:36:53230 options.dbus_task_runner = dbus_thread.message_loop_proxy();
[email protected]e20d39fe2011-09-02 06:56:23231 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
232 ASSERT_FALSE(bus->shutdown_completed());
233
234 // Shut down synchronously.
235 bus->ShutdownOnDBusThreadAndBlock();
236 EXPECT_TRUE(bus->shutdown_completed());
237 dbus_thread.Stop();
238}
[email protected]12e25992011-10-06 00:20:53239
240TEST(BusTest, AddFilterFunction) {
241 dbus::Bus::Options options;
242 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
243 // Should connect before calling AddFilterFunction().
244 bus->Connect();
245
246 int data1 = 100;
247 int data2 = 200;
248 ASSERT_TRUE(bus->AddFilterFunction(&DummyHandler, &data1));
249 // Cannot add the same function with the same data.
250 ASSERT_FALSE(bus->AddFilterFunction(&DummyHandler, &data1));
251 // Can add the same function with different data.
252 ASSERT_TRUE(bus->AddFilterFunction(&DummyHandler, &data2));
253
254 ASSERT_TRUE(bus->RemoveFilterFunction(&DummyHandler, &data1));
255 ASSERT_FALSE(bus->RemoveFilterFunction(&DummyHandler, &data1));
256 ASSERT_TRUE(bus->RemoveFilterFunction(&DummyHandler, &data2));
257
258 bus->ShutdownAndBlock();
259}
[email protected]bae0f882013-01-31 06:08:02260
261TEST(BusTest, DoubleAddAndRemoveMatch) {
262 dbus::Bus::Options options;
263 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
264 dbus::ScopedDBusError error;
265
266 bus->Connect();
267
268 // Adds the same rule twice.
269 bus->AddMatch(
270 "type='signal',interface='org.chromium.TestService',path='/'",
271 error.get());
272 ASSERT_FALSE(error.is_set());
273
274 bus->AddMatch(
275 "type='signal',interface='org.chromium.TestService',path='/'",
276 error.get());
277 ASSERT_FALSE(error.is_set());
278
279 // Removes the same rule twice.
280 ASSERT_TRUE(bus->RemoveMatch(
281 "type='signal',interface='org.chromium.TestService',path='/'",
282 error.get()));
283 ASSERT_FALSE(error.is_set());
284
285 // The rule should be still in the bus since it was removed only once.
286 // A second removal shouldn't give an error.
287 ASSERT_TRUE(bus->RemoveMatch(
288 "type='signal',interface='org.chromium.TestService',path='/'",
289 error.get()));
290 ASSERT_FALSE(error.is_set());
291
292 // A third attemp to remove the same rule should fail.
293 ASSERT_FALSE(bus->RemoveMatch(
294 "type='signal',interface='org.chromium.TestService',path='/'",
295 error.get()));
296
297 bus->ShutdownAndBlock();
298}