[M120 Migration][VD] Fix url crash in RequestCertificateConfirm
[platform/framework/web/chromium-efl.git] / dbus / end_to_end_async_unittest.cc
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6
7 #include <algorithm>
8 #include <memory>
9 #include <string>
10 #include <vector>
11
12 #include "base/functional/bind.h"
13 #include "base/functional/callback_helpers.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/message_loop/message_pump_type.h"
16 #include "base/run_loop.h"
17 #include "base/task/single_thread_task_runner.h"
18 #include "base/test/task_environment.h"
19 #include "base/test/test_timeouts.h"
20 #include "base/threading/thread.h"
21 #include "base/threading/thread_restrictions.h"
22 #include "base/time/time.h"
23 #include "dbus/bus.h"
24 #include "dbus/message.h"
25 #include "dbus/object_path.h"
26 #include "dbus/object_proxy.h"
27 #include "dbus/test_service.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "third_party/abseil-cpp/absl/types/optional.h"
30
31 namespace dbus {
32
33 namespace {
34
35 // See comments in ObjectProxy::RunResponseCallback() for why the number was
36 // chosen.
37 const int kHugePayloadSize = 64 << 20;  // 64 MB
38
39 }  // namespace
40
41 // The end-to-end test exercises the asynchronous APIs in ObjectProxy and
42 // ExportedObject.
43 class EndToEndAsyncTest : public testing::Test {
44  public:
45   void SetUp() override {
46     // Make the main thread not to allow IO.
47     disallow_blocking_.emplace();
48
49     // Start the D-Bus thread.
50     dbus_thread_ = std::make_unique<base::Thread>("D-Bus Thread");
51     base::Thread::Options thread_options;
52     thread_options.message_pump_type = base::MessagePumpType::IO;
53     ASSERT_TRUE(dbus_thread_->StartWithOptions(std::move(thread_options)));
54
55     // Start the test service, using the D-Bus thread.
56     TestService::Options options;
57     options.dbus_task_runner = dbus_thread_->task_runner();
58     test_service_ = std::make_unique<TestService>(options);
59     ASSERT_TRUE(test_service_->StartService());
60     test_service_->WaitUntilServiceIsStarted();
61     ASSERT_TRUE(test_service_->HasDBusThread());
62
63     // Create the client, using the D-Bus thread.
64     Bus::Options bus_options;
65     bus_options.bus_type = Bus::SESSION;
66     bus_options.connection_type = Bus::PRIVATE;
67     bus_options.dbus_task_runner = dbus_thread_->task_runner();
68     bus_ = new Bus(bus_options);
69     object_proxy_ = bus_->GetObjectProxy(
70         test_service_->service_name(),
71         ObjectPath("/org/chromium/TestObject"));
72     ASSERT_TRUE(bus_->HasDBusThread());
73
74     // Connect to the "Test" signal of "org.chromium.TestInterface" from
75     // the remote object.
76     object_proxy_->ConnectToSignal(
77         "org.chromium.TestInterface", "Test",
78         base::BindRepeating(&EndToEndAsyncTest::OnTestSignal,
79                             base::Unretained(this)),
80         base::BindOnce(&EndToEndAsyncTest::OnConnected,
81                        base::Unretained(this)));
82     // Wait until the object proxy is connected to the signal.
83     run_loop_ = std::make_unique<base::RunLoop>();
84     run_loop_->Run();
85
86     // Connect to the "Test2" signal of "org.chromium.TestInterface" from
87     // the remote object. There was a bug where we were emitting error
88     // messages like "Requested to remove an unknown match rule: ..." at
89     // the shutdown of Bus when an object proxy is connected to more than
90     // one signal of the same interface. See crosbug.com/23382 for details.
91     object_proxy_->ConnectToSignal(
92         "org.chromium.TestInterface", "Test2",
93         base::BindRepeating(&EndToEndAsyncTest::OnTest2Signal,
94                             base::Unretained(this)),
95         base::BindOnce(&EndToEndAsyncTest::OnConnected,
96                        base::Unretained(this)));
97     // Wait until the object proxy is connected to the signal.
98     run_loop_ = std::make_unique<base::RunLoop>();
99     run_loop_->Run();
100
101     // Create a second object proxy for the root object.
102     root_object_proxy_ = bus_->GetObjectProxy(test_service_->service_name(),
103                                               ObjectPath("/"));
104     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", "Test",
110         base::BindRepeating(&EndToEndAsyncTest::OnRootTestSignal,
111                             base::Unretained(this)),
112         base::BindOnce(&EndToEndAsyncTest::OnConnected,
113                        base::Unretained(this)));
114     // Wait until the root object proxy is connected to the signal.
115     run_loop_ = std::make_unique<base::RunLoop>();
116     run_loop_->Run();
117   }
118
119   void TearDown() override {
120     bus_->ShutdownOnDBusThreadAndBlock();
121
122     // Shut down the service.
123     test_service_->ShutdownAndBlock();
124
125     // Stopping a thread is considered an IO operation, so do this after
126     // allowing IO.
127     disallow_blocking_.reset();
128     test_service_->Stop();
129   }
130
131  protected:
132   // Replaces the bus with a broken one.
133   void SetUpBrokenBus() {
134     // Shut down the existing bus.
135     bus_->ShutdownOnDBusThreadAndBlock();
136
137     // Create new bus with invalid address.
138     const char kInvalidAddress[] = "";
139     Bus::Options bus_options;
140     bus_options.bus_type = Bus::CUSTOM_ADDRESS;
141     bus_options.address = kInvalidAddress;
142     bus_options.connection_type = Bus::PRIVATE;
143     bus_options.dbus_task_runner = dbus_thread_->task_runner();
144     bus_ = new Bus(bus_options);
145     ASSERT_TRUE(bus_->HasDBusThread());
146
147     // Create new object proxy.
148     object_proxy_ = bus_->GetObjectProxy(
149         test_service_->service_name(),
150         ObjectPath("/org/chromium/TestObject"));
151   }
152
153   // Calls the method asynchronously. OnResponse() will be called once the
154   // response is received.
155   void CallMethod(MethodCall* method_call,
156                   int timeout_ms) {
157     object_proxy_->CallMethod(
158         method_call, timeout_ms,
159         base::BindOnce(&EndToEndAsyncTest::OnResponse, base::Unretained(this)));
160   }
161
162   // Calls the method asynchronously. OnResponse() will be called once the
163   // response is received without error, otherwise OnError() will be called.
164   void CallMethodWithErrorCallback(MethodCall* method_call,
165                                    int timeout_ms) {
166     object_proxy_->CallMethodWithErrorCallback(
167         method_call, timeout_ms,
168         base::BindOnce(&EndToEndAsyncTest::OnResponse, base::Unretained(this)),
169         base::BindOnce(&EndToEndAsyncTest::OnError, base::Unretained(this)));
170   }
171
172   // Wait for the give number of responses.
173   void WaitForResponses(size_t num_responses) {
174     while (response_strings_.size() < num_responses) {
175       run_loop_ = std::make_unique<base::RunLoop>();
176       run_loop_->Run();
177     }
178   }
179
180   // Called when the response is received.
181   void OnResponse(Response* response) {
182     // |response| will be deleted on exit of the function. Copy the
183     // payload to |response_strings_|.
184     if (response) {
185       MessageReader reader(response);
186       std::string response_string;
187       ASSERT_TRUE(reader.PopString(&response_string));
188       response_strings_.push_back(response_string);
189     } else {
190       response_strings_.push_back(std::string());
191     }
192     run_loop_->Quit();
193   }
194
195   // Wait for the given number of errors.
196   void WaitForErrors(size_t num_errors) {
197     while (error_names_.size() < num_errors) {
198       run_loop_ = std::make_unique<base::RunLoop>();
199       run_loop_->Run();
200     }
201   }
202
203   // Called when an error is received.
204   void OnError(ErrorResponse* error) {
205     // |error| will be deleted on exit of the function. Copy the payload to
206     // |error_names_|.
207     if (error) {
208       ASSERT_NE("", error->GetErrorName());
209       error_names_.push_back(error->GetErrorName());
210     } else {
211       error_names_.push_back(std::string());
212     }
213     run_loop_->Quit();
214   }
215
216   // Called when the "Test" signal is received, in the main thread.
217   // Copy the string payload to |test_signal_string_|.
218   void OnTestSignal(Signal* signal) {
219     MessageReader reader(signal);
220     ASSERT_TRUE(reader.PopString(&test_signal_string_));
221     run_loop_->Quit();
222   }
223
224   // Called when the "Test" signal is received, in the main thread, by
225   // the root object proxy. Copy the string payload to
226   // |root_test_signal_string_|.
227   void OnRootTestSignal(Signal* signal) {
228     MessageReader reader(signal);
229     ASSERT_TRUE(reader.PopString(&root_test_signal_string_));
230     run_loop_->Quit();
231   }
232
233   // Called when the "Test2" signal is received, in the main thread.
234   void OnTest2Signal(Signal* signal) {
235     MessageReader reader(signal);
236     run_loop_->Quit();
237   }
238
239   // Called when connected to the signal.
240   void OnConnected(const std::string& interface_name,
241                    const std::string& signal_name,
242                    bool success) {
243     ASSERT_TRUE(success);
244     run_loop_->Quit();
245   }
246
247   // Wait for the hey signal to be received.
248   void WaitForTestSignal() {
249     // OnTestSignal() will quit the message loop.
250     run_loop_ = std::make_unique<base::RunLoop>();
251     run_loop_->Run();
252   }
253
254   base::test::SingleThreadTaskEnvironment task_environment_;
255   absl::optional<base::ScopedDisallowBlocking> disallow_blocking_;
256   std::unique_ptr<base::RunLoop> run_loop_;
257   std::vector<std::string> response_strings_;
258   std::vector<std::string> error_names_;
259   std::unique_ptr<base::Thread> dbus_thread_;
260   scoped_refptr<Bus> bus_;
261   raw_ptr<ObjectProxy, AcrossTasksDanglingUntriaged> object_proxy_;
262   raw_ptr<ObjectProxy, AcrossTasksDanglingUntriaged> root_object_proxy_;
263   std::unique_ptr<TestService> test_service_;
264   // Text message from "Test" signal.
265   std::string test_signal_string_;
266   // Text message from "Test" signal delivered to root.
267   std::string root_test_signal_string_;
268 };
269
270 TEST_F(EndToEndAsyncTest, Echo) {
271   const char* kHello = "hello";
272
273   // Create the method call.
274   MethodCall method_call("org.chromium.TestInterface", "Echo");
275   MessageWriter writer(&method_call);
276   writer.AppendString(kHello);
277
278   // Call the method.
279   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
280   CallMethod(&method_call, timeout_ms);
281
282   // Check the response.
283   WaitForResponses(1);
284   EXPECT_EQ(kHello, response_strings_[0]);
285 }
286
287 TEST_F(EndToEndAsyncTest, EchoWithErrorCallback) {
288   const char* kHello = "hello";
289
290   // Create the method call.
291   MethodCall method_call("org.chromium.TestInterface", "Echo");
292   MessageWriter writer(&method_call);
293   writer.AppendString(kHello);
294
295   // Call the method.
296   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
297   CallMethodWithErrorCallback(&method_call, timeout_ms);
298
299   // Check the response.
300   WaitForResponses(1);
301   EXPECT_EQ(kHello, response_strings_[0]);
302   EXPECT_TRUE(error_names_.empty());
303 }
304
305 // Call Echo method three times.
306 TEST_F(EndToEndAsyncTest, EchoThreeTimes) {
307   const char* kMessages[] = { "foo", "bar", "baz" };
308
309   for (size_t i = 0; i < std::size(kMessages); ++i) {
310     // Create the method call.
311     MethodCall method_call("org.chromium.TestInterface", "Echo");
312     MessageWriter writer(&method_call);
313     writer.AppendString(kMessages[i]);
314
315     // Call the method.
316     const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
317     CallMethod(&method_call, timeout_ms);
318   }
319
320   // Check the responses.
321   WaitForResponses(3);
322   // Sort as the order of the returned messages is not deterministic.
323   std::sort(response_strings_.begin(), response_strings_.end());
324   EXPECT_EQ("bar", response_strings_[0]);
325   EXPECT_EQ("baz", response_strings_[1]);
326   EXPECT_EQ("foo", response_strings_[2]);
327 }
328
329 TEST_F(EndToEndAsyncTest, Echo_HugePayload) {
330   const std::string kHugePayload(kHugePayloadSize, 'o');
331
332   // Create the method call with a huge payload.
333   MethodCall method_call("org.chromium.TestInterface", "Echo");
334   MessageWriter writer(&method_call);
335   writer.AppendString(kHugePayload);
336
337   // Call the method.
338   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
339   CallMethod(&method_call, timeout_ms);
340
341   // This caused a DCHECK failure before. Ensure that the issue is fixed.
342   WaitForResponses(1);
343   EXPECT_EQ(kHugePayload, response_strings_[0]);
344 }
345
346 TEST_F(EndToEndAsyncTest, BrokenBus) {
347   const char* kHello = "hello";
348
349   // Set up a broken bus.
350   SetUpBrokenBus();
351
352   // Create the method call.
353   MethodCall method_call("org.chromium.TestInterface", "Echo");
354   MessageWriter writer(&method_call);
355   writer.AppendString(kHello);
356
357   // Call the method.
358   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
359   CallMethod(&method_call, timeout_ms);
360   WaitForResponses(1);
361
362   // Should fail because of the broken bus.
363   ASSERT_EQ("", response_strings_[0]);
364 }
365
366 TEST_F(EndToEndAsyncTest, BrokenBusWithErrorCallback) {
367   const char* kHello = "hello";
368
369   // Set up a broken bus.
370   SetUpBrokenBus();
371
372   // Create the method call.
373   MethodCall method_call("org.chromium.TestInterface", "Echo");
374   MessageWriter writer(&method_call);
375   writer.AppendString(kHello);
376
377   // Call the method.
378   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
379   CallMethodWithErrorCallback(&method_call, timeout_ms);
380   WaitForErrors(1);
381
382   // Should fail because of the broken bus.
383   ASSERT_TRUE(response_strings_.empty());
384   ASSERT_EQ("", error_names_[0]);
385 }
386
387 TEST_F(EndToEndAsyncTest, Timeout) {
388   const char* kHello = "hello";
389
390   // Create the method call.
391   MethodCall method_call("org.chromium.TestInterface", "SlowEcho");
392   MessageWriter writer(&method_call);
393   writer.AppendString(kHello);
394
395   // Call the method with timeout of 0ms.
396   const int timeout_ms = 0;
397   CallMethod(&method_call, timeout_ms);
398   WaitForResponses(1);
399
400   // Should fail because of timeout.
401   ASSERT_EQ("", response_strings_[0]);
402 }
403
404 TEST_F(EndToEndAsyncTest, TimeoutWithErrorCallback) {
405   const char* kHello = "hello";
406
407   // Create the method call.
408   MethodCall method_call("org.chromium.TestInterface", "SlowEcho");
409   MessageWriter writer(&method_call);
410   writer.AppendString(kHello);
411
412   // Call the method with timeout of 0ms.
413   const int timeout_ms = 0;
414   CallMethodWithErrorCallback(&method_call, timeout_ms);
415   WaitForErrors(1);
416
417   // Should fail because of timeout.
418   ASSERT_TRUE(response_strings_.empty());
419   ASSERT_EQ(DBUS_ERROR_NO_REPLY, error_names_[0]);
420 }
421
422 TEST_F(EndToEndAsyncTest, CancelPendingCalls) {
423   const char* kHello = "hello";
424
425   // Create the method call.
426   MethodCall method_call("org.chromium.TestInterface", "Echo");
427   MessageWriter writer(&method_call);
428   writer.AppendString(kHello);
429
430   // Call the method.
431   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
432   CallMethod(&method_call, timeout_ms);
433
434   // Remove the object proxy before receiving the result.
435   // This results in cancelling the pending method call.
436   bus_->RemoveObjectProxy(test_service_->service_name(),
437                           ObjectPath("/org/chromium/TestObject"),
438                           base::DoNothing());
439
440   // We shouldn't receive any responses. Wait for a while just to make sure.
441   run_loop_ = std::make_unique<base::RunLoop>();
442   task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
443       FROM_HERE, run_loop_->QuitClosure(), TestTimeouts::tiny_timeout());
444   run_loop_->Run();
445   EXPECT_TRUE(response_strings_.empty());
446 }
447
448 // Tests calling a method that sends its reply asynchronously.
449 TEST_F(EndToEndAsyncTest, AsyncEcho) {
450   const char* kHello = "hello";
451
452   // Create the method call.
453   MethodCall method_call("org.chromium.TestInterface", "AsyncEcho");
454   MessageWriter writer(&method_call);
455   writer.AppendString(kHello);
456
457   // Call the method.
458   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
459   CallMethod(&method_call, timeout_ms);
460
461   // Check the response.
462   WaitForResponses(1);
463   EXPECT_EQ(kHello, response_strings_[0]);
464 }
465
466 TEST_F(EndToEndAsyncTest, NonexistentMethod) {
467   MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
468
469   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
470   CallMethod(&method_call, timeout_ms);
471   WaitForResponses(1);
472
473   // Should fail because the method is nonexistent.
474   ASSERT_EQ("", response_strings_[0]);
475 }
476
477 TEST_F(EndToEndAsyncTest, NonexistentMethodWithErrorCallback) {
478   MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
479
480   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
481   CallMethodWithErrorCallback(&method_call, timeout_ms);
482   WaitForErrors(1);
483
484   // Should fail because the method is nonexistent.
485   ASSERT_TRUE(response_strings_.empty());
486   ASSERT_EQ(DBUS_ERROR_UNKNOWN_METHOD, error_names_[0]);
487 }
488
489 TEST_F(EndToEndAsyncTest, BrokenMethod) {
490   MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
491
492   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
493   CallMethod(&method_call, timeout_ms);
494   WaitForResponses(1);
495
496   // Should fail because the method is broken.
497   ASSERT_EQ("", response_strings_[0]);
498 }
499
500 TEST_F(EndToEndAsyncTest, BrokenMethodWithErrorCallback) {
501   MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
502
503   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
504   CallMethodWithErrorCallback(&method_call, timeout_ms);
505   WaitForErrors(1);
506
507   // Should fail because the method is broken.
508   ASSERT_TRUE(response_strings_.empty());
509   ASSERT_EQ(DBUS_ERROR_FAILED, error_names_[0]);
510 }
511
512 TEST_F(EndToEndAsyncTest, InvalidServiceName) {
513   // Bus name cannot contain '/'.
514   const std::string invalid_service_name = ":1/2";
515
516   // Replace object proxy with new one.
517   object_proxy_ = bus_->GetObjectProxy(invalid_service_name,
518                                        ObjectPath("/org/chromium/TestObject"));
519
520   MethodCall method_call("org.chromium.TestInterface", "Echo");
521
522   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
523   CallMethodWithErrorCallback(&method_call, timeout_ms);
524   WaitForErrors(1);
525
526   // Should fail because of the invalid bus name.
527   ASSERT_TRUE(response_strings_.empty());
528   ASSERT_EQ("", error_names_[0]);
529 }
530
531 TEST_F(EndToEndAsyncTest, EmptyResponseCallback) {
532   const char* kHello = "hello";
533
534   // Create the method call.
535   MethodCall method_call("org.chromium.TestInterface", "Echo");
536   MessageWriter writer(&method_call);
537   writer.AppendString(kHello);
538
539   // Call the method with an empty callback.
540   const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
541   object_proxy_->CallMethod(&method_call, timeout_ms, base::DoNothing());
542   // Post a delayed task to quit the RunLoop.
543   run_loop_ = std::make_unique<base::RunLoop>();
544   task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
545       FROM_HERE, run_loop_->QuitClosure(), TestTimeouts::tiny_timeout());
546   run_loop_->Run();
547   // We cannot tell if the empty callback is called, but at least we can
548   // check if the test does not crash.
549 }
550
551 TEST_F(EndToEndAsyncTest, TestSignal) {
552   const char kMessage[] = "hello, world";
553   // Send the test signal from the exported object.
554   test_service_->SendTestSignal(kMessage);
555   // Receive the signal with the object proxy. The signal is handled in
556   // EndToEndAsyncTest::OnTestSignal() in the main thread.
557   WaitForTestSignal();
558   ASSERT_EQ(kMessage, test_signal_string_);
559 }
560
561 TEST_F(EndToEndAsyncTest, TestSignalFromRoot) {
562   const char kMessage[] = "hello, world";
563   // Object proxies are tied to a particular object path, if a signal
564   // arrives from a different object path like "/" the first object proxy
565   // |object_proxy_| should not handle it, and should leave it for the root
566   // object proxy |root_object_proxy_|.
567   test_service_->SendTestSignalFromRoot(kMessage);
568   WaitForTestSignal();
569   // Verify the signal was not received by the specific proxy.
570   ASSERT_TRUE(test_signal_string_.empty());
571   // Verify the string WAS received by the root proxy.
572   ASSERT_EQ(kMessage, root_test_signal_string_);
573 }
574
575 TEST_F(EndToEndAsyncTest, TestHugeSignal) {
576   const std::string kHugeMessage(kHugePayloadSize, 'o');
577
578   // Send the huge signal from the exported object.
579   test_service_->SendTestSignal(kHugeMessage);
580   // This caused a DCHECK failure before. Ensure that the issue is fixed.
581   WaitForTestSignal();
582   ASSERT_EQ(kHugeMessage, test_signal_string_);
583 }
584
585 class SignalMultipleHandlerTest : public EndToEndAsyncTest {
586  public:
587   SignalMultipleHandlerTest() = default;
588
589   void SetUp() override {
590     // Set up base class.
591     EndToEndAsyncTest::SetUp();
592
593     // Connect the root object proxy's signal handler to a new handler
594     // so that we can verify that a second call to ConnectSignal() delivers
595     // to both our new handler and the old.
596     object_proxy_->ConnectToSignal(
597         "org.chromium.TestInterface", "Test",
598         base::BindRepeating(&SignalMultipleHandlerTest::OnAdditionalTestSignal,
599                             base::Unretained(this)),
600         base::BindOnce(&SignalMultipleHandlerTest::OnAdditionalConnected,
601                        base::Unretained(this)));
602     // Wait until the object proxy is connected to the signal.
603     run_loop_ = std::make_unique<base::RunLoop>();
604     run_loop_->Run();
605   }
606
607  protected:
608   // Called when the "Test" signal is received, in the main thread.
609   // Copy the string payload to |additional_test_signal_string_|.
610   void OnAdditionalTestSignal(Signal* signal) {
611     MessageReader reader(signal);
612     ASSERT_TRUE(reader.PopString(&additional_test_signal_string_));
613     run_loop_->Quit();
614   }
615
616   // Called when connected to the signal.
617   void OnAdditionalConnected(const std::string& interface_name,
618                              const std::string& signal_name,
619                              bool success) {
620     ASSERT_TRUE(success);
621     run_loop_->Quit();
622   }
623
624   // Text message from "Test" signal delivered to additional handler.
625   std::string additional_test_signal_string_;
626 };
627
628 TEST_F(SignalMultipleHandlerTest, TestMultipleHandlers) {
629   const char kMessage[] = "hello, world";
630   // Send the test signal from the exported object.
631   test_service_->SendTestSignal(kMessage);
632   // Receive the signal with the object proxy.
633   WaitForTestSignal();
634   // Verify the string WAS received by the original handler.
635   ASSERT_EQ(kMessage, test_signal_string_);
636   // Verify the signal WAS ALSO received by the additional handler.
637   ASSERT_EQ(kMessage, additional_test_signal_string_);
638 }
639
640 }  // namespace dbus