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