1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include <memory>
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
8*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
9*635a8641SAndroid Build Coastguard Worker #include "base/memory/ref_counted.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/message_loop/message_loop.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/run_loop.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/single_thread_task_runner.h"
13*635a8641SAndroid Build Coastguard Worker #include "dbus/message.h"
14*635a8641SAndroid Build Coastguard Worker #include "dbus/mock_bus.h"
15*635a8641SAndroid Build Coastguard Worker #include "dbus/mock_exported_object.h"
16*635a8641SAndroid Build Coastguard Worker #include "dbus/mock_object_proxy.h"
17*635a8641SAndroid Build Coastguard Worker #include "dbus/object_path.h"
18*635a8641SAndroid Build Coastguard Worker #include "dbus/scoped_dbus_error.h"
19*635a8641SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
20*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
21*635a8641SAndroid Build Coastguard Worker
22*635a8641SAndroid Build Coastguard Worker using ::testing::_;
23*635a8641SAndroid Build Coastguard Worker using ::testing::Invoke;
24*635a8641SAndroid Build Coastguard Worker using ::testing::Return;
25*635a8641SAndroid Build Coastguard Worker using ::testing::Unused;
26*635a8641SAndroid Build Coastguard Worker
27*635a8641SAndroid Build Coastguard Worker namespace dbus {
28*635a8641SAndroid Build Coastguard Worker
29*635a8641SAndroid Build Coastguard Worker class MockTest : public testing::Test {
30*635a8641SAndroid Build Coastguard Worker public:
31*635a8641SAndroid Build Coastguard Worker MockTest() = default;
32*635a8641SAndroid Build Coastguard Worker
SetUp()33*635a8641SAndroid Build Coastguard Worker void SetUp() override {
34*635a8641SAndroid Build Coastguard Worker // Create a mock bus.
35*635a8641SAndroid Build Coastguard Worker Bus::Options options;
36*635a8641SAndroid Build Coastguard Worker options.bus_type = Bus::SYSTEM;
37*635a8641SAndroid Build Coastguard Worker mock_bus_ = new MockBus(options);
38*635a8641SAndroid Build Coastguard Worker
39*635a8641SAndroid Build Coastguard Worker // Create a mock proxy.
40*635a8641SAndroid Build Coastguard Worker mock_proxy_ = new MockObjectProxy(
41*635a8641SAndroid Build Coastguard Worker mock_bus_.get(),
42*635a8641SAndroid Build Coastguard Worker "org.chromium.TestService",
43*635a8641SAndroid Build Coastguard Worker ObjectPath("/org/chromium/TestObject"));
44*635a8641SAndroid Build Coastguard Worker
45*635a8641SAndroid Build Coastguard Worker // Set an expectation so mock_proxy's CallMethodAndBlock() will use
46*635a8641SAndroid Build Coastguard Worker // CreateMockProxyResponse() to return responses.
47*635a8641SAndroid Build Coastguard Worker EXPECT_CALL(*mock_proxy_.get(), CallMethodAndBlock(_, _))
48*635a8641SAndroid Build Coastguard Worker .WillRepeatedly(Invoke(this, &MockTest::CreateMockProxyResponse));
49*635a8641SAndroid Build Coastguard Worker EXPECT_CALL(*mock_proxy_.get(),
50*635a8641SAndroid Build Coastguard Worker CallMethodAndBlockWithErrorDetails(_, _, _))
51*635a8641SAndroid Build Coastguard Worker .WillRepeatedly(
52*635a8641SAndroid Build Coastguard Worker Invoke(this, &MockTest::CreateMockProxyResponseWithErrorDetails));
53*635a8641SAndroid Build Coastguard Worker
54*635a8641SAndroid Build Coastguard Worker // Set an expectation so mock_proxy's CallMethod() will use
55*635a8641SAndroid Build Coastguard Worker // HandleMockProxyResponseWithMessageLoop() to return responses.
56*635a8641SAndroid Build Coastguard Worker EXPECT_CALL(*mock_proxy_.get(), DoCallMethod(_, _, _))
57*635a8641SAndroid Build Coastguard Worker .WillRepeatedly(
58*635a8641SAndroid Build Coastguard Worker Invoke(this, &MockTest::HandleMockProxyResponseWithMessageLoop));
59*635a8641SAndroid Build Coastguard Worker
60*635a8641SAndroid Build Coastguard Worker // Set an expectation so mock_bus's GetObjectProxy() for the given
61*635a8641SAndroid Build Coastguard Worker // service name and the object path will return mock_proxy_.
62*635a8641SAndroid Build Coastguard Worker EXPECT_CALL(*mock_bus_.get(),
63*635a8641SAndroid Build Coastguard Worker GetObjectProxy("org.chromium.TestService",
64*635a8641SAndroid Build Coastguard Worker ObjectPath("/org/chromium/TestObject")))
65*635a8641SAndroid Build Coastguard Worker .WillOnce(Return(mock_proxy_.get()));
66*635a8641SAndroid Build Coastguard Worker
67*635a8641SAndroid Build Coastguard Worker // ShutdownAndBlock() will be called in TearDown().
68*635a8641SAndroid Build Coastguard Worker EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
69*635a8641SAndroid Build Coastguard Worker }
70*635a8641SAndroid Build Coastguard Worker
TearDown()71*635a8641SAndroid Build Coastguard Worker void TearDown() override { mock_bus_->ShutdownAndBlock(); }
72*635a8641SAndroid Build Coastguard Worker
73*635a8641SAndroid Build Coastguard Worker // Called when the response is received.
OnResponse(Response * response)74*635a8641SAndroid Build Coastguard Worker void OnResponse(Response* response) {
75*635a8641SAndroid Build Coastguard Worker // |response| will be deleted on exit of the function. Copy the
76*635a8641SAndroid Build Coastguard Worker // payload to |response_string_|.
77*635a8641SAndroid Build Coastguard Worker if (response) {
78*635a8641SAndroid Build Coastguard Worker MessageReader reader(response);
79*635a8641SAndroid Build Coastguard Worker ASSERT_TRUE(reader.PopString(&response_string_));
80*635a8641SAndroid Build Coastguard Worker }
81*635a8641SAndroid Build Coastguard Worker run_loop_->Quit();
82*635a8641SAndroid Build Coastguard Worker };
83*635a8641SAndroid Build Coastguard Worker
84*635a8641SAndroid Build Coastguard Worker protected:
85*635a8641SAndroid Build Coastguard Worker std::string response_string_;
86*635a8641SAndroid Build Coastguard Worker base::MessageLoop message_loop_;
87*635a8641SAndroid Build Coastguard Worker std::unique_ptr<base::RunLoop> run_loop_;
88*635a8641SAndroid Build Coastguard Worker scoped_refptr<MockBus> mock_bus_;
89*635a8641SAndroid Build Coastguard Worker scoped_refptr<MockObjectProxy> mock_proxy_;
90*635a8641SAndroid Build Coastguard Worker
91*635a8641SAndroid Build Coastguard Worker private:
92*635a8641SAndroid Build Coastguard Worker // Returns a response for the given method call. Used to implement
93*635a8641SAndroid Build Coastguard Worker // CallMethodAndBlock() for |mock_proxy_|.
CreateMockProxyResponse(MethodCall * method_call,int timeout_ms)94*635a8641SAndroid Build Coastguard Worker std::unique_ptr<Response> CreateMockProxyResponse(MethodCall* method_call,
95*635a8641SAndroid Build Coastguard Worker int timeout_ms) {
96*635a8641SAndroid Build Coastguard Worker if (method_call->GetInterface() == "org.chromium.TestInterface" &&
97*635a8641SAndroid Build Coastguard Worker method_call->GetMember() == "Echo") {
98*635a8641SAndroid Build Coastguard Worker MessageReader reader(method_call);
99*635a8641SAndroid Build Coastguard Worker std::string text_message;
100*635a8641SAndroid Build Coastguard Worker if (reader.PopString(&text_message)) {
101*635a8641SAndroid Build Coastguard Worker std::unique_ptr<Response> response = Response::CreateEmpty();
102*635a8641SAndroid Build Coastguard Worker MessageWriter writer(response.get());
103*635a8641SAndroid Build Coastguard Worker writer.AppendString(text_message);
104*635a8641SAndroid Build Coastguard Worker return response;
105*635a8641SAndroid Build Coastguard Worker }
106*635a8641SAndroid Build Coastguard Worker }
107*635a8641SAndroid Build Coastguard Worker
108*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Unexpected method call: " << method_call->ToString();
109*635a8641SAndroid Build Coastguard Worker return nullptr;
110*635a8641SAndroid Build Coastguard Worker }
111*635a8641SAndroid Build Coastguard Worker
CreateMockProxyResponseWithErrorDetails(MethodCall * method_call,int timeout_ms,ScopedDBusError * error)112*635a8641SAndroid Build Coastguard Worker std::unique_ptr<Response> CreateMockProxyResponseWithErrorDetails(
113*635a8641SAndroid Build Coastguard Worker MethodCall* method_call, int timeout_ms, ScopedDBusError* error) {
114*635a8641SAndroid Build Coastguard Worker dbus_set_error(error->get(), DBUS_ERROR_NOT_SUPPORTED, "Not implemented");
115*635a8641SAndroid Build Coastguard Worker return nullptr;
116*635a8641SAndroid Build Coastguard Worker }
117*635a8641SAndroid Build Coastguard Worker
118*635a8641SAndroid Build Coastguard Worker // Creates a response and runs the given response callback in the
119*635a8641SAndroid Build Coastguard Worker // message loop with the response. Used to implement for |mock_proxy_|.
HandleMockProxyResponseWithMessageLoop(MethodCall * method_call,int timeout_ms,ObjectProxy::ResponseCallback * response_callback)120*635a8641SAndroid Build Coastguard Worker void HandleMockProxyResponseWithMessageLoop(
121*635a8641SAndroid Build Coastguard Worker MethodCall* method_call,
122*635a8641SAndroid Build Coastguard Worker int timeout_ms,
123*635a8641SAndroid Build Coastguard Worker ObjectProxy::ResponseCallback* response_callback) {
124*635a8641SAndroid Build Coastguard Worker std::unique_ptr<Response> response =
125*635a8641SAndroid Build Coastguard Worker CreateMockProxyResponse(method_call, timeout_ms);
126*635a8641SAndroid Build Coastguard Worker message_loop_.task_runner()->PostTask(
127*635a8641SAndroid Build Coastguard Worker FROM_HERE,
128*635a8641SAndroid Build Coastguard Worker base::BindOnce(&MockTest::RunResponseCallback, base::Unretained(this),
129*635a8641SAndroid Build Coastguard Worker std::move(*response_callback), std::move(response)));
130*635a8641SAndroid Build Coastguard Worker }
131*635a8641SAndroid Build Coastguard Worker
132*635a8641SAndroid Build Coastguard Worker // Runs the given response callback with the given response.
RunResponseCallback(ObjectProxy::ResponseCallback response_callback,std::unique_ptr<Response> response)133*635a8641SAndroid Build Coastguard Worker void RunResponseCallback(
134*635a8641SAndroid Build Coastguard Worker ObjectProxy::ResponseCallback response_callback,
135*635a8641SAndroid Build Coastguard Worker std::unique_ptr<Response> response) {
136*635a8641SAndroid Build Coastguard Worker std::move(response_callback).Run(response.get());
137*635a8641SAndroid Build Coastguard Worker }
138*635a8641SAndroid Build Coastguard Worker };
139*635a8641SAndroid Build Coastguard Worker
140*635a8641SAndroid Build Coastguard Worker // This test demonstrates how to mock a synchronous method call using the
141*635a8641SAndroid Build Coastguard Worker // mock classes.
TEST_F(MockTest,CallMethodAndBlock)142*635a8641SAndroid Build Coastguard Worker TEST_F(MockTest, CallMethodAndBlock) {
143*635a8641SAndroid Build Coastguard Worker const char kHello[] = "Hello";
144*635a8641SAndroid Build Coastguard Worker // Get an object proxy from the mock bus.
145*635a8641SAndroid Build Coastguard Worker ObjectProxy* proxy = mock_bus_->GetObjectProxy(
146*635a8641SAndroid Build Coastguard Worker "org.chromium.TestService",
147*635a8641SAndroid Build Coastguard Worker ObjectPath("/org/chromium/TestObject"));
148*635a8641SAndroid Build Coastguard Worker
149*635a8641SAndroid Build Coastguard Worker // Create a method call.
150*635a8641SAndroid Build Coastguard Worker MethodCall method_call("org.chromium.TestInterface", "Echo");
151*635a8641SAndroid Build Coastguard Worker MessageWriter writer(&method_call);
152*635a8641SAndroid Build Coastguard Worker writer.AppendString(kHello);
153*635a8641SAndroid Build Coastguard Worker
154*635a8641SAndroid Build Coastguard Worker // Call the method.
155*635a8641SAndroid Build Coastguard Worker std::unique_ptr<Response> response(proxy->CallMethodAndBlock(
156*635a8641SAndroid Build Coastguard Worker &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));
157*635a8641SAndroid Build Coastguard Worker
158*635a8641SAndroid Build Coastguard Worker // Check the response.
159*635a8641SAndroid Build Coastguard Worker ASSERT_TRUE(response.get());
160*635a8641SAndroid Build Coastguard Worker MessageReader reader(response.get());
161*635a8641SAndroid Build Coastguard Worker std::string text_message;
162*635a8641SAndroid Build Coastguard Worker ASSERT_TRUE(reader.PopString(&text_message));
163*635a8641SAndroid Build Coastguard Worker // The text message should be echo'ed back.
164*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kHello, text_message);
165*635a8641SAndroid Build Coastguard Worker }
166*635a8641SAndroid Build Coastguard Worker
TEST_F(MockTest,CallMethodAndBlockWithErrorDetails)167*635a8641SAndroid Build Coastguard Worker TEST_F(MockTest, CallMethodAndBlockWithErrorDetails) {
168*635a8641SAndroid Build Coastguard Worker // Get an object proxy from the mock bus.
169*635a8641SAndroid Build Coastguard Worker ObjectProxy* proxy = mock_bus_->GetObjectProxy(
170*635a8641SAndroid Build Coastguard Worker "org.chromium.TestService",
171*635a8641SAndroid Build Coastguard Worker ObjectPath("/org/chromium/TestObject"));
172*635a8641SAndroid Build Coastguard Worker
173*635a8641SAndroid Build Coastguard Worker // Create a method call.
174*635a8641SAndroid Build Coastguard Worker MethodCall method_call("org.chromium.TestInterface", "Echo");
175*635a8641SAndroid Build Coastguard Worker
176*635a8641SAndroid Build Coastguard Worker ScopedDBusError error;
177*635a8641SAndroid Build Coastguard Worker // Call the method.
178*635a8641SAndroid Build Coastguard Worker std::unique_ptr<Response> response(proxy->CallMethodAndBlockWithErrorDetails(
179*635a8641SAndroid Build Coastguard Worker &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT, &error));
180*635a8641SAndroid Build Coastguard Worker
181*635a8641SAndroid Build Coastguard Worker // Check the response.
182*635a8641SAndroid Build Coastguard Worker ASSERT_FALSE(response.get());
183*635a8641SAndroid Build Coastguard Worker ASSERT_TRUE(error.is_set());
184*635a8641SAndroid Build Coastguard Worker EXPECT_STREQ(DBUS_ERROR_NOT_SUPPORTED, error.name());
185*635a8641SAndroid Build Coastguard Worker EXPECT_STREQ("Not implemented", error.message());
186*635a8641SAndroid Build Coastguard Worker }
187*635a8641SAndroid Build Coastguard Worker
188*635a8641SAndroid Build Coastguard Worker // This test demonstrates how to mock an asynchronous method call using the
189*635a8641SAndroid Build Coastguard Worker // mock classes.
TEST_F(MockTest,CallMethod)190*635a8641SAndroid Build Coastguard Worker TEST_F(MockTest, CallMethod) {
191*635a8641SAndroid Build Coastguard Worker const char kHello[] = "hello";
192*635a8641SAndroid Build Coastguard Worker
193*635a8641SAndroid Build Coastguard Worker // Get an object proxy from the mock bus.
194*635a8641SAndroid Build Coastguard Worker ObjectProxy* proxy = mock_bus_->GetObjectProxy(
195*635a8641SAndroid Build Coastguard Worker "org.chromium.TestService",
196*635a8641SAndroid Build Coastguard Worker ObjectPath("/org/chromium/TestObject"));
197*635a8641SAndroid Build Coastguard Worker
198*635a8641SAndroid Build Coastguard Worker // Create a method call.
199*635a8641SAndroid Build Coastguard Worker MethodCall method_call("org.chromium.TestInterface", "Echo");
200*635a8641SAndroid Build Coastguard Worker MessageWriter writer(&method_call);
201*635a8641SAndroid Build Coastguard Worker writer.AppendString(kHello);
202*635a8641SAndroid Build Coastguard Worker
203*635a8641SAndroid Build Coastguard Worker // Call the method.
204*635a8641SAndroid Build Coastguard Worker run_loop_.reset(new base::RunLoop);
205*635a8641SAndroid Build Coastguard Worker proxy->CallMethod(&method_call,
206*635a8641SAndroid Build Coastguard Worker ObjectProxy::TIMEOUT_USE_DEFAULT,
207*635a8641SAndroid Build Coastguard Worker base::Bind(&MockTest::OnResponse,
208*635a8641SAndroid Build Coastguard Worker base::Unretained(this)));
209*635a8641SAndroid Build Coastguard Worker // Run the message loop to let OnResponse be called.
210*635a8641SAndroid Build Coastguard Worker run_loop_->Run();
211*635a8641SAndroid Build Coastguard Worker
212*635a8641SAndroid Build Coastguard Worker EXPECT_EQ(kHello, response_string_);
213*635a8641SAndroid Build Coastguard Worker }
214*635a8641SAndroid Build Coastguard Worker
215*635a8641SAndroid Build Coastguard Worker } // namespace dbus
216