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