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. 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, base::Value::CreateStringValue(value)); 42 } 43 return result.release(); 44 } 45 46 } // namespace 47 48 ValueMatcher::ValueMatcher(const base::Value& value) 49 : expected_value_(value.DeepCopy()) {} 50 51 bool ValueMatcher::MatchAndExplain(const base::Value& value, 52 MatchResultListener* listener) const { 53 return expected_value_->Equals(&value); 54 } 55 56 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 64 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 73 ShillClientUnittestBase::MockClosure::MockClosure() {} 74 75 ShillClientUnittestBase::MockClosure::~MockClosure() {} 76 77 base::Closure ShillClientUnittestBase::MockClosure::GetCallback() { 78 return base::Bind(&MockClosure::Run, base::Unretained(this)); 79 } 80 81 82 ShillClientUnittestBase::MockListValueCallback::MockListValueCallback() {} 83 84 ShillClientUnittestBase::MockListValueCallback::~MockListValueCallback() {} 85 86 ShillClientHelper::ListValueCallback 87 ShillClientUnittestBase::MockListValueCallback::GetCallback() { 88 return base::Bind(&MockListValueCallback::Run, base::Unretained(this)); 89 } 90 91 92 ShillClientUnittestBase::MockErrorCallback::MockErrorCallback() {} 93 94 ShillClientUnittestBase::MockErrorCallback::~MockErrorCallback() {} 95 96 ShillClientUnittestBase::MockPropertyChangeObserver:: 97 MockPropertyChangeObserver() {} 98 99 ShillClientUnittestBase::MockPropertyChangeObserver:: 100 ~MockPropertyChangeObserver() {} 101 102 ShillClientHelper::ErrorCallback 103 ShillClientUnittestBase::MockErrorCallback::GetCallback() { 104 return base::Bind(&MockErrorCallback::Run, base::Unretained(this)); 105 } 106 107 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 116 ShillClientUnittestBase::~ShillClientUnittestBase() { 117 } 118 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())); 160 161 // ShutdownAndBlock() will be called in TearDown(). 162 EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return()); 163 } 164 165 void ShillClientUnittestBase::TearDown() { 166 mock_bus_->ShutdownAndBlock(); 167 } 168 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 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 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 195 void ShillClientUnittestBase::ExpectNoArgument(dbus::MessageReader* reader) { 196 EXPECT_FALSE(reader->HasMoreData()); 197 } 198 199 // static 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 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 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 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 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* 281 ShillClientUnittestBase::CreateExampleServiceProperties() { 282 base::DictionaryValue* properties = new base::DictionaryValue; 283 properties->SetWithoutPathExpansion( 284 shill::kGuidProperty, 285 base::Value::CreateStringValue("00000000-0000-0000-0000-000000000000")); 286 properties->SetWithoutPathExpansion( 287 shill::kModeProperty, 288 base::Value::CreateStringValue(shill::kModeManaged)); 289 properties->SetWithoutPathExpansion( 290 shill::kTypeProperty, 291 base::Value::CreateStringValue(shill::kTypeWifi)); 292 shill_property_util::SetSSID("testssid", properties); 293 properties->SetWithoutPathExpansion( 294 shill::kSecurityProperty, 295 base::Value::CreateStringValue(shill::kSecurityPsk)); 296 return properties; 297 } 298 299 300 // static 301 void ShillClientUnittestBase::ExpectNoResultValue( 302 DBusMethodCallStatus call_status) { 303 EXPECT_EQ(DBUS_METHOD_CALL_SUCCESS, call_status); 304 } 305 306 // static 307 void ShillClientUnittestBase::ExpectObjectPathResult( 308 const dbus::ObjectPath& expected_result, 309 DBusMethodCallStatus call_status, 310 const dbus::ObjectPath& result) { 311 EXPECT_EQ(DBUS_METHOD_CALL_SUCCESS, call_status); 312 EXPECT_EQ(expected_result, result); 313 } 314 315 // static 316 void ShillClientUnittestBase::ExpectObjectPathResultWithoutStatus( 317 const dbus::ObjectPath& expected_result, 318 const dbus::ObjectPath& result) { 319 EXPECT_EQ(expected_result, result); 320 } 321 322 // static 323 void ShillClientUnittestBase::ExpectBoolResultWithoutStatus( 324 bool expected_result, 325 bool result) { 326 EXPECT_EQ(expected_result, result); 327 } 328 329 // static 330 void ShillClientUnittestBase::ExpectStringResultWithoutStatus( 331 const std::string& expected_result, 332 const std::string& result) { 333 EXPECT_EQ(expected_result, result); 334 } 335 336 // static 337 void ShillClientUnittestBase::ExpectDictionaryValueResultWithoutStatus( 338 const base::DictionaryValue* expected_result, 339 const base::DictionaryValue& result) { 340 std::string expected_result_string; 341 base::JSONWriter::Write(expected_result, &expected_result_string); 342 std::string result_string; 343 base::JSONWriter::Write(&result, &result_string); 344 EXPECT_EQ(expected_result_string, result_string); 345 } 346 347 // static 348 void ShillClientUnittestBase::ExpectDictionaryValueResult( 349 const base::DictionaryValue* expected_result, 350 DBusMethodCallStatus call_status, 351 const base::DictionaryValue& result) { 352 EXPECT_EQ(DBUS_METHOD_CALL_SUCCESS, call_status); 353 ExpectDictionaryValueResultWithoutStatus(expected_result, result); 354 } 355 356 void ShillClientUnittestBase::OnConnectToSignal( 357 const std::string& interface_name, 358 const std::string& signal_name, 359 const dbus::ObjectProxy::SignalCallback& signal_callback, 360 const dbus::ObjectProxy::OnConnectedCallback& on_connected_callback) { 361 property_changed_handler_ = signal_callback; 362 const bool success = true; 363 message_loop_.PostTask(FROM_HERE, 364 base::Bind(on_connected_callback, 365 interface_name, 366 signal_name, 367 success)); 368 } 369 370 void ShillClientUnittestBase::OnCallMethod( 371 dbus::MethodCall* method_call, 372 int timeout_ms, 373 const dbus::ObjectProxy::ResponseCallback& response_callback) { 374 EXPECT_EQ(interface_name_, method_call->GetInterface()); 375 EXPECT_EQ(expected_method_name_, method_call->GetMember()); 376 dbus::MessageReader reader(method_call); 377 argument_checker_.Run(&reader); 378 message_loop_.PostTask(FROM_HERE, 379 base::Bind(response_callback, response_)); 380 } 381 382 void ShillClientUnittestBase::OnCallMethodWithErrorCallback( 383 dbus::MethodCall* method_call, 384 int timeout_ms, 385 const dbus::ObjectProxy::ResponseCallback& response_callback, 386 const dbus::ObjectProxy::ErrorCallback& error_callback) { 387 OnCallMethod(method_call, timeout_ms, response_callback); 388 } 389 390 } // namespace chromeos 391