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