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/location.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/values.h"
12 #include "dbus/message.h"
13 #include "dbus/mock_bus.h"
14 #include "dbus/mock_object_proxy.h"
15 #include "dbus/object_path.h"
16 #include "dbus/values_util.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/cros_system_api/dbus/service_constants.h"
22 using ::testing::Invoke
;
23 using ::testing::Return
;
29 // A mock SmsReceivedHandler.
30 class MockSmsReceivedHandler
{
32 MOCK_METHOD2(Run
, void(uint32 index
, bool complete
));
35 // A mock DeleteCallback.
36 class MockDeleteCallback
{
38 MOCK_METHOD0(Run
, void());
41 // A mock GetCallback.
42 class MockGetCallback
{
44 MOCK_METHOD1(Run
, void(const base::DictionaryValue
& sms
));
47 // A mock ListCallback.
48 class MockListCallback
{
50 MOCK_METHOD1(Run
, void(const base::ListValue
& result
));
53 // D-Bus service name used by test.
54 const char kServiceName
[] = "service.name";
55 // D-Bus object path used by test.
56 const char kObjectPath
[] = "/object/path";
58 // Keys of SMS dictionary.
59 const char kNumberKey
[] = "number";
60 const char kTextKey
[] = "text";
62 // Example values of SMS dictionary.
63 const char kExampleNumber
[] = "00012345678";
64 const char kExampleText
[] = "Hello.";
68 class GsmSMSClientTest
: public testing::Test
{
70 GsmSMSClientTest() : expected_index_(0),
72 expected_result_(NULL
) {}
74 void SetUp() override
{
76 dbus::Bus::Options options
;
77 options
.bus_type
= dbus::Bus::SYSTEM
;
78 mock_bus_
= new dbus::MockBus(options
);
80 // Create a mock proxy.
81 mock_proxy_
= new dbus::MockObjectProxy(mock_bus_
.get(),
83 dbus::ObjectPath(kObjectPath
));
85 // Set an expectation so mock_proxy's ConnectToSignal() will use
86 // OnConnectToSignal() to run the callback.
87 EXPECT_CALL(*mock_proxy_
.get(),
88 ConnectToSignal(modemmanager::kModemManagerSMSInterface
,
89 modemmanager::kSMSReceivedSignal
,
92 .WillRepeatedly(Invoke(this, &GsmSMSClientTest::OnConnectToSignal
));
94 // Set an expectation so mock_bus's GetObjectProxy() for the given
95 // service name and the object path will return mock_proxy_.
96 EXPECT_CALL(*mock_bus_
.get(),
97 GetObjectProxy(kServiceName
, dbus::ObjectPath(kObjectPath
)))
98 .WillOnce(Return(mock_proxy_
.get()));
100 // ShutdownAndBlock() will be called in TearDown().
101 EXPECT_CALL(*mock_bus_
.get(), ShutdownAndBlock()).WillOnce(Return());
103 // Create a client with the mock bus.
104 client_
.reset(GsmSMSClient::Create());
105 client_
->Init(mock_bus_
.get());
108 void TearDown() override
{ 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_
.task_runner()->PostTask(FROM_HERE
,
124 base::Bind(callback
, response_
));
127 // Handles Get method call.
128 void OnGet(dbus::MethodCall
* method_call
,
130 const dbus::ObjectProxy::ResponseCallback
& callback
) {
131 EXPECT_EQ(modemmanager::kModemManagerSMSInterface
,
132 method_call
->GetInterface());
133 EXPECT_EQ(modemmanager::kSMSGetFunction
, method_call
->GetMember());
135 dbus::MessageReader
reader(method_call
);
136 EXPECT_TRUE(reader
.PopUint32(&index
));
137 EXPECT_EQ(expected_index_
, index
);
138 EXPECT_FALSE(reader
.HasMoreData());
140 message_loop_
.task_runner()->PostTask(FROM_HERE
,
141 base::Bind(callback
, response_
));
144 // Handles List method call.
145 void OnList(dbus::MethodCall
* method_call
,
147 const dbus::ObjectProxy::ResponseCallback
& callback
) {
148 EXPECT_EQ(modemmanager::kModemManagerSMSInterface
,
149 method_call
->GetInterface());
150 EXPECT_EQ(modemmanager::kSMSListFunction
, method_call
->GetMember());
151 dbus::MessageReader
reader(method_call
);
152 EXPECT_FALSE(reader
.HasMoreData());
154 message_loop_
.task_runner()->PostTask(FROM_HERE
,
155 base::Bind(callback
, response_
));
158 // Checks the results of Get and List.
159 void CheckResult(const base::Value
& result
) {
160 EXPECT_TRUE(result
.Equals(expected_result_
));
164 // The client to be tested.
165 scoped_ptr
<GsmSMSClient
> client_
;
166 // A message loop to emulate asynchronous behavior.
167 base::MessageLoop message_loop_
;
169 scoped_refptr
<dbus::MockBus
> mock_bus_
;
170 // The mock object proxy.
171 scoped_refptr
<dbus::MockObjectProxy
> mock_proxy_
;
172 // The SmsReceived signal handler given by the tested client.
173 dbus::ObjectProxy::SignalCallback sms_received_callback_
;
174 // Expected argument for Delete and Get methods.
175 uint32 expected_index_
;
176 // Response returned by mock methods.
177 dbus::Response
* response_
;
178 // Expected result of Get and List methods.
179 base::Value
* expected_result_
;
182 // Used to implement the mock proxy.
183 void OnConnectToSignal(
184 const std::string
& interface_name
,
185 const std::string
& signal_name
,
186 const dbus::ObjectProxy::SignalCallback
& signal_callback
,
187 const dbus::ObjectProxy::OnConnectedCallback
& on_connected_callback
) {
188 sms_received_callback_
= signal_callback
;
189 const bool success
= true;
190 message_loop_
.task_runner()->PostTask(
191 FROM_HERE
, base::Bind(on_connected_callback
, interface_name
,
192 signal_name
, success
));
196 TEST_F(GsmSMSClientTest
, SmsReceived
) {
198 const uint32 kIndex
= 42;
199 const bool kComplete
= true;
200 MockSmsReceivedHandler handler
;
201 EXPECT_CALL(handler
, Run(kIndex
, kComplete
)).Times(1);
203 client_
->SetSmsReceivedHandler(kServiceName
, dbus::ObjectPath(kObjectPath
),
204 base::Bind(&MockSmsReceivedHandler::Run
,
205 base::Unretained(&handler
)));
207 // Run the message loop to run the signal connection result callback.
208 message_loop_
.RunUntilIdle();
211 dbus::Signal
signal(modemmanager::kModemManagerSMSInterface
,
212 modemmanager::kSMSReceivedSignal
);
213 dbus::MessageWriter
writer(&signal
);
214 writer
.AppendUint32(kIndex
);
215 writer
.AppendBool(kComplete
);
216 ASSERT_FALSE(sms_received_callback_
.is_null());
217 sms_received_callback_
.Run(&signal
);
219 client_
->ResetSmsReceivedHandler(kServiceName
, dbus::ObjectPath(kObjectPath
));
220 // Send signal again.
221 sms_received_callback_
.Run(&signal
);
224 TEST_F(GsmSMSClientTest
, Delete
) {
226 const uint32 kIndex
= 42;
227 expected_index_
= kIndex
;
228 EXPECT_CALL(*mock_proxy_
.get(), CallMethod(_
, _
, _
))
229 .WillOnce(Invoke(this, &GsmSMSClientTest::OnDelete
));
230 MockDeleteCallback callback
;
231 EXPECT_CALL(callback
, Run()).Times(1);
233 scoped_ptr
<dbus::Response
> response(dbus::Response::CreateEmpty());
234 response_
= response
.get();
236 client_
->Delete(kServiceName
, dbus::ObjectPath(kObjectPath
), kIndex
,
237 base::Bind(&MockDeleteCallback::Run
,
238 base::Unretained(&callback
)));
240 // Run the message loop.
241 message_loop_
.RunUntilIdle();
244 TEST_F(GsmSMSClientTest
, Get
) {
246 const uint32 kIndex
= 42;
247 expected_index_
= kIndex
;
248 EXPECT_CALL(*mock_proxy_
.get(), CallMethod(_
, _
, _
))
249 .WillOnce(Invoke(this, &GsmSMSClientTest::OnGet
));
250 MockGetCallback callback
;
251 EXPECT_CALL(callback
, Run(_
))
252 .WillOnce(Invoke(this, &GsmSMSClientTest::CheckResult
));
254 scoped_ptr
<dbus::Response
> response(dbus::Response::CreateEmpty());
255 dbus::MessageWriter
writer(response
.get());
256 dbus::MessageWriter
array_writer(NULL
);
257 writer
.OpenArray("{sv}", &array_writer
);
258 dbus::MessageWriter
entry_writer(NULL
);
259 array_writer
.OpenDictEntry(&entry_writer
);
260 entry_writer
.AppendString(kNumberKey
);
261 entry_writer
.AppendVariantOfString(kExampleNumber
);
262 array_writer
.CloseContainer(&entry_writer
);
263 array_writer
.OpenDictEntry(&entry_writer
);
264 entry_writer
.AppendString(kTextKey
);
265 entry_writer
.AppendVariantOfString(kExampleText
);
266 array_writer
.CloseContainer(&entry_writer
);
267 writer
.CloseContainer(&array_writer
);
268 response_
= response
.get();
269 // Create expected result.
270 base::DictionaryValue expected_result
;
271 expected_result
.SetWithoutPathExpansion(
272 kNumberKey
, new base::StringValue(kExampleNumber
));
273 expected_result
.SetWithoutPathExpansion(kTextKey
,
274 new base::StringValue(kExampleText
));
275 expected_result_
= &expected_result
;
277 client_
->Get(kServiceName
, dbus::ObjectPath(kObjectPath
), kIndex
,
278 base::Bind(&MockGetCallback::Run
, base::Unretained(&callback
)));
280 // Run the message loop.
281 message_loop_
.RunUntilIdle();
284 TEST_F(GsmSMSClientTest
, List
) {
286 EXPECT_CALL(*mock_proxy_
.get(), CallMethod(_
, _
, _
))
287 .WillOnce(Invoke(this, &GsmSMSClientTest::OnList
));
288 MockListCallback callback
;
289 EXPECT_CALL(callback
, Run(_
))
290 .WillOnce(Invoke(this, &GsmSMSClientTest::CheckResult
));
292 scoped_ptr
<dbus::Response
> response(dbus::Response::CreateEmpty());
293 dbus::MessageWriter
writer(response
.get());
294 dbus::MessageWriter
array_writer(NULL
);
295 writer
.OpenArray("a{sv}", &array_writer
);
296 dbus::MessageWriter
sub_array_writer(NULL
);
297 array_writer
.OpenArray("{sv}", &sub_array_writer
);
298 dbus::MessageWriter
entry_writer(NULL
);
299 sub_array_writer
.OpenDictEntry(&entry_writer
);
300 entry_writer
.AppendString(kNumberKey
);
301 entry_writer
.AppendVariantOfString(kExampleNumber
);
302 sub_array_writer
.CloseContainer(&entry_writer
);
303 sub_array_writer
.OpenDictEntry(&entry_writer
);
304 entry_writer
.AppendString(kTextKey
);
305 entry_writer
.AppendVariantOfString(kExampleText
);
306 sub_array_writer
.CloseContainer(&entry_writer
);
307 array_writer
.CloseContainer(&sub_array_writer
);
308 writer
.CloseContainer(&array_writer
);
309 response_
= response
.get();
310 // Create expected result.
311 base::ListValue expected_result
;
312 base::DictionaryValue
* sms
= new base::DictionaryValue
;
313 sms
->SetWithoutPathExpansion(kNumberKey
,
314 new base::StringValue(kExampleNumber
));
315 sms
->SetWithoutPathExpansion(kTextKey
, new base::StringValue(kExampleText
));
316 expected_result
.Append(sms
);
317 expected_result_
= &expected_result
;
319 client_
->List(kServiceName
, dbus::ObjectPath(kObjectPath
),
320 base::Bind(&MockListCallback::Run
,
321 base::Unretained(&callback
)));
323 // Run the message loop.
324 message_loop_
.RunUntilIdle();
327 } // namespace chromeos