mock_unittest.cc 7.3 KB

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