1 /*
2 * Copyright (c) 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 #include <event_handler.h>
16 #include <gtest/gtest.h>
17 #include <string_ex.h>
18 #include <sys/time.h>
19
20 #include <condition_variable>
21 #include <cstdint>
22 #include <functional>
23 #include <mutex>
24 #include <string>
25 #include <thread>
26 #include <vector>
27
28 #include "global.h"
29 #include "i_input_method_agent.h"
30 #include "i_input_method_system_ability.h"
31 #include "input_client_stub.h"
32 #include "input_data_channel_stub.h"
33 #include "input_method_ability.h"
34 #include "input_method_controller.h"
35 #include "input_method_engine_listener_impl.h"
36 #include "input_method_system_ability_proxy.h"
37 #include "input_method_utils.h"
38 #include "keyboard_listener.h"
39 #include "message_parcel.h"
40 #include "tdd_util.h"
41 #include "text_listener.h"
42
43 using namespace testing::ext;
44 namespace OHOS {
45 namespace MiscServices {
46 using WindowMgr = TddUtil::WindowManager;
47 class KeyboardListenerImpl : public KeyboardListener {
48 public:
KeyboardListenerImpl()49 KeyboardListenerImpl(){};
~KeyboardListenerImpl()50 ~KeyboardListenerImpl(){};
51 static int32_t keyCode_;
52 static int32_t keyStatus_;
53 static CursorInfo cursorInfo_;
54 bool OnKeyEvent(int32_t keyCode, int32_t keyStatus) override;
55 bool OnKeyEvent(const std::shared_ptr<MMI::KeyEvent> &keyEvent) override;
56 void OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height) override;
57 void OnSelectionChange(int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd) override;
58 void OnTextChange(const std::string &text) override;
59 void OnEditorAttributeChange(const InputAttribute &inputAttribute) override;
60 };
61 int32_t KeyboardListenerImpl::keyCode_ = 0;
62 int32_t KeyboardListenerImpl::keyStatus_ = 0;
63 CursorInfo KeyboardListenerImpl::cursorInfo_ = {};
OnKeyEvent(int32_t keyCode,int32_t keyStatus)64 bool KeyboardListenerImpl::OnKeyEvent(int32_t keyCode, int32_t keyStatus)
65 {
66 IMSA_HILOGD("KeyboardListenerImpl::OnKeyEvent %{public}d %{public}d", keyCode, keyStatus);
67 keyCode_ = keyCode;
68 keyStatus_ = keyStatus;
69 return true;
70 }
OnKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)71 bool KeyboardListenerImpl::OnKeyEvent(const std::shared_ptr<MMI::KeyEvent> &keyEvent)
72 {
73 return true;
74 }
OnCursorUpdate(int32_t positionX,int32_t positionY,int32_t height)75 void KeyboardListenerImpl::OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height)
76 {
77 IMSA_HILOGD("KeyboardListenerImpl::OnCursorUpdate %{public}d %{public}d %{public}d", positionX, positionY, height);
78 cursorInfo_ = { static_cast<double>(positionX), static_cast<double>(positionY), 0, static_cast<double>(height) };
79 }
OnSelectionChange(int32_t oldBegin,int32_t oldEnd,int32_t newBegin,int32_t newEnd)80 void KeyboardListenerImpl::OnSelectionChange(int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd)
81 {
82 }
OnTextChange(const std::string & text)83 void KeyboardListenerImpl::OnTextChange(const std::string &text)
84 {
85 }
OnEditorAttributeChange(const InputAttribute & inputAttribute)86 void KeyboardListenerImpl::OnEditorAttributeChange(const InputAttribute &inputAttribute)
87 {
88 }
89
90 class InputMethodEditorTest : public testing::Test {
91 public:
92 static void SetUpTestCase(void);
93 static void TearDownTestCase(void);
94 void SetUp();
95 void TearDown();
96 static sptr<InputMethodController> inputMethodController_;
97 static sptr<InputMethodAbility> inputMethodAbility_;
98 static std::shared_ptr<MMI::KeyEvent> keyEvent_;
99 static std::shared_ptr<KeyboardListenerImpl> kbListener_;
100 static std::shared_ptr<InputMethodEngineListenerImpl> imeListener_;
101 static sptr<OnTextChangedListener> textListener_;
102 };
103 sptr<InputMethodController> InputMethodEditorTest::inputMethodController_;
104 sptr<InputMethodAbility> InputMethodEditorTest::inputMethodAbility_;
105 std::shared_ptr<MMI::KeyEvent> InputMethodEditorTest::keyEvent_;
106 std::shared_ptr<KeyboardListenerImpl> InputMethodEditorTest::kbListener_;
107 std::shared_ptr<InputMethodEngineListenerImpl> InputMethodEditorTest::imeListener_;
108 sptr<OnTextChangedListener> InputMethodEditorTest::textListener_;
109
SetUpTestCase(void)110 void InputMethodEditorTest::SetUpTestCase(void)
111 {
112 IMSA_HILOGI("InputMethodEditorTest::SetUpTestCase");
113 TddUtil::StorageSelfTokenID();
114 std::shared_ptr<Property> property = InputMethodController::GetInstance()->GetCurrentInputMethod();
115 std::string bundleName = property != nullptr ? property->name : "default.inputmethod.unittest";
116 TddUtil::SetTestTokenID(TddUtil::GetTestTokenID(bundleName));
117 inputMethodAbility_ = InputMethodAbility::GetInstance();
118 inputMethodAbility_->OnImeReady();
119 inputMethodAbility_->SetCoreAndAgent();
120 kbListener_ = std::make_shared<KeyboardListenerImpl>();
121 imeListener_ = std::make_shared<InputMethodEngineListenerImpl>();
122 inputMethodAbility_->SetKdListener(kbListener_);
123 inputMethodAbility_->SetImeListener(imeListener_);
124
125 textListener_ = new TextListener();
126 inputMethodController_ = InputMethodController::GetInstance();
127
128 keyEvent_ = MMI::KeyEvent::Create();
129 constexpr int32_t keyAction = 2;
130 constexpr int32_t keyCode = 2001;
131 keyEvent_->SetKeyAction(keyAction);
132 keyEvent_->SetKeyCode(keyCode);
133 TextListener::ResetParam();
134 TddUtil::SetTestTokenID(TddUtil::AllocTestTokenID(true, false, "undefine"));
135 TddUtil::WindowManager::RegisterFocusChangeListener();
136 WindowMgr::CreateWindow();
137 }
138
TearDownTestCase(void)139 void InputMethodEditorTest::TearDownTestCase(void)
140 {
141 IMSA_HILOGI("InputMethodEditorTest::TearDownTestCase");
142 TddUtil::RestoreSelfTokenID();
143 TextListener::ResetParam();
144 WindowMgr::DestroyWindow();
145 }
146
SetUp(void)147 void InputMethodEditorTest::SetUp(void)
148 {
149 IMSA_HILOGI("InputMethodEditorTest::SetUp");
150 }
151
TearDown(void)152 void InputMethodEditorTest::TearDown(void)
153 {
154 IMSA_HILOGI("InputMethodEditorTest::TearDown");
155 }
156
157 /**
158 * @tc.name: testIMCAttachUnfocused
159 * @tc.desc: InputMethodEditorTest Attach.
160 * @tc.type: FUNC
161 */
162 HWTEST_F(InputMethodEditorTest, testIMCAttachUnfocused, TestSize.Level0)
163 {
164 IMSA_HILOGD("InputMethodEditorTest Attach Unfocused Test START");
165 int32_t ret = InputMethodEditorTest::inputMethodController_->Attach(textListener_, false);
166 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_FOCUSED);
167 ret = InputMethodEditorTest::inputMethodController_->Attach(textListener_);
168 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_FOCUSED);
169 ret = InputMethodEditorTest::inputMethodController_->Attach(textListener_, true);
170 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_FOCUSED);
171 }
172
173 /**
174 * @tc.name: test Unfocused
175 * @tc.desc: InputMethodEditorTest ShowTextInput Unfocused
176 * @tc.type: FUNC
177 */
178 HWTEST_F(InputMethodEditorTest, testShowTextInputUnfocused, TestSize.Level0)
179 {
180 IMSA_HILOGI("InputMethodEditorTest Unfocused Test START");
181 int32_t ret = InputMethodEditorTest::inputMethodController_->ShowTextInput();
182 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_BOUND);
183 ret = InputMethodEditorTest::inputMethodController_->ShowSoftKeyboard();
184 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
185 bool result = InputMethodEditorTest::inputMethodController_->DispatchKeyEvent(InputMethodEditorTest::keyEvent_);
186 EXPECT_FALSE(result);
187 ret = InputMethodEditorTest::inputMethodController_->ShowSoftKeyboard();
188 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
189 ret = InputMethodEditorTest::inputMethodController_->HideSoftKeyboard();
190 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
191 ret = InputMethodEditorTest::inputMethodController_->StopInputSession();
192 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_FOCUSED);
193 ret = InputMethodEditorTest::inputMethodController_->ShowCurrentInput();
194 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
195 ret = InputMethodEditorTest::inputMethodController_->HideCurrentInput();
196 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
197 }
198
199 /**
200 * @tc.name: test AttachFocused
201 * @tc.desc: InputMethodEditorTest Attach Focused
202 * @tc.type: FUNC
203 */
204 HWTEST_F(InputMethodEditorTest, testAttachFocused, TestSize.Level0)
205 {
206 IMSA_HILOGI("InputMethodEditorTest Attach Focused Test START");
207 WindowMgr::ShowWindow();
208 bool isFocused = FocusChangedListenerTestImpl::isFocused_->GetValue();
209 IMSA_HILOGI("testAttachFocused getFocus end, isFocused = %{public}d", isFocused);
210 InputMethodEditorTest::imeListener_->isInputStart_ = false;
211 InputMethodEditorTest::imeListener_->keyboardState_ = false;
212 int32_t ret = InputMethodEditorTest::inputMethodController_->Attach(InputMethodEditorTest::textListener_, false);
213 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
214
215 InputMethodEditorTest::imeListener_->isInputStart_ = false;
216 InputMethodEditorTest::imeListener_->keyboardState_ = false;
217 ret = InputMethodEditorTest::inputMethodController_->Attach(InputMethodEditorTest::textListener_);
218 EXPECT_TRUE(TextListener::WaitIMACallback());
219 EXPECT_TRUE(imeListener_->isInputStart_ && imeListener_->keyboardState_);
220 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
221
222 InputMethodEditorTest::imeListener_->isInputStart_ = false;
223 InputMethodEditorTest::imeListener_->keyboardState_ = false;
224 ret = InputMethodEditorTest::inputMethodController_->Attach(InputMethodEditorTest::textListener_, true);
225 EXPECT_TRUE(TextListener::WaitIMACallback());
226 EXPECT_TRUE(imeListener_->isInputStart_ && imeListener_->keyboardState_);
227 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
228 InputMethodEditorTest::inputMethodController_->Close();
229 WindowMgr::HideWindow();
230 bool unFocus = FocusChangedListenerTestImpl::unFocused_->GetValue();
231 IMSA_HILOGI("testAttachFocused unFocus end, unFocus = %{public}d", unFocus);
232 }
233
234 /**
235 * @tc.name: testShowSoftKeyboard
236 * @tc.desc: InputMethodEditorTest ShowSoftKeyboard
237 * @tc.type: FUNC
238 */
239 HWTEST_F(InputMethodEditorTest, testShowSoftKeyboard, TestSize.Level0)
240 {
241 IMSA_HILOGI("InputMethodEditorTest ShowSoftKeyboard Test START");
242 TddUtil::SetTestTokenID(TddUtil::AllocTestTokenID(true, true, "undefined"));
243 WindowMgr::ShowWindow();
244 bool isFocused = FocusChangedListenerTestImpl::isFocused_->GetValue();
245 IMSA_HILOGI("testShowSoftKeyboard getFocus end, isFocused = %{public}d", isFocused);
246 InputMethodEditorTest::imeListener_->keyboardState_ = false;
247 TextListener::keyboardStatus_ = KeyboardStatus::NONE;
248 int32_t ret = InputMethodEditorTest::inputMethodController_->Attach(InputMethodEditorTest::textListener_, false);
249 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
250 ret = InputMethodEditorTest::inputMethodController_->ShowSoftKeyboard();
251 EXPECT_TRUE(TextListener::WaitIMACallback());
252 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
253 EXPECT_TRUE(imeListener_->keyboardState_ && TextListener::keyboardStatus_ == KeyboardStatus::SHOW);
254 WindowMgr::HideWindow();
255 bool unFocus = FocusChangedListenerTestImpl::unFocused_->GetValue();
256 IMSA_HILOGI("testShowSoftKeyboard unFocus end, unFocus = %{public}d", unFocus);
257 }
258
259 /**
260 * @tc.name: testIMCHideTextInput.
261 * @tc.desc: InputMethodEditorTest testHideTextInput.
262 * @tc.type: FUNC
263 */
264 HWTEST_F(InputMethodEditorTest, testIMCHideTextInput, TestSize.Level0)
265 {
266 IMSA_HILOGI("InputMethodEditorTest HideTextInputAndShowTextInput Test START");
267 InputMethodEditorTest::inputMethodController_->Close();
268 WindowMgr::ShowWindow();
269 bool isFocused = FocusChangedListenerTestImpl::isFocused_->GetValue();
270 IMSA_HILOGI("testIMCHideTextInput getFocus end, isFocused = %{public}d", isFocused);
271 int32_t ret = InputMethodEditorTest::inputMethodController_->Attach(InputMethodEditorTest::textListener_, true);
272 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
273
274 imeListener_->keyboardState_ = true;
275 TextListener::keyboardStatus_ = KeyboardStatus::NONE;
276 InputMethodEditorTest::inputMethodController_->HideTextInput();
277 bool result = InputMethodEditorTest::inputMethodController_->DispatchKeyEvent(InputMethodEditorTest::keyEvent_);
278 EXPECT_FALSE(result);
279 ret = InputMethodEditorTest::inputMethodController_->ShowSoftKeyboard();
280 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
281 ret = InputMethodEditorTest::inputMethodController_->ShowSoftKeyboard();
282 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
283 ret = InputMethodEditorTest::inputMethodController_->HideSoftKeyboard();
284 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
285 ret = InputMethodEditorTest::inputMethodController_->ShowCurrentInput();
286 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
287 ret = InputMethodEditorTest::inputMethodController_->HideCurrentInput();
288 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
289 WindowMgr::HideWindow();
290 bool unFocus = FocusChangedListenerTestImpl::unFocused_->GetValue();
291 IMSA_HILOGI("testIMCHideTextInput unFocus end, unFocus = %{public}d", unFocus);
292 }
293
294 /**
295 * @tc.name: testShowTextInput
296 * @tc.desc: InputMethodEditorTest ShowTextInput
297 * @tc.type: FUNC
298 */
299 HWTEST_F(InputMethodEditorTest, testShowTextInput, TestSize.Level0)
300 {
301 IMSA_HILOGI("InputMethodEditorTest ShowTextInput Test START");
302 InputMethodEditorTest::inputMethodController_->Close();
303 WindowMgr::ShowWindow();
304 bool isFocused = FocusChangedListenerTestImpl::isFocused_->GetValue();
305 IMSA_HILOGI("testShowTextInput getFocus end, isFocused = %{public}d", isFocused);
306 int32_t ret = InputMethodEditorTest::inputMethodController_->Attach(InputMethodEditorTest::textListener_, true);
307 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
308 InputMethodEditorTest::inputMethodController_->HideTextInput();
309
310 ret = InputMethodEditorTest::inputMethodController_->ShowTextInput();
311 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
312 bool result = InputMethodEditorTest::inputMethodController_->DispatchKeyEvent(InputMethodEditorTest::keyEvent_);
313 usleep(300);
314 ret = ret && kbListener_->keyCode_ == keyEvent_->GetKeyCode()
315 && kbListener_->keyStatus_ == keyEvent_->GetKeyAction();
316 EXPECT_TRUE(result);
317 WindowMgr::HideWindow();
318 bool unFocus = FocusChangedListenerTestImpl::unFocused_->GetValue();
319 IMSA_HILOGI("testShowTextInput unFocus end, unFocus = %{public}d", unFocus);
320 }
321
322 /**
323 * @tc.name: testIMCClose.
324 * @tc.desc: InputMethodEditorTest Close.
325 * @tc.type: FUNC
326 */
327 HWTEST_F(InputMethodEditorTest, testIMCClose, TestSize.Level0)
328 {
329 IMSA_HILOGI("IMC Close Test START");
330 WindowMgr::ShowWindow();
331 bool isFocused = FocusChangedListenerTestImpl::isFocused_->GetValue();
332 IMSA_HILOGI("testIMCClose getFocus end, isFocused = %{public}d", isFocused);
333 int32_t ret = InputMethodEditorTest::inputMethodController_->Attach(InputMethodEditorTest::textListener_, true);
334 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
335 InputMethodEditorTest::inputMethodController_->Close();
336
337 ret = InputMethodEditorTest::inputMethodController_->ShowTextInput();
338 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_BOUND);
339 ret = InputMethodEditorTest::inputMethodController_->ShowSoftKeyboard();
340 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
341 bool result = InputMethodEditorTest::inputMethodController_->DispatchKeyEvent(InputMethodEditorTest::keyEvent_);
342 EXPECT_FALSE(result);
343 ret = InputMethodEditorTest::inputMethodController_->ShowSoftKeyboard();
344 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
345 ret = InputMethodEditorTest::inputMethodController_->HideSoftKeyboard();
346 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
347 ret = InputMethodEditorTest::inputMethodController_->ShowCurrentInput();
348 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
349 ret = InputMethodEditorTest::inputMethodController_->HideCurrentInput();
350 EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
351 WindowMgr::HideWindow();
352 bool unFocus = FocusChangedListenerTestImpl::unFocused_->GetValue();
353 IMSA_HILOGI("testIMCClose unFocus end, unFocus = %{public}d", unFocus);
354 }
355 } // namespace MiscServices
356 } // namespace OHOS
357