Updating trunk VERSION from 912.0 to 913.0
[chromium-blink-merge.git] / dbus / end_to_end_async_unittest.cc
blob7d52130b954190904461701979f2edc7ea5982ee
1 // Copyright (c) 2011 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.
5 #include <algorithm>
6 #include <string>
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop.h"
12 #include "base/stl_util.h"
13 #include "base/threading/thread.h"
14 #include "base/threading/thread_restrictions.h"
15 #include "dbus/bus.h"
16 #include "dbus/message.h"
17 #include "dbus/object_proxy.h"
18 #include "dbus/test_service.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 // The end-to-end test exercises the asynchronous APIs in ObjectProxy and
22 // ExportedObject.
23 class EndToEndAsyncTest : public testing::Test {
24 public:
25 EndToEndAsyncTest() {
28 virtual void SetUp() {
29 // Make the main thread not to allow IO.
30 base::ThreadRestrictions::SetIOAllowed(false);
32 // Start the D-Bus thread.
33 dbus_thread_.reset(new base::Thread("D-Bus Thread"));
34 base::Thread::Options thread_options;
35 thread_options.message_loop_type = MessageLoop::TYPE_IO;
36 ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options));
38 // Start the test service, using the D-Bus thread.
39 dbus::TestService::Options options;
40 options.dbus_thread_message_loop_proxy = dbus_thread_->message_loop_proxy();
41 test_service_.reset(new dbus::TestService(options));
42 ASSERT_TRUE(test_service_->StartService());
43 ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
44 ASSERT_TRUE(test_service_->HasDBusThread());
46 // Create the client, using the D-Bus thread.
47 dbus::Bus::Options bus_options;
48 bus_options.bus_type = dbus::Bus::SESSION;
49 bus_options.connection_type = dbus::Bus::PRIVATE;
50 bus_options.dbus_thread_message_loop_proxy =
51 dbus_thread_->message_loop_proxy();
52 bus_ = new dbus::Bus(bus_options);
53 object_proxy_ = bus_->GetObjectProxy("org.chromium.TestService",
54 "/org/chromium/TestObject");
55 ASSERT_TRUE(bus_->HasDBusThread());
57 // Connect to the "Test" signal from the remote object.
58 object_proxy_->ConnectToSignal(
59 "org.chromium.TestInterface",
60 "Test",
61 base::Bind(&EndToEndAsyncTest::OnTestSignal,
62 base::Unretained(this)),
63 base::Bind(&EndToEndAsyncTest::OnConnected,
64 base::Unretained(this)));
65 // Wait until the object proxy is connected to the signal.
66 message_loop_.Run();
69 virtual void TearDown() {
70 bus_->ShutdownOnDBusThreadAndBlock();
72 // Shut down the service.
73 test_service_->ShutdownAndBlock();
75 // Reset to the default.
76 base::ThreadRestrictions::SetIOAllowed(true);
78 // Stopping a thread is considered an IO operation, so do this after
79 // allowing IO.
80 test_service_->Stop();
83 protected:
84 // Calls the method asynchronously. OnResponse() will be called once the
85 // response is received.
86 void CallMethod(dbus::MethodCall* method_call,
87 int timeout_ms) {
88 object_proxy_->CallMethod(method_call,
89 timeout_ms,
90 base::Bind(&EndToEndAsyncTest::OnResponse,
91 base::Unretained(this)));
94 // Wait for the give number of responses.
95 void WaitForResponses(size_t num_responses) {
96 while (response_strings_.size() < num_responses) {
97 message_loop_.Run();
101 // Called when the response is received.
102 void OnResponse(dbus::Response* response) {
103 // |response| will be deleted on exit of the function. Copy the
104 // payload to |response_strings_|.
105 if (response) {
106 dbus::MessageReader reader(response);
107 std::string response_string;
108 ASSERT_TRUE(reader.PopString(&response_string));
109 response_strings_.push_back(response_string);
110 } else {
111 response_strings_.push_back("");
113 message_loop_.Quit();
116 // Called when the "Test" signal is received, in the main thread.
117 // Copy the string payload to |test_signal_string_|.
118 void OnTestSignal(dbus::Signal* signal) {
119 dbus::MessageReader reader(signal);
120 ASSERT_TRUE(reader.PopString(&test_signal_string_));
121 message_loop_.Quit();
124 // Called when connected to the signal.
125 void OnConnected(const std::string& interface_name,
126 const std::string& signal_name,
127 bool success) {
128 ASSERT_TRUE(success);
129 message_loop_.Quit();
132 // Wait for the hey signal to be received.
133 void WaitForTestSignal() {
134 // OnTestSignal() will quit the message loop.
135 message_loop_.Run();
138 MessageLoop message_loop_;
139 std::vector<std::string> response_strings_;
140 scoped_ptr<base::Thread> dbus_thread_;
141 scoped_refptr<dbus::Bus> bus_;
142 dbus::ObjectProxy* object_proxy_;
143 scoped_ptr<dbus::TestService> test_service_;
144 // Text message from "Test" signal.
145 std::string test_signal_string_;
148 TEST_F(EndToEndAsyncTest, Echo) {
149 const char* kHello = "hello";
151 // Create the method call.
152 dbus::MethodCall method_call("org.chromium.TestInterface", "Echo");
153 dbus::MessageWriter writer(&method_call);
154 writer.AppendString(kHello);
156 // Call the method.
157 const int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT;
158 CallMethod(&method_call, timeout_ms);
160 // Check the response.
161 WaitForResponses(1);
162 EXPECT_EQ(kHello, response_strings_[0]);
165 // Call Echo method three times.
166 TEST_F(EndToEndAsyncTest, EchoThreeTimes) {
167 const char* kMessages[] = { "foo", "bar", "baz" };
169 for (size_t i = 0; i < arraysize(kMessages); ++i) {
170 // Create the method call.
171 dbus::MethodCall method_call("org.chromium.TestInterface", "Echo");
172 dbus::MessageWriter writer(&method_call);
173 writer.AppendString(kMessages[i]);
175 // Call the method.
176 const int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT;
177 CallMethod(&method_call, timeout_ms);
180 // Check the responses.
181 WaitForResponses(3);
182 // Sort as the order of the returned messages is not deterministic.
183 std::sort(response_strings_.begin(), response_strings_.end());
184 EXPECT_EQ("bar", response_strings_[0]);
185 EXPECT_EQ("baz", response_strings_[1]);
186 EXPECT_EQ("foo", response_strings_[2]);
189 TEST_F(EndToEndAsyncTest, Timeout) {
190 const char* kHello = "hello";
192 // Create the method call.
193 dbus::MethodCall method_call("org.chromium.TestInterface", "SlowEcho");
194 dbus::MessageWriter writer(&method_call);
195 writer.AppendString(kHello);
197 // Call the method with timeout of 0ms.
198 const int timeout_ms = 0;
199 CallMethod(&method_call, timeout_ms);
200 WaitForResponses(1);
202 // Should fail because of timeout.
203 ASSERT_EQ("", response_strings_[0]);
206 TEST_F(EndToEndAsyncTest, NonexistentMethod) {
207 dbus::MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
209 const int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT;
210 CallMethod(&method_call, timeout_ms);
211 WaitForResponses(1);
213 // Should fail because the method is nonexistent.
214 ASSERT_EQ("", response_strings_[0]);
217 TEST_F(EndToEndAsyncTest, BrokenMethod) {
218 dbus::MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
220 const int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT;
221 CallMethod(&method_call, timeout_ms);
222 WaitForResponses(1);
224 // Should fail because the method is broken.
225 ASSERT_EQ("", response_strings_[0]);
228 TEST_F(EndToEndAsyncTest, TestSignal) {
229 const char kMessage[] = "hello, world";
230 // Send the test signal from the exported object.
231 test_service_->SendTestSignal(kMessage);
232 // Receive the signal with the object proxy. The signal is handled in
233 // EndToEndAsyncTest::OnTestSignal() in the main thread.
234 WaitForTestSignal();
235 ASSERT_EQ(kMessage, test_signal_string_);
238 TEST_F(EndToEndAsyncTest, TestSignalFromRoot) {
239 const char kMessage[] = "hello, world";
240 // Send the test signal from the root object path, to see if we can
241 // handle signals sent from "/", like dbus-send does.
242 test_service_->SendTestSignalFromRoot(kMessage);
243 // Receive the signal with the object proxy. The signal is handled in
244 // EndToEndAsyncTest::OnTestSignal() in the main thread.
245 WaitForTestSignal();
246 ASSERT_EQ(kMessage, test_signal_string_);