xref: /aosp_15_r20/external/libchrome/dbus/mock_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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