blob: 73e11c4b563fbe54fce6767016160b7c7cdb9fc0 [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"
Peter Kasting88430fa2018-02-13 15:22:40 +090013#include "base/bind_helpers.h"
avi0ad0ce02015-12-23 03:12:45 +090014#include "base/macros.h"
avi@chromium.orga29af562013-07-18 08:00:30 +090015#include "base/message_loop/message_loop.h"
earthdok64401d72014-09-03 19:32:36 +090016#include "base/run_loop.h"
fdoray851719c2016-08-26 00:36:37 +090017#include "base/single_thread_task_runner.h"
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090018#include "base/stl_util.h"
satorux@chromium.orgb1753152011-11-11 17:36:22 +090019#include "base/test/test_timeouts.h"
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090020#include "base/threading/thread.h"
21#include "base/threading/thread_restrictions.h"
22#include "dbus/bus.h"
23#include "dbus/message.h"
keybuk@google.combf4649a2012-02-15 06:29:06 +090024#include "dbus/object_path.h"
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090025#include "dbus/object_proxy.h"
26#include "dbus/test_service.h"
27#include "testing/gtest/include/gtest/gtest.h"
28
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090029namespace dbus {
30
satorux@chromium.org9f10a6e2012-06-02 11:53:20 +090031namespace {
32
33// See comments in ObjectProxy::RunResponseCallback() for why the number was
34// chosen.
35const int kHugePayloadSize = 64 << 20; // 64 MB
36
37} // namespace
38
satorux@chromium.orgc6ac7572011-09-01 03:02:43 +090039// The end-to-end test exercises the asynchronous APIs in ObjectProxy and
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090040// ExportedObject.
41class EndToEndAsyncTest : public testing::Test {
42 public:
dcheng7f5750d2014-12-30 03:30:17 +090043 void SetUp() override {
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090044 // Make the main thread not to allow IO.
45 base::ThreadRestrictions::SetIOAllowed(false);
46
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090047 // Start the D-Bus thread.
48 dbus_thread_.reset(new base::Thread("D-Bus Thread"));
49 base::Thread::Options thread_options;
xhwang@chromium.orgdff6b132013-05-02 01:10:30 +090050 thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
satorux@chromium.org01fbb892011-08-20 10:07:17 +090051 ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options));
satorux@chromium.org163f1cb2011-08-18 05:58:12 +090052
satorux@chromium.org01fbb892011-08-20 10:07:17 +090053 // Start the test service, using the D-Bus thread.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090054 TestService::Options options;
skyostile5a8dc42015-06-18 00:46:04 +090055 options.dbus_task_runner = dbus_thread_->task_runner();
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090056 test_service_.reset(new TestService(options));
satorux@chromium.org01fbb892011-08-20 10:07:17 +090057 ASSERT_TRUE(test_service_->StartService());
58 ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
59 ASSERT_TRUE(test_service_->HasDBusThread());
60
61 // Create the client, using the D-Bus thread.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090062 Bus::Options bus_options;
63 bus_options.bus_type = Bus::SESSION;
64 bus_options.connection_type = Bus::PRIVATE;
skyostile5a8dc42015-06-18 00:46:04 +090065 bus_options.dbus_task_runner = dbus_thread_->task_runner();
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090066 bus_ = new Bus(bus_options);
keybuk@google.combf4649a2012-02-15 06:29:06 +090067 object_proxy_ = bus_->GetObjectProxy(
hashimotof4a4c0d2016-01-05 17:48:03 +090068 test_service_->service_name(),
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090069 ObjectPath("/org/chromium/TestObject"));
satorux@chromium.org01fbb892011-08-20 10:07:17 +090070 ASSERT_TRUE(bus_->HasDBusThread());
satorux@chromium.org7f0c4512011-08-23 16:29:21 +090071
satorux@chromium.org5b3e4962011-11-24 07:08:38 +090072 // Connect to the "Test" signal of "org.chromium.TestInterface" from
73 // the remote object.
satorux@chromium.org7f0c4512011-08-23 16:29:21 +090074 object_proxy_->ConnectToSignal(
75 "org.chromium.TestInterface",
76 "Test",
77 base::Bind(&EndToEndAsyncTest::OnTestSignal,
78 base::Unretained(this)),
79 base::Bind(&EndToEndAsyncTest::OnConnected,
80 base::Unretained(this)));
satorux@chromium.org2b613f22011-12-14 02:08:42 +090081 // Wait until the object proxy is connected to the signal.
earthdok64401d72014-09-03 19:32:36 +090082 run_loop_.reset(new base::RunLoop());
83 run_loop_->Run();
satorux@chromium.org2b613f22011-12-14 02:08:42 +090084
satorux@chromium.org5b3e4962011-11-24 07:08:38 +090085 // Connect to the "Test2" signal of "org.chromium.TestInterface" from
86 // the remote object. There was a bug where we were emitting error
87 // messages like "Requested to remove an unknown match rule: ..." at
88 // the shutdown of Bus when an object proxy is connected to more than
89 // one signal of the same interface. See crosbug.com/23382 for details.
90 object_proxy_->ConnectToSignal(
91 "org.chromium.TestInterface",
92 "Test2",
93 base::Bind(&EndToEndAsyncTest::OnTest2Signal,
94 base::Unretained(this)),
95 base::Bind(&EndToEndAsyncTest::OnConnected,
96 base::Unretained(this)));
satorux@chromium.org7f0c4512011-08-23 16:29:21 +090097 // Wait until the object proxy is connected to the signal.
earthdok64401d72014-09-03 19:32:36 +090098 run_loop_.reset(new base::RunLoop());
99 run_loop_->Run();
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900100
101 // Create a second object proxy for the root object.
hashimotof4a4c0d2016-01-05 17:48:03 +0900102 root_object_proxy_ = bus_->GetObjectProxy(test_service_->service_name(),
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900103 ObjectPath("/"));
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900104 ASSERT_TRUE(bus_->HasDBusThread());
105
106 // Connect to the "Test" signal of "org.chromium.TestInterface" from
107 // the root remote object too.
108 root_object_proxy_->ConnectToSignal(
109 "org.chromium.TestInterface",
110 "Test",
111 base::Bind(&EndToEndAsyncTest::OnRootTestSignal,
112 base::Unretained(this)),
113 base::Bind(&EndToEndAsyncTest::OnConnected,
114 base::Unretained(this)));
115 // Wait until the root object proxy is connected to the signal.
earthdok64401d72014-09-03 19:32:36 +0900116 run_loop_.reset(new base::RunLoop());
117 run_loop_->Run();
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900118 }
119
dcheng7f5750d2014-12-30 03:30:17 +0900120 void TearDown() override {
satorux@chromium.orgd336d452011-09-02 15:56:23 +0900121 bus_->ShutdownOnDBusThreadAndBlock();
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900122
satorux@chromium.org01fbb892011-08-20 10:07:17 +0900123 // Shut down the service.
satorux@chromium.orgd336d452011-09-02 15:56:23 +0900124 test_service_->ShutdownAndBlock();
satorux@chromium.org01fbb892011-08-20 10:07:17 +0900125
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900126 // Reset to the default.
127 base::ThreadRestrictions::SetIOAllowed(true);
128
satorux@chromium.orgc6ac7572011-09-01 03:02:43 +0900129 // Stopping a thread is considered an IO operation, so do this after
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900130 // allowing IO.
131 test_service_->Stop();
132 }
133
134 protected:
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900135 // Replaces the bus with a broken one.
136 void SetUpBrokenBus() {
137 // Shut down the existing bus.
138 bus_->ShutdownOnDBusThreadAndBlock();
139
140 // Create new bus with invalid address.
141 const char kInvalidAddress[] = "";
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900142 Bus::Options bus_options;
143 bus_options.bus_type = Bus::CUSTOM_ADDRESS;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900144 bus_options.address = kInvalidAddress;
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900145 bus_options.connection_type = Bus::PRIVATE;
skyostile5a8dc42015-06-18 00:46:04 +0900146 bus_options.dbus_task_runner = dbus_thread_->task_runner();
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900147 bus_ = new Bus(bus_options);
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900148 ASSERT_TRUE(bus_->HasDBusThread());
149
150 // Create new object proxy.
151 object_proxy_ = bus_->GetObjectProxy(
hashimotof4a4c0d2016-01-05 17:48:03 +0900152 test_service_->service_name(),
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900153 ObjectPath("/org/chromium/TestObject"));
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900154 }
155
satorux@chromium.orgc6ac7572011-09-01 03:02:43 +0900156 // Calls the method asynchronously. OnResponse() will be called once the
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900157 // response is received.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900158 void CallMethod(MethodCall* method_call,
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900159 int timeout_ms) {
160 object_proxy_->CallMethod(method_call,
161 timeout_ms,
162 base::Bind(&EndToEndAsyncTest::OnResponse,
163 base::Unretained(this)));
164 }
165
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900166 // Calls the method asynchronously. OnResponse() will be called once the
167 // response is received without error, otherwise OnError() will be called.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900168 void CallMethodWithErrorCallback(MethodCall* method_call,
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900169 int timeout_ms) {
170 object_proxy_->CallMethodWithErrorCallback(
171 method_call,
172 timeout_ms,
173 base::Bind(&EndToEndAsyncTest::OnResponse, base::Unretained(this)),
174 base::Bind(&EndToEndAsyncTest::OnError, base::Unretained(this)));
175 }
176
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900177 // Wait for the give number of responses.
178 void WaitForResponses(size_t num_responses) {
179 while (response_strings_.size() < num_responses) {
earthdok64401d72014-09-03 19:32:36 +0900180 run_loop_.reset(new base::RunLoop);
181 run_loop_->Run();
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900182 }
183 }
184
185 // Called when the response is received.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900186 void OnResponse(Response* response) {
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900187 // |response| will be deleted on exit of the function. Copy the
188 // payload to |response_strings_|.
189 if (response) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900190 MessageReader reader(response);
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900191 std::string response_string;
192 ASSERT_TRUE(reader.PopString(&response_string));
193 response_strings_.push_back(response_string);
194 } else {
dcheng@chromium.org8164c2c2013-04-09 17:46:45 +0900195 response_strings_.push_back(std::string());
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900196 }
earthdok64401d72014-09-03 19:32:36 +0900197 run_loop_->Quit();
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900198 };
199
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900200 // Wait for the given number of errors.
201 void WaitForErrors(size_t num_errors) {
202 while (error_names_.size() < num_errors) {
earthdok64401d72014-09-03 19:32:36 +0900203 run_loop_.reset(new base::RunLoop);
204 run_loop_->Run();
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900205 }
206 }
207
208 // Called when an error is received.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900209 void OnError(ErrorResponse* error) {
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900210 // |error| will be deleted on exit of the function. Copy the payload to
211 // |error_names_|.
212 if (error) {
213 ASSERT_NE("", error->GetErrorName());
214 error_names_.push_back(error->GetErrorName());
215 } else {
dcheng@chromium.org8164c2c2013-04-09 17:46:45 +0900216 error_names_.push_back(std::string());
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900217 }
earthdok64401d72014-09-03 19:32:36 +0900218 run_loop_->Quit();
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900219 }
220
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900221 // Called when the "Test" signal is received, in the main thread.
222 // Copy the string payload to |test_signal_string_|.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900223 void OnTestSignal(Signal* signal) {
224 MessageReader reader(signal);
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900225 ASSERT_TRUE(reader.PopString(&test_signal_string_));
earthdok64401d72014-09-03 19:32:36 +0900226 run_loop_->Quit();
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900227 }
228
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900229 // Called when the "Test" signal is received, in the main thread, by
230 // the root object proxy. Copy the string payload to
231 // |root_test_signal_string_|.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900232 void OnRootTestSignal(Signal* signal) {
233 MessageReader reader(signal);
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900234 ASSERT_TRUE(reader.PopString(&root_test_signal_string_));
earthdok64401d72014-09-03 19:32:36 +0900235 run_loop_->Quit();
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900236 }
237
satorux@chromium.org5b3e4962011-11-24 07:08:38 +0900238 // Called when the "Test2" signal is received, in the main thread.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900239 void OnTest2Signal(Signal* signal) {
240 MessageReader reader(signal);
earthdok64401d72014-09-03 19:32:36 +0900241 run_loop_->Quit();
satorux@chromium.org5b3e4962011-11-24 07:08:38 +0900242 }
243
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900244 // Called when connected to the signal.
245 void OnConnected(const std::string& interface_name,
246 const std::string& signal_name,
247 bool success) {
248 ASSERT_TRUE(success);
earthdok64401d72014-09-03 19:32:36 +0900249 run_loop_->Quit();
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900250 }
251
252 // Wait for the hey signal to be received.
253 void WaitForTestSignal() {
254 // OnTestSignal() will quit the message loop.
earthdok64401d72014-09-03 19:32:36 +0900255 run_loop_.reset(new base::RunLoop);
256 run_loop_->Run();
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900257 }
258
xhwang@chromium.orgdff6b132013-05-02 01:10:30 +0900259 base::MessageLoop message_loop_;
dcheng30c5a172016-04-09 07:55:04 +0900260 std::unique_ptr<base::RunLoop> run_loop_;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900261 std::vector<std::string> response_strings_;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900262 std::vector<std::string> error_names_;
dcheng30c5a172016-04-09 07:55:04 +0900263 std::unique_ptr<base::Thread> dbus_thread_;
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900264 scoped_refptr<Bus> bus_;
265 ObjectProxy* object_proxy_;
266 ObjectProxy* root_object_proxy_;
dcheng30c5a172016-04-09 07:55:04 +0900267 std::unique_ptr<TestService> test_service_;
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900268 // Text message from "Test" signal.
269 std::string test_signal_string_;
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900270 // Text message from "Test" signal delivered to root.
271 std::string root_test_signal_string_;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900272};
273
274TEST_F(EndToEndAsyncTest, Echo) {
275 const char* kHello = "hello";
276
277 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900278 MethodCall method_call("org.chromium.TestInterface", "Echo");
279 MessageWriter writer(&method_call);
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900280 writer.AppendString(kHello);
281
282 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900283 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900284 CallMethod(&method_call, timeout_ms);
285
286 // Check the response.
287 WaitForResponses(1);
288 EXPECT_EQ(kHello, response_strings_[0]);
289}
290
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900291TEST_F(EndToEndAsyncTest, EchoWithErrorCallback) {
292 const char* kHello = "hello";
293
294 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900295 MethodCall method_call("org.chromium.TestInterface", "Echo");
296 MessageWriter writer(&method_call);
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900297 writer.AppendString(kHello);
298
299 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900300 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900301 CallMethodWithErrorCallback(&method_call, timeout_ms);
302
303 // Check the response.
304 WaitForResponses(1);
305 EXPECT_EQ(kHello, response_strings_[0]);
306 EXPECT_TRUE(error_names_.empty());
307}
308
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900309// Call Echo method three times.
310TEST_F(EndToEndAsyncTest, EchoThreeTimes) {
311 const char* kMessages[] = { "foo", "bar", "baz" };
312
313 for (size_t i = 0; i < arraysize(kMessages); ++i) {
314 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900315 MethodCall method_call("org.chromium.TestInterface", "Echo");
316 MessageWriter writer(&method_call);
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900317 writer.AppendString(kMessages[i]);
318
319 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900320 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900321 CallMethod(&method_call, timeout_ms);
322 }
323
324 // Check the responses.
325 WaitForResponses(3);
326 // Sort as the order of the returned messages is not deterministic.
327 std::sort(response_strings_.begin(), response_strings_.end());
328 EXPECT_EQ("bar", response_strings_[0]);
329 EXPECT_EQ("baz", response_strings_[1]);
330 EXPECT_EQ("foo", response_strings_[2]);
331}
332
satorux@chromium.org9f10a6e2012-06-02 11:53:20 +0900333TEST_F(EndToEndAsyncTest, Echo_HugePayload) {
334 const std::string kHugePayload(kHugePayloadSize, 'o');
335
336 // Create the method call with a huge payload.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900337 MethodCall method_call("org.chromium.TestInterface", "Echo");
338 MessageWriter writer(&method_call);
satorux@chromium.org9f10a6e2012-06-02 11:53:20 +0900339 writer.AppendString(kHugePayload);
340
341 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900342 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.org9f10a6e2012-06-02 11:53:20 +0900343 CallMethod(&method_call, timeout_ms);
344
345 // This caused a DCHECK failure before. Ensure that the issue is fixed.
346 WaitForResponses(1);
347 EXPECT_EQ(kHugePayload, response_strings_[0]);
348}
349
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900350TEST_F(EndToEndAsyncTest, BrokenBus) {
351 const char* kHello = "hello";
352
353 // Set up a broken bus.
354 SetUpBrokenBus();
355
356 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900357 MethodCall method_call("org.chromium.TestInterface", "Echo");
358 MessageWriter writer(&method_call);
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900359 writer.AppendString(kHello);
360
361 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900362 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900363 CallMethod(&method_call, timeout_ms);
364 WaitForResponses(1);
365
366 // Should fail because of the broken bus.
367 ASSERT_EQ("", response_strings_[0]);
368}
369
370TEST_F(EndToEndAsyncTest, BrokenBusWithErrorCallback) {
371 const char* kHello = "hello";
372
373 // Set up a broken bus.
374 SetUpBrokenBus();
375
376 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900377 MethodCall method_call("org.chromium.TestInterface", "Echo");
378 MessageWriter writer(&method_call);
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900379 writer.AppendString(kHello);
380
381 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900382 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900383 CallMethodWithErrorCallback(&method_call, timeout_ms);
384 WaitForErrors(1);
385
386 // Should fail because of the broken bus.
387 ASSERT_TRUE(response_strings_.empty());
388 ASSERT_EQ("", error_names_[0]);
389}
390
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900391TEST_F(EndToEndAsyncTest, Timeout) {
392 const char* kHello = "hello";
393
394 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900395 MethodCall method_call("org.chromium.TestInterface", "SlowEcho");
396 MessageWriter writer(&method_call);
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900397 writer.AppendString(kHello);
398
satorux@chromium.org01fbb892011-08-20 10:07:17 +0900399 // Call the method with timeout of 0ms.
400 const int timeout_ms = 0;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900401 CallMethod(&method_call, timeout_ms);
402 WaitForResponses(1);
403
404 // Should fail because of timeout.
405 ASSERT_EQ("", response_strings_[0]);
406}
407
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900408TEST_F(EndToEndAsyncTest, TimeoutWithErrorCallback) {
409 const char* kHello = "hello";
410
411 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900412 MethodCall method_call("org.chromium.TestInterface", "SlowEcho");
413 MessageWriter writer(&method_call);
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900414 writer.AppendString(kHello);
415
416 // Call the method with timeout of 0ms.
417 const int timeout_ms = 0;
418 CallMethodWithErrorCallback(&method_call, timeout_ms);
419 WaitForErrors(1);
420
421 // Should fail because of timeout.
422 ASSERT_TRUE(response_strings_.empty());
423 ASSERT_EQ(DBUS_ERROR_NO_REPLY, error_names_[0]);
424}
425
hashimoto14eb1502015-03-30 16:01:39 +0900426TEST_F(EndToEndAsyncTest, CancelPendingCalls) {
427 const char* kHello = "hello";
428
429 // Create the method call.
430 MethodCall method_call("org.chromium.TestInterface", "Echo");
431 MessageWriter writer(&method_call);
432 writer.AppendString(kHello);
433
434 // Call the method.
435 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
436 CallMethod(&method_call, timeout_ms);
437
438 // Remove the object proxy before receiving the result.
439 // This results in cancelling the pending method call.
hashimotof4a4c0d2016-01-05 17:48:03 +0900440 bus_->RemoveObjectProxy(test_service_->service_name(),
hashimoto14eb1502015-03-30 16:01:39 +0900441 ObjectPath("/org/chromium/TestObject"),
Peter Kasting24efe5e2018-02-24 09:03:01 +0900442 base::DoNothing());
hashimoto14eb1502015-03-30 16:01:39 +0900443
444 // We shouldn't receive any responses. Wait for a while just to make sure.
445 run_loop_.reset(new base::RunLoop);
fdoray851719c2016-08-26 00:36:37 +0900446 message_loop_.task_runner()->PostDelayedTask(
447 FROM_HERE, run_loop_->QuitClosure(), TestTimeouts::tiny_timeout());
hashimoto14eb1502015-03-30 16:01:39 +0900448 run_loop_->Run();
449 EXPECT_TRUE(response_strings_.empty());
450}
451
vlaviano@chromium.org241215d2011-11-30 13:57:42 +0900452// Tests calling a method that sends its reply asynchronously.
453TEST_F(EndToEndAsyncTest, AsyncEcho) {
454 const char* kHello = "hello";
455
456 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900457 MethodCall method_call("org.chromium.TestInterface", "AsyncEcho");
458 MessageWriter writer(&method_call);
vlaviano@chromium.org241215d2011-11-30 13:57:42 +0900459 writer.AppendString(kHello);
460
461 // Call the method.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900462 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
vlaviano@chromium.org241215d2011-11-30 13:57:42 +0900463 CallMethod(&method_call, timeout_ms);
464
465 // Check the response.
466 WaitForResponses(1);
467 EXPECT_EQ(kHello, response_strings_[0]);
468}
469
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900470TEST_F(EndToEndAsyncTest, NonexistentMethod) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900471 MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900472
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900473 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900474 CallMethod(&method_call, timeout_ms);
475 WaitForResponses(1);
476
477 // Should fail because the method is nonexistent.
478 ASSERT_EQ("", response_strings_[0]);
479}
480
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900481TEST_F(EndToEndAsyncTest, NonexistentMethodWithErrorCallback) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900482 MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900483
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900484 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900485 CallMethodWithErrorCallback(&method_call, timeout_ms);
486 WaitForErrors(1);
487
488 // Should fail because the method is nonexistent.
489 ASSERT_TRUE(response_strings_.empty());
490 ASSERT_EQ(DBUS_ERROR_UNKNOWN_METHOD, error_names_[0]);
491}
492
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900493TEST_F(EndToEndAsyncTest, BrokenMethod) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900494 MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900495
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900496 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
satorux@chromium.org163f1cb2011-08-18 05:58:12 +0900497 CallMethod(&method_call, timeout_ms);
498 WaitForResponses(1);
499
500 // Should fail because the method is broken.
501 ASSERT_EQ("", response_strings_[0]);
502}
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900503
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900504TEST_F(EndToEndAsyncTest, BrokenMethodWithErrorCallback) {
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900505 MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900506
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900507 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.org0d2477e2012-04-20 12:18:27 +0900508 CallMethodWithErrorCallback(&method_call, timeout_ms);
509 WaitForErrors(1);
510
511 // Should fail because the method is broken.
512 ASSERT_TRUE(response_strings_.empty());
513 ASSERT_EQ(DBUS_ERROR_FAILED, error_names_[0]);
514}
515
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900516TEST_F(EndToEndAsyncTest, InvalidServiceName) {
517 // Bus name cannot contain '/'.
518 const std::string invalid_service_name = ":1/2";
519
520 // Replace object proxy with new one.
Ryo Hashimoto61ab06d2017-09-25 16:13:50 +0900521 object_proxy_ = bus_->GetObjectProxy(invalid_service_name,
522 ObjectPath("/org/chromium/TestObject"));
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900523
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900524 MethodCall method_call("org.chromium.TestInterface", "Echo");
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900525
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900526 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
hashimoto@chromium.orgb0305512012-05-23 15:55:22 +0900527 CallMethodWithErrorCallback(&method_call, timeout_ms);
528 WaitForErrors(1);
529
530 // Should fail because of the invalid bus name.
531 ASSERT_TRUE(response_strings_.empty());
532 ASSERT_EQ("", error_names_[0]);
533}
534
satorux@chromium.orgb1753152011-11-11 17:36:22 +0900535TEST_F(EndToEndAsyncTest, EmptyResponseCallback) {
536 const char* kHello = "hello";
537
538 // Create the method call.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900539 MethodCall method_call("org.chromium.TestInterface", "Echo");
540 MessageWriter writer(&method_call);
satorux@chromium.orgb1753152011-11-11 17:36:22 +0900541 writer.AppendString(kHello);
542
543 // Call the method with an empty callback.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900544 const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
Peter Kasting24efe5e2018-02-24 09:03:01 +0900545 object_proxy_->CallMethod(&method_call, timeout_ms, base::DoNothing());
satorux@chromium.orgb1753152011-11-11 17:36:22 +0900546 // Post a delayed task to quit the message loop.
earthdok64401d72014-09-03 19:32:36 +0900547 run_loop_.reset(new base::RunLoop);
fdoray851719c2016-08-26 00:36:37 +0900548 message_loop_.task_runner()->PostDelayedTask(
549 FROM_HERE, run_loop_->QuitClosure(), TestTimeouts::tiny_timeout());
earthdok64401d72014-09-03 19:32:36 +0900550 run_loop_->Run();
satorux@chromium.orgb1753152011-11-11 17:36:22 +0900551 // We cannot tell if the empty callback is called, but at least we can
552 // check if the test does not crash.
553}
554
satorux@chromium.org2b613f22011-12-14 02:08:42 +0900555TEST_F(EndToEndAsyncTest, TestSignal) {
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900556 const char kMessage[] = "hello, world";
557 // Send the test signal from the exported object.
558 test_service_->SendTestSignal(kMessage);
satorux@chromium.orgc6ac7572011-09-01 03:02:43 +0900559 // Receive the signal with the object proxy. The signal is handled in
satorux@chromium.org7f0c4512011-08-23 16:29:21 +0900560 // EndToEndAsyncTest::OnTestSignal() in the main thread.
561 WaitForTestSignal();
562 ASSERT_EQ(kMessage, test_signal_string_);
563}
satorux@chromium.org7225b7a2011-09-15 07:10:24 +0900564
satorux@chromium.org2b613f22011-12-14 02:08:42 +0900565TEST_F(EndToEndAsyncTest, TestSignalFromRoot) {
satorux@chromium.org7225b7a2011-09-15 07:10:24 +0900566 const char kMessage[] = "hello, world";
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900567 // Object proxies are tied to a particular object path, if a signal
568 // arrives from a different object path like "/" the first object proxy
569 // |object_proxy_| should not handle it, and should leave it for the root
570 // object proxy |root_object_proxy_|.
satorux@chromium.org7225b7a2011-09-15 07:10:24 +0900571 test_service_->SendTestSignalFromRoot(kMessage);
satorux@chromium.org7225b7a2011-09-15 07:10:24 +0900572 WaitForTestSignal();
keybuk@chromium.orgb929d752012-03-01 13:01:05 +0900573 // Verify the signal was not received by the specific proxy.
574 ASSERT_TRUE(test_signal_string_.empty());
575 // Verify the string WAS received by the root proxy.
576 ASSERT_EQ(kMessage, root_test_signal_string_);
satorux@chromium.org7225b7a2011-09-15 07:10:24 +0900577}
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900578
satorux@chromium.org9f10a6e2012-06-02 11:53:20 +0900579TEST_F(EndToEndAsyncTest, TestHugeSignal) {
580 const std::string kHugeMessage(kHugePayloadSize, 'o');
581
582 // Send the huge signal from the exported object.
583 test_service_->SendTestSignal(kHugeMessage);
584 // This caused a DCHECK failure before. Ensure that the issue is fixed.
585 WaitForTestSignal();
586 ASSERT_EQ(kHugeMessage, test_signal_string_);
587}
588
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900589class SignalMultipleHandlerTest : public EndToEndAsyncTest {
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900590 public:
Chris Watkins635e8902017-11-29 16:44:11 +0900591 SignalMultipleHandlerTest() = default;
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900592
dcheng7f5750d2014-12-30 03:30:17 +0900593 void SetUp() override {
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900594 // Set up base class.
595 EndToEndAsyncTest::SetUp();
596
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900597 // Connect the root object proxy's signal handler to a new handler
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900598 // so that we can verify that a second call to ConnectSignal() delivers
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900599 // to both our new handler and the old.
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900600 object_proxy_->ConnectToSignal(
601 "org.chromium.TestInterface",
602 "Test",
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900603 base::Bind(&SignalMultipleHandlerTest::OnAdditionalTestSignal,
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900604 base::Unretained(this)),
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900605 base::Bind(&SignalMultipleHandlerTest::OnAdditionalConnected,
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900606 base::Unretained(this)));
607 // Wait until the object proxy is connected to the signal.
earthdok64401d72014-09-03 19:32:36 +0900608 run_loop_.reset(new base::RunLoop);
609 run_loop_->Run();
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900610 }
611
612 protected:
613 // Called when the "Test" signal is received, in the main thread.
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900614 // Copy the string payload to |additional_test_signal_string_|.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900615 void OnAdditionalTestSignal(Signal* signal) {
616 MessageReader reader(signal);
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900617 ASSERT_TRUE(reader.PopString(&additional_test_signal_string_));
earthdok64401d72014-09-03 19:32:36 +0900618 run_loop_->Quit();
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900619 }
620
621 // Called when connected to the signal.
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900622 void OnAdditionalConnected(const std::string& interface_name,
623 const std::string& signal_name,
624 bool success) {
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900625 ASSERT_TRUE(success);
earthdok64401d72014-09-03 19:32:36 +0900626 run_loop_->Quit();
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900627 }
628
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900629 // Text message from "Test" signal delivered to additional handler.
630 std::string additional_test_signal_string_;
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900631};
632
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900633TEST_F(SignalMultipleHandlerTest, TestMultipleHandlers) {
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900634 const char kMessage[] = "hello, world";
635 // Send the test signal from the exported object.
636 test_service_->SendTestSignal(kMessage);
637 // Receive the signal with the object proxy.
638 WaitForTestSignal();
keybuk@chromium.org2594a712013-04-24 09:12:35 +0900639 // Verify the string WAS received by the original handler.
640 ASSERT_EQ(kMessage, test_signal_string_);
641 // Verify the signal WAS ALSO received by the additional handler.
642 ASSERT_EQ(kMessage, additional_test_signal_string_);
keybuk@chromium.orgde7b4a92012-03-22 08:39:17 +0900643}
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900644
645} // namespace dbus