1 /*
2 * Copyright (C) 2021 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 <gtest/gtest.h>
16 #include <sys/time.h>
17 #include <unistd.h>
18
19 #include <condition_variable>
20 #include <string>
21 #include <vector>
22
23 #include "global.h"
24 #include "ime_event_monitor_manager_impl.h"
25 #include "ime_setting_listener_test_impl.h"
26 #include "input_method_controller.h"
27 #include "input_method_property.h"
28 #include "tdd_util.h"
29
30 using namespace testing::ext;
31 namespace OHOS {
32 namespace MiscServices {
33 class InputMethodSwitchTest : public testing::Test {
34 public:
35 static void SetUpTestCase(void);
36 static void TearDownTestCase(void);
37 void SetUp();
38 void TearDown();
39 static void CheckCurrentProp(const std::string &extName);
40 static void CheckCurrentSubProp(const std::string &extName);
41 static void CheckCurrentSubProps();
42 static sptr<InputMethodController> imc_;
43 static std::string newImeBundleName;
44 static std::vector<std::string> newImeSubName;
45 static std::string newExtName;
46 static std::string bundleName;
47 static std::vector<std::string> extName;
48 static std::vector<std::string> language;
49 static std::vector<std::string> locale;
50 };
51 sptr<InputMethodController> InputMethodSwitchTest::imc_;
52 std::string InputMethodSwitchTest::newImeBundleName = "com.example.newTestIme";
53 std::string InputMethodSwitchTest::newExtName = "InputMethodExtAbility";
54 std::vector<std::string> InputMethodSwitchTest::newImeSubName { "lowerInput", "upperInput", "chineseInput" };
55 std::string InputMethodSwitchTest::bundleName = "com.example.testIme";
56 std::vector<std::string> InputMethodSwitchTest::extName { "InputMethodExtAbility", "InputMethodExtAbility2" };
57 std::vector<std::string> InputMethodSwitchTest::language { "chinese", "english" };
58 std::vector<std::string> InputMethodSwitchTest::locale { "zh-CN", "en-US" };
59 constexpr uint32_t IME_EXT_NUM = 2;
60 constexpr uint32_t NEW_IME_SUBTYPE_NUM = 3;
61 constexpr uint32_t TOTAL_IME_MIN_NUM = 2;
62 constexpr uint32_t ENABLE_IME_NUM = 1;
63 constexpr uint32_t WAIT_IME_READY_TIME = 1;
SetUpTestCase(void)64 void InputMethodSwitchTest::SetUpTestCase(void)
65 {
66 IMSA_HILOGI("InputMethodSwitchTest::SetUpTestCase");
67 TddUtil::StorageSelfTokenID();
68 TddUtil::SetTestTokenID(TddUtil::AllocTestTokenID(true, "ohos.inputMethod.test",
69 { "ohos.permission.CONNECT_IME_ABILITY", "ohos.permission.INJECT_INPUT_EVENT" }));
70 TddUtil::EnabledAllIme();
71 imc_ = InputMethodController::GetInstance();
72 auto listener = std::make_shared<ImeSettingListenerTestImpl>();
73 ImeEventMonitorManagerImpl::GetInstance().RegisterImeEventListener(EVENT_IME_CHANGE_MASK, listener);
74 }
75
TearDownTestCase(void)76 void InputMethodSwitchTest::TearDownTestCase(void)
77 {
78 IMSA_HILOGI("InputMethodSwitchTest::TearDownTestCase");
79 InputMethodController::GetInstance()->Close();
80 TddUtil::RestoreSelfTokenID();
81 }
82
SetUp(void)83 void InputMethodSwitchTest::SetUp(void)
84 {
85 IMSA_HILOGI("InputMethodSwitchTest::SetUp");
86 }
87
TearDown(void)88 void InputMethodSwitchTest::TearDown(void)
89 {
90 IMSA_HILOGI("InputMethodSwitchTest::TearDown");
91 }
92
CheckCurrentProp(const std::string & extName)93 void InputMethodSwitchTest::CheckCurrentProp(const std::string &extName)
94 {
95 std::shared_ptr<Property> property = imc_->GetCurrentInputMethod();
96 ASSERT_TRUE(property != nullptr);
97 EXPECT_EQ(property->name, bundleName);
98 EXPECT_EQ(property->id, extName);
99 }
100
CheckCurrentSubProp(const std::string & extName)101 void InputMethodSwitchTest::CheckCurrentSubProp(const std::string &extName)
102 {
103 auto subProperty = imc_->GetCurrentInputMethodSubtype();
104 ASSERT_TRUE(subProperty != nullptr);
105 EXPECT_EQ(subProperty->id, extName);
106 EXPECT_EQ(subProperty->name, bundleName);
107 }
108
CheckCurrentSubProps()109 void InputMethodSwitchTest::CheckCurrentSubProps()
110 {
111 std::vector<SubProperty> subProps;
112 auto ret = imc_->ListCurrentInputMethodSubtype(subProps);
113 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
114 ASSERT_EQ(subProps.size(), IME_EXT_NUM);
115 for (uint32_t i = 0; i < IME_EXT_NUM; i++) {
116 EXPECT_EQ(subProps[i].id, extName[i]);
117 EXPECT_EQ(subProps[i].name, bundleName);
118 EXPECT_EQ(subProps[i].language, language[i]);
119 EXPECT_EQ(subProps[i].locale, locale[i]);
120 }
121 }
122
123 /**
124 * @tc.name: testImeSwitch
125 * @tc.desc: switch to testIme
126 * @tc.type: FUNC
127 * @tc.require: issuesI62BHB
128 * @tc.author: chenyu
129 */
130 HWTEST_F(InputMethodSwitchTest, testImeSwitch, TestSize.Level0)
131 {
132 IMSA_HILOGI("oldIme testImeSwitch Test START");
133 ImeSettingListenerTestImpl::ResetParam();
134 // switch to ext testIme
135 auto ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName);
136 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
137 EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
138 CheckCurrentProp(extName[0]);
139 CheckCurrentSubProp(extName[0]);
140 CheckCurrentSubProps();
141 sleep(WAIT_IME_READY_TIME);
142 }
143
144 /**
145 * @tc.name: testSubTypeSwitch_001
146 * @tc.desc: switch subtype with extName1
147 * @tc.type: FUNC
148 * @tc.require: issuesI62BHB
149 * @tc.author: chenyu
150 */
151 HWTEST_F(InputMethodSwitchTest, testSubTypeSwitch_001, TestSize.Level0)
152 {
153 IMSA_HILOGI("oldIme testSubTypeSwitch_001 Test START");
154 ImeSettingListenerTestImpl::ResetParam();
155 int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName, extName[0]);
156 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
157 EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
158 CheckCurrentProp(extName[0]);
159 CheckCurrentSubProp(extName[0]);
160 CheckCurrentSubProps();
161 }
162
163 /**
164 * @tc.name: testSubTypeSwitch_002
165 * @tc.desc: switch subtype with extName2
166 * @tc.type: FUNC
167 * @tc.require: issuesI62BHB
168 * @tc.author: chenyu
169 */
170 HWTEST_F(InputMethodSwitchTest, testSubTypeSwitch_002, TestSize.Level0)
171 {
172 IMSA_HILOGI("oldIme testSubTypeSwitch_002 Test START");
173 ImeSettingListenerTestImpl::ResetParam();
174 int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName, extName[1]);
175 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
176 EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
177 CheckCurrentProp(extName[0]);
178 CheckCurrentSubProp(extName[1]);
179 CheckCurrentSubProps();
180 }
181
182 /**
183 * @tc.name: testSubTypeSwitch_003
184 * @tc.desc: switch subtype with extName1
185 * @tc.type: FUNC
186 * @tc.require: issuesI62BHB
187 * @tc.author: chenyu
188 */
189 HWTEST_F(InputMethodSwitchTest, testSubTypeSwitch_003, TestSize.Level0)
190 {
191 IMSA_HILOGI("oldIme testSubTypeSwitch_003 Test START");
192 ImeSettingListenerTestImpl::ResetParam();
193 int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName, extName[0]);
194 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
195 EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
196 CheckCurrentProp(extName[0]);
197 CheckCurrentSubProp(extName[0]);
198 CheckCurrentSubProps();
199 }
200
201 /**
202 * @tc.name: testSubTypeSwitchWithErrorSubName
203 * @tc.desc: switch subtype with error subName.
204 * @tc.type: FUNC
205 * @tc.require: issuesI62BHB
206 * @tc.author: chenyu
207 */
208 HWTEST_F(InputMethodSwitchTest, testSubTypeSwitchWithErrorSubName, TestSize.Level0)
209 {
210 IMSA_HILOGI("oldIme testSubTypeSwitchWithErrorSubName Test START");
211 std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
212 int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName, "error subName");
213 EXPECT_EQ(ret, ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED);
214 CheckCurrentProp(subName);
215 CheckCurrentSubProp(subName);
216 CheckCurrentSubProps();
217 }
218
219 /**
220 * @tc.name: testSwitchToCurrentImeWithEmptySubName
221 * @tc.desc: switch to currentIme witch empty subName.
222 * @tc.type: FUNC
223 * @tc.require: issuesI62BHB
224 * @tc.author: chenyu
225 */
226 HWTEST_F(InputMethodSwitchTest, testSwitchToCurrentImeWithEmptySubName, TestSize.Level0)
227 {
228 IMSA_HILOGI("oldIme testSwitchToCurrentImeWithEmptySubName Test START");
229 ImeSettingListenerTestImpl::ResetParam();
230 std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
231 int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName);
232 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
233 EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
234 CheckCurrentProp(subName);
235 CheckCurrentSubProp(subName);
236 CheckCurrentSubProps();
237 }
238
239 /**
240 * @tc.name: testSwitchImeWithErrorBundleName
241 * @tc.desc: switch ime witch error bundleName
242 * @tc.type: FUNC
243 * @tc.require: issuesI62BHB
244 * @tc.author: chenyu
245 */
246 HWTEST_F(InputMethodSwitchTest, testSwitchImeWithErrorBundleName, TestSize.Level0)
247 {
248 IMSA_HILOGI("oldIme testSwitchImeWithErrorBundleName Test START");
249 std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
250 int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, "error bundleName", extName[0]);
251 EXPECT_TRUE(ret == ErrorCode::ERROR_ENABLE_IME || ret == ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED);
252 CheckCurrentProp(subName);
253 CheckCurrentSubProp(subName);
254 CheckCurrentSubProps();
255 }
256
257 /**
258 * @tc.name: testSwitchImeWithErrorBundleNameWitchEmptySubName
259 * @tc.desc: switch ime witch error bundleName and empty subName
260 * @tc.type: FUNC
261 * @tc.require: issuesI62BHB
262 * @tc.author: chenyu
263 */
264 HWTEST_F(InputMethodSwitchTest, testSwitchImeWithErrorBundleNameWitchEmptySubName, TestSize.Level0)
265 {
266 IMSA_HILOGI("oldIme testSwitchImeWithErrorBundleNameWitchEmptySubName Test START");
267 std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
268 int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, "error bundleName", " ");
269 EXPECT_TRUE(ret == ErrorCode::ERROR_ENABLE_IME || ret == ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED);
270 CheckCurrentProp(subName);
271 CheckCurrentSubProp(subName);
272 CheckCurrentSubProps();
273 }
274
275 /**
276 * @tc.name: testIMCListInputMethod
277 * @tc.desc: IMC ListInputMethod
278 * @tc.type: FUNC
279 * @tc.require: issuesI62BHB
280 * @tc.author: chenyu
281 */
282 HWTEST_F(InputMethodSwitchTest, testIMCListInputMethod, TestSize.Level0)
283 {
284 IMSA_HILOGI("IMC testIMCListInputMethod Test Start");
285 std::vector<Property> properties = {};
286 auto ret = imc_->ListInputMethod(properties);
287 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
288 EXPECT_TRUE(properties.size() >= TOTAL_IME_MIN_NUM);
289 bool hasIme = false;
290 bool hasNewIme = false;
291 for (const auto &property : properties) {
292 if (property.name == bundleName) {
293 hasIme = true;
294 }
295 if (property.name == newImeBundleName) {
296 hasNewIme = true;
297 }
298 }
299 EXPECT_TRUE(hasIme && hasNewIme);
300 }
301
302 /**
303 * @tc.name: testIMCListInputMethodDisable
304 * @tc.desc: IMC ListInputMethod
305 * @tc.type: FUNC
306 * @tc.require: issuesI62BHB
307 * @tc.author: chenyu
308 */
309 HWTEST_F(InputMethodSwitchTest, testIMCListInputMethodDisable, TestSize.Level0)
310 {
311 IMSA_HILOGI("IMC testIMCListInputMethodDisable Test Start");
312 std::vector<Property> disableProperties = {};
313 auto ret = imc_->ListInputMethod(false, disableProperties);
314 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
315 EXPECT_GE(disableProperties.size(), 0);
316 }
317
318 /**
319 * @tc.name: testIMCListInputMethodEnable
320 * @tc.desc: IMC ListInputMethod
321 * @tc.type: FUNC
322 * @tc.require: issuesI62BHB
323 * @tc.author: chenyu
324 */
325 HWTEST_F(InputMethodSwitchTest, testIMCListInputMethodEnable, TestSize.Level0)
326 {
327 IMSA_HILOGI("IMC testIMCListInputMethodEnable Test Start");
328 std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
329 std::vector<Property> enableProperties = {};
330 auto ret = imc_->ListInputMethod(true, enableProperties);
331 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
332 EXPECT_GE(enableProperties.size(), ENABLE_IME_NUM);
333 }
334
335 /**
336 * @tc.name: tesIMCtListInputMethodSubtype_001
337 * @tc.desc: ListInputMethodSubtype
338 * @tc.type: FUNC
339 * @tc.require: issuesI62BHB
340 * @tc.author: chenyu
341 */
342 HWTEST_F(InputMethodSwitchTest, tesIMCtListInputMethodSubtype_001, TestSize.Level0)
343 {
344 IMSA_HILOGI("IMC tesIMCtListInputMethodSubtype_001 Test Start");
345 Property property;
346 property.name = newImeBundleName;
347 std::vector<SubProperty> subProps;
348 auto ret = imc_->ListInputMethodSubtype(property, subProps);
349 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
350 ASSERT_EQ(subProps.size(), NEW_IME_SUBTYPE_NUM);
351 for (uint32_t i = 0; i < NEW_IME_SUBTYPE_NUM; i++) {
352 EXPECT_EQ(subProps[i].id, newImeSubName[i]);
353 EXPECT_EQ(subProps[i].name, newImeBundleName);
354 }
355 }
356
357 /**
358 * @tc.name: tesIMCtListInputMethodSubtype_002
359 * @tc.desc: ListInputMethodSubtype
360 * @tc.type: FUNC
361 * @tc.require: issuesI62BHB
362 * @tc.author: chenyu
363 */
364 HWTEST_F(InputMethodSwitchTest, tesIMCtListInputMethodSubtype_002, TestSize.Level0)
365 {
366 IMSA_HILOGI("IMC tesIMCtListInputMethodSubtype_002 Test Start");
367 Property property;
368 property.name = bundleName;
369 std::vector<SubProperty> subProps;
370 auto ret = imc_->ListInputMethodSubtype(property, subProps);
371 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
372 ASSERT_EQ(subProps.size(), IME_EXT_NUM);
373 for (uint32_t i = 0; i < IME_EXT_NUM; i++) {
374 EXPECT_EQ(subProps[i].id, extName[i]);
375 EXPECT_EQ(subProps[i].name, bundleName);
376 }
377 }
378
379 /**
380 * @tc.name: testIMCListInputMethodSubtypeWithErrorBundleName
381 * @tc.desc: IMC ListInputMethodSubtype
382 * @tc.type: FUNC
383 * @tc.require: issuesI62BHB
384 * @tc.author: chenyu
385 */
386 HWTEST_F(InputMethodSwitchTest, testIMCListInputMethodSubtypeWithErrorBundleName, TestSize.Level0)
387 {
388 IMSA_HILOGI("IMC testIMCListInputMethodSubtypeWitchErrorBundleName Test START");
389 std::shared_ptr<Property> property = std::make_shared<Property>();
390 std::vector<SubProperty> properties = {};
391 auto ret = imc_->ListInputMethodSubtype(*property, properties);
392 EXPECT_EQ(ret, ErrorCode::ERROR_BAD_PARAMETERS);
393 EXPECT_TRUE(properties.empty());
394 }
395
396 /**
397 * @tc.name: testShowOptionalInputMethod
398 * @tc.desc: IMC ShowOptionalInputMethod
399 * @tc.type: FUNC
400 */
401 HWTEST_F(InputMethodSwitchTest, testShowOptionalInputMethod, TestSize.Level2)
402 {
403 IMSA_HILOGI("IMC ShowOptionalInputMethod Test START");
404 int32_t ret = imc_->ShowOptionalInputMethod();
405 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
406 }
407
408 /**
409 * @tc.name: testDisplayOptionalInputMethod
410 * @tc.desc: IMC DisplayOptionalInputMethod
411 * @tc.type: FUNC
412 */
413 HWTEST_F(InputMethodSwitchTest, testDisplayOptionalInputMethod, TestSize.Level2)
414 {
415 IMSA_HILOGI("IMC DisplayOptionalInputMethod Test START");
416 sleep(2);
417 int32_t ret = imc_->DisplayOptionalInputMethod();
418 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
419 }
420
421 /**
422 * @tc.name: testCombinationKeySwitchIme_001
423 * @tc.desc: switch ime by combination key.
424 * @tc.type: FUNC
425 * @tc.require: issuesI8RPP3
426 * @tc.author: mashaoyin
427 */
428 HWTEST_F(InputMethodSwitchTest, testCombinationKeySwitchIme_001, TestSize.Level0)
429 {
430 IMSA_HILOGI("testCombinationKeySwitchIme_001 Test START");
431 ImeSettingListenerTestImpl::ResetParam();
432 std::shared_ptr<Property> property = imc_->GetCurrentInputMethod();
433 std::string result;
434 static std::string cmd = "uinput -K -d 2076 -d 2050";
435 auto ret = TddUtil::ExecuteCmd(cmd, result);
436 EXPECT_TRUE(ret);
437 EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
438 imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, property->name, "");
439 }
440
441 /**
442 * @tc.name: testCombinationKeySwitchIme_002
443 * @tc.desc: switch ime by combination key.
444 * @tc.type: FUNC
445 * @tc.require: issuesI8RPP3
446 * @tc.author: mashaoyin
447 */
448 HWTEST_F(InputMethodSwitchTest, testCombinationKeySwitchIme_002, TestSize.Level0)
449 {
450 IMSA_HILOGI("testCombinationKeySwitchIme_002 Test START");
451 ImeSettingListenerTestImpl::ResetParam();
452 std::shared_ptr<Property> property = imc_->GetCurrentInputMethod();
453 std::string result;
454 static std::string cmd = "uinput -K -d 2077 -d 2050";
455 auto ret = TddUtil::ExecuteCmd(cmd, result);
456 EXPECT_TRUE(ret);
457 EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
458 imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, property->name, "");
459 }
460
461 /**
462 * @tc.name: testCombinationKeySwitchIme_003
463 * @tc.desc: switch ime by combination key.
464 * @tc.type: FUNC
465 * @tc.require: issuesI8RPP3
466 * @tc.author: mashaoyin
467 */
468 HWTEST_F(InputMethodSwitchTest, testCombinationKeySwitchIme_003, TestSize.Level0)
469 {
470 IMSA_HILOGI("testCombinationKeySwitchIme_003 Test START");
471 ImeSettingListenerTestImpl::ResetParam();
472 std::shared_ptr<Property> property = imc_->GetCurrentInputMethod();
473 std::vector<Property> props;
474 imc_->ListInputMethod(true, props);
475 std::string result;
476 static std::string cmd = "uinput -K -d 2077 -d 2050 -u 2050 -u 2077";
477 for (auto iter = 0; iter < props.size(); ++iter) {
478 auto ret = TddUtil::ExecuteCmd(cmd, result);
479 EXPECT_TRUE(ret);
480 }
481 EXPECT_TRUE(ImeSettingListenerTestImpl::WaitTargetImeChange(property->name));
482 std::shared_ptr<Property> curProperty = imc_->GetCurrentInputMethod();
483 EXPECT_EQ(property->name, curProperty->name);
484 imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, property->name, "");
485 }
486 } // namespace MiscServices
487 } // namespace OHOS
488