Fix build break
[chromium-blink-merge.git] / dbus / bus_unittest.cc
bloba288d535dcd9b445c29c32ef6cd9f91066a08c6b
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.
5 #include "dbus/bus.h"
7 #include "base/bind.h"
8 #include "base/message_loop.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/threading/thread.h"
11 #include "dbus/exported_object.h"
12 #include "dbus/object_path.h"
13 #include "dbus/object_proxy.h"
14 #include "dbus/scoped_dbus_error.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 namespace {
20 // Used to test AddFilterFunction().
21 DBusHandlerResult DummyHandler(DBusConnection* connection,
22 DBusMessage* raw_message,
23 void* user_data) {
24 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
27 } // namespace
29 TEST(BusTest, GetObjectProxy) {
30 dbus::Bus::Options options;
31 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
33 dbus::ObjectProxy* object_proxy1 =
34 bus->GetObjectProxy("org.chromium.TestService",
35 dbus::ObjectPath("/org/chromium/TestObject"));
36 ASSERT_TRUE(object_proxy1);
38 // This should return the same object.
39 dbus::ObjectProxy* object_proxy2 =
40 bus->GetObjectProxy("org.chromium.TestService",
41 dbus::ObjectPath("/org/chromium/TestObject"));
42 ASSERT_TRUE(object_proxy2);
43 EXPECT_EQ(object_proxy1, object_proxy2);
45 // This should not.
46 dbus::ObjectProxy* object_proxy3 =
47 bus->GetObjectProxy(
48 "org.chromium.TestService",
49 dbus::ObjectPath("/org/chromium/DifferentTestObject"));
50 ASSERT_TRUE(object_proxy3);
51 EXPECT_NE(object_proxy1, object_proxy3);
53 bus->ShutdownAndBlock();
56 TEST(BusTest, GetObjectProxyIgnoreUnknownService) {
57 dbus::Bus::Options options;
58 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
60 dbus::ObjectProxy* object_proxy1 =
61 bus->GetObjectProxyWithOptions(
62 "org.chromium.TestService",
63 dbus::ObjectPath("/org/chromium/TestObject"),
64 dbus::ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
65 ASSERT_TRUE(object_proxy1);
67 // This should return the same object.
68 dbus::ObjectProxy* object_proxy2 =
69 bus->GetObjectProxyWithOptions(
70 "org.chromium.TestService",
71 dbus::ObjectPath("/org/chromium/TestObject"),
72 dbus::ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
73 ASSERT_TRUE(object_proxy2);
74 EXPECT_EQ(object_proxy1, object_proxy2);
76 // This should not.
77 dbus::ObjectProxy* object_proxy3 =
78 bus->GetObjectProxyWithOptions(
79 "org.chromium.TestService",
80 dbus::ObjectPath("/org/chromium/DifferentTestObject"),
81 dbus::ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
82 ASSERT_TRUE(object_proxy3);
83 EXPECT_NE(object_proxy1, object_proxy3);
85 bus->ShutdownAndBlock();
88 TEST(BusTest, RemoveObjectProxy) {
89 // Setup the current thread's MessageLoop.
90 MessageLoop message_loop;
92 // Start the D-Bus thread.
93 base::Thread::Options thread_options;
94 thread_options.message_loop_type = MessageLoop::TYPE_IO;
95 base::Thread dbus_thread("D-Bus thread");
96 dbus_thread.StartWithOptions(thread_options);
98 // Create the bus.
99 dbus::Bus::Options options;
100 options.dbus_task_runner = dbus_thread.message_loop_proxy();
101 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
102 ASSERT_FALSE(bus->shutdown_completed());
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)));
110 dbus::ObjectProxy* object_proxy1 =
111 bus->GetObjectProxy("org.chromium.TestService",
112 dbus::ObjectPath("/org/chromium/TestObject"));
113 ASSERT_TRUE(object_proxy1);
115 // Increment the reference count to the object proxy to avoid destroying it
116 // while removing the object.
117 object_proxy1->AddRef();
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)));
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);
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);
138 // Release object_proxy1.
139 object_proxy1->Release();
141 // Shut down synchronously.
142 bus->ShutdownOnDBusThreadAndBlock();
143 EXPECT_TRUE(bus->shutdown_completed());
144 dbus_thread.Stop();
147 TEST(BusTest, GetExportedObject) {
148 dbus::Bus::Options options;
149 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
151 dbus::ExportedObject* object_proxy1 =
152 bus->GetExportedObject(dbus::ObjectPath("/org/chromium/TestObject"));
153 ASSERT_TRUE(object_proxy1);
155 // This should return the same object.
156 dbus::ExportedObject* object_proxy2 =
157 bus->GetExportedObject(dbus::ObjectPath("/org/chromium/TestObject"));
158 ASSERT_TRUE(object_proxy2);
159 EXPECT_EQ(object_proxy1, object_proxy2);
161 // This should not.
162 dbus::ExportedObject* object_proxy3 =
163 bus->GetExportedObject(
164 dbus::ObjectPath("/org/chromium/DifferentTestObject"));
165 ASSERT_TRUE(object_proxy3);
166 EXPECT_NE(object_proxy1, object_proxy3);
168 bus->ShutdownAndBlock();
171 TEST(BusTest, UnregisterExportedObject) {
172 // Start the D-Bus thread.
173 base::Thread::Options thread_options;
174 thread_options.message_loop_type = MessageLoop::TYPE_IO;
175 base::Thread dbus_thread("D-Bus thread");
176 dbus_thread.StartWithOptions(thread_options);
178 // Create the bus.
179 dbus::Bus::Options options;
180 options.dbus_task_runner = dbus_thread.message_loop_proxy();
181 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
182 ASSERT_FALSE(bus->shutdown_completed());
184 dbus::ExportedObject* object_proxy1 =
185 bus->GetExportedObject(dbus::ObjectPath("/org/chromium/TestObject"));
186 ASSERT_TRUE(object_proxy1);
188 // 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();
193 bus->UnregisterExportedObject(dbus::ObjectPath("/org/chromium/TestObject"));
195 // This should return a new object because the object_proxy1 is still in
196 // alloc'ed memory.
197 dbus::ExportedObject* object_proxy2 =
198 bus->GetExportedObject(dbus::ObjectPath("/org/chromium/TestObject"));
199 ASSERT_TRUE(object_proxy2);
200 EXPECT_NE(object_proxy1, object_proxy2);
202 // Release the incremented reference.
203 object_proxy1->Release();
205 // Shut down synchronously.
206 bus->ShutdownOnDBusThreadAndBlock();
207 EXPECT_TRUE(bus->shutdown_completed());
208 dbus_thread.Stop();
211 TEST(BusTest, ShutdownAndBlock) {
212 dbus::Bus::Options options;
213 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
214 ASSERT_FALSE(bus->shutdown_completed());
216 // Shut down synchronously.
217 bus->ShutdownAndBlock();
218 EXPECT_TRUE(bus->shutdown_completed());
221 TEST(BusTest, ShutdownAndBlockWithDBusThread) {
222 // Start the D-Bus thread.
223 base::Thread::Options thread_options;
224 thread_options.message_loop_type = MessageLoop::TYPE_IO;
225 base::Thread dbus_thread("D-Bus thread");
226 dbus_thread.StartWithOptions(thread_options);
228 // Create the bus.
229 dbus::Bus::Options options;
230 options.dbus_task_runner = dbus_thread.message_loop_proxy();
231 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
232 ASSERT_FALSE(bus->shutdown_completed());
234 // Shut down synchronously.
235 bus->ShutdownOnDBusThreadAndBlock();
236 EXPECT_TRUE(bus->shutdown_completed());
237 dbus_thread.Stop();
240 TEST(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();
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));
254 ASSERT_TRUE(bus->RemoveFilterFunction(&DummyHandler, &data1));
255 ASSERT_FALSE(bus->RemoveFilterFunction(&DummyHandler, &data1));
256 ASSERT_TRUE(bus->RemoveFilterFunction(&DummyHandler, &data2));
258 bus->ShutdownAndBlock();
261 TEST(BusTest, DoubleAddAndRemoveMatch) {
262 dbus::Bus::Options options;
263 scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
264 dbus::ScopedDBusError error;
266 bus->Connect();
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());
274 bus->AddMatch(
275 "type='signal',interface='org.chromium.TestService',path='/'",
276 error.get());
277 ASSERT_FALSE(error.is_set());
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());
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());
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()));
297 bus->ShutdownAndBlock();