blob: b02b043941882aa0433a0137c321be9f944f9866 [file] [log] [blame]
keybuk@google.combf4649a2012-02-15 06:29:06 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
satorux@chromium.org163f1cb2011-08-18 05:58:12 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avi0ad0ce02015-12-23 03:12:45 +09005#include <stddef.h>
6
satorux@chromium.org163f1cb2011-08-18 05:58:12 +09007#include <algorithm>
dcheng30c5a172016-04-09 07:55:04 +09008#include <memory>
satorux@chromium.org163f1cb2011-08-18 05:58:12 +09009#include <string>
10#include <vector>
11
12#include "base/bind.h"
avi0ad0ce02015-12-23 03:12:45 +090013#include "base/macros.h"
avi@chromium.orga29af562013-07-18 08:00:30 +090014#include "base/message_loop/message_loop.h"
earthdok64401d72014-09-03 19:32:36 +090015#include "base/run_loop.h"
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090016#include "base/stl_util.h"
satorux@chromium.orgb1753152011-11-11 17:36:22 +090017#include "base/test/test_timeouts.h"
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090018#include "base/threading/thread.h"
19#include "base/threading/thread_restrictions.h"
20#include "dbus/bus.h"
21#include "dbus/message.h"
keybuk@google.combf4649a2012-02-15 06:29:06 +090022#include "dbus/object_path.h"
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090023#include "dbus/object_proxy.h"
24#include "dbus/test_service.h"
25#include "testing/gtest/include/gtest/gtest.h"
26
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090027namespace dbus {
28
satorux@chromium.org9f10a6e2012-06-02 11:53:20 +090029namespace {
30
31// See comments in ObjectProxy::RunResponseCallback() for why the number was
32// chosen.
33const int kHugePayloadSize = 64 << 20; // 64 MB
34
35} // namespace
36
satorux@chromium.orgc6ac7572011-09-01 03:02:43 +090037// The end-to-end test exercises the asynchronous APIs in ObjectProxy and
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090038// ExportedObject.
39class EndToEndAsyncTest : public testing::Test {
40 public:
dcheng7f5750d2014-12-30 03:30:17 +090041 void SetUp() override {
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090042 // Make the main thread not to allow IO.
43 base::ThreadRestrictions::SetIOAllowed(false);
44
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090045 // Start the D-Bus thread.
46 dbus_thread_.reset(new base::Thread("D-Bus Thread"));
47 base::Thread::Options thread_options;
xhwang@chromium.orgdff6b132013-05-02 01:10:30 +090048 thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
satorux@chromium.org01fbb892011-08-20 10:07:17 +090049 ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options));
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090050
satorux@chromium.org01fbb892011-08-20 10:07:17 +090051 // Start the test service, using the D-Bus thread.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090052 TestService::Options options;
skyostile5a8dc42015-06-18 00:46:04 +090053 options.dbus_task_runner = dbus_thread_->task_runner();
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090054 test_service_.reset(new TestService(options));
satorux@chromium.org01fbb892011-08-20 10:07:17 +090055 ASSERT_TRUE(test_service_->StartService());
56 ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
57 ASSERT_TRUE(test_service_->HasDBusThread());
58
59 // Create the client, using the D-Bus thread.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090060 Bus::Options bus_options;
61 bus_options.bus_type = Bus::SESSION;
62 bus_options.connection_type = Bus::PRIVATE;
skyostile5a8dc42015-06-18 00:46:04 +090063 bus_options.dbus_task_runner = dbus_thread_->task_runner();
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090064 bus_ = new Bus(bus_options);
keybuk@google.combf4649a2012-02-15 06:29:06 +090065 object_proxy_ = bus_->GetObjectProxy(
hashimotof4a4c0d2016-01-05 17:48:03 +090066 test_service_->service_name(),
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090067 ObjectPath("/org/chromium/TestObject"));
satorux@chromium.org01fbb892011-08-20 10:07:17 +090068 ASSERT_TRUE(bus_->HasDBusThread());
satorux@chromium.org7f0c4512011-08-23 16:29:21 +090069
satorux@chromium.org5b3e4962011-11-24 07:08:38 +090070 // Connect to the "Test" signal of "org.chromium.TestInterface" from
71 // the remote object.
satorux@chromium.org7f0c4512011-08-23 16:29:21 +090072 object_proxy_->ConnectToSignal(
73 "org.chromium.TestInterface",
74 "Test",
75 base::Bind(&EndToEndAsyncTest::OnTestSignal,
76 base::Unretained(this)),
77 base::Bind(&EndToEndAsyncTest::OnConnected,
78 base::Unretained(this)));
satorux@chromium.org2b613f22011-12-14 02:08:42 +090079 // Wait until the object proxy is connected to the signal.
earthdok64401d72014-09-03 19:32:36 +090080 run_loop_.reset(new base::RunLoop());
81 run_loop_->Run();
satorux@chromium.org2b613f22011-12-14 02:08:42 +090082
satorux@chromium.org5b3e4962011-11-24 07:08:38 +090083 // Connect to the "Test2" signal of "org.chromium.TestInterface" from
84 // the remote object. There was a bug where we were emitting error
85 // messages like "Requested to remove an unknown match rule: ..." at
86 // the shutdown of Bus when an object proxy is connected to more than
87 // one signal of the same interface. See crosbug.com/23382 for details.
88 object_proxy_->ConnectToSignal(
89 "org.chromium.TestInterface",
90 "Test2",
91 base::Bind(&EndToEndAsyncTest::OnTest2Signal,
92 base::Unretained(this)),
93 base::Bind(&EndToEndAsyncTest::OnConnected,
94 base::Unretained(this)));
satorux@chromium.org7f0c4512011-08-23 16:29:21 +090095 // Wait until the object proxy is connected to the signal.
earthdok64401d72014-09-03 19:32:36 +090096 run_loop_.reset(new base::RunLoop());
97 run_loop_->Run();
keybuk@chromium.orgb929d752012-03-01 13:01:05 +090098
99 // Create a second object proxy for the root object.
hashimotof4a4c0d2016-01-05 17:48:03 +0900100 root_object_proxy_ = bus_->GetObjectProxy(test_service_->service_name(),
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900101 ObjectPath("/"));
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900102 ASSERT_TRUE(bus_->HasDBusThread());
103
104 // Connect to the "Test" signal of "org.chromium.TestInterface" from
105 // the root remote object too.
106 root_object_proxy_->ConnectToSignal(
107 "org.chromium.TestInterface",
108 "Test",
109 base::Bind(&EndToEndAsyncTest::OnRootTestSignal,
110 base::Unretained(this)),
111 base::Bind(&EndToEndAsyncTest::OnConnected,
112 base::Unretained(this)));
113 // Wait until the root object proxy is connected to the signal.
earthdok64401d72014-09-03 19:32:36 +0900114 run_loop_.reset(new base::RunLoop());
115 run_loop_->Run();
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900116 }
117
dcheng7f5750d2014-12-30 03:30:17 +0900118 void TearDown() override {
satorux@chromium.orgd336d452011-09-02 15:56:23 +0900119 bus_->ShutdownOnDBusThreadAndBlock();
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900120
satorux@chromium.org01fbb892011-08-20 10:07:17 +0900121 // Shut down the service.
satorux@chromium.orgd336d452011-09-02 15:56:23 +0900122 test_service_->ShutdownAndBlock();
satorux@chromium.org01fbb892011-08-20 10:07:17 +0900123
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900124 // Reset to the default.
125 base::ThreadRestrictions::SetIOAllowed(true);
126
satorux@chromium.orgc6ac7572011-09-01 03:02:43 +0900127 // Stopping a thread is considered an IO operation, so do this after
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900128 // allowing IO.
129 test_service_->Stop();
130 }
131
132 protected:
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900133 // Replaces the bus with a broken one.
134 void SetUpBrokenBus() {
135 // Shut down the existing bus.
136 bus_->ShutdownOnDBusThreadAndBlock();
137
138 // Create new bus with invalid address.
139 const char kInvalidAddress[] = "";
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900140 Bus::Options bus_options;
141 bus_options.bus_type = Bus::CUSTOM_ADDRESS;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900142 bus_options.address = kInvalidAddress;
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900143 bus_options.connection_type = Bus::PRIVATE;
skyostile5a8dc42015-06-18 00:46:04 +0900144 bus_options.dbus_task_runner = dbus_thread_->task_runner();
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900145 bus_ = new Bus(bus_options);
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900146 ASSERT_TRUE(bus_->HasDBusThread());
147
148 // Create new object proxy.
149 object_proxy_ = bus_->GetObjectProxy(
hashimotof4a4c0d2016-01-05 17:48:03 +0900150 test_service_->service_name(),
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900151 ObjectPath("/org/chromium/TestObject"));
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900152 }
153
satorux@chromium.orgc6ac7572011-09-01 03:02:43 +0900154 // Calls the method asynchronously. OnResponse() will be called once the
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900155 // response is received.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900156 void CallMethod(MethodCall* method_call,
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900157 int timeout_ms) {
158 object_proxy_->CallMethod(method_call,
159 timeout_ms,
160 base::Bind(&EndToEndAsyncTest::OnResponse,
161 base::Unretained(this)));
162 }
163
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900164 // Calls the method asynchronously. OnResponse() will be called once the
165 // response is received without error, otherwise OnError() will be called.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900166 void CallMethodWithErrorCallback(MethodCall* method_call,
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900167 int timeout_ms) {
168 object_proxy_->CallMethodWithErrorCallback(
169 method_call,
170 timeout_ms,
171 base::Bind(&EndToEndAsyncTest::OnResponse, base::Unretained(this)),
172 base::Bind(&EndToEndAsyncTest::OnError, base::Unretained(this)));
173 }
174
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900175 // Wait for the give number of responses.
176 void WaitForResponses(size_t num_responses) {
177 while (response_strings_.size() < num_responses) {
earthdok64401d72014-09-03 19:32:36 +0900178 run_loop_.reset(new base::RunLoop);
179 run_loop_->Run();
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900180 }
181 }
182
183 // Called when the response is received.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900184 void OnResponse(Response* response) {
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900185 // |response| will be deleted on exit of the function. Copy the
186 // payload to |response_strings_|.
187 if (response) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900188 MessageReader reader(response);
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900189 std::string response_string;
190 ASSERT_TRUE(reader.PopString(&response_string));
191 response_strings_.push_back(response_string);
192 } else {
dcheng@chromium.org8164c2c2013-04-09 17:46:45 +0900193 response_strings_.push_back(std::string());
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900194 }
earthdok64401d72014-09-03 19:32:36 +0900195 run_loop_->Quit();
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900196 };
197
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900198 // Wait for the given number of errors.
199 void WaitForErrors(size_t num_errors) {
200 while (error_names_.size() < num_errors) {
earthdok64401d72014-09-03 19:32:36 +0900201 run_loop_.reset(new base::RunLoop);
202 run_loop_->Run();
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900203 }
204 }
205
206 // Called when an error is received.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900207 void OnError(ErrorResponse* error) {
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900208 // |error| will be deleted on exit of the function. Copy the payload to
209 // |error_names_|.
210 if (error) {
211 ASSERT_NE("", error->GetErrorName());
212 error_names_.push_back(error->GetErrorName());
213 } else {
dcheng@chromium.org8164c2c2013-04-09 17:46:45 +0900214 error_names_.push_back(std::string());
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900215 }
earthdok64401d72014-09-03 19:32:36 +0900216 run_loop_->Quit();
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900217 }
218
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900219 // Called when the "Test" signal is received, in the main thread.
220 // Copy the string payload to |test_signal_string_|.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900221 void OnTestSignal(Signal* signal) {
222 MessageReader reader(signal);
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900223 ASSERT_TRUE(reader.PopString(&test_signal_string_));
earthdok64401d72014-09-03 19:32:36 +0900224 run_loop_->Quit();
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900225 }
226
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900227 // Called when the "Test" signal is received, in the main thread, by
228 // the root object proxy. Copy the string payload to
229 // |root_test_signal_string_|.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900230 void OnRootTestSignal(Signal* signal) {
231 MessageReader reader(signal);
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900232 ASSERT_TRUE(reader.PopString(&root_test_signal_string_));
earthdok64401d72014-09-03 19:32:36 +0900233 run_loop_->Quit();
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900234 }
235
satorux@chromium.org5b3e4962011-11-24 07:08:38 +0900236 // Called when the "Test2" signal is received, in the main thread.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900237 void OnTest2Signal(Signal* signal) {
238 MessageReader reader(signal);
earthdok64401d72014-09-03 19:32:36 +0900239 run_loop_->Quit();
satorux@chromium.org5b3e4962011-11-24 07:08:38 +0900240 }
241
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900242 // Called when connected to the signal.
243 void OnConnected(const std::string& interface_name,
244 const std::string& signal_name,
245 bool success) {
246 ASSERT_TRUE(success);
earthdok64401d72014-09-03 19:32:36 +0900247 run_loop_->Quit();
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900248 }
249
250 // Wait for the hey signal to be received.
251 void WaitForTestSignal() {
252 // OnTestSignal() will quit the message loop.
earthdok64401d72014-09-03 19:32:36 +0900253 run_loop_.reset(new base::RunLoop);
254 run_loop_->Run();
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900255 }
256
xhwang@chromium.orgdff6b132013-05-02 01:10:30 +0900257 base::MessageLoop message_loop_;
dcheng30c5a172016-04-09 07:55:04 +0900258 std::unique_ptr<base::RunLoop> run_loop_;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900259 std::vector<std::string> response_strings_;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900260 std::vector<std::string> error_names_;
dcheng30c5a172016-04-09 07:55:04 +0900261 std::unique_ptr<base::Thread> dbus_thread_;
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900262 scoped_refptr<Bus> bus_;
263 ObjectProxy* object_proxy_;
264 ObjectProxy* root_object_proxy_;
dcheng30c5a172016-04-09 07:55:04 +0900265 std::unique_ptr<TestService> test_service_;
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900266 // Text message from "Test" signal.
267 std::string test_signal_string_;
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900268 // Text message from "Test" signal delivered to root.
269 std::string root_test_signal_string_;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900270};
271
272TEST_F(EndToEndAsyncTest, Echo) {
273 const char* kHello = "hello";
274
275 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900276 MethodCall method_call("org.chromium.TestInterface", "Echo");
277 MessageWriter writer(&method_call);
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900278 writer.AppendString(kHello);
279
280 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900281 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900282 CallMethod(&method_call, timeout_ms);
283
284 // Check the response.
285 WaitForResponses(1);
286 EXPECT_EQ(kHello, response_strings_[0]);
287}
288
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900289TEST_F(EndToEndAsyncTest, EchoWithErrorCallback) {
290 const char* kHello = "hello";
291
292 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900293 MethodCall method_call("org.chromium.TestInterface", "Echo");
294 MessageWriter writer(&method_call);
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900295 writer.AppendString(kHello);
296
297 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900298 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900299 CallMethodWithErrorCallback(&method_call, timeout_ms);
300
301 // Check the response.
302 WaitForResponses(1);
303 EXPECT_EQ(kHello, response_strings_[0]);
304 EXPECT_TRUE(error_names_.empty());
305}
306
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900307// Call Echo method three times.
308TEST_F(EndToEndAsyncTest, EchoThreeTimes) {
309 const char* kMessages[] = { "foo", "bar", "baz" };
310
311 for (size_t i = 0; i < arraysize(kMessages); ++i) {
312 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900313 MethodCall method_call("org.chromium.TestInterface", "Echo");
314 MessageWriter writer(&method_call);
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900315 writer.AppendString(kMessages[i]);
316
317 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900318 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900319 CallMethod(&method_call, timeout_ms);
320 }
321
322 // Check the responses.
323 WaitForResponses(3);
324 // Sort as the order of the returned messages is not deterministic.
325 std::sort(response_strings_.begin(), response_strings_.end());
326 EXPECT_EQ("bar", response_strings_[0]);
327 EXPECT_EQ("baz", response_strings_[1]);
328 EXPECT_EQ("foo", response_strings_[2]);
329}
330
satorux@chromium.org9f10a6e2012-06-02 11:53:20 +0900331TEST_F(EndToEndAsyncTest, Echo_HugePayload) {
332 const std::string kHugePayload(kHugePayloadSize, 'o');
333
334 // Create the method call with a huge payload.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900335 MethodCall method_call("org.chromium.TestInterface", "Echo");
336 MessageWriter writer(&method_call);
satorux@chromium.org9f10a6e2012-06-02 11:53:20 +0900337 writer.AppendString(kHugePayload);
338
339 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900340 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.org9f10a6e2012-06-02 11:53:20 +0900341 CallMethod(&method_call, timeout_ms);
342
343 // This caused a DCHECK failure before. Ensure that the issue is fixed.
344 WaitForResponses(1);
345 EXPECT_EQ(kHugePayload, response_strings_[0]);
346}
347
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900348TEST_F(EndToEndAsyncTest, BrokenBus) {
349 const char* kHello = "hello";
350
351 // Set up a broken bus.
352 SetUpBrokenBus();
353
354 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900355 MethodCall method_call("org.chromium.TestInterface", "Echo");
356 MessageWriter writer(&method_call);
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900357 writer.AppendString(kHello);
358
359 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900360 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900361 CallMethod(&method_call, timeout_ms);
362 WaitForResponses(1);
363
364 // Should fail because of the broken bus.
365 ASSERT_EQ("", response_strings_[0]);
366}
367
368TEST_F(EndToEndAsyncTest, BrokenBusWithErrorCallback) {
369 const char* kHello = "hello";
370
371 // Set up a broken bus.
372 SetUpBrokenBus();
373
374 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900375 MethodCall method_call("org.chromium.TestInterface", "Echo");
376 MessageWriter writer(&method_call);
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900377 writer.AppendString(kHello);
378
379 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900380 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900381 CallMethodWithErrorCallback(&method_call, timeout_ms);
382 WaitForErrors(1);
383
384 // Should fail because of the broken bus.
385 ASSERT_TRUE(response_strings_.empty());
386 ASSERT_EQ("", error_names_[0]);
387}
388
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900389TEST_F(EndToEndAsyncTest, Timeout) {
390 const char* kHello = "hello";
391
392 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900393 MethodCall method_call("org.chromium.TestInterface", "SlowEcho");
394 MessageWriter writer(&method_call);
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900395 writer.AppendString(kHello);
396
satorux@chromium.org01fbb892011-08-20 10:07:17 +0900397 // Call the method with timeout of 0ms.
398 const int timeout_ms = 0;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900399 CallMethod(&method_call, timeout_ms);
400 WaitForResponses(1);
401
402 // Should fail because of timeout.
403 ASSERT_EQ("", response_strings_[0]);
404}
405
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900406TEST_F(EndToEndAsyncTest, TimeoutWithErrorCallback) {
407 const char* kHello = "hello";
408
409 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900410 MethodCall method_call("org.chromium.TestInterface", "SlowEcho");
411 MessageWriter writer(&method_call);
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900412 writer.AppendString(kHello);
413
414 // Call the method with timeout of 0ms.
415 const int timeout_ms = 0;
416 CallMethodWithErrorCallback(&method_call, timeout_ms);
417 WaitForErrors(1);
418
419 // Should fail because of timeout.
420 ASSERT_TRUE(response_strings_.empty());
421 ASSERT_EQ(DBUS_ERROR_NO_REPLY, error_names_[0]);
422}
423
hashimoto14eb1502015-03-30 16:01:39 +0900424TEST_F(EndToEndAsyncTest, CancelPendingCalls) {
425 const char* kHello = "hello";
426
427 // Create the method call.
428 MethodCall method_call("org.chromium.TestInterface", "Echo");
429 MessageWriter writer(&method_call);
430 writer.AppendString(kHello);
431
432 // Call the method.
433 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
434 CallMethod(&method_call, timeout_ms);
435
436 // Remove the object proxy before receiving the result.
437 // This results in cancelling the pending method call.
hashimotof4a4c0d2016-01-05 17:48:03 +0900438 bus_->RemoveObjectProxy(test_service_->service_name(),
hashimoto14eb1502015-03-30 16:01:39 +0900439 ObjectPath("/org/chromium/TestObject"),
440 base::Bind(&base::DoNothing));
441
442 // We shouldn't receive any responses. Wait for a while just to make sure.
443 run_loop_.reset(new base::RunLoop);
444 message_loop_.PostDelayedTask(FROM_HERE,
445 run_loop_->QuitClosure(),
446 TestTimeouts::tiny_timeout());
447 run_loop_->Run();
448 EXPECT_TRUE(response_strings_.empty());
449}
450
vlaviano@chromium.org241215d2011-11-30 13:57:42 +0900451// Tests calling a method that sends its reply asynchronously.
452TEST_F(EndToEndAsyncTest, AsyncEcho) {
453 const char* kHello = "hello";
454
455 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900456 MethodCall method_call("org.chromium.TestInterface", "AsyncEcho");
457 MessageWriter writer(&method_call);
vlaviano@chromium.org241215d2011-11-30 13:57:42 +0900458 writer.AppendString(kHello);
459
460 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900461 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
vlaviano@chromium.org241215d2011-11-30 13:57:42 +0900462 CallMethod(&method_call, timeout_ms);
463
464 // Check the response.
465 WaitForResponses(1);
466 EXPECT_EQ(kHello, response_strings_[0]);
467}
468
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900469TEST_F(EndToEndAsyncTest, NonexistentMethod) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900470 MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900471
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900472 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900473 CallMethod(&method_call, timeout_ms);
474 WaitForResponses(1);
475
476 // Should fail because the method is nonexistent.
477 ASSERT_EQ("", response_strings_[0]);
478}
479
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900480TEST_F(EndToEndAsyncTest, NonexistentMethodWithErrorCallback) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900481 MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900482
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900483 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900484 CallMethodWithErrorCallback(&method_call, timeout_ms);
485 WaitForErrors(1);
486
487 // Should fail because the method is nonexistent.
488 ASSERT_TRUE(response_strings_.empty());
489 ASSERT_EQ(DBUS_ERROR_UNKNOWN_METHOD, error_names_[0]);
490}
491
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900492TEST_F(EndToEndAsyncTest, BrokenMethod) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900493 MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900494
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900495 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900496 CallMethod(&method_call, timeout_ms);
497 WaitForResponses(1);
498
499 // Should fail because the method is broken.
500 ASSERT_EQ("", response_strings_[0]);
501}
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900502
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900503TEST_F(EndToEndAsyncTest, BrokenMethodWithErrorCallback) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900504 MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900505
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900506 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900507 CallMethodWithErrorCallback(&method_call, timeout_ms);
508 WaitForErrors(1);
509
510 // Should fail because the method is broken.
511 ASSERT_TRUE(response_strings_.empty());
512 ASSERT_EQ(DBUS_ERROR_FAILED, error_names_[0]);
513}
514
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900515TEST_F(EndToEndAsyncTest, InvalidObjectPath) {
516 // Trailing '/' is only allowed for the root path.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900517 const ObjectPath invalid_object_path("/org/chromium/TestObject/");
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900518
519 // Replace object proxy with new one.
hashimotof4a4c0d2016-01-05 17:48:03 +0900520 object_proxy_ = bus_->GetObjectProxy(test_service_->service_name(),
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900521 invalid_object_path);
522
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900523 MethodCall method_call("org.chromium.TestInterface", "Echo");
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900524
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900525 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900526 CallMethodWithErrorCallback(&method_call, timeout_ms);
527 WaitForErrors(1);
528
529 // Should fail because of the invalid path.
530 ASSERT_TRUE(response_strings_.empty());
531 ASSERT_EQ("", error_names_[0]);
532}
533
534TEST_F(EndToEndAsyncTest, InvalidServiceName) {
535 // Bus name cannot contain '/'.
536 const std::string invalid_service_name = ":1/2";
537
538 // Replace object proxy with new one.
539 object_proxy_ = bus_->GetObjectProxy(
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900540 invalid_service_name, ObjectPath("org.chromium.TestObject"));
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900541
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900542 MethodCall method_call("org.chromium.TestInterface", "Echo");
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900543
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900544 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900545 CallMethodWithErrorCallback(&method_call, timeout_ms);
546 WaitForErrors(1);
547
548 // Should fail because of the invalid bus name.
549 ASSERT_TRUE(response_strings_.empty());
550 ASSERT_EQ("", error_names_[0]);
551}
552
satorux@chromium.orgb1753152011-11-11 17:36:22 +0900553TEST_F(EndToEndAsyncTest, EmptyResponseCallback) {
554 const char* kHello = "hello";
555
556 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900557 MethodCall method_call("org.chromium.TestInterface", "Echo");
558 MessageWriter writer(&method_call);
satorux@chromium.orgb1753152011-11-11 17:36:22 +0900559 writer.AppendString(kHello);
560
561 // Call the method with an empty callback.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900562 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.orgb1753152011-11-11 17:36:22 +0900563 object_proxy_->CallMethod(&method_call,
564 timeout_ms,
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900565 ObjectProxy::EmptyResponseCallback());
satorux@chromium.orgb1753152011-11-11 17:36:22 +0900566 // Post a delayed task to quit the message loop.
earthdok64401d72014-09-03 19:32:36 +0900567 run_loop_.reset(new base::RunLoop);
satorux@chromium.orgb1753152011-11-11 17:36:22 +0900568 message_loop_.PostDelayedTask(FROM_HERE,
earthdok64401d72014-09-03 19:32:36 +0900569 run_loop_->QuitClosure(),
tedvessenes@gmail.com8d7a8762012-03-11 10:12:20 +0900570 TestTimeouts::tiny_timeout());
earthdok64401d72014-09-03 19:32:36 +0900571 run_loop_->Run();
satorux@chromium.orgb1753152011-11-11 17:36:22 +0900572 // We cannot tell if the empty callback is called, but at least we can
573 // check if the test does not crash.
574}
575
satorux@chromium.org2b613f22011-12-14 02:08:42 +0900576TEST_F(EndToEndAsyncTest, TestSignal) {
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900577 const char kMessage[] = "hello, world";
578 // Send the test signal from the exported object.
579 test_service_->SendTestSignal(kMessage);
satorux@chromium.orgc6ac7572011-09-01 03:02:43 +0900580 // Receive the signal with the object proxy. The signal is handled in
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900581 // EndToEndAsyncTest::OnTestSignal() in the main thread.
582 WaitForTestSignal();
583 ASSERT_EQ(kMessage, test_signal_string_);
584}
satorux@chromium.org7225b7a2011-09-15 07:10:24 +0900585
satorux@chromium.org2b613f22011-12-14 02:08:42 +0900586TEST_F(EndToEndAsyncTest, TestSignalFromRoot) {
satorux@chromium.org7225b7a2011-09-15 07:10:24 +0900587 const char kMessage[] = "hello, world";
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900588 // Object proxies are tied to a particular object path, if a signal
589 // arrives from a different object path like "/" the first object proxy
590 // |object_proxy_| should not handle it, and should leave it for the root
591 // object proxy |root_object_proxy_|.
satorux@chromium.org7225b7a2011-09-15 07:10:24 +0900592 test_service_->SendTestSignalFromRoot(kMessage);
satorux@chromium.org7225b7a2011-09-15 07:10:24 +0900593 WaitForTestSignal();
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900594 // Verify the signal was not received by the specific proxy.
595 ASSERT_TRUE(test_signal_string_.empty());
596 // Verify the string WAS received by the root proxy.
597 ASSERT_EQ(kMessage, root_test_signal_string_);
satorux@chromium.org7225b7a2011-09-15 07:10:24 +0900598}
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900599
satorux@chromium.org9f10a6e2012-06-02 11:53:20 +0900600TEST_F(EndToEndAsyncTest, TestHugeSignal) {
601 const std::string kHugeMessage(kHugePayloadSize, 'o');
602
603 // Send the huge signal from the exported object.
604 test_service_->SendTestSignal(kHugeMessage);
605 // This caused a DCHECK failure before. Ensure that the issue is fixed.
606 WaitForTestSignal();
607 ASSERT_EQ(kHugeMessage, test_signal_string_);
608}
609
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900610class SignalMultipleHandlerTest : public EndToEndAsyncTest {
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900611 public:
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900612 SignalMultipleHandlerTest() {
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900613 }
614
dcheng7f5750d2014-12-30 03:30:17 +0900615 void SetUp() override {
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900616 // Set up base class.
617 EndToEndAsyncTest::SetUp();
618
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900619 // Connect the root object proxy's signal handler to a new handler
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900620 // so that we can verify that a second call to ConnectSignal() delivers
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900621 // to both our new handler and the old.
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900622 object_proxy_->ConnectToSignal(
623 "org.chromium.TestInterface",
624 "Test",
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900625 base::Bind(&SignalMultipleHandlerTest::OnAdditionalTestSignal,
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900626 base::Unretained(this)),
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900627 base::Bind(&SignalMultipleHandlerTest::OnAdditionalConnected,
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900628 base::Unretained(this)));
629 // Wait until the object proxy is connected to the signal.
earthdok64401d72014-09-03 19:32:36 +0900630 run_loop_.reset(new base::RunLoop);
631 run_loop_->Run();
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900632 }
633
634 protected:
635 // Called when the "Test" signal is received, in the main thread.
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900636 // Copy the string payload to |additional_test_signal_string_|.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900637 void OnAdditionalTestSignal(Signal* signal) {
638 MessageReader reader(signal);
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900639 ASSERT_TRUE(reader.PopString(&additional_test_signal_string_));
earthdok64401d72014-09-03 19:32:36 +0900640 run_loop_->Quit();
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900641 }
642
643 // Called when connected to the signal.
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900644 void OnAdditionalConnected(const std::string& interface_name,
645 const std::string& signal_name,
646 bool success) {
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900647 ASSERT_TRUE(success);
earthdok64401d72014-09-03 19:32:36 +0900648 run_loop_->Quit();
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900649 }
650
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900651 // Text message from "Test" signal delivered to additional handler.
652 std::string additional_test_signal_string_;
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900653};
654
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900655TEST_F(SignalMultipleHandlerTest, TestMultipleHandlers) {
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900656 const char kMessage[] = "hello, world";
657 // Send the test signal from the exported object.
658 test_service_->SendTestSignal(kMessage);
659 // Receive the signal with the object proxy.
660 WaitForTestSignal();
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900661 // Verify the string WAS received by the original handler.
662 ASSERT_EQ(kMessage, test_signal_string_);
663 // Verify the signal WAS ALSO received by the additional handler.
664 ASSERT_EQ(kMessage, additional_test_signal_string_);
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900665}
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900666
667} // namespace dbus