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 18using ::testing::_; 19using ::testing::Invoke; 20using ::testing::Return; 21 22namespace chromeos { 23 24namespace { 25 26// Pops a string-to-string dictionary from the reader. 27base::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 48ValueMatcher::ValueMatcher(const base::Value& value) 49 : expected_value_(value.DeepCopy()) {} 50 51bool ValueMatcher::MatchAndExplain(const base::Value& value, 52 MatchResultListener* listener) const { 53 return expected_value_->Equals(&value); 54} 55 56void 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 64void 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 73ShillClientUnittestBase::MockClosure::MockClosure() {} 74 75ShillClientUnittestBase::MockClosure::~MockClosure() {} 76 77base::Closure ShillClientUnittestBase::MockClosure::GetCallback() { 78 return base::Bind(&MockClosure::Run, base::Unretained(this)); 79} 80 81 82ShillClientUnittestBase::MockListValueCallback::MockListValueCallback() {} 83 84ShillClientUnittestBase::MockListValueCallback::~MockListValueCallback() {} 85 86ShillClientHelper::ListValueCallback 87ShillClientUnittestBase::MockListValueCallback::GetCallback() { 88 return base::Bind(&MockListValueCallback::Run, base::Unretained(this)); 89} 90 91 92ShillClientUnittestBase::MockErrorCallback::MockErrorCallback() {} 93 94ShillClientUnittestBase::MockErrorCallback::~MockErrorCallback() {} 95 96ShillClientUnittestBase::MockPropertyChangeObserver:: 97 MockPropertyChangeObserver() {} 98 99ShillClientUnittestBase::MockPropertyChangeObserver:: 100 ~MockPropertyChangeObserver() {} 101 102ShillClientHelper::ErrorCallback 103ShillClientUnittestBase::MockErrorCallback::GetCallback() { 104 return base::Bind(&MockErrorCallback::Run, base::Unretained(this)); 105} 106 107 108ShillClientUnittestBase::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 116ShillClientUnittestBase::~ShillClientUnittestBase() { 117} 118 119void 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 165void ShillClientUnittestBase::TearDown() { 166 mock_bus_->ShutdownAndBlock(); 167} 168 169void 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 178void ShillClientUnittestBase::SendPropertyChangedSignal( 179 dbus::Signal* signal) { 180 ASSERT_FALSE(property_changed_handler_.is_null()); 181 property_changed_handler_.Run(signal); 182} 183 184// static 185void 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 195void ShillClientUnittestBase::ExpectNoArgument(dbus::MessageReader* reader) { 196 EXPECT_FALSE(reader->HasMoreData()); 197} 198 199// static 200void 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 210void 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 220void 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 230void 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 244void 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 280base::DictionaryValue* 281ShillClientUnittestBase::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 298void ShillClientUnittestBase::ExpectNoResultValue( 299 DBusMethodCallStatus call_status) { 300 EXPECT_EQ(DBUS_METHOD_CALL_SUCCESS, call_status); 301} 302 303// static 304void 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 313void ShillClientUnittestBase::ExpectObjectPathResultWithoutStatus( 314 const dbus::ObjectPath& expected_result, 315 const dbus::ObjectPath& result) { 316 EXPECT_EQ(expected_result, result); 317} 318 319// static 320void ShillClientUnittestBase::ExpectBoolResultWithoutStatus( 321 bool expected_result, 322 bool result) { 323 EXPECT_EQ(expected_result, result); 324} 325 326// static 327void ShillClientUnittestBase::ExpectStringResultWithoutStatus( 328 const std::string& expected_result, 329 const std::string& result) { 330 EXPECT_EQ(expected_result, result); 331} 332 333// static 334void 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 345void 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 353void 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 367void 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 379void 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