Home | History | Annotate | Download | only in ibus
      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/ibus/ibus_client.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/values.h"
     10 #include "chromeos/dbus/ibus/ibus_constants.h"
     11 #include "dbus/message.h"
     12 #include "dbus/mock_bus.h"
     13 #include "dbus/mock_object_proxy.h"
     14 #include "dbus/object_path.h"
     15 #include "dbus/values_util.h"
     16 #include "testing/gmock/include/gmock/gmock.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 using testing::Invoke;
     20 using testing::Return;
     21 using testing::_;
     22 
     23 namespace chromeos {
     24 
     25 namespace {
     26 const char kClientName[] = "chrome";
     27 const char kEngineName[] = "engine";
     28 const bool kRestartFlag = true;
     29 }  // namespace
     30 
     31 class MockCreateInputContextCallback {
     32  public:
     33   MOCK_METHOD1(Run, void(const dbus::ObjectPath& object_path));
     34 };
     35 
     36 class MockErrorCallback {
     37  public:
     38   MOCK_METHOD0(Run, void());
     39 };
     40 
     41 class IBusClientTest : public testing::Test {
     42  public:
     43   IBusClientTest() : response_(NULL) {}
     44 
     45   // Handles CreateInputContext method call.
     46   void OnCreateInputContext(
     47       dbus::MethodCall* method_call,
     48       int timeout_ms,
     49       const dbus::ObjectProxy::ResponseCallback& callback,
     50       const dbus::ObjectProxy::ErrorCallback& error_callback) {
     51     dbus::MessageReader reader(method_call);
     52     std::string client_name;
     53     EXPECT_TRUE(reader.PopString(&client_name));
     54     EXPECT_EQ(kClientName, client_name);
     55     EXPECT_FALSE(reader.HasMoreData());
     56 
     57     message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_));
     58   }
     59 
     60   // Handles fail case of CreateInputContext method call.
     61   void OnCreateInputContextFail(
     62       dbus::MethodCall* method_call,
     63       int timeout_ms,
     64       const dbus::ObjectProxy::ResponseCallback& callback,
     65       const dbus::ObjectProxy::ErrorCallback& error_callback) {
     66     dbus::MessageReader reader(method_call);
     67     std::string client_name;
     68     EXPECT_TRUE(reader.PopString(&client_name));
     69     EXPECT_EQ(kClientName, client_name);
     70     EXPECT_FALSE(reader.HasMoreData());
     71 
     72     message_loop_.PostTask(FROM_HERE, base::Bind(error_callback,
     73                                                  error_response_));
     74   }
     75 
     76   // Handles SetGlobalEngine method call.
     77   void OnSetGlobalEngine(
     78       dbus::MethodCall* method_call,
     79       int timeout_ms,
     80       const dbus::ObjectProxy::ResponseCallback& callback,
     81       const dbus::ObjectProxy::ErrorCallback& error_callback) {
     82     dbus::MessageReader reader(method_call);
     83     std::string engine_name;
     84     EXPECT_TRUE(reader.PopString(&engine_name));
     85     EXPECT_EQ(kEngineName, engine_name);
     86     EXPECT_FALSE(reader.HasMoreData());
     87     message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_));
     88   }
     89 
     90   // Handles fail case of SetGlobalEngine method call.
     91   void OnSetGlobalEngineFail(
     92       dbus::MethodCall* method_call,
     93       int timeout_ms,
     94       const dbus::ObjectProxy::ResponseCallback& callback,
     95       const dbus::ObjectProxy::ErrorCallback& error_callback) {
     96     dbus::MessageReader reader(method_call);
     97     std::string engine_name;
     98     EXPECT_TRUE(reader.PopString(&engine_name));
     99     EXPECT_EQ(kEngineName, engine_name);
    100     EXPECT_FALSE(reader.HasMoreData());
    101     message_loop_.PostTask(FROM_HERE, base::Bind(error_callback,
    102                                                  error_response_));
    103   }
    104 
    105   // Handles Exit method call.
    106   void OnExit(dbus::MethodCall* method_call,
    107               int timeout_ms,
    108               const dbus::ObjectProxy::ResponseCallback& callback,
    109               const dbus::ObjectProxy::ErrorCallback& error_callback) {
    110     dbus::MessageReader reader(method_call);
    111     bool restart = false;
    112     EXPECT_TRUE(reader.PopBool(&restart));
    113     EXPECT_EQ(kRestartFlag, restart);
    114     EXPECT_FALSE(reader.HasMoreData());
    115     message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_));
    116   }
    117 
    118   // Handles fail case of Exit method call.
    119   void OnExitFail(dbus::MethodCall* method_call,
    120                   int timeout_ms,
    121                   const dbus::ObjectProxy::ResponseCallback& callback,
    122                   const dbus::ObjectProxy::ErrorCallback& error_callback) {
    123     dbus::MessageReader reader(method_call);
    124     bool restart = false;
    125     EXPECT_TRUE(reader.PopBool(&restart));
    126     EXPECT_EQ(kRestartFlag, restart);
    127     EXPECT_FALSE(reader.HasMoreData());
    128     message_loop_.PostTask(FROM_HERE, base::Bind(error_callback,
    129                                                  error_response_));
    130   }
    131 
    132  protected:
    133   virtual void SetUp() OVERRIDE {
    134     dbus::Bus::Options options;
    135     mock_bus_ = new dbus::MockBus(options);
    136     mock_proxy_ = new dbus::MockObjectProxy(mock_bus_.get(),
    137                                             ibus::kServiceName,
    138                                             dbus::ObjectPath(
    139                                                 ibus::bus::kServicePath));
    140     EXPECT_CALL(*mock_bus_.get(),
    141                 GetObjectProxy(ibus::kServiceName,
    142                                dbus::ObjectPath(ibus::bus::kServicePath)))
    143         .WillOnce(Return(mock_proxy_.get()));
    144 
    145     EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock());
    146     client_.reset(
    147         IBusClient::Create(REAL_DBUS_CLIENT_IMPLEMENTATION, mock_bus_.get()));
    148   }
    149 
    150   virtual void TearDown() OVERRIDE {
    151     mock_bus_->ShutdownAndBlock();
    152   }
    153 
    154   // The IBus client to be tested.
    155   scoped_ptr<IBusClient> client_;
    156 
    157   // A message loop to emulate asynchronous behavior.
    158   base::MessageLoop message_loop_;
    159   scoped_refptr<dbus::MockBus> mock_bus_;
    160   scoped_refptr<dbus::MockObjectProxy> mock_proxy_;
    161 
    162   // Response returned by mock methods.
    163   dbus::Response* response_;
    164   dbus::ErrorResponse* error_response_;
    165 };
    166 
    167 TEST_F(IBusClientTest, CreateInputContextTest) {
    168   // Set expectations.
    169   const dbus::ObjectPath kInputContextObjectPath =
    170       dbus::ObjectPath("/some/object/path");
    171   EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
    172       .WillOnce(Invoke(this, &IBusClientTest::OnCreateInputContext));
    173   MockCreateInputContextCallback callback;
    174   EXPECT_CALL(callback, Run(kInputContextObjectPath));
    175   MockErrorCallback error_callback;
    176   EXPECT_CALL(error_callback, Run()).Times(0);
    177 
    178   // Create response.
    179   scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
    180   dbus::MessageWriter writer(response.get());
    181   writer.AppendObjectPath(kInputContextObjectPath);
    182   response_ = response.get();
    183 
    184   // Call CreateInputContext.
    185   client_->CreateInputContext(
    186       kClientName,
    187       base::Bind(&MockCreateInputContextCallback::Run,
    188                  base::Unretained(&callback)),
    189       base::Bind(&MockErrorCallback::Run,
    190                  base::Unretained(&error_callback)));
    191 
    192   // Run the message loop.
    193   message_loop_.RunUntilIdle();
    194 }
    195 
    196 TEST_F(IBusClientTest, CreateInputContext_NullResponseFail) {
    197   // Set expectations.
    198   EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
    199       .WillOnce(Invoke(this, &IBusClientTest::OnCreateInputContext));
    200   MockCreateInputContextCallback callback;
    201   EXPECT_CALL(callback, Run(_)).Times(0);
    202   MockErrorCallback error_callback;
    203   EXPECT_CALL(error_callback, Run());
    204 
    205   // Set NULL response.
    206   response_ = NULL;
    207 
    208   // Call CreateInputContext.
    209   client_->CreateInputContext(
    210       kClientName,
    211       base::Bind(&MockCreateInputContextCallback::Run,
    212                  base::Unretained(&callback)),
    213       base::Bind(&MockErrorCallback::Run,
    214                  base::Unretained(&error_callback)));
    215 
    216   // Run the message loop.
    217   message_loop_.RunUntilIdle();
    218 }
    219 
    220 TEST_F(IBusClientTest, CreateInputContext_InvalidResponseFail) {
    221   // Set expectations.
    222   EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
    223       .WillOnce(Invoke(this, &IBusClientTest::OnCreateInputContext));
    224   MockCreateInputContextCallback callback;
    225   EXPECT_CALL(callback, Run(_)).Times(0);
    226   MockErrorCallback error_callback;
    227   EXPECT_CALL(error_callback, Run());
    228 
    229   // Create invalid(empty) response.
    230   scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
    231   response_ = response.get();
    232 
    233   // Call CreateInputContext.
    234   client_->CreateInputContext(
    235       kClientName,
    236       base::Bind(&MockCreateInputContextCallback::Run,
    237                  base::Unretained(&callback)),
    238       base::Bind(&MockErrorCallback::Run,
    239                  base::Unretained(&error_callback)));
    240 
    241   // Run the message loop.
    242   message_loop_.RunUntilIdle();
    243 }
    244 
    245 TEST_F(IBusClientTest, CreateInputContext_MethodCallFail) {
    246   // Set expectations
    247   EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
    248       .WillOnce(Invoke(this, &IBusClientTest::OnCreateInputContextFail));
    249   MockCreateInputContextCallback callback;
    250   EXPECT_CALL(callback, Run(_)).Times(0);
    251   MockErrorCallback error_callback;
    252   EXPECT_CALL(error_callback, Run());
    253 
    254   // The error response is not used in CreateInputContext.
    255   error_response_ = NULL;
    256 
    257   // Call CreateInputContext.
    258   client_->CreateInputContext(
    259       kClientName,
    260       base::Bind(&MockCreateInputContextCallback::Run,
    261                  base::Unretained(&callback)),
    262       base::Bind(&MockErrorCallback::Run,
    263                  base::Unretained(&error_callback)));
    264 
    265   // Run the message loop.
    266   message_loop_.RunUntilIdle();
    267 }
    268 
    269 TEST_F(IBusClientTest, SetGlobalEngineTest) {
    270   // Set expectations
    271   EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
    272       .WillOnce(Invoke(this, &IBusClientTest::OnSetGlobalEngine));
    273   MockErrorCallback error_callback;
    274   EXPECT_CALL(error_callback, Run()).Times(0);
    275 
    276   // Create empty response.
    277   scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
    278   response_ = response.get();
    279 
    280   // The error response is not used in SetGLobalEngine.
    281   error_response_ = NULL;
    282 
    283   // Call CreateInputContext.
    284   client_->SetGlobalEngine(
    285       kEngineName,
    286       base::Bind(&MockErrorCallback::Run,
    287                  base::Unretained(&error_callback)));
    288 
    289   // Run the message loop.
    290   message_loop_.RunUntilIdle();
    291 }
    292 
    293 TEST_F(IBusClientTest, SetGlobalEngineTest_InvalidResponse) {
    294   // Set expectations
    295   EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
    296       .WillOnce(Invoke(this, &IBusClientTest::OnSetGlobalEngineFail));
    297   MockErrorCallback error_callback;
    298   EXPECT_CALL(error_callback, Run());
    299 
    300   // Set invalid response.
    301   response_ = NULL;
    302 
    303   // The error response is not used in SetGLobalEngine.
    304   error_response_ = NULL;
    305 
    306   // Call CreateInputContext.
    307   client_->SetGlobalEngine(
    308       kEngineName,
    309       base::Bind(&MockErrorCallback::Run,
    310                  base::Unretained(&error_callback)));
    311 
    312   // Run the message loop.
    313   message_loop_.RunUntilIdle();
    314 }
    315 
    316 TEST_F(IBusClientTest, SetGlobalEngineTest_MethodCallFail) {
    317   // Set expectations
    318   EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
    319       .WillOnce(Invoke(this, &IBusClientTest::OnSetGlobalEngineFail));
    320   MockErrorCallback error_callback;
    321   EXPECT_CALL(error_callback, Run());
    322 
    323   // Create empty response.
    324   scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
    325   response_ = response.get();
    326 
    327   // The error response is not used in SetGLobalEngine.
    328   error_response_ = NULL;
    329 
    330   // Call CreateInputContext.
    331   client_->SetGlobalEngine(
    332       kEngineName,
    333       base::Bind(&MockErrorCallback::Run,
    334                  base::Unretained(&error_callback)));
    335 
    336   // Run the message loop.
    337   message_loop_.RunUntilIdle();
    338 }
    339 
    340 TEST_F(IBusClientTest, ExitTest) {
    341   // Set expectations
    342   EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
    343       .WillOnce(Invoke(this, &IBusClientTest::OnExit));
    344   MockErrorCallback error_callback;
    345   EXPECT_CALL(error_callback, Run()).Times(0);
    346 
    347   // Create empty response.
    348   scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
    349   response_ = response.get();
    350 
    351   // The error response is not used in SetGLobalEngine.
    352   error_response_ = NULL;
    353 
    354   // Call CreateInputContext.
    355   client_->Exit(
    356       IBusClient::RESTART_IBUS_DAEMON,
    357       base::Bind(&MockErrorCallback::Run,
    358                  base::Unretained(&error_callback)));
    359 
    360   // Run the message loop.
    361   message_loop_.RunUntilIdle();
    362 }
    363 
    364 TEST_F(IBusClientTest, ExitTest_InvalidResponse) {
    365   // Set expectations
    366   EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
    367       .WillOnce(Invoke(this, &IBusClientTest::OnExit));
    368   MockErrorCallback error_callback;
    369   EXPECT_CALL(error_callback, Run());
    370 
    371   // Set invalid response.
    372   response_ = NULL;
    373 
    374   // The error response is not used in SetGLobalEngine.
    375   error_response_ = NULL;
    376 
    377   // Call CreateInputContext.
    378   client_->Exit(
    379       IBusClient::RESTART_IBUS_DAEMON,
    380       base::Bind(&MockErrorCallback::Run,
    381                  base::Unretained(&error_callback)));
    382 
    383   // Run the message loop.
    384   message_loop_.RunUntilIdle();
    385 }
    386 
    387 TEST_F(IBusClientTest, ExitTest_MethodCallFail) {
    388   // Set expectations
    389   EXPECT_CALL(*mock_proxy_.get(), CallMethodWithErrorCallback(_, _, _, _))
    390       .WillOnce(Invoke(this, &IBusClientTest::OnExitFail));
    391   MockErrorCallback error_callback;
    392   EXPECT_CALL(error_callback, Run());
    393 
    394   // Create empty response.
    395   scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
    396   response_ = response.get();
    397 
    398   // The error response is not used in SetGLobalEngine.
    399   error_response_ = NULL;
    400 
    401   // Call CreateInputContext.
    402   client_->Exit(
    403       IBusClient::RESTART_IBUS_DAEMON,
    404       base::Bind(&MockErrorCallback::Run,
    405                  base::Unretained(&error_callback)));
    406 
    407   // Run the message loop.
    408   message_loop_.RunUntilIdle();
    409 }
    410 
    411 }  // namespace chromeos
    412