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_engine_factory_service.h"
      6 
      7 #include <map>
      8 #include <string>
      9 #include "base/message_loop/message_loop.h"
     10 #include "chromeos/dbus/ibus/ibus_constants.h"
     11 #include "dbus/message.h"
     12 #include "dbus/mock_bus.h"
     13 #include "dbus/mock_exported_object.h"
     14 #include "testing/gmock/include/gmock/gmock.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 using ::testing::Invoke;
     18 using ::testing::Return;
     19 using ::testing::StrEq;
     20 using ::testing::_;
     21 
     22 namespace chromeos {
     23 
     24 class SynchronousCreateEngineHandler {
     25  public:
     26   explicit SynchronousCreateEngineHandler(const dbus::ObjectPath& path)
     27       : path_(path) {}
     28 
     29   void Run(const IBusEngineFactoryService::CreateEngineResponseSender& sender) {
     30     sender.Run(path_);
     31   }
     32 
     33  private:
     34   dbus::ObjectPath path_;
     35 
     36   DISALLOW_COPY_AND_ASSIGN(SynchronousCreateEngineHandler);
     37 };
     38 
     39 class AsynchronousCreateEngineHandler {
     40  public:
     41   AsynchronousCreateEngineHandler(const dbus::ObjectPath& path,
     42                                   base::MessageLoop* message_loop)
     43       : path_(path),
     44         message_loop_(message_loop) {}
     45 
     46   void Run(const IBusEngineFactoryService::CreateEngineResponseSender& sender) {
     47     message_loop_->PostTask(FROM_HERE, base::Bind(sender, path_));
     48   }
     49 
     50  private:
     51   dbus::ObjectPath path_;
     52   base::MessageLoop* message_loop_;
     53 
     54   DISALLOW_COPY_AND_ASSIGN(AsynchronousCreateEngineHandler);
     55 };
     56 
     57 class MockCreateEngineResponseSender {
     58  public:
     59   explicit MockCreateEngineResponseSender(const dbus::ObjectPath& expected_path)
     60       : expected_path_(expected_path) {}
     61   // GMock doesn't support mocking methods which take scoped_ptr<>.
     62   MOCK_METHOD1(MockRun, void(dbus::Response*));
     63   void Run(scoped_ptr<dbus::Response> response) {
     64     MockRun(response.get());
     65   }
     66 
     67   // Checks the given |response| meets expectation for the CreateEngine method.
     68   void CheckCreateEngineResponsePtr(dbus::Response* response) {
     69     dbus::MessageReader reader(response);
     70     dbus::ObjectPath actual_path;
     71     ASSERT_TRUE(reader.PopObjectPath(&actual_path));
     72     EXPECT_EQ(expected_path_, actual_path);
     73   }
     74   void CheckCreateEngineResponse(scoped_ptr<dbus::Response> response) {
     75     CheckCreateEngineResponsePtr(response.get());
     76   }
     77 
     78  private:
     79   dbus::ObjectPath expected_path_;
     80 };
     81 
     82 class IBusEngineFactoryServiceTest : public testing::Test {
     83  public:
     84   IBusEngineFactoryServiceTest() {}
     85 
     86   virtual void SetUp() OVERRIDE {
     87     // Create a mock bus.
     88     dbus::Bus::Options options;
     89     options.bus_type = dbus::Bus::SYSTEM;
     90     mock_bus_ = new dbus::MockBus(options);
     91 
     92     // Create a mock exported object.
     93     mock_exported_object_ = new dbus::MockExportedObject(
     94         mock_bus_.get(),
     95         dbus::ObjectPath(ibus::engine_factory::kServicePath));
     96 
     97     EXPECT_CALL(
     98         *mock_bus_.get(),
     99         GetExportedObject(dbus::ObjectPath(ibus::engine_factory::kServicePath)))
    100         .WillOnce(Return(mock_exported_object_.get()));
    101 
    102     EXPECT_CALL(*mock_bus_.get(), AssertOnOriginThread())
    103         .WillRepeatedly(Return());
    104 
    105     EXPECT_CALL(*mock_exported_object_.get(),
    106                 ExportMethod(ibus::engine_factory::kServiceInterface,
    107                              ibus::engine_factory::kCreateEngineMethod,
    108                              _,
    109                              _))
    110         .WillRepeatedly(
    111              Invoke(this, &IBusEngineFactoryServiceTest::OnMethodExported));
    112 
    113     service_.reset(IBusEngineFactoryService::Create(
    114         mock_bus_.get(), REAL_DBUS_CLIENT_IMPLEMENTATION));
    115   }
    116 
    117  protected:
    118   // The service to be tested.
    119   scoped_ptr<IBusEngineFactoryService> service_;
    120   // The mock bus.
    121   scoped_refptr<dbus::MockBus> mock_bus_;
    122   // The mock exported object.
    123   scoped_refptr<dbus::MockExportedObject> mock_exported_object_;
    124   // The map from method name to method call handler.
    125   std::map<std::string, dbus::ExportedObject::MethodCallCallback>
    126       method_exported_map_;
    127   // A message loop to emulate asynchronous behavior.
    128   base::MessageLoop message_loop_;
    129 
    130  private:
    131   // Used to implement the method call exportation.
    132   void OnMethodExported(
    133       const std::string& interface_name,
    134       const std::string& method_name,
    135       const dbus::ExportedObject::MethodCallCallback& method_callback,
    136       const dbus::ExportedObject::OnExportedCallback& on_exported_callback) {
    137     method_exported_map_[method_name] = method_callback;
    138     const bool success = true;
    139     message_loop_.PostTask(FROM_HERE, base::Bind(on_exported_callback,
    140                                                  interface_name,
    141                                                  method_name,
    142                                                  success));
    143   }
    144 };
    145 
    146 TEST_F(IBusEngineFactoryServiceTest, SyncCreateEngineTest) {
    147   // Set expectations.
    148   const char kSampleEngine[] = "Sample Engine";
    149   const dbus::ObjectPath kObjectPath("/org/freedesktop/IBus/Engine/10");
    150   MockCreateEngineResponseSender response_sender(kObjectPath);
    151   EXPECT_CALL(response_sender, MockRun(_))
    152       .WillOnce(
    153           Invoke(&response_sender,
    154                  &MockCreateEngineResponseSender::
    155                  CheckCreateEngineResponsePtr));
    156 
    157   SynchronousCreateEngineHandler handler(kObjectPath);
    158   // Set handler expectations.
    159   service_->SetCreateEngineHandler(
    160       kSampleEngine,
    161       base::Bind(&SynchronousCreateEngineHandler::Run,
    162                  base::Unretained(&handler)));
    163   message_loop_.RunUntilIdle();
    164 
    165   // Invoke method call.
    166   dbus::MethodCall method_call(
    167       ibus::engine_factory::kServiceInterface,
    168       ibus::engine_factory::kCreateEngineMethod);
    169   method_call.SetSerial(10);
    170   dbus::MessageWriter writer(&method_call);
    171   writer.AppendString(kSampleEngine);
    172   ASSERT_FALSE(
    173       method_exported_map_[ibus::engine_factory::kCreateEngineMethod]
    174           .is_null());
    175   method_exported_map_[ibus::engine_factory::kCreateEngineMethod].Run(
    176       &method_call,
    177       base::Bind(&MockCreateEngineResponseSender::Run,
    178                  base::Unretained(&response_sender)));
    179 
    180   // Unset the handler so expect not calling handler.
    181   service_->UnsetCreateEngineHandler(kSampleEngine);
    182   method_exported_map_[ibus::engine_factory::kCreateEngineMethod].Run(
    183       &method_call,
    184       base::Bind(&MockCreateEngineResponseSender::CheckCreateEngineResponse,
    185                  base::Unretained(&response_sender)));
    186   message_loop_.RunUntilIdle();
    187 }
    188 
    189 TEST_F(IBusEngineFactoryServiceTest, AsyncCreateEngineTest) {
    190   // Set expectations.
    191   const char kSampleEngine[] = "Sample Engine";
    192   const dbus::ObjectPath kObjectPath("/org/freedesktop/IBus/Engine/10");
    193   MockCreateEngineResponseSender response_sender(kObjectPath);
    194   EXPECT_CALL(response_sender, MockRun(_))
    195       .WillOnce(
    196           Invoke(&response_sender,
    197                  &MockCreateEngineResponseSender::
    198                  CheckCreateEngineResponsePtr));
    199 
    200   AsynchronousCreateEngineHandler handler(kObjectPath, &message_loop_);
    201   // Set handler expectations.
    202   service_->SetCreateEngineHandler(
    203       kSampleEngine,
    204       base::Bind(&AsynchronousCreateEngineHandler::Run,
    205                  base::Unretained(&handler)));
    206   message_loop_.RunUntilIdle();
    207 
    208   // Invoke method call.
    209   dbus::MethodCall method_call(
    210       ibus::engine_factory::kServiceInterface,
    211       ibus::engine_factory::kCreateEngineMethod);
    212   method_call.SetSerial(10);
    213   dbus::MessageWriter writer(&method_call);
    214   writer.AppendString(kSampleEngine);
    215   ASSERT_FALSE(
    216       method_exported_map_[ibus::engine_factory::kCreateEngineMethod]
    217           .is_null());
    218   method_exported_map_[ibus::engine_factory::kCreateEngineMethod].Run(
    219       &method_call,
    220       base::Bind(&MockCreateEngineResponseSender::Run,
    221                  base::Unretained(&response_sender)));
    222 
    223   // Unset the handler so expect not calling handler.
    224   service_->UnsetCreateEngineHandler(kSampleEngine);
    225   method_exported_map_[ibus::engine_factory::kCreateEngineMethod].Run(
    226       &method_call,
    227       base::Bind(&MockCreateEngineResponseSender::CheckCreateEngineResponse,
    228                  base::Unretained(&response_sender)));
    229   message_loop_.RunUntilIdle();
    230 }
    231 
    232 }  // namespace chromeos
    233