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