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 "chrome/browser/chromeos/dbus/service_provider_test_helper.h"
6
7#include "base/bind.h"
8#include "dbus/message.h"
9#include "dbus/mock_bus.h"
10#include "testing/gmock/include/gmock/gmock.h"
11#include "testing/gtest/include/gtest/gtest.h"
12#include "third_party/cros_system_api/dbus/service_constants.h"
13
14using ::testing::_;
15using ::testing::AllOf;
16using ::testing::Invoke;
17using ::testing::ResultOf;
18using ::testing::Return;
19using ::testing::Unused;
20
21namespace chromeos {
22
23ServiceProviderTestHelper::ServiceProviderTestHelper()
24    : response_received_(false) {
25}
26
27ServiceProviderTestHelper::~ServiceProviderTestHelper() {
28}
29
30void ServiceProviderTestHelper::SetUp(
31    const std::string& exported_method_name,
32    CrosDBusService::ServiceProviderInterface* service_provider) {
33  // Create a mock bus.
34  dbus::Bus::Options options;
35  options.bus_type = dbus::Bus::SYSTEM;
36  mock_bus_ = new dbus::MockBus(options);
37
38  // ShutdownAndBlock() will be called in TearDown().
39  EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
40
41  // Create a mock exported object that behaves as
42  // org.chromium.CrosDBusService.
43  mock_exported_object_ =
44      new dbus::MockExportedObject(mock_bus_.get(),
45                                   dbus::ObjectPath(kLibCrosServicePath));
46
47  // |mock_exported_object_|'s ExportMethod() will use
48  // |MockExportedObject().
49  EXPECT_CALL(
50      *mock_exported_object_.get(),
51      ExportMethod(kLibCrosServiceInterface, exported_method_name, _, _))
52      .WillOnce(Invoke(this, &ServiceProviderTestHelper::MockExportMethod));
53
54  // Create a mock object proxy, with which we call a method of
55  // |mock_exported_object_|.
56  mock_object_proxy_ =
57      new dbus::MockObjectProxy(mock_bus_.get(),
58                                kLibCrosServiceName,
59                                dbus::ObjectPath(kLibCrosServicePath));
60  // |mock_object_proxy_|'s MockCallMethodAndBlock() will use
61  // MockCallMethodAndBlock() to return responses.
62  EXPECT_CALL(*mock_object_proxy_.get(),
63              MockCallMethodAndBlock(
64                  AllOf(ResultOf(std::mem_fun(&dbus::MethodCall::GetInterface),
65                                 kLibCrosServiceInterface),
66                        ResultOf(std::mem_fun(&dbus::MethodCall::GetMember),
67                                 exported_method_name)),
68                  _))
69      .WillOnce(
70           Invoke(this, &ServiceProviderTestHelper::MockCallMethodAndBlock));
71
72  service_provider->Start(mock_exported_object_.get());
73}
74
75void ServiceProviderTestHelper::TearDown() {
76  mock_bus_->ShutdownAndBlock();
77  mock_exported_object_ = NULL;
78  mock_object_proxy_ = NULL;
79  mock_bus_ = NULL;
80}
81
82void ServiceProviderTestHelper::SetUpReturnSignal(
83    const std::string& interface_name,
84    const std::string& signal_name,
85    dbus::ObjectProxy::SignalCallback signal_callback,
86    dbus::ObjectProxy::OnConnectedCallback on_connected_callback) {
87  // |mock_exported_object_|'s SendSignal() will use
88  // MockSendSignal().
89  EXPECT_CALL(*mock_exported_object_.get(), SendSignal(_))
90      .WillOnce(Invoke(this, &ServiceProviderTestHelper::MockSendSignal));
91
92  // |mock_object_proxy_|'s ConnectToSignal will use
93  // MockConnectToSignal().
94  EXPECT_CALL(*mock_object_proxy_.get(),
95              ConnectToSignal(interface_name, signal_name, _, _))
96      .WillOnce(Invoke(this, &ServiceProviderTestHelper::MockConnectToSignal));
97
98  mock_object_proxy_->ConnectToSignal(interface_name, signal_name,
99                                      signal_callback, on_connected_callback);
100}
101
102scoped_ptr<dbus::Response> ServiceProviderTestHelper::CallMethod(
103    dbus::MethodCall* method_call) {
104  return mock_object_proxy_->CallMethodAndBlock(
105      method_call,
106      dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
107}
108
109void ServiceProviderTestHelper::MockExportMethod(
110    const std::string& interface_name,
111    const std::string& method_name,
112    dbus::ExportedObject::MethodCallCallback method_callback,
113    dbus::ExportedObject::OnExportedCallback on_exported_callback) {
114  // Tell the call back that the method is exported successfully.
115  on_exported_callback.Run(interface_name, method_name, true);
116  // Capture the callback, so we can run this at a later time.
117  method_callback_ = method_callback;
118}
119
120dbus::Response* ServiceProviderTestHelper::MockCallMethodAndBlock(
121    dbus::MethodCall* method_call,
122    Unused) {
123  // Set the serial number to non-zero, so
124  // dbus_message_new_method_return() won't emit a warning.
125  method_call->SetSerial(1);
126  // Run the callback captured in MockExportMethod(). In addition to returning
127  // a response that the caller will ignore, this will send a signal, which
128  // will be received by |on_signal_callback_|.
129  method_callback_.Run(method_call,
130                       base::Bind(&ServiceProviderTestHelper::OnResponse,
131                                  base::Unretained(this)));
132  // Check for a response.
133  if (!response_received_)
134    message_loop_.Run();
135  // Return response.
136  return response_.release();
137}
138
139void ServiceProviderTestHelper::MockConnectToSignal(
140    const std::string& interface_name,
141    const std::string& signal_name,
142    dbus::ObjectProxy::SignalCallback signal_callback,
143    dbus::ObjectProxy::OnConnectedCallback connected_callback) {
144  // Tell the callback that the object proxy is connected to the signal.
145  connected_callback.Run(interface_name, signal_name, true);
146  // Capture the callback, so we can run this at a later time.
147  on_signal_callback_ = signal_callback;
148}
149
150void ServiceProviderTestHelper::MockSendSignal(dbus::Signal* signal) {
151  // Run the callback captured in MockConnectToSignal(). This will call
152  // OnSignalReceived().
153  on_signal_callback_.Run(signal);
154}
155
156void ServiceProviderTestHelper::OnResponse(
157    scoped_ptr<dbus::Response> response) {
158  response_ = response.Pass();
159  response_received_ = true;
160  if (message_loop_.is_running())
161    message_loop_.Quit();
162}
163
164}  // namespace chromeos
165