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 "chromeos/dbus/shill_client_unittest_base.h"
6
7 #include "base/bind.h"
8 #include "base/json/json_writer.h"
9 #include "base/values.h"
10 #include "chromeos/network/shill_property_util.h"
11 #include "dbus/message.h"
12 #include "dbus/object_path.h"
13 #include "dbus/values_util.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/cros_system_api/dbus/service_constants.h"
17
18 using ::testing::_;
19 using ::testing::Invoke;
20 using ::testing::Return;
21
22 namespace chromeos {
23
24 namespace {
25
26 // Pops a string-to-string dictionary from the reader.
PopStringToStringDictionary(dbus::MessageReader * reader)27 base::DictionaryValue* PopStringToStringDictionary(
28 dbus::MessageReader* reader) {
29 dbus::MessageReader array_reader(NULL);
30 if (!reader->PopArray(&array_reader))
31 return NULL;
32 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
33 while (array_reader.HasMoreData()) {
34 dbus::MessageReader entry_reader(NULL);
35 std::string key;
36 std::string value;
37 if (!array_reader.PopDictEntry(&entry_reader) ||
38 !entry_reader.PopString(&key) ||
39 !entry_reader.PopString(&value))
40 return NULL;
41 result->SetWithoutPathExpansion(key, new base::StringValue(value));
42 }
43 return result.release();
44 }
45
46 } // namespace
47
ValueMatcher(const base::Value & value)48 ValueMatcher::ValueMatcher(const base::Value& value)
49 : expected_value_(value.DeepCopy()) {}
50
MatchAndExplain(const base::Value & value,MatchResultListener * listener) const51 bool ValueMatcher::MatchAndExplain(const base::Value& value,
52 MatchResultListener* listener) const {
53 return expected_value_->Equals(&value);
54 }
55
DescribeTo(::std::ostream * os) const56 void ValueMatcher::DescribeTo(::std::ostream* os) const {
57 std::string expected_value_str;
58 base::JSONWriter::WriteWithOptions(expected_value_.get(),
59 base::JSONWriter::OPTIONS_PRETTY_PRINT,
60 &expected_value_str);
61 *os << "value equals " << expected_value_str;
62 }
63
DescribeNegationTo(::std::ostream * os) const64 void ValueMatcher::DescribeNegationTo(::std::ostream* os) const {
65 std::string expected_value_str;
66 base::JSONWriter::WriteWithOptions(expected_value_.get(),
67 base::JSONWriter::OPTIONS_PRETTY_PRINT,
68 &expected_value_str);
69 *os << "value does not equal " << expected_value_str;
70 }
71
72
MockClosure()73 ShillClientUnittestBase::MockClosure::MockClosure() {}
74
~MockClosure()75 ShillClientUnittestBase::MockClosure::~MockClosure() {}
76
GetCallback()77 base::Closure ShillClientUnittestBase::MockClosure::GetCallback() {
78 return base::Bind(&MockClosure::Run, base::Unretained(this));
79 }
80
81
MockListValueCallback()82 ShillClientUnittestBase::MockListValueCallback::MockListValueCallback() {}
83
~MockListValueCallback()84 ShillClientUnittestBase::MockListValueCallback::~MockListValueCallback() {}
85
86 ShillClientHelper::ListValueCallback
GetCallback()87 ShillClientUnittestBase::MockListValueCallback::GetCallback() {
88 return base::Bind(&MockListValueCallback::Run, base::Unretained(this));
89 }
90
91
MockErrorCallback()92 ShillClientUnittestBase::MockErrorCallback::MockErrorCallback() {}
93
~MockErrorCallback()94 ShillClientUnittestBase::MockErrorCallback::~MockErrorCallback() {}
95
96 ShillClientUnittestBase::MockPropertyChangeObserver::
MockPropertyChangeObserver()97 MockPropertyChangeObserver() {}
98
99 ShillClientUnittestBase::MockPropertyChangeObserver::
~MockPropertyChangeObserver()100 ~MockPropertyChangeObserver() {}
101
102 ShillClientHelper::ErrorCallback
GetCallback()103 ShillClientUnittestBase::MockErrorCallback::GetCallback() {
104 return base::Bind(&MockErrorCallback::Run, base::Unretained(this));
105 }
106
107
ShillClientUnittestBase(const std::string & interface_name,const dbus::ObjectPath & object_path)108 ShillClientUnittestBase::ShillClientUnittestBase(
109 const std::string& interface_name,
110 const dbus::ObjectPath& object_path)
111 : interface_name_(interface_name),
112 object_path_(object_path),
113 response_(NULL) {
114 }
115
~ShillClientUnittestBase()116 ShillClientUnittestBase::~ShillClientUnittestBase() {
117 }
118
SetUp()119 void ShillClientUnittestBase::SetUp() {
120 // Create a mock bus.
121 dbus::Bus::Options options;
122 options.bus_type = dbus::Bus::SYSTEM;
123 mock_bus_ = new dbus::MockBus(options);
124
125 // Create a mock proxy.
126 mock_proxy_ = new dbus::MockObjectProxy(
127 mock_bus_.get(),
128 shill::kFlimflamServiceName,
129 object_path_);
130
131 // Set an expectation so mock_proxy's CallMethod() will use OnCallMethod()
132 // to return responses.
133 EXPECT_CALL(*mock_proxy_.get(), CallMethod(_, _, _))
134 .WillRepeatedly(Invoke(this, &ShillClientUnittestBase::OnCallMethod));
135
136 // Set an expectation so mock_proxy's CallMethodWithErrorCallback() will use
137 // OnCallMethodWithErrorCallback() to return responses.
138 EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
139 .WillRepeatedly(Invoke(
140 this, &ShillClientUnittestBase::OnCallMethodWithErrorCallback));
141
142 // Set an expectation so mock_proxy's ConnectToSignal() will use
143 // OnConnectToSignal() to run the callback.
144 EXPECT_CALL(
145 *mock_proxy_.get(),
146 ConnectToSignal(interface_name_, shill::kMonitorPropertyChanged, _, _))
147 .WillRepeatedly(
148 Invoke(this, &ShillClientUnittestBase::OnConnectToSignal));
149
150 // Set an expectation so mock_bus's GetObjectProxy() for the given
151 // service name and the object path will return mock_proxy_.
152 EXPECT_CALL(*mock_bus_.get(),
153 GetObjectProxy(shill::kFlimflamServiceName, object_path_))
154 .WillOnce(Return(mock_proxy_.get()));
155
156 // Set an expectation so mock_bus's GetDBusTaskRunner will return the current
157 // task runner.
158 EXPECT_CALL(*mock_bus_.get(), GetDBusTaskRunner())
159 .WillRepeatedly(Return(message_loop_.message_loop_proxy().get()));
160
161 // ShutdownAndBlock() will be called in TearDown().
162 EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
163 }
164
TearDown()165 void ShillClientUnittestBase::TearDown() {
166 mock_bus_->ShutdownAndBlock();
167 }
168
PrepareForMethodCall(const std::string & method_name,const ArgumentCheckCallback & argument_checker,dbus::Response * response)169 void ShillClientUnittestBase::PrepareForMethodCall(
170 const std::string& method_name,
171 const ArgumentCheckCallback& argument_checker,
172 dbus::Response* response) {
173 expected_method_name_ = method_name;
174 argument_checker_ = argument_checker;
175 response_ = response;
176 }
177
SendPropertyChangedSignal(dbus::Signal * signal)178 void ShillClientUnittestBase::SendPropertyChangedSignal(
179 dbus::Signal* signal) {
180 ASSERT_FALSE(property_changed_handler_.is_null());
181 property_changed_handler_.Run(signal);
182 }
183
184 // static
ExpectPropertyChanged(const std::string & expected_name,const base::Value * expected_value,const std::string & name,const base::Value & value)185 void ShillClientUnittestBase::ExpectPropertyChanged(
186 const std::string& expected_name,
187 const base::Value* expected_value,
188 const std::string& name,
189 const base::Value& value) {
190 EXPECT_EQ(expected_name, name);
191 EXPECT_TRUE(expected_value->Equals(&value));
192 }
193
194 // static
ExpectNoArgument(dbus::MessageReader * reader)195 void ShillClientUnittestBase::ExpectNoArgument(dbus::MessageReader* reader) {
196 EXPECT_FALSE(reader->HasMoreData());
197 }
198
199 // static
ExpectStringArgument(const std::string & expected_string,dbus::MessageReader * reader)200 void ShillClientUnittestBase::ExpectStringArgument(
201 const std::string& expected_string,
202 dbus::MessageReader* reader) {
203 std::string str;
204 ASSERT_TRUE(reader->PopString(&str));
205 EXPECT_EQ(expected_string, str);
206 EXPECT_FALSE(reader->HasMoreData());
207 }
208
209 // static
ExpectArrayOfStringsArgument(const std::vector<std::string> & expected_strings,dbus::MessageReader * reader)210 void ShillClientUnittestBase::ExpectArrayOfStringsArgument(
211 const std::vector<std::string>& expected_strings,
212 dbus::MessageReader* reader) {
213 std::vector<std::string> strs;
214 ASSERT_TRUE(reader->PopArrayOfStrings(&strs));
215 EXPECT_EQ(expected_strings, strs);
216 EXPECT_FALSE(reader->HasMoreData());
217 }
218
219 // static
ExpectValueArgument(const base::Value * expected_value,dbus::MessageReader * reader)220 void ShillClientUnittestBase::ExpectValueArgument(
221 const base::Value* expected_value,
222 dbus::MessageReader* reader) {
223 scoped_ptr<base::Value> value(dbus::PopDataAsValue(reader));
224 ASSERT_TRUE(value.get());
225 EXPECT_TRUE(value->Equals(expected_value));
226 EXPECT_FALSE(reader->HasMoreData());
227 }
228
229 // static
ExpectStringAndValueArguments(const std::string & expected_string,const base::Value * expected_value,dbus::MessageReader * reader)230 void ShillClientUnittestBase::ExpectStringAndValueArguments(
231 const std::string& expected_string,
232 const base::Value* expected_value,
233 dbus::MessageReader* reader) {
234 std::string str;
235 ASSERT_TRUE(reader->PopString(&str));
236 EXPECT_EQ(expected_string, str);
237 scoped_ptr<base::Value> value(dbus::PopDataAsValue(reader));
238 ASSERT_TRUE(value.get());
239 EXPECT_TRUE(value->Equals(expected_value));
240 EXPECT_FALSE(reader->HasMoreData());
241 }
242
243 // static
ExpectDictionaryValueArgument(const base::DictionaryValue * expected_dictionary,dbus::MessageReader * reader)244 void ShillClientUnittestBase::ExpectDictionaryValueArgument(
245 const base::DictionaryValue* expected_dictionary,
246 dbus::MessageReader* reader) {
247 dbus::MessageReader array_reader(NULL);
248 ASSERT_TRUE(reader->PopArray(&array_reader));
249 while (array_reader.HasMoreData()) {
250 dbus::MessageReader entry_reader(NULL);
251 ASSERT_TRUE(array_reader.PopDictEntry(&entry_reader));
252 std::string key;
253 ASSERT_TRUE(entry_reader.PopString(&key));
254 dbus::MessageReader variant_reader(NULL);
255 ASSERT_TRUE(entry_reader.PopVariant(&variant_reader));
256 scoped_ptr<base::Value> value;
257 // Variants in the dictionary can be basic types or string-to-string
258 // dictinoary.
259 switch (variant_reader.GetDataType()) {
260 case dbus::Message::ARRAY:
261 value.reset(PopStringToStringDictionary(&variant_reader));
262 break;
263 case dbus::Message::BOOL:
264 case dbus::Message::INT32:
265 case dbus::Message::STRING:
266 value.reset(dbus::PopDataAsValue(&variant_reader));
267 break;
268 default:
269 NOTREACHED();
270 }
271 ASSERT_TRUE(value.get());
272 const base::Value* expected_value = NULL;
273 EXPECT_TRUE(expected_dictionary->GetWithoutPathExpansion(key,
274 &expected_value));
275 EXPECT_TRUE(value->Equals(expected_value));
276 }
277 }
278
279 // static
280 base::DictionaryValue*
CreateExampleServiceProperties()281 ShillClientUnittestBase::CreateExampleServiceProperties() {
282 base::DictionaryValue* properties = new base::DictionaryValue;
283 properties->SetWithoutPathExpansion(
284 shill::kGuidProperty,
285 new base::StringValue("00000000-0000-0000-0000-000000000000"));
286 properties->SetWithoutPathExpansion(
287 shill::kModeProperty, new base::StringValue(shill::kModeManaged));
288 properties->SetWithoutPathExpansion(shill::kTypeProperty,
289 new base::StringValue(shill::kTypeWifi));
290 shill_property_util::SetSSID("testssid", properties);
291 properties->SetWithoutPathExpansion(
292 shill::kSecurityProperty, new base::StringValue(shill::kSecurityPsk));
293 return properties;
294 }
295
296
297 // static
ExpectNoResultValue(DBusMethodCallStatus call_status)298 void ShillClientUnittestBase::ExpectNoResultValue(
299 DBusMethodCallStatus call_status) {
300 EXPECT_EQ(DBUS_METHOD_CALL_SUCCESS, call_status);
301 }
302
303 // static
ExpectObjectPathResult(const dbus::ObjectPath & expected_result,DBusMethodCallStatus call_status,const dbus::ObjectPath & result)304 void ShillClientUnittestBase::ExpectObjectPathResult(
305 const dbus::ObjectPath& expected_result,
306 DBusMethodCallStatus call_status,
307 const dbus::ObjectPath& result) {
308 EXPECT_EQ(DBUS_METHOD_CALL_SUCCESS, call_status);
309 EXPECT_EQ(expected_result, result);
310 }
311
312 // static
ExpectObjectPathResultWithoutStatus(const dbus::ObjectPath & expected_result,const dbus::ObjectPath & result)313 void ShillClientUnittestBase::ExpectObjectPathResultWithoutStatus(
314 const dbus::ObjectPath& expected_result,
315 const dbus::ObjectPath& result) {
316 EXPECT_EQ(expected_result, result);
317 }
318
319 // static
ExpectBoolResultWithoutStatus(bool expected_result,bool result)320 void ShillClientUnittestBase::ExpectBoolResultWithoutStatus(
321 bool expected_result,
322 bool result) {
323 EXPECT_EQ(expected_result, result);
324 }
325
326 // static
ExpectStringResultWithoutStatus(const std::string & expected_result,const std::string & result)327 void ShillClientUnittestBase::ExpectStringResultWithoutStatus(
328 const std::string& expected_result,
329 const std::string& result) {
330 EXPECT_EQ(expected_result, result);
331 }
332
333 // static
ExpectDictionaryValueResultWithoutStatus(const base::DictionaryValue * expected_result,const base::DictionaryValue & result)334 void ShillClientUnittestBase::ExpectDictionaryValueResultWithoutStatus(
335 const base::DictionaryValue* expected_result,
336 const base::DictionaryValue& result) {
337 std::string expected_result_string;
338 base::JSONWriter::Write(expected_result, &expected_result_string);
339 std::string result_string;
340 base::JSONWriter::Write(&result, &result_string);
341 EXPECT_EQ(expected_result_string, result_string);
342 }
343
344 // static
ExpectDictionaryValueResult(const base::DictionaryValue * expected_result,DBusMethodCallStatus call_status,const base::DictionaryValue & result)345 void ShillClientUnittestBase::ExpectDictionaryValueResult(
346 const base::DictionaryValue* expected_result,
347 DBusMethodCallStatus call_status,
348 const base::DictionaryValue& result) {
349 EXPECT_EQ(DBUS_METHOD_CALL_SUCCESS, call_status);
350 ExpectDictionaryValueResultWithoutStatus(expected_result, result);
351 }
352
OnConnectToSignal(const std::string & interface_name,const std::string & signal_name,const dbus::ObjectProxy::SignalCallback & signal_callback,const dbus::ObjectProxy::OnConnectedCallback & on_connected_callback)353 void ShillClientUnittestBase::OnConnectToSignal(
354 const std::string& interface_name,
355 const std::string& signal_name,
356 const dbus::ObjectProxy::SignalCallback& signal_callback,
357 const dbus::ObjectProxy::OnConnectedCallback& on_connected_callback) {
358 property_changed_handler_ = signal_callback;
359 const bool success = true;
360 message_loop_.PostTask(FROM_HERE,
361 base::Bind(on_connected_callback,
362 interface_name,
363 signal_name,
364 success));
365 }
366
OnCallMethod(dbus::MethodCall * method_call,int timeout_ms,const dbus::ObjectProxy::ResponseCallback & response_callback)367 void ShillClientUnittestBase::OnCallMethod(
368 dbus::MethodCall* method_call,
369 int timeout_ms,
370 const dbus::ObjectProxy::ResponseCallback& response_callback) {
371 EXPECT_EQ(interface_name_, method_call->GetInterface());
372 EXPECT_EQ(expected_method_name_, method_call->GetMember());
373 dbus::MessageReader reader(method_call);
374 argument_checker_.Run(&reader);
375 message_loop_.PostTask(FROM_HERE,
376 base::Bind(response_callback, response_));
377 }
378
OnCallMethodWithErrorCallback(dbus::MethodCall * method_call,int timeout_ms,const dbus::ObjectProxy::ResponseCallback & response_callback,const dbus::ObjectProxy::ErrorCallback & error_callback)379 void ShillClientUnittestBase::OnCallMethodWithErrorCallback(
380 dbus::MethodCall* method_call,
381 int timeout_ms,
382 const dbus::ObjectProxy::ResponseCallback& response_callback,
383 const dbus::ObjectProxy::ErrorCallback& error_callback) {
384 OnCallMethod(method_call, timeout_ms, response_callback);
385 }
386
387 } // namespace chromeos
388