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