OLD | NEW |
(Empty) | |
| 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_input_context_client.h" |
| 6 |
| 7 #include <map> |
| 8 #include <string> |
| 9 #include "base/message_loop.h" |
| 10 #include "chromeos/dbus/ibus/ibus_text.h" |
| 11 #include "dbus/message.h" |
| 12 #include "dbus/mock_bus.h" |
| 13 #include "dbus/mock_object_proxy.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::_; |
| 20 |
| 21 namespace chromeos { |
| 22 |
| 23 namespace { |
| 24 const char kServiceName[] = "org.freedesktop.IBus"; |
| 25 const char kInputContextInterface[] = "org.freedesktop.IBus.InputContext"; |
| 26 const char kObjectPath[] = "/org/freedesktop/IBus/InputContext_1010"; |
| 27 |
| 28 // Signal names. |
| 29 const char kCommitTextSignal[] = "CommitText"; |
| 30 const char kForwardKeyEventSignal[] = "ForwardKeyEvent"; |
| 31 const char kHidePreeditTextSignal[] = "HidePreeditSignal"; |
| 32 const char kShowPreeditTextSignal[] = "ShowPreeditText"; |
| 33 const char kUpdatePreeditTextSignal[] = "UpdatePreeditText"; |
| 34 |
| 35 // Method names. |
| 36 const char kFocusInMethod[] = "FocusIn"; |
| 37 const char kFocusOutMethod[] = "FocusOut"; |
| 38 const char kResetMethod[] = "Reset"; |
| 39 const char kSetCapabilitiesMethod[] = "SetCapabilities"; |
| 40 const char kSetCursorLocationMethod[] = "SetCursorLocation"; |
| 41 const char kProcessKeyEventMethod[] = "ProcessKeyEvent"; |
| 42 |
| 43 // Following variables are used in callback expectations. |
| 44 const uint32 kCapabilities = 12345; |
| 45 const int32 kCursorX = 30; |
| 46 const int32 kCursorY = 31; |
| 47 const int32 kCursorWidth = 32; |
| 48 const int32 kCursorHeight = 33; |
| 49 const uint32 kKeyval = 34; |
| 50 const uint32 kKeycode = 35; |
| 51 const uint32 kState = 36; |
| 52 const bool kIsKeyHandled = false; |
| 53 |
| 54 class MockCommitTextHandler { |
| 55 public: |
| 56 MOCK_METHOD1(Run, void(const IBusText& text)); |
| 57 }; |
| 58 |
| 59 class MockForwardKeyEventHandler { |
| 60 public: |
| 61 MOCK_METHOD3(Run, void(uint32 keyval, uint32 keycode, uint32 state)); |
| 62 }; |
| 63 |
| 64 class MockHidePreeditTextHandler { |
| 65 public: |
| 66 MOCK_METHOD0(Run, void()); |
| 67 }; |
| 68 |
| 69 class MockShowPreeditTextHandler { |
| 70 public: |
| 71 MOCK_METHOD0(Run, void()); |
| 72 }; |
| 73 |
| 74 class MockUpdatePreeditTextHandler { |
| 75 public: |
| 76 MOCK_METHOD3(Run, void(const IBusText& text, uint32 cursor_pos, |
| 77 bool visible)); |
| 78 }; |
| 79 |
| 80 class MockProcessKeyEventHandler { |
| 81 public: |
| 82 MOCK_METHOD1(Run, void(bool is_key_handled)); |
| 83 }; |
| 84 |
| 85 MATCHER_P(IBusTextEq, expected_text, "The expected IBusText does not match") { |
| 86 // TODO(nona): Check attributes. |
| 87 return (arg.text() == expected_text->text()); |
| 88 } |
| 89 |
| 90 } // namespace |
| 91 |
| 92 class IBusInputContextClientTest : public testing::Test { |
| 93 public: |
| 94 IBusInputContextClientTest() : response_(NULL) {} |
| 95 |
| 96 virtual void SetUp() OVERRIDE { |
| 97 // Create a mock bus. |
| 98 dbus::Bus::Options options; |
| 99 options.bus_type = dbus::Bus::SYSTEM; |
| 100 mock_bus_ = new dbus::MockBus(options); |
| 101 |
| 102 // Create a mock proxy. |
| 103 mock_proxy_ = new dbus::MockObjectProxy(mock_bus_.get(), |
| 104 kServiceName, |
| 105 dbus::ObjectPath(kObjectPath)); |
| 106 |
| 107 // Create a client. |
| 108 client_.reset(IBusInputContextClient::Create( |
| 109 REAL_DBUS_CLIENT_IMPLEMENTATION)); |
| 110 |
| 111 // Set an expectation so mock_bus's GetObjectProxy() for the given service |
| 112 // name and the object path will return mock_proxy_. The GetObjectProxy |
| 113 // function is called in Initialized function. |
| 114 EXPECT_CALL(*mock_bus_, GetObjectProxy(kServiceName, |
| 115 dbus::ObjectPath(kObjectPath))) |
| 116 .WillOnce(Return(mock_proxy_.get())); |
| 117 |
| 118 // Set expectations so mock_proxy's ConnectToSignal will use |
| 119 // OnConnectToSignal() to run the callback. The ConnectToSignal is called in |
| 120 // Initialize function. |
| 121 EXPECT_CALL(*mock_proxy_, ConnectToSignal( |
| 122 kInputContextInterface, kCommitTextSignal, _, _)) |
| 123 .WillRepeatedly( |
| 124 Invoke(this, &IBusInputContextClientTest::OnConnectToSignal)); |
| 125 EXPECT_CALL(*mock_proxy_, ConnectToSignal( |
| 126 kInputContextInterface, kForwardKeyEventSignal, _, _)) |
| 127 .WillRepeatedly( |
| 128 Invoke(this, &IBusInputContextClientTest::OnConnectToSignal)); |
| 129 EXPECT_CALL(*mock_proxy_, ConnectToSignal( |
| 130 kInputContextInterface, kHidePreeditTextSignal, _, _)) |
| 131 .WillRepeatedly( |
| 132 Invoke(this, &IBusInputContextClientTest::OnConnectToSignal)); |
| 133 EXPECT_CALL(*mock_proxy_, ConnectToSignal( |
| 134 kInputContextInterface, kShowPreeditTextSignal, _, _)) |
| 135 .WillRepeatedly( |
| 136 Invoke(this, &IBusInputContextClientTest::OnConnectToSignal)); |
| 137 EXPECT_CALL(*mock_proxy_, ConnectToSignal( |
| 138 kInputContextInterface, kUpdatePreeditTextSignal, _, _)) |
| 139 .WillRepeatedly( |
| 140 Invoke(this, &IBusInputContextClientTest::OnConnectToSignal)); |
| 141 |
| 142 // Call Initialize to create object proxy and connect signals. |
| 143 client_->Initialize(mock_bus_.get(), dbus::ObjectPath(kObjectPath)); |
| 144 } |
| 145 |
| 146 virtual void TearDown() OVERRIDE { |
| 147 EXPECT_TRUE(client_->IsConnected()); |
| 148 client_->ResetObjectProxy(); |
| 149 EXPECT_FALSE(client_->IsConnected()); |
| 150 } |
| 151 |
| 152 // Handles FocusIn method call. |
| 153 void OnFocusIn(dbus::MethodCall* method_call, |
| 154 int timeout_ms, |
| 155 const dbus::ObjectProxy::ResponseCallback& callback) { |
| 156 EXPECT_EQ(kInputContextInterface, method_call->GetInterface()); |
| 157 EXPECT_EQ(kFocusInMethod, method_call->GetMember()); |
| 158 dbus::MessageReader reader(method_call); |
| 159 EXPECT_FALSE(reader.HasMoreData()); |
| 160 |
| 161 message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_)); |
| 162 } |
| 163 |
| 164 // Handles FocusOut method call. |
| 165 void OnFocusOut(dbus::MethodCall* method_call, |
| 166 int timeout_ms, |
| 167 const dbus::ObjectProxy::ResponseCallback& callback) { |
| 168 EXPECT_EQ(kInputContextInterface, method_call->GetInterface()); |
| 169 EXPECT_EQ(kFocusOutMethod, method_call->GetMember()); |
| 170 dbus::MessageReader reader(method_call); |
| 171 EXPECT_FALSE(reader.HasMoreData()); |
| 172 |
| 173 message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_)); |
| 174 } |
| 175 |
| 176 // Handles Reset method call. |
| 177 void OnReset(dbus::MethodCall* method_call, |
| 178 int timeout_ms, |
| 179 const dbus::ObjectProxy::ResponseCallback& callback) { |
| 180 EXPECT_EQ(kInputContextInterface, method_call->GetInterface()); |
| 181 EXPECT_EQ(kResetMethod, method_call->GetMember()); |
| 182 dbus::MessageReader reader(method_call); |
| 183 EXPECT_FALSE(reader.HasMoreData()); |
| 184 |
| 185 message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_)); |
| 186 } |
| 187 |
| 188 // Handles SetCursorLocation method call. |
| 189 void OnSetCursorLocation( |
| 190 dbus::MethodCall* method_call, |
| 191 int timeout_ms, |
| 192 const dbus::ObjectProxy::ResponseCallback& callback) { |
| 193 EXPECT_EQ(kInputContextInterface, method_call->GetInterface()); |
| 194 EXPECT_EQ(kSetCursorLocationMethod, method_call->GetMember()); |
| 195 dbus::MessageReader reader(method_call); |
| 196 int32 x, y, width, height; |
| 197 EXPECT_TRUE(reader.PopInt32(&x)); |
| 198 EXPECT_TRUE(reader.PopInt32(&y)); |
| 199 EXPECT_TRUE(reader.PopInt32(&width)); |
| 200 EXPECT_TRUE(reader.PopInt32(&height)); |
| 201 EXPECT_FALSE(reader.HasMoreData()); |
| 202 |
| 203 message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_)); |
| 204 } |
| 205 |
| 206 // Handles SetCapabilities method call. |
| 207 void OnSetCapabilities(dbus::MethodCall* method_call, |
| 208 int timeout_ms, |
| 209 const dbus::ObjectProxy::ResponseCallback& callback) { |
| 210 EXPECT_EQ(kInputContextInterface, method_call->GetInterface()); |
| 211 EXPECT_EQ(kSetCapabilitiesMethod, method_call->GetMember()); |
| 212 uint32 capabilities; |
| 213 dbus::MessageReader reader(method_call); |
| 214 EXPECT_TRUE(reader.PopUint32(&capabilities)); |
| 215 EXPECT_EQ(kCapabilities, capabilities); |
| 216 EXPECT_FALSE(reader.HasMoreData()); |
| 217 |
| 218 message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_)); |
| 219 } |
| 220 |
| 221 // Handles ProcessKeyEvent method call. |
| 222 void OnProcessKeyEvent(dbus::MethodCall* method_call, |
| 223 int timeout_ms, |
| 224 const dbus::ObjectProxy::ResponseCallback& callback) { |
| 225 EXPECT_EQ(kInputContextInterface, method_call->GetInterface()); |
| 226 EXPECT_EQ(kProcessKeyEventMethod, method_call->GetMember()); |
| 227 uint32 keyval, keycode, state; |
| 228 dbus::MessageReader reader(method_call); |
| 229 EXPECT_TRUE(reader.PopUint32(&keyval)); |
| 230 EXPECT_TRUE(reader.PopUint32(&keycode)); |
| 231 EXPECT_TRUE(reader.PopUint32(&state)); |
| 232 EXPECT_FALSE(reader.HasMoreData()); |
| 233 |
| 234 message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_)); |
| 235 } |
| 236 |
| 237 protected: |
| 238 // The client to be tested. |
| 239 scoped_ptr<IBusInputContextClient> client_; |
| 240 // The mock bus. |
| 241 scoped_refptr<dbus::MockBus> mock_bus_; |
| 242 // The mock object proxy. |
| 243 scoped_refptr<dbus::MockObjectProxy> mock_proxy_; |
| 244 // Response returned by mock methods. |
| 245 dbus::Response* response_; |
| 246 // A message loop to emulate asynchronous behavior. |
| 247 MessageLoop message_loop_; |
| 248 // The map from signal to signal handler. |
| 249 std::map<std::string, dbus::ObjectProxy::SignalCallback> signal_callback_map_; |
| 250 |
| 251 private: |
| 252 // Used to implement the mock proxy. |
| 253 void OnConnectToSignal( |
| 254 const std::string& interface_name, |
| 255 const std::string& signal_name, |
| 256 const dbus::ObjectProxy::SignalCallback& signal_callback, |
| 257 const dbus::ObjectProxy::OnConnectedCallback& on_connected_callback) { |
| 258 signal_callback_map_[signal_name] = signal_callback; |
| 259 const bool success = true; |
| 260 message_loop_.PostTask(FROM_HERE, base::Bind(on_connected_callback, |
| 261 interface_name, |
| 262 signal_name, |
| 263 success)); |
| 264 } |
| 265 }; |
| 266 |
| 267 TEST_F(IBusInputContextClientTest, CommitTextHandler) { |
| 268 const char kSampleText[] = "Sample Text"; |
| 269 IBusText ibus_text; |
| 270 ibus_text.set_text(kSampleText); |
| 271 |
| 272 // Set handler expectations. |
| 273 MockCommitTextHandler handler; |
| 274 EXPECT_CALL(handler, Run(IBusTextEq(&ibus_text))); |
| 275 client_->SetCommitTextHandler(base::Bind(&MockCommitTextHandler::Run, |
| 276 base::Unretained(&handler))); |
| 277 message_loop_.RunAllPending(); |
| 278 |
| 279 // Emit signal. |
| 280 dbus::Signal signal(kInputContextInterface, kCommitTextSignal); |
| 281 dbus::MessageWriter writer(&signal); |
| 282 AppendIBusText(ibus_text, &writer); |
| 283 ASSERT_FALSE(signal_callback_map_[kCommitTextSignal].is_null()); |
| 284 signal_callback_map_[kCommitTextSignal].Run(&signal); |
| 285 |
| 286 // Unset the handler so expect not calling handler. |
| 287 client_->UnsetCommitTextHandler(); |
| 288 signal_callback_map_[kCommitTextSignal].Run(&signal); |
| 289 } |
| 290 |
| 291 TEST_F(IBusInputContextClientTest, ForwardKeyEventHandlerTest) { |
| 292 // Set handler expectations. |
| 293 MockForwardKeyEventHandler handler; |
| 294 EXPECT_CALL(handler, Run(kKeyval, kKeycode, kState)); |
| 295 client_->SetForwardKeyEventHandler( |
| 296 base::Bind(&MockForwardKeyEventHandler::Run, |
| 297 base::Unretained(&handler))); |
| 298 message_loop_.RunAllPending(); |
| 299 |
| 300 // Emit signal. |
| 301 dbus::Signal signal(kInputContextInterface, kForwardKeyEventSignal); |
| 302 dbus::MessageWriter writer(&signal); |
| 303 writer.AppendUint32(kKeyval); |
| 304 writer.AppendUint32(kKeycode); |
| 305 writer.AppendUint32(kState); |
| 306 ASSERT_FALSE(signal_callback_map_[kForwardKeyEventSignal].is_null()); |
| 307 signal_callback_map_[kForwardKeyEventSignal].Run(&signal); |
| 308 |
| 309 // Unset the handler so expect not calling handler. |
| 310 client_->UnsetForwardKeyEventHandler(); |
| 311 signal_callback_map_[kForwardKeyEventSignal].Run(&signal); |
| 312 } |
| 313 |
| 314 TEST_F(IBusInputContextClientTest, HidePreeditTextHandlerTest) { |
| 315 // Set handler expectations. |
| 316 MockHidePreeditTextHandler handler; |
| 317 EXPECT_CALL(handler, Run()); |
| 318 client_->SetHidePreeditTextHandler( |
| 319 base::Bind(&MockHidePreeditTextHandler::Run, |
| 320 base::Unretained(&handler))); |
| 321 message_loop_.RunAllPending(); |
| 322 |
| 323 // Emit signal. |
| 324 dbus::Signal signal(kInputContextInterface, kHidePreeditTextSignal); |
| 325 ASSERT_FALSE(signal_callback_map_[kHidePreeditTextSignal].is_null()); |
| 326 signal_callback_map_[kHidePreeditTextSignal].Run(&signal); |
| 327 |
| 328 // Unset the handler so expect not calling handler. |
| 329 client_->UnsetHidePreeditTextHandler(); |
| 330 signal_callback_map_[kHidePreeditTextSignal].Run(&signal); |
| 331 } |
| 332 |
| 333 TEST_F(IBusInputContextClientTest, ShowPreeditTextHandlerTest) { |
| 334 // Set handler expectations. |
| 335 MockShowPreeditTextHandler handler; |
| 336 EXPECT_CALL(handler, Run()); |
| 337 client_->SetShowPreeditTextHandler( |
| 338 base::Bind(&MockShowPreeditTextHandler::Run, |
| 339 base::Unretained(&handler))); |
| 340 message_loop_.RunAllPending(); |
| 341 |
| 342 // Emit signal. |
| 343 dbus::Signal signal(kInputContextInterface, kShowPreeditTextSignal); |
| 344 ASSERT_FALSE(signal_callback_map_[kShowPreeditTextSignal].is_null()); |
| 345 signal_callback_map_[kShowPreeditTextSignal].Run(&signal); |
| 346 |
| 347 // Unset the handler so expect not calling handler. |
| 348 client_->UnsetShowPreeditTextHandler(); |
| 349 signal_callback_map_[kShowPreeditTextSignal].Run(&signal); |
| 350 } |
| 351 |
| 352 TEST_F(IBusInputContextClientTest, UpdatePreeditTextHandlerTest) { |
| 353 const uint32 kCursorPos = 20; |
| 354 const bool kVisible = false; |
| 355 const char kSampleText[] = "Sample Text"; |
| 356 IBusText ibus_text; |
| 357 ibus_text.set_text(kSampleText); |
| 358 |
| 359 // Set handler expectations. |
| 360 MockUpdatePreeditTextHandler handler; |
| 361 EXPECT_CALL(handler, Run(IBusTextEq(&ibus_text), kCursorPos, kVisible)); |
| 362 client_->SetUpdatePreeditTextHandler( |
| 363 base::Bind(&MockUpdatePreeditTextHandler::Run, |
| 364 base::Unretained(&handler))); |
| 365 message_loop_.RunAllPending(); |
| 366 |
| 367 // Emit signal. |
| 368 dbus::Signal signal(kInputContextInterface, kUpdatePreeditTextSignal); |
| 369 dbus::MessageWriter writer(&signal); |
| 370 AppendIBusText(ibus_text, &writer); |
| 371 writer.AppendUint32(kCursorPos); |
| 372 writer.AppendBool(kVisible); |
| 373 ASSERT_FALSE(signal_callback_map_[kUpdatePreeditTextSignal].is_null()); |
| 374 signal_callback_map_[kUpdatePreeditTextSignal].Run(&signal); |
| 375 |
| 376 // Unset the handler so expect not calling handler. |
| 377 client_->UnsetUpdatePreeditTextHandler(); |
| 378 signal_callback_map_[kUpdatePreeditTextSignal].Run(&signal); |
| 379 } |
| 380 |
| 381 TEST_F(IBusInputContextClientTest, FocusInTest) { |
| 382 // Set expectations. |
| 383 EXPECT_CALL(*mock_proxy_, CallMethod(_, _, _)) |
| 384 .WillOnce(Invoke(this, &IBusInputContextClientTest::OnFocusIn)); |
| 385 // Create response. |
| 386 scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); |
| 387 response_ = response.get(); |
| 388 |
| 389 // Call FocusIn. |
| 390 client_->FocusIn(); |
| 391 // Run the message loop. |
| 392 message_loop_.RunAllPending(); |
| 393 } |
| 394 |
| 395 TEST_F(IBusInputContextClientTest, FocusOutTest) { |
| 396 // Set expectations. |
| 397 EXPECT_CALL(*mock_proxy_, CallMethod(_, _, _)) |
| 398 .WillOnce(Invoke(this, &IBusInputContextClientTest::OnFocusOut)); |
| 399 // Create response. |
| 400 scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); |
| 401 response_ = response.get(); |
| 402 |
| 403 // Call FocusOut. |
| 404 client_->FocusOut(); |
| 405 // Run the message loop. |
| 406 message_loop_.RunAllPending(); |
| 407 } |
| 408 |
| 409 TEST_F(IBusInputContextClientTest, ResetTest) { |
| 410 // Set expectations. |
| 411 EXPECT_CALL(*mock_proxy_, CallMethod(_, _, _)) |
| 412 .WillOnce(Invoke(this, &IBusInputContextClientTest::OnReset)); |
| 413 // Create response. |
| 414 scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); |
| 415 response_ = response.get(); |
| 416 |
| 417 // Call Reset. |
| 418 client_->Reset(); |
| 419 // Run the message loop. |
| 420 message_loop_.RunAllPending(); |
| 421 } |
| 422 |
| 423 TEST_F(IBusInputContextClientTest, SetCapabilitiesTest) { |
| 424 // Set expectations. |
| 425 EXPECT_CALL(*mock_proxy_, CallMethod(_, _, _)) |
| 426 .WillOnce(Invoke(this, &IBusInputContextClientTest::OnSetCapabilities)); |
| 427 // Create response. |
| 428 scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); |
| 429 response_ = response.get(); |
| 430 |
| 431 // Call SetCapabilities. |
| 432 client_->SetCapabilities(kCapabilities); |
| 433 // Run the message loop. |
| 434 message_loop_.RunAllPending(); |
| 435 } |
| 436 |
| 437 TEST_F(IBusInputContextClientTest, SetCursorLocationTest) { |
| 438 // Set expectations. |
| 439 EXPECT_CALL(*mock_proxy_, CallMethod(_, _, _)) |
| 440 .WillOnce(Invoke(this, &IBusInputContextClientTest::OnSetCursorLocation)); |
| 441 // Create response. |
| 442 scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); |
| 443 response_ = response.get(); |
| 444 |
| 445 // Call SetCursorLocation. |
| 446 client_->SetCursorLocation(kCursorX, kCursorY, kCursorWidth, kCursorHeight); |
| 447 // Run the message loop. |
| 448 message_loop_.RunAllPending(); |
| 449 } |
| 450 |
| 451 TEST_F(IBusInputContextClientTest, OnProcessKeyEvent) { |
| 452 // Set expectations. |
| 453 EXPECT_CALL(*mock_proxy_, CallMethod(_, _, _)) |
| 454 .WillOnce(Invoke(this, &IBusInputContextClientTest::OnProcessKeyEvent)); |
| 455 MockProcessKeyEventHandler callback; |
| 456 EXPECT_CALL(callback, Run(kIsKeyHandled)); |
| 457 // Create response. |
| 458 scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); |
| 459 dbus::MessageWriter writer(response.get()); |
| 460 writer.AppendBool(kIsKeyHandled); |
| 461 response_ = response.get(); |
| 462 |
| 463 // Call ProcessKeyEvent. |
| 464 client_->ProcessKeyEvent(kKeyval, |
| 465 kKeycode, |
| 466 kState, |
| 467 base::Bind(&MockProcessKeyEventHandler::Run, |
| 468 base::Unretained(&callback))); |
| 469 // Run the message loop. |
| 470 message_loop_.RunAllPending(); |
| 471 } |
| 472 |
| 473 } // namespace chromeos |
OLD | NEW |