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