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/gsm_sms_client.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/values.h"
     10 #include "dbus/message.h"
     11 #include "dbus/mock_bus.h"
     12 #include "dbus/mock_object_proxy.h"
     13 #include "dbus/object_path.h"
     14 #include "dbus/values_util.h"
     15 #include "testing/gmock/include/gmock/gmock.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 #include "third_party/cros_system_api/dbus/service_constants.h"
     18 
     19 using ::testing::_;
     20 using ::testing::Invoke;
     21 using ::testing::Return;
     22 
     23 namespace chromeos {
     24 
     25 namespace {
     26 
     27 // A mock SmsReceivedHandler.
     28 class MockSmsReceivedHandler {
     29  public:
     30   MOCK_METHOD2(Run, void(uint32 index, bool complete));
     31 };
     32 
     33 // A mock DeleteCallback.
     34 class MockDeleteCallback {
     35  public:
     36   MOCK_METHOD0(Run, void());
     37 };
     38 
     39 // A mock GetCallback.
     40 class MockGetCallback {
     41  public:
     42   MOCK_METHOD1(Run, void(const base::DictionaryValue& sms));
     43 };
     44 
     45 // A mock ListCallback.
     46 class MockListCallback {
     47  public:
     48   MOCK_METHOD1(Run, void(const base::ListValue& result));
     49 };
     50 
     51 // D-Bus service name used by test.
     52 const char kServiceName[] = "service.name";
     53 // D-Bus object path used by test.
     54 const char kObjectPath[] = "/object/path";
     55 
     56 // Keys of SMS dictionary.
     57 const char kNumberKey[] = "number";
     58 const char kTextKey[] = "text";
     59 
     60 // Example values of SMS dictionary.
     61 const char kExampleNumber[] = "00012345678";
     62 const char kExampleText[] = "Hello.";
     63 
     64 }  // namespace
     65 
     66 class GsmSMSClientTest : public testing::Test {
     67  public:
     68   GsmSMSClientTest() : expected_index_(0),
     69                        response_(NULL),
     70                        expected_result_(NULL) {}
     71 
     72   virtual void SetUp() OVERRIDE {
     73     // Create a mock bus.
     74     dbus::Bus::Options options;
     75     options.bus_type = dbus::Bus::SYSTEM;
     76     mock_bus_ = new dbus::MockBus(options);
     77 
     78     // Create a mock proxy.
     79     mock_proxy_ = new dbus::MockObjectProxy(mock_bus_.get(),
     80                                             kServiceName,
     81                                             dbus::ObjectPath(kObjectPath));
     82 
     83     // Set an expectation so mock_proxy's ConnectToSignal() will use
     84     // OnConnectToSignal() to run the callback.
     85     EXPECT_CALL(*mock_proxy_.get(),
     86                 ConnectToSignal(modemmanager::kModemManagerSMSInterface,
     87                                 modemmanager::kSMSReceivedSignal,
     88                                 _,
     89                                 _))
     90         .WillRepeatedly(Invoke(this, &GsmSMSClientTest::OnConnectToSignal));
     91 
     92     // Set an expectation so mock_bus's GetObjectProxy() for the given
     93     // service name and the object path will return mock_proxy_.
     94     EXPECT_CALL(*mock_bus_.get(),
     95                 GetObjectProxy(kServiceName, dbus::ObjectPath(kObjectPath)))
     96         .WillOnce(Return(mock_proxy_.get()));
     97 
     98     // ShutdownAndBlock() will be called in TearDown().
     99     EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
    100 
    101     // Create a client with the mock bus.
    102     client_.reset(GsmSMSClient::Create());
    103     client_->Init(mock_bus_.get());
    104   }
    105 
    106   virtual void TearDown() OVERRIDE {
    107     mock_bus_->ShutdownAndBlock();
    108   }
    109 
    110   // Handles Delete method call.
    111   void OnDelete(dbus::MethodCall* method_call,
    112                 int timeout_ms,
    113                 const dbus::ObjectProxy::ResponseCallback& callback) {
    114     EXPECT_EQ(modemmanager::kModemManagerSMSInterface,
    115               method_call->GetInterface());
    116     EXPECT_EQ(modemmanager::kSMSDeleteFunction, method_call->GetMember());
    117     uint32 index = 0;
    118     dbus::MessageReader reader(method_call);
    119     EXPECT_TRUE(reader.PopUint32(&index));
    120     EXPECT_EQ(expected_index_, index);
    121     EXPECT_FALSE(reader.HasMoreData());
    122 
    123     message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_));
    124   }
    125 
    126   // Handles Get method call.
    127   void OnGet(dbus::MethodCall* method_call,
    128              int timeout_ms,
    129              const dbus::ObjectProxy::ResponseCallback& callback) {
    130     EXPECT_EQ(modemmanager::kModemManagerSMSInterface,
    131               method_call->GetInterface());
    132     EXPECT_EQ(modemmanager::kSMSGetFunction, method_call->GetMember());
    133     uint32 index = 0;
    134     dbus::MessageReader reader(method_call);
    135     EXPECT_TRUE(reader.PopUint32(&index));
    136     EXPECT_EQ(expected_index_, index);
    137     EXPECT_FALSE(reader.HasMoreData());
    138 
    139     message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_));
    140   }
    141 
    142   // Handles List method call.
    143   void OnList(dbus::MethodCall* method_call,
    144               int timeout_ms,
    145               const dbus::ObjectProxy::ResponseCallback& callback) {
    146     EXPECT_EQ(modemmanager::kModemManagerSMSInterface,
    147               method_call->GetInterface());
    148     EXPECT_EQ(modemmanager::kSMSListFunction, method_call->GetMember());
    149     dbus::MessageReader reader(method_call);
    150     EXPECT_FALSE(reader.HasMoreData());
    151 
    152     message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_));
    153   }
    154 
    155   // Checks the results of Get and List.
    156   void CheckResult(const base::Value& result) {
    157     EXPECT_TRUE(result.Equals(expected_result_));
    158   }
    159 
    160  protected:
    161   // The client to be tested.
    162   scoped_ptr<GsmSMSClient> client_;
    163   // A message loop to emulate asynchronous behavior.
    164   base::MessageLoop message_loop_;
    165   // The mock bus.
    166   scoped_refptr<dbus::MockBus> mock_bus_;
    167   // The mock object proxy.
    168   scoped_refptr<dbus::MockObjectProxy> mock_proxy_;
    169   // The SmsReceived signal handler given by the tested client.
    170   dbus::ObjectProxy::SignalCallback sms_received_callback_;
    171   // Expected argument for Delete and Get methods.
    172   uint32 expected_index_;
    173   // Response returned by mock methods.
    174   dbus::Response* response_;
    175   // Expected result of Get and List methods.
    176   base::Value* expected_result_;
    177 
    178  private:
    179   // Used to implement the mock proxy.
    180   void OnConnectToSignal(
    181       const std::string& interface_name,
    182       const std::string& signal_name,
    183       const dbus::ObjectProxy::SignalCallback& signal_callback,
    184       const dbus::ObjectProxy::OnConnectedCallback& on_connected_callback) {
    185     sms_received_callback_ = signal_callback;
    186     const bool success = true;
    187     message_loop_.PostTask(FROM_HERE, base::Bind(on_connected_callback,
    188                                                  interface_name,
    189                                                  signal_name,
    190                                                  success));
    191   }
    192 };
    193 
    194 TEST_F(GsmSMSClientTest, SmsReceived) {
    195   // Set expectations.
    196   const uint32 kIndex = 42;
    197   const bool kComplete = true;
    198   MockSmsReceivedHandler handler;
    199   EXPECT_CALL(handler, Run(kIndex, kComplete)).Times(1);
    200   // Set handler.
    201   client_->SetSmsReceivedHandler(kServiceName, dbus::ObjectPath(kObjectPath),
    202                                  base::Bind(&MockSmsReceivedHandler::Run,
    203                                             base::Unretained(&handler)));
    204 
    205   // Run the message loop to run the signal connection result callback.
    206   message_loop_.RunUntilIdle();
    207 
    208   // Send signal.
    209   dbus::Signal signal(modemmanager::kModemManagerSMSInterface,
    210                       modemmanager::kSMSReceivedSignal);
    211   dbus::MessageWriter writer(&signal);
    212   writer.AppendUint32(kIndex);
    213   writer.AppendBool(kComplete);
    214   ASSERT_FALSE(sms_received_callback_.is_null());
    215   sms_received_callback_.Run(&signal);
    216   // Reset handler.
    217   client_->ResetSmsReceivedHandler(kServiceName, dbus::ObjectPath(kObjectPath));
    218   // Send signal again.
    219   sms_received_callback_.Run(&signal);
    220 }
    221 
    222 TEST_F(GsmSMSClientTest, Delete) {
    223   // Set expectations.
    224   const uint32 kIndex = 42;
    225   expected_index_ = kIndex;
    226   EXPECT_CALL(*mock_proxy_.get(), CallMethod(_, _, _))
    227       .WillOnce(Invoke(this, &GsmSMSClientTest::OnDelete));
    228   MockDeleteCallback callback;
    229   EXPECT_CALL(callback, Run()).Times(1);
    230   // Create response.
    231   scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
    232   response_ = response.get();
    233   // Call Delete.
    234   client_->Delete(kServiceName, dbus::ObjectPath(kObjectPath), kIndex,
    235                   base::Bind(&MockDeleteCallback::Run,
    236                              base::Unretained(&callback)));
    237 
    238   // Run the message loop.
    239   message_loop_.RunUntilIdle();
    240 }
    241 
    242 TEST_F(GsmSMSClientTest, Get) {
    243   // Set expectations.
    244   const uint32 kIndex = 42;
    245   expected_index_ = kIndex;
    246   EXPECT_CALL(*mock_proxy_.get(), CallMethod(_, _, _))
    247       .WillOnce(Invoke(this, &GsmSMSClientTest::OnGet));
    248   MockGetCallback callback;
    249   EXPECT_CALL(callback, Run(_))
    250       .WillOnce(Invoke(this, &GsmSMSClientTest::CheckResult));
    251   // Create response.
    252   scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
    253   dbus::MessageWriter writer(response.get());
    254   dbus::MessageWriter array_writer(NULL);
    255   writer.OpenArray("{sv}", &array_writer);
    256   dbus::MessageWriter entry_writer(NULL);
    257   array_writer.OpenDictEntry(&entry_writer);
    258   entry_writer.AppendString(kNumberKey);
    259   entry_writer.AppendVariantOfString(kExampleNumber);
    260   array_writer.CloseContainer(&entry_writer);
    261   array_writer.OpenDictEntry(&entry_writer);
    262   entry_writer.AppendString(kTextKey);
    263   entry_writer.AppendVariantOfString(kExampleText);
    264   array_writer.CloseContainer(&entry_writer);
    265   writer.CloseContainer(&array_writer);
    266   response_ = response.get();
    267   // Create expected result.
    268   base::DictionaryValue expected_result;
    269   expected_result.SetWithoutPathExpansion(
    270       kNumberKey, base::Value::CreateStringValue(kExampleNumber));
    271   expected_result.SetWithoutPathExpansion(
    272       kTextKey, base::Value::CreateStringValue(kExampleText));
    273   expected_result_ = &expected_result;
    274   // Call Delete.
    275   client_->Get(kServiceName, dbus::ObjectPath(kObjectPath), kIndex,
    276                base::Bind(&MockGetCallback::Run, base::Unretained(&callback)));
    277 
    278   // Run the message loop.
    279   message_loop_.RunUntilIdle();
    280 }
    281 
    282 TEST_F(GsmSMSClientTest, List) {
    283   // Set expectations.
    284   EXPECT_CALL(*mock_proxy_.get(), CallMethod(_, _, _))
    285       .WillOnce(Invoke(this, &GsmSMSClientTest::OnList));
    286   MockListCallback callback;
    287   EXPECT_CALL(callback, Run(_))
    288       .WillOnce(Invoke(this, &GsmSMSClientTest::CheckResult));
    289   // Create response.
    290   scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
    291   dbus::MessageWriter writer(response.get());
    292   dbus::MessageWriter array_writer(NULL);
    293   writer.OpenArray("a{sv}", &array_writer);
    294   dbus::MessageWriter sub_array_writer(NULL);
    295   array_writer.OpenArray("{sv}", &sub_array_writer);
    296   dbus::MessageWriter entry_writer(NULL);
    297   sub_array_writer.OpenDictEntry(&entry_writer);
    298   entry_writer.AppendString(kNumberKey);
    299   entry_writer.AppendVariantOfString(kExampleNumber);
    300   sub_array_writer.CloseContainer(&entry_writer);
    301   sub_array_writer.OpenDictEntry(&entry_writer);
    302   entry_writer.AppendString(kTextKey);
    303   entry_writer.AppendVariantOfString(kExampleText);
    304   sub_array_writer.CloseContainer(&entry_writer);
    305   array_writer.CloseContainer(&sub_array_writer);
    306   writer.CloseContainer(&array_writer);
    307   response_ = response.get();
    308   // Create expected result.
    309   base::ListValue expected_result;
    310   base::DictionaryValue* sms = new base::DictionaryValue;
    311   sms->SetWithoutPathExpansion(
    312       kNumberKey, base::Value::CreateStringValue(kExampleNumber));
    313   sms->SetWithoutPathExpansion(
    314       kTextKey, base::Value::CreateStringValue(kExampleText));
    315   expected_result.Append(sms);
    316   expected_result_ = &expected_result;
    317   // Call List.
    318   client_->List(kServiceName, dbus::ObjectPath(kObjectPath),
    319                 base::Bind(&MockListCallback::Run,
    320                            base::Unretained(&callback)));
    321 
    322   // Run the message loop.
    323   message_loop_.RunUntilIdle();
    324 }
    325 
    326 }  // namespace chromeos
    327