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 <gtest/gtest.h>
22 #include <string_ex.h>
23 #include <sys/time.h>
24
25 #include <condition_variable>
26 #include <csignal>
27 #include <cstdint>
28 #include <functional>
29 #include <mutex>
30 #include <string>
31 #include <thread>
32 #include <unordered_map>
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 "scope_utils.h"
53 #include "system_ability.h"
54 #include "system_ability_definition.h"
55 #include "tdd_util.h"
56 #include "text_listener.h"
57
58 using namespace testing;
59 using namespace testing::ext;
60 namespace OHOS {
61 namespace MiscServices {
62 constexpr uint32_t RETRY_TIME = 200 * 1000;
63 constexpr uint32_t RETRY_TIMES = 5;
64 constexpr uint32_t WAIT_INTERVAL = 500;
65 constexpr size_t PRIVATE_COMMAND_SIZE_MAX = 32 * 1024;
66 constexpr uint32_t WAIT_SA_DIE_TIME_OUT = 3;
67
68 class SelectListenerMock : public ControllerListener {
69 public:
70 SelectListenerMock() = default;
71 ~SelectListenerMock() override = default;
72
OnSelectByRange(int32_t start,int32_t end)73 void OnSelectByRange(int32_t start, int32_t end) override
74 {
75 start_ = start;
76 end_ = end;
77 selectListenerCv_.notify_all();
78 }
79
OnSelectByMovement(int32_t direction)80 void OnSelectByMovement(int32_t direction) override
81 {
82 direction_ = direction;
83 selectListenerCv_.notify_all();
84 }
85 static void WaitSelectListenerCallback();
86 static int32_t start_;
87 static int32_t end_;
88 static int32_t direction_;
89 static std::mutex selectListenerMutex_;
90 static std::condition_variable selectListenerCv_;
91 };
92
93 int32_t SelectListenerMock::start_ = 0;
94 int32_t SelectListenerMock::end_ = 0;
95 int32_t SelectListenerMock::direction_ = 0;
96 std::mutex SelectListenerMock::selectListenerMutex_;
97 std::condition_variable SelectListenerMock::selectListenerCv_;
WaitSelectListenerCallback()98 void SelectListenerMock::WaitSelectListenerCallback()
99 {
100 std::unique_lock<std::mutex> lock(selectListenerMutex_);
101 selectListenerCv_.wait_for(lock, std::chrono::milliseconds(WAIT_INTERVAL));
102 }
103
104 class InputMethodControllerTest : public testing::Test {
105 public:
106 static void SetUpTestCase(void);
107 static void TearDownTestCase(void);
108 void SetUp();
109 void TearDown();
110 static void SetInputDeathRecipient();
111 static void OnRemoteSaDied(const wptr<IRemoteObject> &remote);
112 static void CheckKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent);
113 static bool WaitRemoteDiedCallback();
114 static void WaitKeyboardStatusCallback(bool keyboardState);
115 static void TriggerConfigurationChangeCallback(Configuration &info);
116 static void TriggerCursorUpdateCallback(CursorInfo &info);
117 static void TriggerSelectionChangeCallback(std::u16string &text, int start, int end);
118 static void CheckProxyObject();
119 static void DispatchKeyEventCallback(std::shared_ptr<MMI::KeyEvent> &keyEvent, bool isConsumed);
120 static bool WaitKeyEventCallback();
121 static void CheckTextConfig(const TextConfig &config);
122 static sptr<InputMethodController> inputMethodController_;
123 static sptr<InputMethodAbility> inputMethodAbility_;
124 static std::shared_ptr<MMI::KeyEvent> keyEvent_;
125 static std::shared_ptr<InputMethodEngineListenerImpl> imeListener_;
126 static std::shared_ptr<SelectListenerMock> controllerListener_;
127 static sptr<OnTextChangedListener> textListener_;
128 static std::mutex keyboardListenerMutex_;
129 static std::condition_variable keyboardListenerCv_;
130 static BlockData<std::shared_ptr<MMI::KeyEvent>> blockKeyEvent_;
131 static BlockData<std::shared_ptr<MMI::KeyEvent>> blockFullKeyEvent_;
132 static std::mutex onRemoteSaDiedMutex_;
133 static std::condition_variable onRemoteSaDiedCv_;
134 static sptr<InputDeathRecipient> deathRecipient_;
135 static CursorInfo cursorInfo_;
136 static int32_t oldBegin_;
137 static int32_t oldEnd_;
138 static int32_t newBegin_;
139 static int32_t newEnd_;
140 static std::string text_;
141 static bool doesKeyEventConsume_;
142 static bool doesFUllKeyEventConsume_;
143 static std::condition_variable keyEventCv_;
144 static std::mutex keyEventLock_;
145 static bool consumeResult_;
146 static InputAttribute inputAttribute_;
147 static std::shared_ptr<AppExecFwk::EventHandler> textConfigHandler_;
148 static constexpr uint32_t DELAY_TIME = 1;
149 static constexpr uint32_t KEY_EVENT_DELAY_TIME = 100;
150 static constexpr int32_t TASK_DELAY_TIME = 10;
151 static uint64_t defaultImeTokenId_;
152 static uint64_t permissionTokenId_;
153
154 class KeyboardListenerImpl : public KeyboardListener {
155 public:
KeyboardListenerImpl()156 KeyboardListenerImpl()
157 {
158 std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("InputMethodControllerTe"
159 "st");
160 textConfigHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
161 };
~KeyboardListenerImpl()162 ~KeyboardListenerImpl(){};
OnKeyEvent(int32_t keyCode,int32_t keyStatus,sptr<KeyEventConsumerProxy> & consumer)163 bool OnKeyEvent(int32_t keyCode, int32_t keyStatus, sptr<KeyEventConsumerProxy> &consumer) override
164 {
165 if (!doesKeyEventConsume_) {
166 return false;
167 }
168 IMSA_HILOGI("KeyboardListenerImpl::OnKeyEvent %{public}d %{public}d", keyCode, keyStatus);
169 auto keyEvent = KeyEventUtil::CreateKeyEvent(keyCode, keyStatus);
170 blockKeyEvent_.SetValue(keyEvent);
171 return true;
172 }
OnKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent,sptr<KeyEventConsumerProxy> & consumer)173 bool OnKeyEvent(const std::shared_ptr<MMI::KeyEvent> &keyEvent, sptr<KeyEventConsumerProxy> &consumer) override
174 {
175 if (!doesFUllKeyEventConsume_) {
176 return false;
177 }
178 IMSA_HILOGI("KeyboardListenerImpl::OnKeyEvent %{public}d %{public}d", keyEvent->GetKeyCode(),
179 keyEvent->GetKeyAction());
180 auto fullKey = keyEvent;
181 blockFullKeyEvent_.SetValue(fullKey);
182 return true;
183 }
OnDealKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent,sptr<KeyEventConsumerProxy> & consumer)184 bool OnDealKeyEvent(
185 const std::shared_ptr<MMI::KeyEvent> &keyEvent, sptr<KeyEventConsumerProxy> &consumer) override
186 {
187 bool isKeyCodeConsume = OnKeyEvent(keyEvent->GetKeyCode(), keyEvent->GetKeyAction(), consumer);
188 bool isKeyEventConsume = OnKeyEvent(keyEvent, consumer);
189 if (consumer != nullptr) {
190 consumer->OnKeyEventResult(isKeyEventConsume | isKeyCodeConsume);
191 }
192 return true;
193 }
OnCursorUpdate(int32_t positionX,int32_t positionY,int32_t height)194 void OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height) override
195 {
196 IMSA_HILOGD(
197 "KeyboardListenerImpl::OnCursorUpdate %{public}d %{public}d %{public}d", positionX, positionY, height);
198 cursorInfo_ = { static_cast<double>(positionX), static_cast<double>(positionY), 0,
199 static_cast<double>(height) };
200 InputMethodControllerTest::keyboardListenerCv_.notify_one();
201 }
OnSelectionChange(int32_t oldBegin,int32_t oldEnd,int32_t newBegin,int32_t newEnd)202 void OnSelectionChange(int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd) override
203 {
204 IMSA_HILOGD("KeyboardListenerImpl::OnSelectionChange %{public}d %{public}d %{public}d %{public}d",
205 oldBegin, oldEnd, newBegin, newBegin);
206 oldBegin_ = oldBegin;
207 oldEnd_ = oldEnd;
208 newBegin_ = newBegin;
209 newEnd_ = newEnd;
210 InputMethodControllerTest::keyboardListenerCv_.notify_one();
211 }
OnTextChange(const std::string & text)212 void OnTextChange(const std::string &text) override
213 {
214 IMSA_HILOGD("KeyboardListenerImpl::OnTextChange text: %{public}s", text.c_str());
215 text_ = text;
216 InputMethodControllerTest::keyboardListenerCv_.notify_one();
217 }
OnEditorAttributeChange(const InputAttribute & inputAttribute)218 void OnEditorAttributeChange(const InputAttribute &inputAttribute) override
219 {
220 IMSA_HILOGD("KeyboardListenerImpl in.");
221 inputAttribute_ = inputAttribute;
222 InputMethodControllerTest::keyboardListenerCv_.notify_one();
223 }
224 };
225 };
226 sptr<InputMethodController> InputMethodControllerTest::inputMethodController_;
227 sptr<InputMethodAbility> InputMethodControllerTest::inputMethodAbility_;
228 std::shared_ptr<MMI::KeyEvent> InputMethodControllerTest::keyEvent_;
229 std::shared_ptr<InputMethodEngineListenerImpl> InputMethodControllerTest::imeListener_;
230 std::shared_ptr<SelectListenerMock> InputMethodControllerTest::controllerListener_;
231 sptr<OnTextChangedListener> InputMethodControllerTest::textListener_;
232 CursorInfo InputMethodControllerTest::cursorInfo_ = {};
233 int32_t InputMethodControllerTest::oldBegin_ = 0;
234 int32_t InputMethodControllerTest::oldEnd_ = 0;
235 int32_t InputMethodControllerTest::newBegin_ = 0;
236 int32_t InputMethodControllerTest::newEnd_ = 0;
237 std::string InputMethodControllerTest::text_;
238 InputAttribute InputMethodControllerTest::inputAttribute_;
239 std::mutex InputMethodControllerTest::keyboardListenerMutex_;
240 std::condition_variable InputMethodControllerTest::keyboardListenerCv_;
241 sptr<InputDeathRecipient> InputMethodControllerTest::deathRecipient_;
242 std::mutex InputMethodControllerTest::onRemoteSaDiedMutex_;
243 std::condition_variable InputMethodControllerTest::onRemoteSaDiedCv_;
244 BlockData<std::shared_ptr<MMI::KeyEvent>> InputMethodControllerTest::blockKeyEvent_{
245 InputMethodControllerTest::KEY_EVENT_DELAY_TIME, nullptr
246 };
247 BlockData<std::shared_ptr<MMI::KeyEvent>> InputMethodControllerTest::blockFullKeyEvent_{
248 InputMethodControllerTest::KEY_EVENT_DELAY_TIME, nullptr
249 };
250 bool InputMethodControllerTest::doesKeyEventConsume_{ false };
251 bool InputMethodControllerTest::doesFUllKeyEventConsume_{ false };
252 std::condition_variable InputMethodControllerTest::keyEventCv_;
253 std::mutex InputMethodControllerTest::keyEventLock_;
254 bool InputMethodControllerTest::consumeResult_{ false };
255 std::shared_ptr<AppExecFwk::EventHandler> InputMethodControllerTest::textConfigHandler_{ nullptr };
256 uint64_t InputMethodControllerTest::defaultImeTokenId_ = 0;
257 uint64_t InputMethodControllerTest::permissionTokenId_ = 0;
258
SetUpTestCase(void)259 void InputMethodControllerTest::SetUpTestCase(void)
260 {
261 IMSA_HILOGI("InputMethodControllerTest::SetUpTestCase");
262 TddUtil::StorageSelfTokenID();
263 // Set the tokenID to the tokenID of the current ime
264 std::shared_ptr<Property> property = InputMethodController::GetInstance()->GetCurrentInputMethod();
265 std::string bundleName = property != nullptr ? property->name : "default.inputmethod.unittest";
266 {
267 TokenScope tokenScope(TddUtil::GetTestTokenID(bundleName));
268 inputMethodAbility_ = InputMethodAbility::GetInstance();
269 inputMethodAbility_->SetCoreAndAgent();
270 }
271 imeListener_ = std::make_shared<InputMethodEngineListenerImpl>();
272 controllerListener_ = std::make_shared<SelectListenerMock>();
273 textListener_ = new TextListener();
274 inputMethodAbility_->SetKdListener(std::make_shared<KeyboardListenerImpl>());
275 inputMethodAbility_->SetImeListener(imeListener_);
276 inputMethodController_ = InputMethodController::GetInstance();
277
278 keyEvent_ = KeyEventUtil::CreateKeyEvent(MMI::KeyEvent::KEYCODE_A, MMI::KeyEvent::KEY_ACTION_DOWN);
279 keyEvent_->SetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY, 0);
280 keyEvent_->SetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY, 1);
281 keyEvent_->SetFunctionKey(MMI::KeyEvent::SCROLL_LOCK_FUNCTION_KEY, 1);
282
283 TddUtil::InitWindow(true);
284 SetInputDeathRecipient();
285 TextListener::ResetParam();
286
287 auto ret = InputMethodController::GetInstance()->GetDefaultInputMethod(property);
288 auto defaultIme = ret == ErrorCode::NO_ERROR ? property->name : "default.inputmethod.unittest";
289 defaultImeTokenId_ = TddUtil::GetTestTokenID(defaultIme);
290 permissionTokenId_ = TddUtil::AllocTestTokenID(false, "undefine", { "ohos.permission.CONNECT_IME_ABILITY" });
291 }
292
TearDownTestCase(void)293 void InputMethodControllerTest::TearDownTestCase(void)
294 {
295 IMSA_HILOGI("InputMethodControllerTest::TearDownTestCase");
296 TextListener::ResetParam();
297 TddUtil::DestroyWindow();
298 inputMethodController_->SetControllerListener(nullptr);
299 TddUtil::RestoreSelfTokenID();
300 }
301
SetUp(void)302 void InputMethodControllerTest::SetUp(void)
303 {
304 IMSA_HILOGI("InputMethodControllerTest::SetUp");
305 }
306
TearDown(void)307 void InputMethodControllerTest::TearDown(void)
308 {
309 IMSA_HILOGI("InputMethodControllerTest::TearDown");
310 }
311
SetInputDeathRecipient()312 void InputMethodControllerTest::SetInputDeathRecipient()
313 {
314 IMSA_HILOGI("InputMethodControllerTest::SetInputDeathRecipient");
315 sptr<ISystemAbilityManager> systemAbilityManager =
316 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
317 if (systemAbilityManager == nullptr) {
318 IMSA_HILOGI("InputMethodControllerTest, system ability manager is nullptr");
319 return;
320 }
321 auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, "");
322 if (systemAbility == nullptr) {
323 IMSA_HILOGI("InputMethodControllerTest, system ability is nullptr");
324 return;
325 }
326 deathRecipient_ = new (std::nothrow) InputDeathRecipient();
327 if (deathRecipient_ == nullptr) {
328 IMSA_HILOGE("InputMethodControllerTest, new death recipient failed");
329 return;
330 }
331 deathRecipient_->SetDeathRecipient([](const wptr<IRemoteObject> &remote) { OnRemoteSaDied(remote); });
332 if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) {
333 IMSA_HILOGE("InputMethodControllerTest, failed to add death recipient.");
334 return;
335 }
336 }
337
OnRemoteSaDied(const wptr<IRemoteObject> & remote)338 void InputMethodControllerTest::OnRemoteSaDied(const wptr<IRemoteObject> &remote)
339 {
340 IMSA_HILOGI("InputMethodControllerTest::OnRemoteSaDied");
341 onRemoteSaDiedCv_.notify_one();
342 }
343
WaitRemoteDiedCallback()344 bool InputMethodControllerTest::WaitRemoteDiedCallback()
345 {
346 IMSA_HILOGI("InputMethodControllerTest::WaitRemoteDiedCallback");
347 std::unique_lock<std::mutex> lock(onRemoteSaDiedMutex_);
348 return onRemoteSaDiedCv_.wait_for(lock, std::chrono::seconds(WAIT_SA_DIE_TIME_OUT)) != std::cv_status::timeout;
349 }
350
CheckProxyObject()351 void InputMethodControllerTest::CheckProxyObject()
352 {
353 for (uint32_t retryTimes = 0; retryTimes < RETRY_TIMES; ++retryTimes) {
354 IMSA_HILOGI("times = %{public}d", retryTimes);
355 sptr<ISystemAbilityManager> systemAbilityManager =
356 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
357 if (systemAbilityManager == nullptr) {
358 IMSA_HILOGI("system ability manager is nullptr");
359 continue;
360 }
361 auto systemAbility = systemAbilityManager->CheckSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID);
362 if (systemAbility != nullptr) {
363 IMSA_HILOGI("CheckProxyObject success!");
364 break;
365 }
366 usleep(RETRY_TIME);
367 }
368 }
369
CheckKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent)370 void InputMethodControllerTest::CheckKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent)
371 {
372 ASSERT_NE(keyEvent, nullptr);
373 bool ret = keyEvent->GetKeyCode() == keyEvent_->GetKeyCode();
374 EXPECT_TRUE(ret);
375 ret = keyEvent->GetKeyAction() == keyEvent_->GetKeyAction();
376 EXPECT_TRUE(ret);
377 ret = keyEvent->GetKeyIntention() == keyEvent_->GetKeyIntention();
378 EXPECT_TRUE(ret);
379 // check function key state
380 ret = keyEvent->GetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY)
381 == keyEvent_->GetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY);
382 EXPECT_TRUE(ret);
383 ret = keyEvent->GetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY)
384 == keyEvent_->GetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY);
385 EXPECT_TRUE(ret);
386 ret = keyEvent->GetFunctionKey(MMI::KeyEvent::SCROLL_LOCK_FUNCTION_KEY)
387 == keyEvent_->GetFunctionKey(MMI::KeyEvent::SCROLL_LOCK_FUNCTION_KEY);
388 EXPECT_TRUE(ret);
389 // check KeyItem
390 ret = keyEvent->GetKeyItems().size() == keyEvent_->GetKeyItems().size();
391 EXPECT_TRUE(ret);
392 ret = keyEvent->GetKeyItem()->GetKeyCode() == keyEvent_->GetKeyItem()->GetKeyCode();
393 EXPECT_TRUE(ret);
394 ret = keyEvent->GetKeyItem()->GetDownTime() == keyEvent_->GetKeyItem()->GetDownTime();
395 EXPECT_TRUE(ret);
396 ret = keyEvent->GetKeyItem()->GetDeviceId() == keyEvent_->GetKeyItem()->GetDeviceId();
397 EXPECT_TRUE(ret);
398 ret = keyEvent->GetKeyItem()->IsPressed() == keyEvent_->GetKeyItem()->IsPressed();
399 EXPECT_TRUE(ret);
400 ret = keyEvent->GetKeyItem()->GetUnicode() == keyEvent_->GetKeyItem()->GetUnicode();
401 EXPECT_TRUE(ret);
402 }
403
WaitKeyboardStatusCallback(bool keyboardState)404 void InputMethodControllerTest::WaitKeyboardStatusCallback(bool keyboardState)
405 {
406 std::unique_lock<std::mutex> lock(InputMethodEngineListenerImpl::imeListenerMutex_);
407 InputMethodEngineListenerImpl::imeListenerCv_.wait_for(lock,
408 std::chrono::seconds(InputMethodControllerTest::DELAY_TIME),
409 [keyboardState] { return InputMethodEngineListenerImpl::keyboardState_ == keyboardState; });
410 }
411
TriggerConfigurationChangeCallback(Configuration & info)412 void InputMethodControllerTest::TriggerConfigurationChangeCallback(Configuration &info)
413 {
414 textConfigHandler_->PostTask(
415 [info]() { inputMethodController_->OnConfigurationChange(info); }, InputMethodControllerTest::TASK_DELAY_TIME);
416 {
417 std::unique_lock<std::mutex> lock(InputMethodControllerTest::keyboardListenerMutex_);
418 InputMethodControllerTest::keyboardListenerCv_.wait_for(
419 lock, std::chrono::seconds(InputMethodControllerTest::DELAY_TIME), [&info] {
420 return (static_cast<OHOS::MiscServices::TextInputType>(
421 InputMethodControllerTest::inputAttribute_.inputPattern)
422 == info.GetTextInputType())
423 && (static_cast<OHOS::MiscServices::EnterKeyType>(
424 InputMethodControllerTest::inputAttribute_.enterKeyType)
425 == info.GetEnterKeyType());
426 });
427 }
428 }
429
TriggerCursorUpdateCallback(CursorInfo & info)430 void InputMethodControllerTest::TriggerCursorUpdateCallback(CursorInfo &info)
431 {
432 textConfigHandler_->PostTask(
433 [info]() { inputMethodController_->OnCursorUpdate(info); }, InputMethodControllerTest::TASK_DELAY_TIME);
434 {
435 std::unique_lock<std::mutex> lock(InputMethodControllerTest::keyboardListenerMutex_);
436 InputMethodControllerTest::keyboardListenerCv_.wait_for(lock,
437 std::chrono::seconds(InputMethodControllerTest::DELAY_TIME),
438 [&info] { return InputMethodControllerTest::cursorInfo_ == info; });
439 }
440 }
441
TriggerSelectionChangeCallback(std::u16string & text,int start,int end)442 void InputMethodControllerTest::TriggerSelectionChangeCallback(std::u16string &text, int start, int end)
443 {
444 textConfigHandler_->PostTask([text, start, end]() { inputMethodController_->OnSelectionChange(text, start, end); },
445 InputMethodControllerTest::TASK_DELAY_TIME);
446 {
447 std::unique_lock<std::mutex> lock(InputMethodControllerTest::keyboardListenerMutex_);
448 InputMethodControllerTest::keyboardListenerCv_.wait_for(lock,
449 std::chrono::seconds(InputMethodControllerTest::DELAY_TIME),
450 [&text] { return InputMethodControllerTest::text_ == Str16ToStr8(text); });
451 }
452 }
453
CheckTextConfig(const TextConfig & config)454 void InputMethodControllerTest::CheckTextConfig(const TextConfig &config)
455 {
456 EXPECT_EQ(imeListener_->windowId_, config.windowId);
457 EXPECT_EQ(cursorInfo_.left, config.cursorInfo.left);
458 EXPECT_EQ(cursorInfo_.top, config.cursorInfo.top);
459 EXPECT_EQ(cursorInfo_.height, config.cursorInfo.height);
460 EXPECT_EQ(newBegin_, config.range.start);
461 EXPECT_EQ(newEnd_, config.range.end);
462 EXPECT_EQ(inputAttribute_.inputPattern, config.inputAttribute.inputPattern);
463 EXPECT_EQ(inputAttribute_.enterKeyType, config.inputAttribute.enterKeyType);
464 }
465
DispatchKeyEventCallback(std::shared_ptr<MMI::KeyEvent> & keyEvent,bool isConsumed)466 void InputMethodControllerTest::DispatchKeyEventCallback(std::shared_ptr<MMI::KeyEvent> &keyEvent, bool isConsumed)
467 {
468 consumeResult_ = isConsumed;
469 keyEventCv_.notify_one();
470 }
471
WaitKeyEventCallback()472 bool InputMethodControllerTest::WaitKeyEventCallback()
473 {
474 std::unique_lock<std::mutex> lock(keyEventLock_);
475 keyEventCv_.wait_for(lock, std::chrono::seconds(DELAY_TIME), [] { return consumeResult_; });
476 return consumeResult_;
477 }
478
479 /**
480 * @tc.name: testIMCAttach001
481 * @tc.desc: IMC Attach.
482 * @tc.type: FUNC
483 * @tc.require:
484 */
485 HWTEST_F(InputMethodControllerTest, testIMCAttach001, TestSize.Level0)
486 {
487 IMSA_HILOGD("IMC testIMCAttach001 Test START");
488 imeListener_->isInputStart_ = false;
489 TextListener::ResetParam();
490 inputMethodController_->Attach(textListener_, false);
491 inputMethodController_->Attach(textListener_);
492 inputMethodController_->Attach(textListener_, true);
493 EXPECT_TRUE(TextListener::WaitSendKeyboardStatusCallback(KeyboardStatus::SHOW));
494 EXPECT_TRUE(imeListener_->isInputStart_ && imeListener_->keyboardState_);
495 }
496
497 /**
498 * @tc.name: testIMCAttach002
499 * @tc.desc: IMC Attach.
500 * @tc.type: FUNC
501 * @tc.require:
502 */
503 HWTEST_F(InputMethodControllerTest, testIMCAttach002, TestSize.Level0)
504 {
505 IMSA_HILOGD("IMC testIMCAttach002 Test START");
506 TextListener::ResetParam();
507 CursorInfo cursorInfo = { 1, 1, 1, 1 };
508 Range selectionRange = { 1, 2 };
509 InputAttribute attribute = { 1, 1 };
510 uint32_t windowId = 10;
511 TextConfig textConfig = {
512 .inputAttribute = attribute, .cursorInfo = cursorInfo, .range = selectionRange, .windowId = windowId
513 };
514
515 inputMethodController_->Attach(textListener_, true, textConfig);
516 InputMethodControllerTest::CheckTextConfig(textConfig);
517
518 TextListener::ResetParam();
519 cursorInfo = { 2, 2, 2, 2 };
520 selectionRange = { 3, 4 };
521 attribute = { 2, 2 };
522 windowId = 11;
523 textConfig = {
524 .inputAttribute = attribute, .cursorInfo = cursorInfo, .range = selectionRange, .windowId = windowId
525 };
526 inputMethodController_->Attach(textListener_, true, textConfig);
527 InputMethodControllerTest::CheckTextConfig(textConfig);
528 }
529
530 /**
531 * @tc.name: testIMCSetCallingWindow
532 * @tc.desc: IMC SetCallingWindow.
533 * @tc.type: FUNC
534 * @tc.require:
535 */
536 HWTEST_F(InputMethodControllerTest, testIMCSetCallingWindow, TestSize.Level0)
537 {
538 IMSA_HILOGD("IMC SetCallingWindow Test START");
539 auto ret = inputMethodController_->Attach(textListener_);
540 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
541 uint32_t windowId = 3;
542 ret = inputMethodController_->SetCallingWindow(windowId);
543 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
544 EXPECT_EQ(windowId, imeListener_->windowId_);
545 }
546
547 /**
548 * @tc.name: testGetIMSAProxy
549 * @tc.desc: Get Imsa Proxy.
550 * @tc.type: FUNC
551 */
552 HWTEST_F(InputMethodControllerTest, testGetIMSAProxy, TestSize.Level0)
553 {
554 auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
555 ASSERT_NE(systemAbilityManager, nullptr);
556 auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, "");
557 EXPECT_TRUE(systemAbility != nullptr);
558 }
559
560 /**
561 * @tc.name: testWriteReadIInputDataChannel
562 * @tc.desc: Checkout IInputDataChannel.
563 * @tc.type: FUNC
564 */
565 HWTEST_F(InputMethodControllerTest, testWriteReadIInputDataChannel, TestSize.Level0)
566 {
567 sptr<InputDataChannelStub> mInputDataChannel = new InputDataChannelStub();
568 MessageParcel data;
569 auto ret = data.WriteRemoteObject(mInputDataChannel->AsObject());
570 EXPECT_TRUE(ret);
571 auto remoteObject = data.ReadRemoteObject();
572 sptr<IInputDataChannel> iface = iface_cast<IInputDataChannel>(remoteObject);
573 EXPECT_TRUE(iface != nullptr);
574 }
575
576 /**
577 * @tc.name: testIMCBindToIMSA
578 * @tc.desc: Bind IMSA.
579 * @tc.type: FUNC
580 */
581 HWTEST_F(InputMethodControllerTest, testIMCBindToIMSA, TestSize.Level0)
582 {
583 sptr<InputClientStub> mClient = new InputClientStub();
584 MessageParcel data;
585 auto ret = data.WriteRemoteObject(mClient->AsObject());
586 EXPECT_TRUE(ret);
587 auto remoteObject = data.ReadRemoteObject();
588 sptr<IInputClient> iface = iface_cast<IInputClient>(remoteObject);
589 EXPECT_TRUE(iface != nullptr);
590 }
591
592 /**
593 * @tc.name: testIMCDispatchKeyEvent001
594 * @tc.desc: test IMC DispatchKeyEvent with 'keyDown/KeyUP'.
595 * @tc.type: FUNC
596 * @tc.require:
597 */
598 HWTEST_F(InputMethodControllerTest, testIMCDispatchKeyEvent001, TestSize.Level0)
599 {
600 IMSA_HILOGI("IMC testIMCDispatchKeyEvent001 Test START");
601 doesKeyEventConsume_ = true;
602 doesFUllKeyEventConsume_ = false;
603 blockKeyEvent_.Clear(nullptr);
604 auto res = inputMethodController_->Attach(textListener_);
605 EXPECT_EQ(res, ErrorCode::NO_ERROR);
606
607 bool ret = inputMethodController_->DispatchKeyEvent(keyEvent_, DispatchKeyEventCallback);
608 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
609
610 EXPECT_TRUE(WaitKeyEventCallback());
611
612 auto keyEvent = blockKeyEvent_.GetValue();
613 ASSERT_NE(keyEvent, nullptr);
614 EXPECT_EQ(keyEvent->GetKeyCode(), keyEvent_->GetKeyCode());
615 EXPECT_EQ(keyEvent->GetKeyAction(), keyEvent_->GetKeyAction());
616
617 doesKeyEventConsume_ = false;
618 ret = inputMethodController_->DispatchKeyEvent(keyEvent_, DispatchKeyEventCallback);
619 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
620
621 EXPECT_TRUE(!WaitKeyEventCallback());
622 }
623
624 /**
625 * @tc.name: testIMCDispatchKeyEvent002
626 * @tc.desc: test IMC DispatchKeyEvent with 'keyEvent'.
627 * @tc.type: FUNC
628 * @tc.require:
629 */
630 HWTEST_F(InputMethodControllerTest, testIMCDispatchKeyEvent002, TestSize.Level0)
631 {
632 IMSA_HILOGI("IMC testIMCDispatchKeyEvent002 Test START");
633 doesKeyEventConsume_ = false;
634 doesFUllKeyEventConsume_ = true;
635 blockFullKeyEvent_.Clear(nullptr);
636 int32_t ret = inputMethodController_->DispatchKeyEvent(
__anon6e7e40f40a02(std::shared_ptr<MMI::KeyEvent> &keyEvent, bool isConsumed) 637 keyEvent_, [](std::shared_ptr<MMI::KeyEvent> &keyEvent, bool isConsumed) {});
638 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
639 auto keyEvent = blockFullKeyEvent_.GetValue();
640 ASSERT_NE(keyEvent, nullptr);
641 CheckKeyEvent(keyEvent);
642 }
643
644 /**
645 * @tc.name: testIMCDispatchKeyEvent003
646 * @tc.desc: test IMC DispatchKeyEvent with 'keyDown/KeyUP' and 'keyEvent'.
647 * @tc.type: FUNC
648 * @tc.require:
649 */
650 HWTEST_F(InputMethodControllerTest, testIMCDispatchKeyEvent003, TestSize.Level0)
651 {
652 IMSA_HILOGI("IMC testIMCDispatchKeyEvent003 Test START");
653 doesKeyEventConsume_ = true;
654 doesFUllKeyEventConsume_ = true;
655 blockKeyEvent_.Clear(nullptr);
656 blockFullKeyEvent_.Clear(nullptr);
657 int32_t ret = inputMethodController_->DispatchKeyEvent(
__anon6e7e40f40b02(std::shared_ptr<MMI::KeyEvent> &keyEvent, bool isConsumed) 658 keyEvent_, [](std::shared_ptr<MMI::KeyEvent> &keyEvent, bool isConsumed) {});
659 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
660 auto keyEvent = blockKeyEvent_.GetValue();
661 auto keyFullEvent = blockFullKeyEvent_.GetValue();
662 ASSERT_NE(keyEvent, nullptr);
663 EXPECT_EQ(keyEvent->GetKeyCode(), keyEvent_->GetKeyCode());
664 EXPECT_EQ(keyEvent->GetKeyAction(), keyEvent_->GetKeyAction());
665 ASSERT_NE(keyFullEvent, nullptr);
666 CheckKeyEvent(keyFullEvent);
667 }
668
669 /**
670 * @tc.name: testIMCOnCursorUpdate01
671 * @tc.desc: Test update cursorInfo, call 'OnCursorUpdate' twice, if cursorInfo is the same,
672 * the second time will not get callback.
673 * @tc.type: FUNC
674 * @tc.require:
675 * @tc.author: Zhaolinglan
676 */
677 HWTEST_F(InputMethodControllerTest, testIMCOnCursorUpdate01, TestSize.Level0)
678 {
679 IMSA_HILOGI("IMC testIMCOnCursorUpdate01 Test START");
680 auto ret = inputMethodController_->Attach(textListener_, false);
681 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
682 CursorInfo info = { 1, 3, 0, 5 };
683 InputMethodControllerTest::TriggerCursorUpdateCallback(info);
684 EXPECT_EQ(InputMethodControllerTest::cursorInfo_, info);
685
686 InputMethodControllerTest::cursorInfo_ = {};
687 InputMethodControllerTest::TriggerCursorUpdateCallback(info);
688 EXPECT_FALSE(InputMethodControllerTest::cursorInfo_ == info);
689 }
690
691 /**
692 * @tc.name: testIMCOnCursorUpdate02
693 * @tc.desc: Test update cursorInfo, 'Attach'->'OnCursorUpdate'->'Close'->'Attach'->'OnCursorUpdate',
694 * it will get callback two time.
695 * @tc.type: FUNC
696 * @tc.require:
697 * @tc.author: Zhaolinglan
698 */
699 HWTEST_F(InputMethodControllerTest, testIMCOnCursorUpdate02, TestSize.Level0)
700 {
701 IMSA_HILOGI("IMC testIMCOnCursorUpdate02 Test START");
702 auto ret = inputMethodController_->Attach(textListener_, false);
703 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
704 CursorInfo info = { 2, 4, 0, 6 };
705 InputMethodControllerTest::TriggerCursorUpdateCallback(info);
706 EXPECT_EQ(InputMethodControllerTest::cursorInfo_, info);
707
708 InputMethodControllerTest::cursorInfo_ = {};
709 ret = InputMethodControllerTest::inputMethodController_->Close();
710 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
711 ret = inputMethodController_->Attach(textListener_, false);
712 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
713 InputMethodControllerTest::TriggerCursorUpdateCallback(info);
714 EXPECT_EQ(InputMethodControllerTest::cursorInfo_, info);
715 }
716
717 /**
718 * @tc.name: testIMCOnSelectionChange01
719 * @tc.desc: Test change selection, call 'OnSelectionChange' twice, if selection is the same,
720 * the second time will not get callback.
721 * @tc.type: FUNC
722 * @tc.require:
723 * @tc.author: Zhaolinglan
724 */
725 HWTEST_F(InputMethodControllerTest, testIMCOnSelectionChange01, TestSize.Level0)
726 {
727 IMSA_HILOGI("IMC testIMCOnSelectionChange01 Test START");
728 auto ret = inputMethodController_->Attach(textListener_, false);
729 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
730 std::u16string text = Str8ToStr16("testSelect");
731 int start = 1;
732 int end = 2;
733 InputMethodControllerTest::TriggerSelectionChangeCallback(text, start, end);
734 EXPECT_EQ(InputMethodControllerTest::text_, Str16ToStr8(text));
735
736 InputMethodControllerTest::text_ = "";
737 InputMethodControllerTest::TriggerSelectionChangeCallback(text, start, end);
738 EXPECT_NE(InputMethodControllerTest::text_, Str16ToStr8(text));
739 }
740
741 /**
742 * @tc.name: testIMCOnSelectionChange02
743 * @tc.desc: Test change selection, 'Attach'->'OnSelectionChange'->'Close'->'Attach'->'OnSelectionChange',
744 * it will get callback two time.
745 * @tc.type: FUNC
746 * @tc.require:
747 * @tc.author: Zhaolinglan
748 */
749 HWTEST_F(InputMethodControllerTest, testIMCOnSelectionChange02, TestSize.Level0)
750 {
751 IMSA_HILOGI("IMC testIMCOnSelectionChange02 Test START");
752 auto ret = inputMethodController_->Attach(textListener_, false);
753 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
754 std::u16string text = Str8ToStr16("testSelect2");
755 int start = 1;
756 int end = 2;
757 InputMethodControllerTest::TriggerSelectionChangeCallback(text, start, end);
758 EXPECT_EQ(InputMethodControllerTest::text_, Str16ToStr8(text));
759
760 InputMethodControllerTest::text_ = "";
761 InputMethodControllerTest::inputMethodController_->Close();
762 inputMethodController_->Attach(textListener_, false);
763 InputMethodControllerTest::TriggerSelectionChangeCallback(text, start, end);
764 EXPECT_EQ(InputMethodControllerTest::text_, Str16ToStr8(text));
765 }
766
767 /**
768 * @tc.name: testShowTextInput
769 * @tc.desc: IMC ShowTextInput
770 * @tc.type: FUNC
771 */
772 HWTEST_F(InputMethodControllerTest, testShowTextInput, TestSize.Level0)
773 {
774 IMSA_HILOGI("IMC ShowTextInput Test START");
775 TextListener::ResetParam();
776 inputMethodController_->ShowTextInput();
777 EXPECT_TRUE(TextListener::WaitSendKeyboardStatusCallback(KeyboardStatus::SHOW));
778 }
779
780 /**
781 * @tc.name: testShowSoftKeyboard
782 * @tc.desc: IMC ShowSoftKeyboard
783 * @tc.type: FUNC
784 */
785 HWTEST_F(InputMethodControllerTest, testShowSoftKeyboard, TestSize.Level0)
786 {
787 IMSA_HILOGI("IMC ShowSoftKeyboard Test START");
788 TokenScope scope(InputMethodControllerTest::permissionTokenId_);
789 imeListener_->keyboardState_ = false;
790 TextListener::ResetParam();
791 int32_t ret = inputMethodController_->ShowSoftKeyboard();
792 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
793 EXPECT_TRUE(imeListener_->keyboardState_ && TextListener::WaitSendKeyboardStatusCallback(KeyboardStatus::SHOW));
794 }
795
796 /**
797 * @tc.name: testShowCurrentInput
798 * @tc.desc: IMC ShowCurrentInput
799 * @tc.type: FUNC
800 */
801 HWTEST_F(InputMethodControllerTest, testShowCurrentInput, TestSize.Level0)
802 {
803 IMSA_HILOGI("IMC ShowCurrentInput Test START");
804 imeListener_->keyboardState_ = false;
805 TextListener::ResetParam();
806 int32_t ret = inputMethodController_->ShowCurrentInput();
807 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
808 EXPECT_TRUE(imeListener_->keyboardState_ && TextListener::WaitSendKeyboardStatusCallback(KeyboardStatus::SHOW));
809 }
810
811 /**
812 * @tc.name: testIMCGetEnterKeyType
813 * @tc.desc: IMC testGetEnterKeyType.
814 * @tc.type: FUNC
815 * @tc.require:
816 */
817 HWTEST_F(InputMethodControllerTest, testIMCGetEnterKeyType, TestSize.Level0)
818 {
819 IMSA_HILOGI("IMC GetEnterKeyType Test START");
820 int32_t keyType;
821 inputMethodController_->GetEnterKeyType(keyType);
822 EXPECT_TRUE(keyType >= static_cast<int32_t>(EnterKeyType::UNSPECIFIED)
823 && keyType <= static_cast<int32_t>(EnterKeyType::PREVIOUS));
824 }
825
826 /**
827 * @tc.name: testIMCGetInputPattern
828 * @tc.desc: IMC testGetInputPattern.
829 * @tc.type: FUNC
830 * @tc.require:
831 */
832 HWTEST_F(InputMethodControllerTest, testIMCGetInputPattern, TestSize.Level0)
833 {
834 IMSA_HILOGI("IMC GetInputPattern Test START");
835 int32_t inputPattern;
836 inputMethodController_->GetInputPattern(inputPattern);
837 EXPECT_TRUE(inputPattern >= static_cast<int32_t>(TextInputType::NONE)
838 && inputPattern <= static_cast<int32_t>(TextInputType::VISIBLE_PASSWORD));
839 }
840
841 /**
842 * @tc.name: testOnEditorAttributeChanged
843 * @tc.desc: IMC testOnEditorAttributeChanged.
844 * @tc.type: FUNC
845 * @tc.require:
846 */
847 HWTEST_F(InputMethodControllerTest, testOnEditorAttributeChanged, TestSize.Level0)
848 {
849 IMSA_HILOGI("IMC testOnEditorAttributeChanged Test START");
850 auto ret = inputMethodController_->Attach(textListener_, false);
851 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
852 Configuration info;
853 info.SetEnterKeyType(EnterKeyType::GO);
854 info.SetTextInputType(TextInputType::NUMBER);
855 InputMethodControllerTest::TriggerConfigurationChangeCallback(info);
856 EXPECT_EQ(InputMethodControllerTest::inputAttribute_.inputPattern, static_cast<int32_t>(info.GetTextInputType()));
857 EXPECT_EQ(InputMethodControllerTest::inputAttribute_.enterKeyType, static_cast<int32_t>(info.GetEnterKeyType()));
858 }
859
860 /**
861 * @tc.name: testHideSoftKeyboard
862 * @tc.desc: IMC HideSoftKeyboard
863 * @tc.type: FUNC
864 */
865 HWTEST_F(InputMethodControllerTest, testHideSoftKeyboard, TestSize.Level0)
866 {
867 IMSA_HILOGI("IMC HideSoftKeyboard Test START");
868 TokenScope scope(InputMethodControllerTest::permissionTokenId_);
869 imeListener_->keyboardState_ = true;
870 TextListener::ResetParam();
871 int32_t ret = inputMethodController_->HideSoftKeyboard();
872 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
873 EXPECT_TRUE(!imeListener_->keyboardState_ && TextListener::WaitSendKeyboardStatusCallback(KeyboardStatus::HIDE));
874 }
875
876 /**
877 * @tc.name: testIMCHideCurrentInput
878 * @tc.desc: IMC HideCurrentInput.
879 * @tc.type: FUNC
880 * @tc.require:
881 */
882 HWTEST_F(InputMethodControllerTest, testIMCHideCurrentInput, TestSize.Level0)
883 {
884 IMSA_HILOGI("IMC HideCurrentInput Test START");
885 imeListener_->keyboardState_ = true;
886 TextListener::ResetParam();
887 int32_t ret = inputMethodController_->HideCurrentInput();
888 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
889 EXPECT_TRUE(!imeListener_->keyboardState_ && TextListener::WaitSendKeyboardStatusCallback(KeyboardStatus::HIDE));
890 }
891
892 /**
893 * @tc.name: testIMCInputStopSession
894 * @tc.desc: IMC testInputStopSession.
895 * @tc.type: FUNC
896 * @tc.require: issueI5U8FZ
897 * @tc.author: Hollokin
898 */
899 HWTEST_F(InputMethodControllerTest, testIMCInputStopSession, TestSize.Level0)
900 {
901 IMSA_HILOGI("IMC StopInputSession Test START");
902 imeListener_->keyboardState_ = true;
903 int32_t ret = inputMethodController_->StopInputSession();
904 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
905 WaitKeyboardStatusCallback(false);
906 EXPECT_TRUE(!imeListener_->keyboardState_);
907 }
908
909 /**
910 * @tc.name: testIMCHideTextInput.
911 * @tc.desc: IMC testHideTextInput.
912 * @tc.type: FUNC
913 */
914 HWTEST_F(InputMethodControllerTest, testIMCHideTextInput, TestSize.Level0)
915 {
916 IMSA_HILOGI("IMC HideTextInput Test START");
917 imeListener_->keyboardState_ = true;
918 inputMethodController_->HideTextInput();
919 WaitKeyboardStatusCallback(false);
920 EXPECT_TRUE(!imeListener_->keyboardState_);
921 }
922
923 /**
924 * @tc.name: testIMCRequestShowInput.
925 * @tc.desc: IMC testIMCRequestShowInput.
926 * @tc.type: FUNC
927 */
928 HWTEST_F(InputMethodControllerTest, testIMCRequestShowInput, TestSize.Level0)
929 {
930 IMSA_HILOGI("IMC testIMCRequestShowInput Test START");
931 imeListener_->keyboardState_ = false;
932 int32_t ret = InputMethodControllerTest::inputMethodController_->RequestShowInput();
933 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
934 EXPECT_TRUE(imeListener_->keyboardState_);
935 }
936
937 /**
938 * @tc.name: testIMCRequestHideInput.
939 * @tc.desc: IMC testIMCRequestHideInput.
940 * @tc.type: FUNC
941 */
942 HWTEST_F(InputMethodControllerTest, testIMCRequestHideInput, TestSize.Level0)
943 {
944 IMSA_HILOGI("IMC testIMCRequestHideInput Test START");
945 imeListener_->keyboardState_ = true;
946 int32_t ret = InputMethodControllerTest::inputMethodController_->RequestHideInput();
947 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
948 EXPECT_FALSE(imeListener_->keyboardState_);
949 }
950
951 /**
952 * @tc.name: testSetControllerListener
953 * @tc.desc: IMC SetControllerListener
954 * @tc.type: FUNC
955 */
956 HWTEST_F(InputMethodControllerTest, testSetControllerListener, TestSize.Level0)
957 {
958 IMSA_HILOGI("IMC SetControllerListener Test START");
959 inputMethodController_->SetControllerListener(controllerListener_);
960
961 int32_t ret = inputMethodController_->Attach(textListener_, false);
962 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
963 SelectListenerMock::start_ = 0;
964 SelectListenerMock::end_ = 0;
965 inputMethodAbility_->SelectByRange(1, 2);
966 SelectListenerMock::WaitSelectListenerCallback();
967 EXPECT_EQ(SelectListenerMock::start_, 1);
968 EXPECT_EQ(SelectListenerMock::end_, 2);
969
970 SelectListenerMock::direction_ = 0;
971 inputMethodAbility_->SelectByMovement(static_cast<int32_t>(Direction::UP));
972 SelectListenerMock::WaitSelectListenerCallback();
973 EXPECT_EQ(SelectListenerMock::direction_, static_cast<int32_t>(Direction::UP));
974
975 SelectListenerMock::direction_ = 0;
976 inputMethodAbility_->SelectByMovement(static_cast<int32_t>(Direction::DOWN));
977 SelectListenerMock::WaitSelectListenerCallback();
978 EXPECT_EQ(SelectListenerMock::direction_, static_cast<int32_t>(Direction::DOWN));
979
980 SelectListenerMock::direction_ = 0;
981 inputMethodAbility_->SelectByMovement(static_cast<int32_t>(Direction::LEFT));
982 SelectListenerMock::WaitSelectListenerCallback();
983 EXPECT_EQ(SelectListenerMock::direction_, static_cast<int32_t>(Direction::LEFT));
984
985 SelectListenerMock::direction_ = 0;
986 inputMethodAbility_->SelectByMovement(static_cast<int32_t>(Direction::RIGHT));
987 SelectListenerMock::WaitSelectListenerCallback();
988 EXPECT_EQ(SelectListenerMock::direction_, static_cast<int32_t>(Direction::RIGHT));
989 }
990
991 /**
992 * @tc.name: testWasAttached
993 * @tc.desc: IMC WasAttached
994 * @tc.type: FUNC
995 */
996 HWTEST_F(InputMethodControllerTest, testWasAttached, TestSize.Level0)
997 {
998 IMSA_HILOGI("IMC WasAttached Test START");
999 inputMethodController_->Close();
1000 bool result = inputMethodController_->WasAttached();
1001 EXPECT_FALSE(result);
1002 int32_t ret = inputMethodController_->Attach(textListener_, false);
1003 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1004 result = inputMethodController_->WasAttached();
1005 EXPECT_TRUE(result);
1006 inputMethodController_->Close();
1007 }
1008
1009 /**
1010 * @tc.name: testGetDefaultInputMethod
1011 * @tc.desc: IMC GetDefaultInputMethod
1012 * @tc.type: FUNC
1013 */
1014 HWTEST_F(InputMethodControllerTest, testGetDefaultInputMethod, TestSize.Level0)
1015 {
1016 IMSA_HILOGI("IMC testGetDefaultInputMethod Test START");
1017 std::shared_ptr<Property> property;
1018 int32_t ret = inputMethodController_->GetDefaultInputMethod(property);
1019 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1020 EXPECT_FALSE(property->name.empty());
1021 }
1022
1023 /**
1024 * @tc.name: testGetSystemInputMethodConfig
1025 * @tc.desc: IMC GetSystemInputMethodConfig
1026 * @tc.type: FUNC
1027 */
1028 HWTEST_F(InputMethodControllerTest, GetSystemInputMethodConfig, TestSize.Level0)
1029 {
1030 IMSA_HILOGI("IMC GetSystemInputMethodConfig Test START");
1031 OHOS::AppExecFwk::ElementName inputMethodConfig;
1032 int32_t ret = inputMethodController_->GetInputMethodConfig(inputMethodConfig);
1033 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1034 EXPECT_GE(inputMethodConfig.GetBundleName().length(), 0);
1035 EXPECT_GE(inputMethodConfig.GetAbilityName().length(), 0);
1036 }
1037
1038 /**
1039 * @tc.name: testWithoutEditableState
1040 * @tc.desc: IMC testWithoutEditableState
1041 * @tc.type: FUNC
1042 * @tc.require:
1043 */
1044 HWTEST_F(InputMethodControllerTest, testWithoutEditableState, TestSize.Level0)
1045 {
1046 IMSA_HILOGI("IMC WithouteEditableState Test START");
1047 auto ret = inputMethodController_->Attach(textListener_, false);
1048 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1049 ret = inputMethodController_->HideTextInput();
1050 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1051
1052 int32_t deleteForwardLength = 1;
1053 ret = inputMethodAbility_->DeleteForward(deleteForwardLength);
1054 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1055 EXPECT_NE(TextListener::deleteForwardLength_, deleteForwardLength);
1056
1057 int32_t deleteBackwardLength = 2;
1058 ret = inputMethodAbility_->DeleteBackward(deleteBackwardLength);
1059 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1060 EXPECT_NE(TextListener::deleteBackwardLength_, deleteBackwardLength);
1061
1062 std::string insertText = "t";
1063 ret = inputMethodAbility_->InsertText(insertText);
1064 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1065 EXPECT_NE(TextListener::insertText_, Str8ToStr16(insertText));
1066
1067 constexpr int32_t funcKey = 1;
1068 ret = inputMethodAbility_->SendFunctionKey(funcKey);
1069 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1070 EXPECT_NE(TextListener::key_, funcKey);
1071
1072 constexpr int32_t keyCode = 4;
1073 ret = inputMethodAbility_->MoveCursor(keyCode);
1074 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1075 EXPECT_NE(TextListener::direction_, keyCode);
1076 }
1077
1078 /**
1079 * @tc.name: testIsInputTypeSupported
1080 * @tc.desc: IsInputTypeSupported
1081 * @tc.type: FUNC
1082 * @tc.require:
1083 * @tc.author: chenyu
1084 */
1085 HWTEST_F(InputMethodControllerTest, testIsInputTypeSupported, TestSize.Level0)
1086 {
1087 IMSA_HILOGI("IMC testIsInputTypeSupported Test START");
1088 auto ret = inputMethodController_->IsInputTypeSupported(InputType::NONE);
1089 EXPECT_FALSE(ret);
1090 }
1091
1092 /**
1093 * @tc.name: testStartInputType
1094 * @tc.desc: StartInputType
1095 * @tc.type: FUNC
1096 * @tc.require:
1097 * @tc.author: chenyu
1098 */
1099 HWTEST_F(InputMethodControllerTest, testStartInputType, TestSize.Level0)
1100 {
1101 IMSA_HILOGI("IMC testStartInputType Test START");
1102 auto ret = inputMethodController_->StartInputType(InputType::NONE);
1103 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1104 }
1105
1106 /**
1107 * @tc.name: testSendPrivateCommand_001
1108 * @tc.desc: IMC SendPrivateCommand without default ime
1109 * @tc.type: FUNC
1110 * @tc.require:
1111 * @tc.author: mashaoyin
1112 */
1113 HWTEST_F(InputMethodControllerTest, testSendPrivateCommand_001, TestSize.Level0)
1114 {
1115 IMSA_HILOGI("IMC testSendPrivateCommand_001 Test START");
1116 InputMethodEngineListenerImpl::ResetParam();
1117 auto ret = inputMethodController_->Attach(textListener_, false);
1118 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1119 std::unordered_map<std::string, PrivateDataValue> privateCommand;
1120 PrivateDataValue privateDataValue1 = std::string("stringValue");
1121 privateCommand.emplace("value1", privateDataValue1);
1122 ret = inputMethodController_->SendPrivateCommand(privateCommand);
1123 EXPECT_EQ(ret, ErrorCode::ERROR_NOT_DEFAULT_IME);
1124 inputMethodController_->Close();
1125 }
1126
1127 /**
1128 * @tc.name: testSendPrivateCommand_002
1129 * @tc.desc: SendPrivateCommand not bound, and empty privateCommand.
1130 * @tc.type: FUNC
1131 * @tc.require:
1132 * @tc.author: mashaoyin
1133 */
1134 HWTEST_F(InputMethodControllerTest, testSendPrivateCommand_002, TestSize.Level0)
1135 {
1136 IMSA_HILOGI("IMC testSendPrivateCommand_002 Test START");
1137 TokenScope scope(InputMethodControllerTest::defaultImeTokenId_);
1138 InputMethodEngineListenerImpl::ResetParam();
1139 inputMethodController_->Close();
1140 std::unordered_map<std::string, PrivateDataValue> privateCommand;
1141 auto ret = inputMethodController_->SendPrivateCommand(privateCommand);
1142 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_BOUND);
1143
1144 ret = inputMethodController_->Attach(textListener_, false);
1145 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1146 ret = inputMethodController_->SendPrivateCommand(privateCommand);
1147 EXPECT_EQ(ret, ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE);
1148 inputMethodController_->Close();
1149 }
1150
1151 /**
1152 * @tc.name: testSendPrivateCommand_003
1153 * @tc.desc: IMC SendPrivateCommand with normal private command.
1154 * @tc.type: FUNC
1155 * @tc.require:
1156 * @tc.author: mashaoyin
1157 */
1158 HWTEST_F(InputMethodControllerTest, testSendPrivateCommand_003, TestSize.Level0)
1159 {
1160 IMSA_HILOGI("IMC testSendPrivateCommand_003 Test START");
1161 TokenScope scope(InputMethodControllerTest::defaultImeTokenId_);
1162 InputMethodEngineListenerImpl::ResetParam();
1163 auto ret = inputMethodController_->Attach(textListener_, false);
1164 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1165 std::unordered_map<std::string, PrivateDataValue> privateCommand;
1166 PrivateDataValue privateDataValue1 = std::string("stringValue");
1167 privateCommand.emplace("value1", privateDataValue1);
1168 ret = inputMethodController_->SendPrivateCommand(privateCommand);
1169 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1170 inputMethodController_->Close();
1171 }
1172
1173 /**
1174 * @tc.name: testSendPrivateCommand_004
1175 * @tc.desc: IMC SendPrivateCommand with correct data format and all data type.
1176 * @tc.type: FUNC
1177 * @tc.require:
1178 * @tc.author: mashaoyin
1179 */
1180 HWTEST_F(InputMethodControllerTest, testSendPrivateCommand_004, TestSize.Level0)
1181 {
1182 IMSA_HILOGI("IMC testSendPrivateCommand_004 Test START");
1183 TokenScope scope(InputMethodControllerTest::defaultImeTokenId_);
1184 InputMethodEngineListenerImpl::ResetParam();
1185 auto ret = inputMethodController_->Attach(textListener_, false);
1186 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1187 std::unordered_map<std::string, PrivateDataValue> privateCommand;
1188 PrivateDataValue privateDataValue1 = std::string("stringValue");
1189 PrivateDataValue privateDataValue2 = true;
1190 PrivateDataValue privateDataValue3 = 100;
1191 privateCommand.emplace("value1", privateDataValue1);
1192 privateCommand.emplace("value2", privateDataValue2);
1193 privateCommand.emplace("value3", privateDataValue3);
1194 ret = inputMethodController_->SendPrivateCommand(privateCommand);
1195 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1196 EXPECT_TRUE(InputMethodEngineListenerImpl::WaitSendPrivateCommand(privateCommand));
1197 inputMethodController_->Close();
1198 }
1199
1200 /**
1201 * @tc.name: testSendPrivateCommand_005
1202 * @tc.desc: IMC SendPrivateCommand with more than 5 private command.
1203 * @tc.type: FUNC
1204 * @tc.require:
1205 * @tc.author: mashaoyin
1206 */
1207 HWTEST_F(InputMethodControllerTest, testSendPrivateCommand_005, TestSize.Level0)
1208 {
1209 IMSA_HILOGI("IMC testSendPrivateCommand_005 Test START");
1210 TokenScope scope(InputMethodControllerTest::defaultImeTokenId_);
1211 InputMethodEngineListenerImpl::ResetParam();
1212 auto ret = inputMethodController_->Attach(textListener_, false);
1213 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1214 std::unordered_map<std::string, PrivateDataValue> privateCommand;
1215 PrivateDataValue privateDataValue1 = std::string("stringValue");
1216 privateCommand.emplace("value1", privateDataValue1);
1217 privateCommand.emplace("value2", privateDataValue1);
1218 privateCommand.emplace("value3", privateDataValue1);
1219 privateCommand.emplace("value4", privateDataValue1);
1220 privateCommand.emplace("value5", privateDataValue1);
1221 privateCommand.emplace("value6", privateDataValue1);
1222 ret = inputMethodController_->SendPrivateCommand(privateCommand);
1223 EXPECT_EQ(ret, ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE);
1224 inputMethodController_->Close();
1225 }
1226
1227 /**
1228 * @tc.name: testSendPrivateCommand_006
1229 * @tc.desc: IMC SendPrivateCommand size is more than 32KB.
1230 * @tc.type: FUNC
1231 * @tc.require:
1232 * @tc.author: mashaoyin
1233 */
1234 HWTEST_F(InputMethodControllerTest, testSendPrivateCommand_006, TestSize.Level0)
1235 {
1236 IMSA_HILOGI("IMC testSendPrivateCommand_006 Test START");
1237 TokenScope scope(InputMethodControllerTest::defaultImeTokenId_);
1238 InputMethodEngineListenerImpl::ResetParam();
1239 std::unordered_map<std::string, PrivateDataValue> privateCommand;
1240 PrivateDataValue privateDataValue1 = std::string("stringValue");
1241 PrivateDataValue privateDataValue2 = true;
1242 PrivateDataValue privateDataValue3 = 100;
1243 privateCommand.emplace("value1", privateDataValue1);
1244 privateCommand.emplace("value2", privateDataValue2);
1245 privateCommand.emplace("value3", privateDataValue3);
1246 TextConfig textConfig;
1247 textConfig.privateCommand = privateCommand;
1248 textConfig.windowId = 1;
1249 auto ret = inputMethodController_->Attach(textListener_, false, textConfig);
1250 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1251 EXPECT_TRUE(InputMethodEngineListenerImpl::WaitSendPrivateCommand(privateCommand));
1252 inputMethodController_->Close();
1253 }
1254
1255 /**
1256 * @tc.name: testSendPrivateCommand_007
1257 * @tc.desc: IMC SendPrivateCommand with Attach.
1258 * @tc.type: FUNC
1259 * @tc.require:
1260 * @tc.author: mashaoyin
1261 */
1262 HWTEST_F(InputMethodControllerTest, testSendPrivateCommand_007, TestSize.Level0)
1263 {
1264 IMSA_HILOGI("IMC testSendPrivateCommand_007 Test START");
1265 TokenScope scope(InputMethodControllerTest::defaultImeTokenId_);
1266 TextListener::ResetParam();
1267 auto ret = inputMethodController_->Attach(textListener_, false);
1268 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1269 string str(32768, 'a');
1270 std::unordered_map<std::string, PrivateDataValue> privateCommand;
1271 PrivateDataValue privateDataValue1 = str;
1272 privateCommand.emplace("value1", privateDataValue1);
1273 ret = inputMethodController_->SendPrivateCommand(privateCommand);
1274 EXPECT_EQ(ret, ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE);
1275 inputMethodController_->Close();
1276 }
1277
1278 /**
1279 * @tc.name: testSendPrivateCommand_008
1280 * @tc.desc: IMA SendPrivateCommand total size is 32KB, 32KB - 1, 32KB + 1.
1281 * @tc.type: IMC
1282 * @tc.require:
1283 * @tc.author: mashaoyin
1284 */
1285 HWTEST_F(InputMethodControllerTest, testSendPrivateCommand_008, TestSize.Level0)
1286 {
1287 IMSA_HILOGI("IMC testSendPrivateCommand_008 Test START");
1288 auto ret = inputMethodController_->Attach(textListener_, false);
1289 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1290 TokenScope scope(InputMethodControllerTest::defaultImeTokenId_);
1291 TextListener::ResetParam();
1292 std::unordered_map<std::string, PrivateDataValue> privateCommand1{ { "v",
1293 string(PRIVATE_COMMAND_SIZE_MAX - 2, 'a') } };
1294 std::unordered_map<std::string, PrivateDataValue> privateCommand2{ { "v",
1295 string(PRIVATE_COMMAND_SIZE_MAX - 1, 'a') } };
1296 std::unordered_map<std::string, PrivateDataValue> privateCommand3{ { "v",
1297 string(PRIVATE_COMMAND_SIZE_MAX, 'a') } };
1298 ret = inputMethodController_->SendPrivateCommand(privateCommand1);
1299 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1300 ret = inputMethodController_->SendPrivateCommand(privateCommand2);
1301 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1302 ret = inputMethodController_->SendPrivateCommand(privateCommand3);
1303 EXPECT_EQ(ret, ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE);
1304 TddUtil::RestoreSelfTokenID();
1305 inputMethodController_->Close();
1306 }
1307
1308 /**
1309 * @tc.name: testOnRemoteDied
1310 * @tc.desc: IMC OnRemoteDied
1311 * @tc.type: FUNC
1312 */
1313 HWTEST_F(InputMethodControllerTest, testOnRemoteDied, TestSize.Level0)
1314 {
1315 IMSA_HILOGI("IMC OnRemoteDied Test START");
1316 int32_t ret = inputMethodController_->Attach(textListener_, true);
1317 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
1318 TextListener::ResetParam();
1319 bool result = TddUtil::KillImsaProcess();
1320 EXPECT_TRUE(result);
1321 EXPECT_TRUE(WaitRemoteDiedCallback());
1322 CheckProxyObject();
1323 inputMethodController_->OnRemoteSaDied(nullptr);
1324 EXPECT_TRUE(TextListener::WaitSendKeyboardStatusCallback(KeyboardStatus::SHOW));
1325 result = inputMethodController_->WasAttached();
1326 EXPECT_TRUE(result);
1327 inputMethodController_->Close();
1328 }
1329 } // namespace MiscServices
1330 } // namespace OHOS