1 /*
2 * Copyright (C) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #define private public
16 #define protected public
17 #include "input_method_controller.h"
18 #undef private
19
20 #include <event_handler.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <string_ex.h>
24 #include <sys/time.h>
25
26 #include <condition_variable>
27 #include <csignal>
28 #include <cstdint>
29 #include <functional>
30 #include <mutex>
31 #include <string>
32 #include <thread>
33 #include <vector>
34
35 #include "ability_manager_client.h"
36 #include "block_data.h"
37 #include "global.h"
38 #include "i_input_method_agent.h"
39 #include "i_input_method_system_ability.h"
40 #include "if_system_ability_manager.h"
41 #include "input_client_stub.h"
42 #include "input_data_channel_stub.h"
43 #include "input_death_recipient.h"
44 #include "input_method_ability.h"
45 #include "input_method_engine_listener_impl.h"
46 #include "input_method_system_ability_proxy.h"
47 #include "input_method_utils.h"
48 #include "iservice_registry.h"
49 #include "key_event_util.h"
50 #include "keyboard_listener.h"
51 #include "message_parcel.h"
52 #include "system_ability.h"
53 #include "system_ability_definition.h"
54 #include "tdd_util.h"
55 #include "text_listener.h"
56
57 using namespace testing;
58 using namespace testing::ext;
59 namespace OHOS {
60 namespace MiscServices {
61 constexpr uint32_t RETRY_TIME = 200 * 1000;
62 constexpr uint32_t RETRY_TIMES = 5;
63 using WindowMgr = TddUtil::WindowManager;
64
65 class SelectListenerMock : public ControllerListener {
66 public:
67 SelectListenerMock() = default;
68 ~SelectListenerMock() override = default;
69
70 MOCK_METHOD2(OnSelectByRange, void(int32_t start, int32_t end));
71 MOCK_METHOD1(OnSelectByMovement, void(int32_t direction));
72 };
73
74 class InputMethodControllerTest : public testing::Test {
75 public:
76 static void SetUpTestCase(void);
77 static void TearDownTestCase(void);
78 void SetUp();
79 void TearDown();
80 static void SetInputDeathRecipient();
81 static void OnRemoteSaDied(const wptr<IRemoteObject> &remote);
82 static bool CheckKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent);
83 static bool WaitRemoteDiedCallback();
84 static void WaitKeyboardStatusCallback(bool keyboardState);
85 static void TriggerConfigurationChangeCallback(Configuration &info);
86 static void TriggerCursorUpdateCallback(CursorInfo &info);
87 static void TriggerSelectionChangeCallback(std::u16string &text, int start, int end);
88 static void CheckProxyObject();
89 static sptr<InputMethodController> inputMethodController_;
90 static sptr<InputMethodAbility> inputMethodAbility_;
91 static std::shared_ptr<MMI::KeyEvent> keyEvent_;
92 static std::shared_ptr<InputMethodEngineListenerImpl> imeListener_;
93 static std::shared_ptr<SelectListenerMock> controllerListener_;
94 static sptr<OnTextChangedListener> textListener_;
95 static std::mutex keyboardListenerMutex_;
96 static std::condition_variable keyboardListenerCv_;
97 static BlockData<std::shared_ptr<MMI::KeyEvent>> blockKeyEvent_;
98 static BlockData<std::shared_ptr<MMI::KeyEvent>> blockFullKeyEvent_;
99 static std::mutex onRemoteSaDiedMutex_;
100 static std::condition_variable onRemoteSaDiedCv_;
101 static sptr<InputDeathRecipient> deathRecipient_;
102 static CursorInfo cursorInfo_;
103 static int32_t oldBegin_;
104 static int32_t oldEnd_;
105 static int32_t newBegin_;
106 static int32_t newEnd_;
107 static std::string text_;
108 static bool doesKeyEventConsume_;
109 static bool doesFUllKeyEventConsume_;
110 static InputAttribute inputAttribute_;
111 static std::shared_ptr<AppExecFwk::EventHandler> textConfigHandler_;
112 static constexpr uint32_t DELAY_TIME = 1;
113 static constexpr uint32_t KEY_EVENT_DELAY_TIME = 100;
114 static constexpr int32_t TASK_DELAY_TIME = 10;
115
116 class KeyboardListenerImpl : public KeyboardListener {
117 public:
KeyboardListenerImpl()118 KeyboardListenerImpl()
119 {
120 std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("InputMethodControllerTe"
121 "st");
122 textConfigHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
123 };
~KeyboardListenerImpl()124 ~KeyboardListenerImpl(){};
OnKeyEvent(int32_t keyCode,int32_t keyStatus)125 bool OnKeyEvent(int32_t keyCode, int32_t keyStatus) override
126 {
127 if (!doesKeyEventConsume_) {
128 return false;
129 }
130 IMSA_HILOGI("KeyboardListenerImpl::OnKeyEvent %{public}d %{public}d", keyCode, keyStatus);
131 auto keyEvent = KeyEventUtil::CreateKeyEvent(keyCode, keyStatus);
132 blockKeyEvent_.SetValue(keyEvent);
133 return true;
134 }
OnKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)135 bool OnKeyEvent(const std::shared_ptr<MMI::KeyEvent> &keyEvent) override
136 {
137 if (!doesFUllKeyEventConsume_) {
138 return false;
139 }
140 IMSA_HILOGI("KeyboardListenerImpl::OnKeyEvent %{public}d %{public}d", keyEvent->GetKeyCode(),
141 keyEvent->GetKeyAction());
142 auto fullKey = keyEvent;
143 blockFullKeyEvent_.SetValue(fullKey);
144 return true;
145 }
OnCursorUpdate(int32_t positionX,int32_t positionY,int32_t height)146 void OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height) override
147 {
148 IMSA_HILOGD(
149 "KeyboardListenerImpl::OnCursorUpdate %{public}d %{public}d %{public}d", positionX, positionY, height);
150 cursorInfo_ = { static_cast<double>(positionX), static_cast<double>(positionY), 0,
151 static_cast<double>(height) };
152 InputMethodControllerTest::keyboardListenerCv_.notify_one();
153 }
OnSelectionChange(int32_t oldBegin,int32_t oldEnd,int32_t newBegin,int32_t newEnd)154 void OnSelectionChange(int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd) override
155 {
156 IMSA_HILOGD("KeyboardListenerImpl::OnSelectionChange %{public}d %{public}d %{public}d %{public}d",
157 oldBegin, oldEnd, newBegin, newBegin);
158 oldBegin_ = oldBegin;
159 oldEnd_ = oldEnd;
160 newBegin_ = newBegin;
161 newEnd_ = newEnd;
162 InputMethodControllerTest::keyboardListenerCv_.notify_one();
163 }
OnTextChange(const std::string & text)164 void OnTextChange(const std::string &text) override
165 {
166 IMSA_HILOGD("KeyboardListenerImpl::OnTextChange text: %{public}s", text.c_str());
167 text_ = text;
168 InputMethodControllerTest::keyboardListenerCv_.notify_one();
169 }
OnEditorAttributeChange(const InputAttribute & inputAttribute)170 void OnEditorAttributeChange(const InputAttribute &inputAttribute) override
171 {
172 IMSA_HILOGD("KeyboardListenerImpl in.");
173 inputAttribute_ = inputAttribute;
174 InputMethodControllerTest::keyboardListenerCv_.notify_one();
175 }
176 };
177 };
178 sptr<InputMethodController> InputMethodControllerTest::inputMethodController_;
179 sptr<InputMethodAbility> InputMethodControllerTest::inputMethodAbility_;
180 std::shared_ptr<MMI::KeyEvent> InputMethodControllerTest::keyEvent_;
181 std::shared_ptr<InputMethodEngineListenerImpl> InputMethodControllerTest::imeListener_;
182 std::shared_ptr<SelectListenerMock> InputMethodControllerTest::controllerListener_;
183 sptr<OnTextChangedListener> InputMethodControllerTest::textListener_;
184 CursorInfo InputMethodControllerTest::cursorInfo_ = {};
185 int32_t InputMethodControllerTest::oldBegin_ = 0;
186 int32_t InputMethodControllerTest::oldEnd_ = 0;
187 int32_t InputMethodControllerTest::newBegin_ = 0;
188 int32_t InputMethodControllerTest::newEnd_ = 0;
189 std::string InputMethodControllerTest::text_;
190 InputAttribute InputMethodControllerTest::inputAttribute_;
191 std::mutex InputMethodControllerTest::keyboardListenerMutex_;
192 std::condition_variable InputMethodControllerTest::keyboardListenerCv_;
193 sptr<InputDeathRecipient> InputMethodControllerTest::deathRecipient_;
194 std::mutex InputMethodControllerTest::onRemoteSaDiedMutex_;
195 std::condition_variable InputMethodControllerTest::onRemoteSaDiedCv_;
196 BlockData<std::shared_ptr<MMI::KeyEvent>> InputMethodControllerTest::blockKeyEvent_{
197 InputMethodControllerTest::KEY_EVENT_DELAY_TIME, nullptr
198 };
199 BlockData<std::shared_ptr<MMI::KeyEvent>> InputMethodControllerTest::blockFullKeyEvent_{
200 InputMethodControllerTest::KEY_EVENT_DELAY_TIME, nullptr
201 };
202 bool InputMethodControllerTest::doesKeyEventConsume_{ false };
203 bool InputMethodControllerTest::doesFUllKeyEventConsume_{ false };
204 std::shared_ptr<AppExecFwk::EventHandler> InputMethodControllerTest::textConfigHandler_{ nullptr };
205
SetUpTestCase(void)206 void InputMethodControllerTest::SetUpTestCase(void)
207 {
208 IMSA_HILOGI("InputMethodControllerTest::SetUpTestCase");
209 TddUtil::StorageSelfTokenID();
210 // Set the tokenID to the tokenID of the current ime
211 std::shared_ptr<Property> property = InputMethodController::GetInstance()->GetCurrentInputMethod();
212 std::string bundleName = property != nullptr ? property->name : "default.inputmethod.unittest";
213 TddUtil::SetTestTokenID(TddUtil::GetTestTokenID(bundleName));
214 inputMethodAbility_ = InputMethodAbility::GetInstance();
215 inputMethodAbility_->SetCoreAndAgent();
216 inputMethodAbility_->OnImeReady();
217 imeListener_ = std::make_shared<InputMethodEngineListenerImpl>();
218 controllerListener_ = std::make_shared<SelectListenerMock>();
219 textListener_ = new TextListener();
220 inputMethodAbility_->SetKdListener(std::make_shared<KeyboardListenerImpl>());
221 inputMethodAbility_->SetImeListener(imeListener_);
222 inputMethodController_ = InputMethodController::GetInstance();
223
224 keyEvent_ = KeyEventUtil::CreateKeyEvent(MMI::KeyEvent::KEYCODE_A, MMI::KeyEvent::KEY_ACTION_DOWN);
225 keyEvent_->SetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY, 0);
226 keyEvent_->SetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY, 1);
227 keyEvent_->SetFunctionKey(MMI::KeyEvent::SCROLL_LOCK_FUNCTION_KEY, 1);
228 TddUtil::SetTestTokenID(TddUtil::AllocTestTokenID(true, true, "undefine"));
229
230 TddUtil::WindowManager::RegisterFocusChangeListener();
231 WindowMgr::CreateWindow();
232 WindowMgr::ShowWindow();
233 bool isFocused = FocusChangedListenerTestImpl::isFocused_->GetValue();
234 IMSA_HILOGI("getFocus end, isFocused = %{public}d", isFocused);
235 SetInputDeathRecipient();
236 TextListener::ResetParam();
237 }
238
TearDownTestCase(void)239 void InputMethodControllerTest::TearDownTestCase(void)
240 {
241 IMSA_HILOGI("InputMethodControllerTest::TearDownTestCase");
242 TddUtil::RestoreSelfTokenID();
243 TextListener::ResetParam();
244 WindowMgr::HideWindow();
245 WindowMgr::DestroyWindow();
246 inputMethodController_->SetControllerListener(nullptr);
247 }
248
SetUp(void)249 void InputMethodControllerTest::SetUp(void)
250 {
251 IMSA_HILOGI("InputMethodControllerTest::SetUp");
252 }
253
TearDown(void)254 void InputMethodControllerTest::TearDown(void)
255 {
256 IMSA_HILOGI("InputMethodControllerTest::TearDown");
257 }
258
SetInputDeathRecipient()259 void InputMethodControllerTest::SetInputDeathRecipient()
260 {
261 IMSA_HILOGI("InputMethodControllerTest::SetInputDeathRecipient");
262 sptr<ISystemAbilityManager> systemAbilityManager =
263 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
264 if (systemAbilityManager == nullptr) {
265 IMSA_HILOGI("InputMethodControllerTest, system ability manager is nullptr");
266 return;
267 }
268 auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, "");
269 if (systemAbility == nullptr) {
270 IMSA_HILOGI("InputMethodControllerTest, system ability is nullptr");
271 return;
272 }
273 deathRecipient_ = new (std::nothrow) InputDeathRecipient();
274 if (deathRecipient_ == nullptr) {
275 IMSA_HILOGE("InputMethodControllerTest, new death recipient failed");
276 return;
277 }
278 deathRecipient_->SetDeathRecipient([](const wptr<IRemoteObject> &remote) { OnRemoteSaDied(remote); });
279 if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) {
280 IMSA_HILOGE("InputMethodControllerTest, failed to add death recipient.");
281 return;
282 }
283 }
284
OnRemoteSaDied(const wptr<IRemoteObject> & remote)285 void InputMethodControllerTest::OnRemoteSaDied(const wptr<IRemoteObject> &remote)
286 {
287 IMSA_HILOGI("InputMethodControllerTest::OnRemoteSaDied");
288 onRemoteSaDiedCv_.notify_one();
289 }
290
WaitRemoteDiedCallback()291 bool InputMethodControllerTest::WaitRemoteDiedCallback()
292 {
293 IMSA_HILOGI("InputMethodControllerTest::WaitRemoteDiedCallback");
294 std::unique_lock<std::mutex> lock(onRemoteSaDiedMutex_);
295 // 2 means wait 2 seconds.
296 return onRemoteSaDiedCv_.wait_for(lock, std::chrono::seconds(2)) != std::cv_status::timeout;
297 }
298
CheckProxyObject()299 void InputMethodControllerTest::CheckProxyObject()
300 {
301 for (uint32_t retryTimes = 0; retryTimes < RETRY_TIMES; ++retryTimes) {
302 IMSA_HILOGI("times = %{public}d", retryTimes);
303 sptr<ISystemAbilityManager> systemAbilityManager =
304 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
305 if (systemAbilityManager == nullptr) {
306 IMSA_HILOGI("system ability manager is nullptr");
307 continue;
308 }
309 auto systemAbility = systemAbilityManager->CheckSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID);
310 if (systemAbility != nullptr) {
311 IMSA_HILOGI("CheckProxyObject success!");
312 break;
313 }
314 usleep(RETRY_TIME);
315 }
316 }
317
CheckKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent)318 bool InputMethodControllerTest::CheckKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent)
319 {
320 bool ret = keyEvent->GetKeyCode() == keyEvent_->GetKeyCode();
321 EXPECT_TRUE(ret);
322 ret = keyEvent->GetKeyAction() == keyEvent_->GetKeyAction();
323 EXPECT_TRUE(ret);
324 ret = keyEvent->GetKeyIntention() == keyEvent_->GetKeyIntention();
325 EXPECT_TRUE(ret);
326 // check function key state
327 ret = keyEvent->GetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY)
328 == keyEvent_->GetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY);
329 EXPECT_TRUE(ret);
330 ret = keyEvent->GetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY)
331 == keyEvent_->GetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY);
332 EXPECT_TRUE(ret);
333 ret = keyEvent->GetFunctionKey(MMI::KeyEvent::SCROLL_LOCK_FUNCTION_KEY)
334 == keyEvent_->GetFunctionKey(MMI::KeyEvent::SCROLL_LOCK_FUNCTION_KEY);
335 EXPECT_TRUE(ret);
336 // check KeyItem
337 ret = keyEvent->GetKeyItems().size() == keyEvent_->GetKeyItems().size();
338 EXPECT_TRUE(ret);
339 ret = keyEvent->GetKeyItem()->GetKeyCode() == keyEvent_->GetKeyItem()->GetKeyCode();
340 EXPECT_TRUE(ret);
341 ret = keyEvent->GetKeyItem()->GetDownTime() == keyEvent_->GetKeyItem()->GetDownTime();
342 EXPECT_TRUE(ret);
343 ret = keyEvent->GetKeyItem()->GetDeviceId() == keyEvent_->GetKeyItem()->GetDeviceId();
344 EXPECT_TRUE(ret);
345 ret = keyEvent->GetKeyItem()->IsPressed() == keyEvent_->GetKeyItem()->IsPressed();
346 EXPECT_TRUE(ret);
347 ret = keyEvent->GetKeyItem()->GetUnicode() == keyEvent_->GetKeyItem()->GetUnicode();
348 EXPECT_TRUE(ret);
349 return ret;
350 }
351
WaitKeyboardStatusCallback(bool keyboardState)352 void InputMethodControllerTest::WaitKeyboardStatusCallback(bool keyboardState)
353 {
354 std::unique_lock<std::mutex> lock(InputMethodEngineListenerImpl::imeListenerMutex_);
355 InputMethodEngineListenerImpl::imeListenerCv_.wait_for(lock,
356 std::chrono::seconds(InputMethodControllerTest::DELAY_TIME),
357 [keyboardState] { return InputMethodEngineListenerImpl::keyboardState_ == keyboardState; });
358 }
359
TriggerConfigurationChangeCallback(Configuration & info)360 void InputMethodControllerTest::TriggerConfigurationChangeCallback(Configuration &info)
361 {
362 textConfigHandler_->PostTask(
363 [info]() { inputMethodController_->OnConfigurationChange(info); }, InputMethodControllerTest::TASK_DELAY_TIME);
364 {
365 std::unique_lock<std::mutex> lock(InputMethodControllerTest::keyboardListenerMutex_);
366 InputMethodControllerTest::keyboardListenerCv_.wait_for(
367 lock, std::chrono::seconds(InputMethodControllerTest::DELAY_TIME), [&info] {
368 return (static_cast<OHOS::MiscServices::TextInputType>(
369 InputMethodControllerTest::inputAttribute_.inputPattern)
370 == info.GetTextInputType())
371 && (static_cast<OHOS::MiscServices::EnterKeyType>(
372 InputMethodControllerTest::inputAttribute_.enterKeyType)
373 == info.GetEnterKeyType());
374 });
375 }
376 }
377
TriggerCursorUpdateCallback(CursorInfo & info)378 void InputMethodControllerTest::TriggerCursorUpdateCallback(CursorInfo &info)
379 {
380 textConfigHandler_->PostTask(
381 [info]() { inputMethodController_->OnCursorUpdate(info); }, InputMethodControllerTest::TASK_DELAY_TIME);
382 {
383 std::unique_lock<std::mutex> lock(InputMethodControllerTest::keyboardListenerMutex_);
384 InputMethodControllerTest::keyboardListenerCv_.wait_for(lock,
385 std::chrono::seconds(InputMethodControllerTest::DELAY_TIME),
386 [&info] { return InputMethodControllerTest::cursorInfo_ == info; });
387 }
388 }
389
TriggerSelectionChangeCallback(std::u16string & text,int start,int end)390 void InputMethodControllerTest::TriggerSelectionChangeCallback(std::u16string &text, int start, int end)
391 {
392 textConfigHandler_->PostTask([text, start, end]() { inputMethodController_->OnSelectionChange(text, start, end); },
393 InputMethodControllerTest::TASK_DELAY_TIME);
394 {
395 std::unique_lock<std::mutex> lock(InputMethodControllerTest::keyboardListenerMutex_);
396 InputMethodControllerTest::keyboardListenerCv_.wait_for(lock,
397 std::chrono::seconds(InputMethodControllerTest::DELAY_TIME),
398 [&text] { return InputMethodControllerTest::text_ == Str16ToStr8(text); });
399 }
400 }
401
402 /**
403 * @tc.name: testIMCAttach
404 * @tc.desc: IMC Attach.
405 * @tc.type: FUNC
406 * @tc.require:
407 */
408 HWTEST_F(InputMethodControllerTest, testIMCAttach, TestSize.Level0)
409 {
410 IMSA_HILOGD("IMC Attach Test START");
411 imeListener_->isInputStart_ = false;
412 inputMethodController_->Attach(textListener_, false);
413 inputMethodController_->Attach(textListener_);
414 inputMethodController_->Attach(textListener_, true);
415 EXPECT_TRUE(TextListener::WaitIMACallback());
416 EXPECT_TRUE(imeListener_->isInputStart_ && imeListener_->keyboardState_);
417 }
418
419 /**
420 * @tc.name: testIMCSetCallingWindow
421 * @tc.desc: IMC SetCallingWindow.
422 * @tc.type: FUNC
423 * @tc.require:
424 */
425 HWTEST_F(InputMethodControllerTest, testIMCSetCallingWindow, TestSize.Level0)
426 {
427 IMSA_HILOGD("IMC SetCallingWindow Test START");
428 auto ret = inputMethodController_->Attach(textListener_);
429 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
430 uint32_t windowId = 3;
431 ret = inputMethodController_->SetCallingWindow(windowId);
432 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
433 EXPECT_EQ(windowId, imeListener_->windowId_);
434 }
435
436 /**
437 * @tc.name: testGetIMSAProxy
438 * @tc.desc: Get Imsa Proxy.
439 * @tc.type: FUNC
440 */
441 HWTEST_F(InputMethodControllerTest, testGetIMSAProxy, TestSize.Level0)
442 {
443 auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
444 EXPECT_TRUE(systemAbilityManager != nullptr);
445 auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, "");
446 EXPECT_TRUE(systemAbility != nullptr);
447 }
448
449 /**
450 * @tc.name: testWriteReadIInputDataChannel
451 * @tc.desc: Checkout IInputDataChannel.
452 * @tc.type: FUNC
453 */
454 HWTEST_F(InputMethodControllerTest, testWriteReadIInputDataChannel, TestSize.Level0)
455 {
456 sptr<InputDataChannelStub> mInputDataChannel = new InputDataChannelStub();
457 MessageParcel data;
458 auto ret = data.WriteRemoteObject(mInputDataChannel->AsObject());
459 EXPECT_TRUE(ret);
460 auto remoteObject = data.ReadRemoteObject();
461 sptr<IInputDataChannel> iface = iface_cast<IInputDataChannel>(remoteObject);
462 EXPECT_TRUE(iface != nullptr);
463 }
464
465 /**
466 * @tc.name: testIMCBindToIMSA
467 * @tc.desc: Bind IMSA.
468 * @tc.type: FUNC
469 */
470 HWTEST_F(InputMethodControllerTest, testIMCBindToIMSA, TestSize.Level0)
471 {
472 sptr<InputClientStub> mClient = new InputClientStub();
473 MessageParcel data;
474 auto ret = data.WriteRemoteObject(mClient->AsObject());
475 EXPECT_TRUE(ret);
476 auto remoteObject = data.ReadRemoteObject();
477 sptr<IInputClient> iface = iface_cast<IInputClient>(remoteObject);
478 EXPECT_TRUE(iface != nullptr);
479 }
480
481 /**
482 * @tc.name: testIMCDispatchKeyEvent001
483 * @tc.desc: test IMC DispatchKeyEvent with 'keyDown/KeyUP'.
484 * @tc.type: FUNC
485 * @tc.require:
486 */
487 HWTEST_F(InputMethodControllerTest, testIMCDispatchKeyEvent001, TestSize.Level0)
488 {
489 IMSA_HILOGI("IMC testIMCDispatchKeyEvent001 Test START");
490 doesKeyEventConsume_ = true;
491 doesFUllKeyEventConsume_ = false;
492 blockKeyEvent_.Clear(nullptr);
493 auto res = inputMethodController_->Attach(textListener_);
494 EXPECT_EQ(res, ErrorCode::NO_ERROR);
495 bool ret = inputMethodController_->DispatchKeyEvent(keyEvent_);
496 EXPECT_TRUE(ret);
497 auto keyEvent = blockKeyEvent_.GetValue();
498 ASSERT_NE(keyEvent, nullptr);
499 EXPECT_EQ(keyEvent->GetKeyCode(), keyEvent_->GetKeyCode());
500 EXPECT_EQ(keyEvent->GetKeyAction(), keyEvent_->GetKeyAction());
501 }
502
503 /**
504 * @tc.name: testIMCDispatchKeyEvent002
505 * @tc.desc: test IMC DispatchKeyEvent with 'keyEvent'.
506 * @tc.type: FUNC
507 * @tc.require:
508 */
509 HWTEST_F(InputMethodControllerTest, testIMCDispatchKeyEvent002, TestSize.Level0)
510 {
511 IMSA_HILOGI("IMC testIMCDispatchKeyEvent002 Test START");
512 doesKeyEventConsume_ = false;
513 doesFUllKeyEventConsume_ = true;
514 blockFullKeyEvent_.Clear(nullptr);
515 bool ret = inputMethodController_->DispatchKeyEvent(keyEvent_);
516 EXPECT_TRUE(ret);
517 auto keyEvent = blockFullKeyEvent_.GetValue();
518 EXPECT_NE(keyEvent, nullptr);
519 EXPECT_TRUE(CheckKeyEvent(keyEvent));
520 }
521
522 /**
523 * @tc.name: testIMCDispatchKeyEvent003
524 * @tc.desc: test IMC DispatchKeyEvent with 'keyDown/KeyUP' and 'keyEvent'.
525 * @tc.type: FUNC
526 * @tc.require:
527 */
528 HWTEST_F(InputMethodControllerTest, testIMCDispatchKeyEvent003, TestSize.Level0)
529 {
530 IMSA_HILOGI("IMC testIMCDispatchKeyEvent003 Test START");
531 doesKeyEventConsume_ = true;
532 doesFUllKeyEventConsume_ = true;
533 blockKeyEvent_.Clear(nullptr);
534 blockFullKeyEvent_.Clear(nullptr);
535 bool ret = inputMethodController_->DispatchKeyEvent(keyEvent_);
536 EXPECT_TRUE(ret);
537 auto keyEvent = blockKeyEvent_.GetValue();
538 auto keyFullEvent = blockFullKeyEvent_.GetValue();
539 EXPECT_NE(keyEvent, nullptr);
540 EXPECT_NE(keyFullEvent, nullptr);
541 EXPECT_EQ(keyEvent->GetKeyCode(), keyEvent_->GetKeyCode());
542 EXPECT_EQ(keyEvent->GetKeyAction(), keyEvent_->GetKeyAction());
543 EXPECT_TRUE(CheckKeyEvent(keyFullEvent));
544 }
545
546 /**
547 * @tc.name: testIMCOnCursorUpdate01
548 * @tc.desc: Test update cursorInfo, call 'OnCursorUpdate' twice, if cursorInfo is the same,
549 * the second time will not get callback.
550 * @tc.type: FUNC
551 * @tc.require:
552 * @tc.author: Zhaolinglan
553 */
554 HWTEST_F(InputMethodControllerTest, testIMCOnCursorUpdate01, TestSize.Level0)
555 {
556 IMSA_HILOGI("IMC testIMCOnCursorUpdate01 Test START");
557 auto ret = inputMethodController_->Attach(textListener_, false);
558 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
559 CursorInfo info = { 1, 3, 0, 5 };
560 InputMethodControllerTest::TriggerCursorUpdateCallback(info);
561 EXPECT_EQ(InputMethodControllerTest::cursorInfo_, info);
562
563 InputMethodControllerTest::cursorInfo_ = {};
564 InputMethodControllerTest::TriggerCursorUpdateCallback(info);
565 EXPECT_FALSE(InputMethodControllerTest::cursorInfo_ == info);
566 }
567
568 /**
569 * @tc.name: testIMCOnCursorUpdate02
570 * @tc.desc: Test update cursorInfo, 'Attach'->'OnCursorUpdate'->'Close'->'Attach'->'OnCursorUpdate',
571 * it will get callback two time.
572 * @tc.type: FUNC
573 * @tc.require:
574 * @tc.author: Zhaolinglan
575 */
576 HWTEST_F(InputMethodControllerTest, testIMCOnCursorUpdate02, TestSize.Level0)
577 {
578 IMSA_HILOGI("IMC testIMCOnCursorUpdate02 Test START");
579 auto ret = inputMethodController_->Attach(textListener_, false);
580 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
581 CursorInfo info = { 2, 4, 0, 6 };
582 InputMethodControllerTest::TriggerCursorUpdateCallback(info);
583 EXPECT_EQ(InputMethodControllerTest::cursorInfo_, info);
584
585 InputMethodControllerTest::cursorInfo_ = {};
586 ret = InputMethodControllerTest::inputMethodController_->Close();
587 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
588 ret = inputMethodController_->Attach(textListener_, false);
589 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
590 InputMethodControllerTest::TriggerCursorUpdateCallback(info);
591 EXPECT_EQ(InputMethodControllerTest::cursorInfo_, info);
592 }
593
594 /**
595 * @tc.name: testIMCOnSelectionChange01
596 * @tc.desc: Test change selection, call 'OnSelectionChange' twice, if selection is the same,
597 * the second time will not get callback.
598 * @tc.type: FUNC
599 * @tc.require:
600 * @tc.author: Zhaolinglan
601 */
602 HWTEST_F(InputMethodControllerTest, testIMCOnSelectionChange01, TestSize.Level0)
603 {
604 IMSA_HILOGI("IMC testIMCOnSelectionChange01 Test START");
605 auto ret = inputMethodController_->Attach(textListener_, false);
606 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
607 std::u16string text = Str8ToStr16("testSelect");
608 int start = 1;
609 int end = 2;
610 InputMethodControllerTest::TriggerSelectionChangeCallback(text, start, end);
611 EXPECT_EQ(InputMethodControllerTest::text_, Str16ToStr8(text));
612
613 InputMethodControllerTest::text_ = "";
614 InputMethodControllerTest::TriggerSelectionChangeCallback(text, start, end);
615 EXPECT_NE(InputMethodControllerTest::text_, Str16ToStr8(text));
616 }
617
618 /**
619 * @tc.name: testIMCOnSelectionChange02
620 * @tc.desc: Test change selection, 'Attach'->'OnSelectionChange'->'Close'->'Attach'->'OnSelectionChange',
621 * it will get callback two time.
622 * @tc.type: FUNC
623 * @tc.require:
624 * @tc.author: Zhaolinglan
625 */
626 HWTEST_F(InputMethodControllerTest, testIMCOnSelectionChange02, TestSize.Level0)
627 {
628 IMSA_HILOGI("IMC testIMCOnSelectionChange02 Test START");
629 auto ret = inputMethodController_->Attach(textListener_, false);
630 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
631 std::u16string text = Str8ToStr16("testSelect2");
632 int start = 1;
633 int end = 2;
634 InputMethodControllerTest::TriggerSelectionChangeCallback(text, start, end);
635 EXPECT_EQ(InputMethodControllerTest::text_, Str16ToStr8(text));
636
637 InputMethodControllerTest::text_ = "";
638 InputMethodControllerTest::inputMethodController_->Close();
639 inputMethodController_->Attach(textListener_, false);
640 InputMethodControllerTest::TriggerSelectionChangeCallback(text, start, end);
641 EXPECT_EQ(InputMethodControllerTest::text_, Str16ToStr8(text));
642 }
643
644 /**
645 * @tc.name: testShowTextInput
646 * @tc.desc: IMC ShowTextInput
647 * @tc.type: FUNC
648 */
649 HWTEST_F(InputMethodControllerTest, testShowTextInput, TestSize.Level0)
650 {
651 IMSA_HILOGI("IMC ShowTextInput Test START");
652 TextListener::keyboardStatus_ = KeyboardStatus::NONE;
653 inputMethodController_->ShowTextInput();
654 EXPECT_TRUE(TextListener::WaitIMACallback());
655 EXPECT_TRUE(TextListener::keyboardStatus_ == KeyboardStatus::SHOW);
656 }
657
658 /**
659 * @tc.name: testShowSoftKeyboard
660 * @tc.desc: IMC ShowSoftKeyboard
661 * @tc.type: FUNC
662 */
663 HWTEST_F(InputMethodControllerTest, testShowSoftKeyboard, TestSize.Level0)
664 {
665 IMSA_HILOGI("IMC ShowSoftKeyboard Test START");
666 imeListener_->keyboardState_ = false;
667 TextListener::keyboardStatus_ = KeyboardStatus::NONE;
668 int32_t ret = inputMethodController_->ShowSoftKeyboard();
669 EXPECT_TRUE(TextListener::WaitIMACallback());
670 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
671 EXPECT_TRUE(imeListener_->keyboardState_ && TextListener::keyboardStatus_ == KeyboardStatus::SHOW);
672 }
673
674 /**
675 * @tc.name: testShowCurrentInput
676 * @tc.desc: IMC ShowCurrentInput
677 * @tc.type: FUNC
678 */
679 HWTEST_F(InputMethodControllerTest, testShowCurrentInput, TestSize.Level0)
680 {
681 IMSA_HILOGI("IMC ShowCurrentInput Test START");
682 imeListener_->keyboardState_ = false;
683 TextListener::keyboardStatus_ = KeyboardStatus::NONE;
684 int32_t ret = inputMethodController_->ShowCurrentInput();
685 EXPECT_TRUE(TextListener::WaitIMACallback());
686 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
687 EXPECT_TRUE(imeListener_->keyboardState_ && TextListener::keyboardStatus_ == KeyboardStatus::SHOW);
688 }
689
690 /**
691 * @tc.name: testIMCGetEnterKeyType
692 * @tc.desc: IMC testGetEnterKeyType.
693 * @tc.type: FUNC
694 * @tc.require:
695 */
696 HWTEST_F(InputMethodControllerTest, testIMCGetEnterKeyType, TestSize.Level0)
697 {
698 IMSA_HILOGI("IMC GetEnterKeyType Test START");
699 int32_t keyType;
700 inputMethodController_->GetEnterKeyType(keyType);
701 EXPECT_TRUE(keyType >= static_cast<int32_t>(EnterKeyType::UNSPECIFIED)
702 && keyType <= static_cast<int32_t>(EnterKeyType::PREVIOUS));
703 }
704
705 /**
706 * @tc.name: testIMCGetInputPattern
707 * @tc.desc: IMC testGetInputPattern.
708 * @tc.type: FUNC
709 * @tc.require:
710 */
711 HWTEST_F(InputMethodControllerTest, testIMCGetInputPattern, TestSize.Level0)
712 {
713 IMSA_HILOGI("IMC GetInputPattern Test START");
714 int32_t inputPattern;
715 inputMethodController_->GetInputPattern(inputPattern);
716 EXPECT_TRUE(inputPattern >= static_cast<int32_t>(TextInputType::NONE)
717 && inputPattern <= static_cast<int32_t>(TextInputType::VISIBLE_PASSWORD));
718 }
719
720 /**
721 * @tc.name: testOnEditorAttributeChanged
722 * @tc.desc: IMC testOnEditorAttributeChanged.
723 * @tc.type: FUNC
724 * @tc.require:
725 */
726 HWTEST_F(InputMethodControllerTest, testOnEditorAttributeChanged, TestSize.Level0)
727 {
728 IMSA_HILOGI("IMC testOnEditorAttributeChanged Test START");
729 auto ret = inputMethodController_->Attach(textListener_, false);
730 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
731 Configuration info;
732 info.SetEnterKeyType(EnterKeyType::GO);
733 info.SetTextInputType(TextInputType::NUMBER);
734 InputMethodControllerTest::TriggerConfigurationChangeCallback(info);
735 EXPECT_EQ(InputMethodControllerTest::inputAttribute_.inputPattern, static_cast<int32_t>(info.GetTextInputType()));
736 EXPECT_EQ(InputMethodControllerTest::inputAttribute_.enterKeyType, static_cast<int32_t>(info.GetEnterKeyType()));
737 }
738
739 /**
740 * @tc.name: testHideSoftKeyboard
741 * @tc.desc: IMC HideSoftKeyboard
742 * @tc.type: FUNC
743 */
744 HWTEST_F(InputMethodControllerTest, testHideSoftKeyboard, TestSize.Level0)
745 {
746 IMSA_HILOGI("IMC HideSoftKeyboard Test START");
747 imeListener_->keyboardState_ = true;
748 TextListener::keyboardStatus_ = KeyboardStatus::NONE;
749 int32_t ret = inputMethodController_->HideSoftKeyboard();
750 EXPECT_TRUE(TextListener::WaitIMACallback());
751 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
752 EXPECT_TRUE(!imeListener_->keyboardState_ && TextListener::keyboardStatus_ == KeyboardStatus::HIDE);
753 }
754
755 /**
756 * @tc.name: testIMCHideCurrentInput
757 * @tc.desc: IMC HideCurrentInput.
758 * @tc.type: FUNC
759 * @tc.require:
760 */
761 HWTEST_F(InputMethodControllerTest, testIMCHideCurrentInput, TestSize.Level0)
762 {
763 IMSA_HILOGI("IMC HideCurrentInput Test START");
764 imeListener_->keyboardState_ = true;
765 TextListener::keyboardStatus_ = KeyboardStatus::NONE;
766 int32_t ret = inputMethodController_->HideCurrentInput();
767 EXPECT_TRUE(TextListener::WaitIMACallback());
768 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
769 EXPECT_TRUE(!imeListener_->keyboardState_ && TextListener::keyboardStatus_ == KeyboardStatus::HIDE);
770 }
771
772 /**
773 * @tc.name: testIMCInputStopSession
774 * @tc.desc: IMC testInputStopSession.
775 * @tc.type: FUNC
776 * @tc.require: issueI5U8FZ
777 * @tc.author: Hollokin
778 */
779 HWTEST_F(InputMethodControllerTest, testIMCInputStopSession, TestSize.Level0)
780 {
781 IMSA_HILOGI("IMC StopInputSession Test START");
782 imeListener_->keyboardState_ = true;
783 TextListener::keyboardStatus_ = KeyboardStatus::NONE;
784 int32_t ret = inputMethodController_->StopInputSession();
785 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
786 WaitKeyboardStatusCallback(false);
787 EXPECT_TRUE(!imeListener_->keyboardState_);
788 }
789
790 /**
791 * @tc.name: testIMCHideTextInput.
792 * @tc.desc: IMC testHideTextInput.
793 * @tc.type: FUNC
794 */
795 HWTEST_F(InputMethodControllerTest, testIMCHideTextInput, TestSize.Level0)
796 {
797 IMSA_HILOGI("IMC HideTextInput Test START");
798 imeListener_->keyboardState_ = true;
799 TextListener::keyboardStatus_ = KeyboardStatus::NONE;
800 inputMethodController_->HideTextInput();
801 WaitKeyboardStatusCallback(false);
802 EXPECT_TRUE(!imeListener_->keyboardState_);
803 }
804
805 /**
806 * @tc.name: testSetControllerListener
807 * @tc.desc: IMC SetControllerListener
808 * @tc.type: FUNC
809 */
810 HWTEST_F(InputMethodControllerTest, testSetControllerListener, TestSize.Level0)
811 {
812 IMSA_HILOGI("IMC SetControllerListener Test START");
813 inputMethodController_->SetControllerListener(controllerListener_);
814
815 int32_t ret = inputMethodController_->Attach(textListener_, false);
816 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
817 EXPECT_CALL(*controllerListener_, OnSelectByRange(Eq(1), Eq(2))).Times(1);
818 inputMethodAbility_->SelectByRange(1, 2);
819
820 Sequence s;
821 EXPECT_CALL(*controllerListener_, OnSelectByMovement(Eq(static_cast<int32_t>(Direction::UP))))
822 .Times(1)
823 .InSequence(s);
824 EXPECT_CALL(*controllerListener_, OnSelectByMovement(Eq(static_cast<int32_t>(Direction::DOWN))))
825 .Times(1)
826 .InSequence(s);
827 EXPECT_CALL(*controllerListener_, OnSelectByMovement(Eq(static_cast<int32_t>(Direction::LEFT))))
828 .Times(1)
829 .InSequence(s);
830 EXPECT_CALL(*controllerListener_, OnSelectByMovement(Eq(static_cast<int32_t>(Direction::RIGHT))))
831 .Times(1)
832 .InSequence(s);
833 inputMethodAbility_->SelectByMovement(static_cast<int32_t>(Direction::UP));
834 inputMethodAbility_->SelectByMovement(static_cast<int32_t>(Direction::DOWN));
835 inputMethodAbility_->SelectByMovement(static_cast<int32_t>(Direction::LEFT));
836 inputMethodAbility_->SelectByMovement(static_cast<int32_t>(Direction::RIGHT));
837 controllerListener_ = nullptr;
838 }
839
840 /**
841 * @tc.name: testWasAttached
842 * @tc.desc: IMC WasAttached
843 * @tc.type: FUNC
844 */
845 HWTEST_F(InputMethodControllerTest, testWasAttached, TestSize.Level0)
846 {
847 IMSA_HILOGI("IMC WasAttached Test START");
848 inputMethodController_->Close();
849 bool result = inputMethodController_->WasAttached();
850 EXPECT_FALSE(result);
851 int32_t ret = inputMethodController_->Attach(textListener_, false);
852 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
853 result = inputMethodController_->WasAttached();
854 EXPECT_TRUE(result);
855 inputMethodController_->Close();
856 }
857
858 /**
859 * @tc.name: testWithoutEditableState
860 * @tc.desc: IMC testWithoutEditableState
861 * @tc.type: FUNC
862 * @tc.require:
863 */
864 HWTEST_F(InputMethodControllerTest, testWithoutEditableState, TestSize.Level0)
865 {
866 IMSA_HILOGI("IMC WithouteEditableState Test START");
867 auto ret = inputMethodController_->Attach(textListener_, false);
868 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
869 ret = inputMethodController_->HideTextInput();
870 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
871
872 int32_t deleteForwardLength = 1;
873 ret = inputMethodAbility_->DeleteForward(deleteForwardLength);
874 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
875 usleep(100);
876 EXPECT_NE(TextListener::deleteForwardLength_, deleteForwardLength);
877
878 int32_t deleteBackwardLength = 2;
879 ret = inputMethodAbility_->DeleteBackward(deleteBackwardLength);
880 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
881 usleep(100);
882 EXPECT_NE(TextListener::deleteBackwardLength_, deleteBackwardLength);
883
884 std::string insertText = "t";
885 ret = inputMethodAbility_->InsertText(insertText);
886 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
887 usleep(100);
888 EXPECT_NE(TextListener::insertText_, Str8ToStr16(insertText));
889
890 constexpr int32_t funcKey = 1;
891 ret = inputMethodAbility_->SendFunctionKey(funcKey);
892 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
893 usleep(100);
894 EXPECT_NE(TextListener::key_, funcKey);
895
896 constexpr int32_t keyCode = 4;
897 ret = inputMethodAbility_->MoveCursor(keyCode);
898 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
899 usleep(100);
900 EXPECT_NE(TextListener::direction_, keyCode);
901 }
902
903 /**
904 * @tc.name: testOnRemoteDied
905 * @tc.desc: IMC OnRemoteDied
906 * @tc.type: FUNC
907 */
908 HWTEST_F(InputMethodControllerTest, testOnRemoteDied, TestSize.Level0)
909 {
910 IMSA_HILOGI("IMC OnRemoteDied Test START");
911 int32_t ret = inputMethodController_->Attach(textListener_, true);
912 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
913 pid_t pid = TddUtil::GetImsaPid();
914 EXPECT_TRUE(pid > 0);
915 ret = kill(pid, SIGTERM);
916 EXPECT_EQ(ret, 0);
917 EXPECT_TRUE(WaitRemoteDiedCallback());
918 CheckProxyObject();
919 inputMethodController_->OnRemoteSaDied(nullptr);
920 EXPECT_TRUE(TextListener::WaitIMACallback());
921 bool result = inputMethodController_->WasAttached();
922 EXPECT_TRUE(result);
923 inputMethodController_->Close();
924 }
925 } // namespace MiscServices
926 } // namespace OHOS
927