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, new base::StringValue(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().get())); 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 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 298 void ShillClientUnittestBase::ExpectNoResultValue( 299 DBusMethodCallStatus call_status) { 300 EXPECT_EQ(DBUS_METHOD_CALL_SUCCESS, call_status); 301 } 302 303 // static 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 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 320 void ShillClientUnittestBase::ExpectBoolResultWithoutStatus( 321 bool expected_result, 322 bool result) { 323 EXPECT_EQ(expected_result, result); 324 } 325 326 // static 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 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 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 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 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 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