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 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 void TearDown() override
{ mock_bus_
->ShutdownAndBlock(); }
108 // Handles Delete method call.
109 void OnDelete(dbus::MethodCall
* method_call
,
111 const dbus::ObjectProxy::ResponseCallback
& callback
) {
112 EXPECT_EQ(modemmanager::kModemManagerSMSInterface
,
113 method_call
->GetInterface());
114 EXPECT_EQ(modemmanager::kSMSDeleteFunction
, method_call
->GetMember());
116 dbus::MessageReader
reader(method_call
);
117 EXPECT_TRUE(reader
.PopUint32(&index
));
118 EXPECT_EQ(expected_index_
, index
);
119 EXPECT_FALSE(reader
.HasMoreData());
121 message_loop_
.PostTask(FROM_HERE
, base::Bind(callback
, response_
));
124 // Handles Get method call.
125 void OnGet(dbus::MethodCall
* method_call
,
127 const dbus::ObjectProxy::ResponseCallback
& callback
) {
128 EXPECT_EQ(modemmanager::kModemManagerSMSInterface
,
129 method_call
->GetInterface());
130 EXPECT_EQ(modemmanager::kSMSGetFunction
, method_call
->GetMember());
132 dbus::MessageReader
reader(method_call
);
133 EXPECT_TRUE(reader
.PopUint32(&index
));
134 EXPECT_EQ(expected_index_
, index
);
135 EXPECT_FALSE(reader
.HasMoreData());
137 message_loop_
.PostTask(FROM_HERE
, base::Bind(callback
, response_
));
140 // Handles List method call.
141 void OnList(dbus::MethodCall
* method_call
,
143 const dbus::ObjectProxy::ResponseCallback
& callback
) {
144 EXPECT_EQ(modemmanager::kModemManagerSMSInterface
,
145 method_call
->GetInterface());
146 EXPECT_EQ(modemmanager::kSMSListFunction
, method_call
->GetMember());
147 dbus::MessageReader
reader(method_call
);
148 EXPECT_FALSE(reader
.HasMoreData());
150 message_loop_
.PostTask(FROM_HERE
, base::Bind(callback
, response_
));
153 // Checks the results of Get and List.
154 void CheckResult(const base::Value
& result
) {
155 EXPECT_TRUE(result
.Equals(expected_result_
));
159 // The client to be tested.
160 scoped_ptr
<GsmSMSClient
> client_
;
161 // A message loop to emulate asynchronous behavior.
162 base::MessageLoop message_loop_
;
164 scoped_refptr
<dbus::MockBus
> mock_bus_
;
165 // The mock object proxy.
166 scoped_refptr
<dbus::MockObjectProxy
> mock_proxy_
;
167 // The SmsReceived signal handler given by the tested client.
168 dbus::ObjectProxy::SignalCallback sms_received_callback_
;
169 // Expected argument for Delete and Get methods.
170 uint32 expected_index_
;
171 // Response returned by mock methods.
172 dbus::Response
* response_
;
173 // Expected result of Get and List methods.
174 base::Value
* expected_result_
;
177 // Used to implement the mock proxy.
178 void OnConnectToSignal(
179 const std::string
& interface_name
,
180 const std::string
& signal_name
,
181 const dbus::ObjectProxy::SignalCallback
& signal_callback
,
182 const dbus::ObjectProxy::OnConnectedCallback
& on_connected_callback
) {
183 sms_received_callback_
= signal_callback
;
184 const bool success
= true;
185 message_loop_
.PostTask(FROM_HERE
, base::Bind(on_connected_callback
,
192 TEST_F(GsmSMSClientTest
, SmsReceived
) {
194 const uint32 kIndex
= 42;
195 const bool kComplete
= true;
196 MockSmsReceivedHandler handler
;
197 EXPECT_CALL(handler
, Run(kIndex
, kComplete
)).Times(1);
199 client_
->SetSmsReceivedHandler(kServiceName
, dbus::ObjectPath(kObjectPath
),
200 base::Bind(&MockSmsReceivedHandler::Run
,
201 base::Unretained(&handler
)));
203 // Run the message loop to run the signal connection result callback.
204 message_loop_
.RunUntilIdle();
207 dbus::Signal
signal(modemmanager::kModemManagerSMSInterface
,
208 modemmanager::kSMSReceivedSignal
);
209 dbus::MessageWriter
writer(&signal
);
210 writer
.AppendUint32(kIndex
);
211 writer
.AppendBool(kComplete
);
212 ASSERT_FALSE(sms_received_callback_
.is_null());
213 sms_received_callback_
.Run(&signal
);
215 client_
->ResetSmsReceivedHandler(kServiceName
, dbus::ObjectPath(kObjectPath
));
216 // Send signal again.
217 sms_received_callback_
.Run(&signal
);
220 TEST_F(GsmSMSClientTest
, Delete
) {
222 const uint32 kIndex
= 42;
223 expected_index_
= kIndex
;
224 EXPECT_CALL(*mock_proxy_
.get(), CallMethod(_
, _
, _
))
225 .WillOnce(Invoke(this, &GsmSMSClientTest::OnDelete
));
226 MockDeleteCallback callback
;
227 EXPECT_CALL(callback
, Run()).Times(1);
229 scoped_ptr
<dbus::Response
> response(dbus::Response::CreateEmpty());
230 response_
= response
.get();
232 client_
->Delete(kServiceName
, dbus::ObjectPath(kObjectPath
), kIndex
,
233 base::Bind(&MockDeleteCallback::Run
,
234 base::Unretained(&callback
)));
236 // Run the message loop.
237 message_loop_
.RunUntilIdle();
240 TEST_F(GsmSMSClientTest
, Get
) {
242 const uint32 kIndex
= 42;
243 expected_index_
= kIndex
;
244 EXPECT_CALL(*mock_proxy_
.get(), CallMethod(_
, _
, _
))
245 .WillOnce(Invoke(this, &GsmSMSClientTest::OnGet
));
246 MockGetCallback callback
;
247 EXPECT_CALL(callback
, Run(_
))
248 .WillOnce(Invoke(this, &GsmSMSClientTest::CheckResult
));
250 scoped_ptr
<dbus::Response
> response(dbus::Response::CreateEmpty());
251 dbus::MessageWriter
writer(response
.get());
252 dbus::MessageWriter
array_writer(NULL
);
253 writer
.OpenArray("{sv}", &array_writer
);
254 dbus::MessageWriter
entry_writer(NULL
);
255 array_writer
.OpenDictEntry(&entry_writer
);
256 entry_writer
.AppendString(kNumberKey
);
257 entry_writer
.AppendVariantOfString(kExampleNumber
);
258 array_writer
.CloseContainer(&entry_writer
);
259 array_writer
.OpenDictEntry(&entry_writer
);
260 entry_writer
.AppendString(kTextKey
);
261 entry_writer
.AppendVariantOfString(kExampleText
);
262 array_writer
.CloseContainer(&entry_writer
);
263 writer
.CloseContainer(&array_writer
);
264 response_
= response
.get();
265 // Create expected result.
266 base::DictionaryValue expected_result
;
267 expected_result
.SetWithoutPathExpansion(
268 kNumberKey
, new base::StringValue(kExampleNumber
));
269 expected_result
.SetWithoutPathExpansion(kTextKey
,
270 new base::StringValue(kExampleText
));
271 expected_result_
= &expected_result
;
273 client_
->Get(kServiceName
, dbus::ObjectPath(kObjectPath
), kIndex
,
274 base::Bind(&MockGetCallback::Run
, base::Unretained(&callback
)));
276 // Run the message loop.
277 message_loop_
.RunUntilIdle();
280 TEST_F(GsmSMSClientTest
, List
) {
282 EXPECT_CALL(*mock_proxy_
.get(), CallMethod(_
, _
, _
))
283 .WillOnce(Invoke(this, &GsmSMSClientTest::OnList
));
284 MockListCallback callback
;
285 EXPECT_CALL(callback
, Run(_
))
286 .WillOnce(Invoke(this, &GsmSMSClientTest::CheckResult
));
288 scoped_ptr
<dbus::Response
> response(dbus::Response::CreateEmpty());
289 dbus::MessageWriter
writer(response
.get());
290 dbus::MessageWriter
array_writer(NULL
);
291 writer
.OpenArray("a{sv}", &array_writer
);
292 dbus::MessageWriter
sub_array_writer(NULL
);
293 array_writer
.OpenArray("{sv}", &sub_array_writer
);
294 dbus::MessageWriter
entry_writer(NULL
);
295 sub_array_writer
.OpenDictEntry(&entry_writer
);
296 entry_writer
.AppendString(kNumberKey
);
297 entry_writer
.AppendVariantOfString(kExampleNumber
);
298 sub_array_writer
.CloseContainer(&entry_writer
);
299 sub_array_writer
.OpenDictEntry(&entry_writer
);
300 entry_writer
.AppendString(kTextKey
);
301 entry_writer
.AppendVariantOfString(kExampleText
);
302 sub_array_writer
.CloseContainer(&entry_writer
);
303 array_writer
.CloseContainer(&sub_array_writer
);
304 writer
.CloseContainer(&array_writer
);
305 response_
= response
.get();
306 // Create expected result.
307 base::ListValue expected_result
;
308 base::DictionaryValue
* sms
= new base::DictionaryValue
;
309 sms
->SetWithoutPathExpansion(kNumberKey
,
310 new base::StringValue(kExampleNumber
));
311 sms
->SetWithoutPathExpansion(kTextKey
, new base::StringValue(kExampleText
));
312 expected_result
.Append(sms
);
313 expected_result_
= &expected_result
;
315 client_
->List(kServiceName
, dbus::ObjectPath(kObjectPath
),
316 base::Bind(&MockListCallback::Run
,
317 base::Unretained(&callback
)));
319 // Run the message loop.
320 message_loop_
.RunUntilIdle();
323 } // namespace chromeos