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.
5 #include "chromeos/dbus/gsm_sms_client.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/values.h"
10 #include "dbus/message.h"
11 #include "dbus/mock_bus.h"
12 #include "dbus/mock_object_proxy.h"
13 #include "dbus/object_path.h"
14 #include "dbus/values_util.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
20 using ::testing::Invoke
;
21 using ::testing::Return
;
27 // A mock SmsReceivedHandler.
28 class MockSmsReceivedHandler
{
30 MOCK_METHOD2(Run
, void(uint32 index
, bool complete
));
33 // A mock DeleteCallback.
34 class MockDeleteCallback
{
36 MOCK_METHOD0(Run
, void());
39 // A mock GetCallback.
40 class MockGetCallback
{
42 MOCK_METHOD1(Run
, void(const base::DictionaryValue
& sms
));
45 // A mock ListCallback.
46 class MockListCallback
{
48 MOCK_METHOD1(Run
, void(const base::ListValue
& result
));
51 // D-Bus service name used by test.
52 const char kServiceName
[] = "service.name";
53 // D-Bus object path used by test.
54 const char kObjectPath
[] = "/object/path";
56 // Keys of SMS dictionary.
57 const char kNumberKey
[] = "number";
58 const char kTextKey
[] = "text";
60 // Example values of SMS dictionary.
61 const char kExampleNumber
[] = "00012345678";
62 const char kExampleText
[] = "Hello.";
66 class GsmSMSClientTest
: public testing::Test
{
68 GsmSMSClientTest() : expected_index_(0),
70 expected_result_(NULL
) {}
72 virtual void SetUp() OVERRIDE
{
74 dbus::Bus::Options options
;
75 options
.bus_type
= dbus::Bus::SYSTEM
;
76 mock_bus_
= new dbus::MockBus(options
);
78 // Create a mock proxy.
79 mock_proxy_
= new dbus::MockObjectProxy(mock_bus_
.get(),
81 dbus::ObjectPath(kObjectPath
));
83 // Set an expectation so mock_proxy's ConnectToSignal() will use
84 // OnConnectToSignal() to run the callback.
85 EXPECT_CALL(*mock_proxy_
.get(),
86 ConnectToSignal(modemmanager::kModemManagerSMSInterface
,
87 modemmanager::kSMSReceivedSignal
,
90 .WillRepeatedly(Invoke(this, &GsmSMSClientTest::OnConnectToSignal
));
92 // Set an expectation so mock_bus's GetObjectProxy() for the given
93 // service name and the object path will return mock_proxy_.
94 EXPECT_CALL(*mock_bus_
.get(),
95 GetObjectProxy(kServiceName
, dbus::ObjectPath(kObjectPath
)))
96 .WillOnce(Return(mock_proxy_
.get()));
98 // ShutdownAndBlock() will be called in TearDown().
99 EXPECT_CALL(*mock_bus_
.get(), ShutdownAndBlock()).WillOnce(Return());
101 // Create a client with the mock bus.
102 client_
.reset(GsmSMSClient::Create());
103 client_
->Init(mock_bus_
.get());
106 virtual void TearDown() OVERRIDE
{
107 mock_bus_
->ShutdownAndBlock();
110 // Handles Delete method call.
111 void OnDelete(dbus::MethodCall
* method_call
,
113 const dbus::ObjectProxy::ResponseCallback
& callback
) {
114 EXPECT_EQ(modemmanager::kModemManagerSMSInterface
,
115 method_call
->GetInterface());
116 EXPECT_EQ(modemmanager::kSMSDeleteFunction
, method_call
->GetMember());
118 dbus::MessageReader
reader(method_call
);
119 EXPECT_TRUE(reader
.PopUint32(&index
));
120 EXPECT_EQ(expected_index_
, index
);
121 EXPECT_FALSE(reader
.HasMoreData());
123 message_loop_
.PostTask(FROM_HERE
, base::Bind(callback
, response_
));
126 // Handles Get method call.
127 void OnGet(dbus::MethodCall
* method_call
,
129 const dbus::ObjectProxy::ResponseCallback
& callback
) {
130 EXPECT_EQ(modemmanager::kModemManagerSMSInterface
,
131 method_call
->GetInterface());
132 EXPECT_EQ(modemmanager::kSMSGetFunction
, method_call
->GetMember());
134 dbus::MessageReader
reader(method_call
);
135 EXPECT_TRUE(reader
.PopUint32(&index
));
136 EXPECT_EQ(expected_index_
, index
);
137 EXPECT_FALSE(reader
.HasMoreData());
139 message_loop_
.PostTask(FROM_HERE
, base::Bind(callback
, response_
));
142 // Handles List method call.
143 void OnList(dbus::MethodCall
* method_call
,
145 const dbus::ObjectProxy::ResponseCallback
& callback
) {
146 EXPECT_EQ(modemmanager::kModemManagerSMSInterface
,
147 method_call
->GetInterface());
148 EXPECT_EQ(modemmanager::kSMSListFunction
, method_call
->GetMember());
149 dbus::MessageReader
reader(method_call
);
150 EXPECT_FALSE(reader
.HasMoreData());
152 message_loop_
.PostTask(FROM_HERE
, base::Bind(callback
, response_
));
155 // Checks the results of Get and List.
156 void CheckResult(const base::Value
& result
) {
157 EXPECT_TRUE(result
.Equals(expected_result_
));
161 // The client to be tested.
162 scoped_ptr
<GsmSMSClient
> client_
;
163 // A message loop to emulate asynchronous behavior.
164 base::MessageLoop message_loop_
;
166 scoped_refptr
<dbus::MockBus
> mock_bus_
;
167 // The mock object proxy.
168 scoped_refptr
<dbus::MockObjectProxy
> mock_proxy_
;
169 // The SmsReceived signal handler given by the tested client.
170 dbus::ObjectProxy::SignalCallback sms_received_callback_
;
171 // Expected argument for Delete and Get methods.
172 uint32 expected_index_
;
173 // Response returned by mock methods.
174 dbus::Response
* response_
;
175 // Expected result of Get and List methods.
176 base::Value
* expected_result_
;
179 // Used to implement the mock proxy.
180 void OnConnectToSignal(
181 const std::string
& interface_name
,
182 const std::string
& signal_name
,
183 const dbus::ObjectProxy::SignalCallback
& signal_callback
,
184 const dbus::ObjectProxy::OnConnectedCallback
& on_connected_callback
) {
185 sms_received_callback_
= signal_callback
;
186 const bool success
= true;
187 message_loop_
.PostTask(FROM_HERE
, base::Bind(on_connected_callback
,
194 TEST_F(GsmSMSClientTest
, SmsReceived
) {
196 const uint32 kIndex
= 42;
197 const bool kComplete
= true;
198 MockSmsReceivedHandler handler
;
199 EXPECT_CALL(handler
, Run(kIndex
, kComplete
)).Times(1);
201 client_
->SetSmsReceivedHandler(kServiceName
, dbus::ObjectPath(kObjectPath
),
202 base::Bind(&MockSmsReceivedHandler::Run
,
203 base::Unretained(&handler
)));
205 // Run the message loop to run the signal connection result callback.
206 message_loop_
.RunUntilIdle();
209 dbus::Signal
signal(modemmanager::kModemManagerSMSInterface
,
210 modemmanager::kSMSReceivedSignal
);
211 dbus::MessageWriter
writer(&signal
);
212 writer
.AppendUint32(kIndex
);
213 writer
.AppendBool(kComplete
);
214 ASSERT_FALSE(sms_received_callback_
.is_null());
215 sms_received_callback_
.Run(&signal
);
217 client_
->ResetSmsReceivedHandler(kServiceName
, dbus::ObjectPath(kObjectPath
));
218 // Send signal again.
219 sms_received_callback_
.Run(&signal
);
222 TEST_F(GsmSMSClientTest
, Delete
) {
224 const uint32 kIndex
= 42;
225 expected_index_
= kIndex
;
226 EXPECT_CALL(*mock_proxy_
.get(), CallMethod(_
, _
, _
))
227 .WillOnce(Invoke(this, &GsmSMSClientTest::OnDelete
));
228 MockDeleteCallback callback
;
229 EXPECT_CALL(callback
, Run()).Times(1);
231 scoped_ptr
<dbus::Response
> response(dbus::Response::CreateEmpty());
232 response_
= response
.get();
234 client_
->Delete(kServiceName
, dbus::ObjectPath(kObjectPath
), kIndex
,
235 base::Bind(&MockDeleteCallback::Run
,
236 base::Unretained(&callback
)));
238 // Run the message loop.
239 message_loop_
.RunUntilIdle();
242 TEST_F(GsmSMSClientTest
, Get
) {
244 const uint32 kIndex
= 42;
245 expected_index_
= kIndex
;
246 EXPECT_CALL(*mock_proxy_
.get(), CallMethod(_
, _
, _
))
247 .WillOnce(Invoke(this, &GsmSMSClientTest::OnGet
));
248 MockGetCallback callback
;
249 EXPECT_CALL(callback
, Run(_
))
250 .WillOnce(Invoke(this, &GsmSMSClientTest::CheckResult
));
252 scoped_ptr
<dbus::Response
> response(dbus::Response::CreateEmpty());
253 dbus::MessageWriter
writer(response
.get());
254 dbus::MessageWriter
array_writer(NULL
);
255 writer
.OpenArray("{sv}", &array_writer
);
256 dbus::MessageWriter
entry_writer(NULL
);
257 array_writer
.OpenDictEntry(&entry_writer
);
258 entry_writer
.AppendString(kNumberKey
);
259 entry_writer
.AppendVariantOfString(kExampleNumber
);
260 array_writer
.CloseContainer(&entry_writer
);
261 array_writer
.OpenDictEntry(&entry_writer
);
262 entry_writer
.AppendString(kTextKey
);
263 entry_writer
.AppendVariantOfString(kExampleText
);
264 array_writer
.CloseContainer(&entry_writer
);
265 writer
.CloseContainer(&array_writer
);
266 response_
= response
.get();
267 // Create expected result.
268 base::DictionaryValue expected_result
;
269 expected_result
.SetWithoutPathExpansion(
270 kNumberKey
, new base::StringValue(kExampleNumber
));
271 expected_result
.SetWithoutPathExpansion(kTextKey
,
272 new base::StringValue(kExampleText
));
273 expected_result_
= &expected_result
;
275 client_
->Get(kServiceName
, dbus::ObjectPath(kObjectPath
), kIndex
,
276 base::Bind(&MockGetCallback::Run
, base::Unretained(&callback
)));
278 // Run the message loop.
279 message_loop_
.RunUntilIdle();
282 TEST_F(GsmSMSClientTest
, List
) {
284 EXPECT_CALL(*mock_proxy_
.get(), CallMethod(_
, _
, _
))
285 .WillOnce(Invoke(this, &GsmSMSClientTest::OnList
));
286 MockListCallback callback
;
287 EXPECT_CALL(callback
, Run(_
))
288 .WillOnce(Invoke(this, &GsmSMSClientTest::CheckResult
));
290 scoped_ptr
<dbus::Response
> response(dbus::Response::CreateEmpty());
291 dbus::MessageWriter
writer(response
.get());
292 dbus::MessageWriter
array_writer(NULL
);
293 writer
.OpenArray("a{sv}", &array_writer
);
294 dbus::MessageWriter
sub_array_writer(NULL
);
295 array_writer
.OpenArray("{sv}", &sub_array_writer
);
296 dbus::MessageWriter
entry_writer(NULL
);
297 sub_array_writer
.OpenDictEntry(&entry_writer
);
298 entry_writer
.AppendString(kNumberKey
);
299 entry_writer
.AppendVariantOfString(kExampleNumber
);
300 sub_array_writer
.CloseContainer(&entry_writer
);
301 sub_array_writer
.OpenDictEntry(&entry_writer
);
302 entry_writer
.AppendString(kTextKey
);
303 entry_writer
.AppendVariantOfString(kExampleText
);
304 sub_array_writer
.CloseContainer(&entry_writer
);
305 array_writer
.CloseContainer(&sub_array_writer
);
306 writer
.CloseContainer(&array_writer
);
307 response_
= response
.get();
308 // Create expected result.
309 base::ListValue expected_result
;
310 base::DictionaryValue
* sms
= new base::DictionaryValue
;
311 sms
->SetWithoutPathExpansion(kNumberKey
,
312 new base::StringValue(kExampleNumber
));
313 sms
->SetWithoutPathExpansion(kTextKey
, new base::StringValue(kExampleText
));
314 expected_result
.Append(sms
);
315 expected_result_
= &expected_result
;
317 client_
->List(kServiceName
, dbus::ObjectPath(kObjectPath
),
318 base::Bind(&MockListCallback::Run
,
319 base::Unretained(&callback
)));
321 // Run the message loop.
322 message_loop_
.RunUntilIdle();
325 } // namespace chromeos