Home | History | Annotate | Download | only in dbus
      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