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 <string>
20 #include <vector>
21
22 #include "global.h"
23 #include "input_method_controller.h"
24 #include "input_method_property.h"
25 #include "tdd_util.h"
26
27 using namespace testing::ext;
28 namespace OHOS {
29 namespace MiscServices {
30 class InputMethodSwitchTest : public testing::Test {
31 public:
32 static void SetUpTestCase(void);
33 static void TearDownTestCase(void);
34 void SetUp();
35 void TearDown();
36 static void CheckCurrentProp(const std::string &extName);
37 static void CheckCurrentSubProp(const std::string &extName);
38 static void CheckCurrentSubProps();
39 static std::mutex imeChangeFlagLock;
40 static std::condition_variable conditionVar;
41 static sptr<InputMethodController> imc_;
42 static bool imeChangeFlag;
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 };
49 std::mutex InputMethodSwitchTest::imeChangeFlagLock;
50 std::condition_variable InputMethodSwitchTest::conditionVar;
51 bool InputMethodSwitchTest::imeChangeFlag = false;
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 constexpr uint32_t IME_EXT_NUM = 2;
59 constexpr uint32_t NEW_IME_SUBTYPE_NUM = 3;
60 constexpr uint32_t TOTAL_IME_MIN_NUM = 2;
61 constexpr uint32_t ENABLE_IME_NUM = 1;
62 constexpr uint32_t SUBTYPE_SWITCH_DELAY_TIME = 20;
63 constexpr uint32_t IME_SWITCH_DELAY_TIME = 200;
64 constexpr uint32_t WAIT_IME_READY_TIME = 1;
65 class InputMethodSettingListenerImpl : public InputMethodSettingListener {
66 public:
67 InputMethodSettingListenerImpl() = default;
68 ~InputMethodSettingListenerImpl() = default;
OnImeChange(const Property & property,const SubProperty & subProperty)69 void OnImeChange(const Property &property, const SubProperty &subProperty)
70 {
71 {
72 std::unique_lock<std::mutex> lock(InputMethodSwitchTest::imeChangeFlagLock);
73 InputMethodSwitchTest::imeChangeFlag = true;
74 }
75 InputMethodSwitchTest::conditionVar.notify_one();
76 IMSA_HILOGI("InputMethodSettingListenerImpl OnImeChange");
77 }
OnPanelStatusChange(const InputWindowStatus & status,const std::vector<InputWindowInfo> & windowInfo)78 void OnPanelStatusChange(const InputWindowStatus &status, const std::vector<InputWindowInfo> &windowInfo)
79 {
80 }
81 };
82
SetUpTestCase(void)83 void InputMethodSwitchTest::SetUpTestCase(void)
84 {
85 IMSA_HILOGI("InputMethodSwitchTest::SetUpTestCase");
86 TddUtil::StorageSelfTokenID();
87 TddUtil::SetTestTokenID(TddUtil::AllocTestTokenID(true, true, "ohos.inputMethod.test"));
88 imc_ = InputMethodController::GetInstance();
89 imc_->SetSettingListener(std::make_shared<InputMethodSettingListenerImpl>());
90 imc_->UpdateListenEventFlag("imeChange", true);
91 }
92
TearDownTestCase(void)93 void InputMethodSwitchTest::TearDownTestCase(void)
94 {
95 IMSA_HILOGI("InputMethodSwitchTest::TearDownTestCase");
96 InputMethodController::GetInstance()->Close();
97 TddUtil::RestoreSelfTokenID();
98 }
99
SetUp(void)100 void InputMethodSwitchTest::SetUp(void)
101 {
102 IMSA_HILOGI("InputMethodSwitchTest::SetUp");
103 }
104
TearDown(void)105 void InputMethodSwitchTest::TearDown(void)
106 {
107 IMSA_HILOGI("InputMethodSwitchTest::TearDown");
108 }
109
CheckCurrentProp(const std::string & extName)110 void InputMethodSwitchTest::CheckCurrentProp(const std::string &extName)
111 {
112 std::shared_ptr<Property> property = imc_->GetCurrentInputMethod();
113 ASSERT_TRUE(property != nullptr);
114 EXPECT_EQ(property->name, bundleName);
115 EXPECT_EQ(property->id, extName);
116 }
117
CheckCurrentSubProp(const std::string & extName)118 void InputMethodSwitchTest::CheckCurrentSubProp(const std::string &extName)
119 {
120 auto subProperty = imc_->GetCurrentInputMethodSubtype();
121 ASSERT_TRUE(subProperty != nullptr);
122 EXPECT_EQ(subProperty->id, extName);
123 EXPECT_EQ(subProperty->name, bundleName);
124 }
125
CheckCurrentSubProps()126 void InputMethodSwitchTest::CheckCurrentSubProps()
127 {
128 std::vector<SubProperty> subProps;
129 auto ret = imc_->ListCurrentInputMethodSubtype(subProps);
130 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
131 ASSERT_EQ(subProps.size(), IME_EXT_NUM);
132 for (uint32_t i = 0; i < IME_EXT_NUM; i++) {
133 EXPECT_EQ(subProps[i].id, extName[i]);
134 EXPECT_EQ(subProps[i].name, bundleName);
135 EXPECT_EQ(subProps[i].language, language[i]);
136 EXPECT_EQ(subProps[i].locale, "");
137 }
138 }
139
140 /**
141 * @tc.name: testImeSwitch
142 * @tc.desc: switch to testIme
143 * @tc.type: FUNC
144 * @tc.require: issuesI62BHB
145 * @tc.author: chenyu
146 */
147 HWTEST_F(InputMethodSwitchTest, testImeSwitch, TestSize.Level0)
148 {
149 IMSA_HILOGI("oldIme testImeSwitch Test START");
150 std::unique_lock<std::mutex> lock(imeChangeFlagLock);
151 imeChangeFlag = false;
152 // switch to ext testIme
153 auto ret = imc_->SwitchInputMethod(bundleName);
154 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
__anon2b3816f50102null155 conditionVar.wait_for(lock, std::chrono::milliseconds(IME_SWITCH_DELAY_TIME), [] { return imeChangeFlag == true; });
156 EXPECT_TRUE(imeChangeFlag);
157 CheckCurrentProp(extName[0]);
158 CheckCurrentSubProp(extName[0]);
159 CheckCurrentSubProps();
160 sleep(WAIT_IME_READY_TIME);
161 }
162
163 /**
164 * @tc.name: testSubTypeSwitch_001
165 * @tc.desc: switch subtype with extName1
166 * @tc.type: FUNC
167 * @tc.require: issuesI62BHB
168 * @tc.author: chenyu
169 */
170 HWTEST_F(InputMethodSwitchTest, testSubTypeSwitch_001, TestSize.Level0)
171 {
172 IMSA_HILOGI("oldIme testSubTypeSwitch_001 Test START");
173 std::unique_lock<std::mutex> lock(imeChangeFlagLock);
174 imeChangeFlag = false;
175 int32_t ret = imc_->SwitchInputMethod(bundleName, extName[0]);
176 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
177 conditionVar.wait_for(
__anon2b3816f50202null178 lock, std::chrono::milliseconds(SUBTYPE_SWITCH_DELAY_TIME), [] { return imeChangeFlag == true; });
179 EXPECT_FALSE(imeChangeFlag);
180 CheckCurrentProp(extName[0]);
181 CheckCurrentSubProp(extName[0]);
182 CheckCurrentSubProps();
183 }
184
185 /**
186 * @tc.name: testSubTypeSwitch_002
187 * @tc.desc: switch subtype with extName2
188 * @tc.type: FUNC
189 * @tc.require: issuesI62BHB
190 * @tc.author: chenyu
191 */
192 HWTEST_F(InputMethodSwitchTest, testSubTypeSwitch_002, TestSize.Level0)
193 {
194 IMSA_HILOGI("oldIme testSubTypeSwitch_002 Test START");
195 std::unique_lock<std::mutex> lock(imeChangeFlagLock);
196 imeChangeFlag = false;
197 int32_t ret = imc_->SwitchInputMethod(bundleName, extName[1]);
198 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
199 conditionVar.wait_for(
__anon2b3816f50302null200 lock, std::chrono::milliseconds(SUBTYPE_SWITCH_DELAY_TIME), [] { return imeChangeFlag == true; });
201 EXPECT_TRUE(imeChangeFlag);
202 CheckCurrentProp(extName[1]);
203 CheckCurrentSubProp(extName[1]);
204 CheckCurrentSubProps();
205 }
206
207 /**
208 * @tc.name: testSubTypeSwitchWithErrorSubName
209 * @tc.desc: switch subtype with error subName.
210 * @tc.type: FUNC
211 * @tc.require: issuesI62BHB
212 * @tc.author: chenyu
213 */
214 HWTEST_F(InputMethodSwitchTest, testSubTypeSwitchWithErrorSubName, TestSize.Level0)
215 {
216 IMSA_HILOGI("oldIme testSubTypeSwitchWithErrorSubName Test START");
217 std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
218 int32_t ret = imc_->SwitchInputMethod(bundleName, "error subName");
219 EXPECT_EQ(ret, ErrorCode::ERROR_BAD_PARAMETERS);
220 CheckCurrentProp(subName);
221 CheckCurrentSubProp(subName);
222 CheckCurrentSubProps();
223 }
224
225 /**
226 * @tc.name: testSwitchToCurrentImeWithEmptySubName
227 * @tc.desc: switch to currentIme witch empty subName.
228 * @tc.type: FUNC
229 * @tc.require: issuesI62BHB
230 * @tc.author: chenyu
231 */
232 HWTEST_F(InputMethodSwitchTest, testSwitchToCurrentImeWithEmptySubName, TestSize.Level0)
233 {
234 IMSA_HILOGI("oldIme testSwitchToCurrentImeWithEmptySubName Test START");
235 std::unique_lock<std::mutex> lock(imeChangeFlagLock);
236 imeChangeFlag = false;
237 std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
238 int32_t ret = imc_->SwitchInputMethod(bundleName);
239 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
240 InputMethodSwitchTest::conditionVar.wait_for(
__anon2b3816f50402null241 lock, std::chrono::milliseconds(SUBTYPE_SWITCH_DELAY_TIME), [] { return imeChangeFlag == true; });
242 EXPECT_FALSE(imeChangeFlag);
243 CheckCurrentProp(subName);
244 CheckCurrentSubProp(subName);
245 CheckCurrentSubProps();
246 }
247
248 /**
249 * @tc.name: testSwitchImeWithErrorBundleName
250 * @tc.desc: switch ime witch error bundleName
251 * @tc.type: FUNC
252 * @tc.require: issuesI62BHB
253 * @tc.author: chenyu
254 */
255 HWTEST_F(InputMethodSwitchTest, testSwitchImeWithErrorBundleName, TestSize.Level0)
256 {
257 IMSA_HILOGI("oldIme testSwitchImeWithErrorBundleName Test START");
258 std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
259 int32_t ret = imc_->SwitchInputMethod("error bundleName", extName[0]);
260 EXPECT_EQ(ret, ErrorCode::ERROR_BAD_PARAMETERS);
261 CheckCurrentProp(subName);
262 CheckCurrentSubProp(subName);
263 CheckCurrentSubProps();
264 }
265
266 /**
267 * @tc.name: testSwitchImeWithErrorBundleNameWitchEmptySubName
268 * @tc.desc: switch ime witch error bundleName and empty subName
269 * @tc.type: FUNC
270 * @tc.require: issuesI62BHB
271 * @tc.author: chenyu
272 */
273 HWTEST_F(InputMethodSwitchTest, testSwitchImeWithErrorBundleNameWitchEmptySubName, TestSize.Level0)
274 {
275 IMSA_HILOGI("oldIme testSwitchImeWithErrorBundleNameWitchEmptySubName Test START");
276 std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
277 int32_t ret = imc_->SwitchInputMethod("error bundleName", " ");
278 EXPECT_EQ(ret, ErrorCode::ERROR_BAD_PARAMETERS);
279 CheckCurrentProp(subName);
280 CheckCurrentSubProp(subName);
281 CheckCurrentSubProps();
282 }
283
284 /**
285 * @tc.name: testIMCListInputMethod
286 * @tc.desc: IMC ListInputMethod
287 * @tc.type: FUNC
288 * @tc.require: issuesI62BHB
289 * @tc.author: chenyu
290 */
291 HWTEST_F(InputMethodSwitchTest, testIMCListInputMethod, TestSize.Level0)
292 {
293 IMSA_HILOGI("IMC testIMCListInputMethod Test Start");
294 std::vector<Property> properties = {};
295 auto ret = imc_->ListInputMethod(properties);
296 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
297 EXPECT_TRUE(properties.size() >= TOTAL_IME_MIN_NUM);
298 bool hasIme = false;
299 bool hasNewIme = false;
300 for (const auto &property : properties) {
301 if (property.name == bundleName) {
302 hasIme = true;
303 }
304 if (property.name == newImeBundleName) {
305 hasNewIme = true;
306 }
307 }
308 EXPECT_TRUE(hasIme && hasNewIme);
309 }
310
311 /**
312 * @tc.name: testIMCListInputMethodDisable
313 * @tc.desc: IMC ListInputMethod
314 * @tc.type: FUNC
315 * @tc.require: issuesI62BHB
316 * @tc.author: chenyu
317 */
318 HWTEST_F(InputMethodSwitchTest, testIMCListInputMethodDisable, TestSize.Level0)
319 {
320 IMSA_HILOGI("IMC testIMCListInputMethodDisable Test Start");
321 std::vector<Property> disableProperties = {};
322 auto ret = imc_->ListInputMethod(false, disableProperties);
323 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
324 bool hasNewIme = false;
325 for (const auto &disableProperty : disableProperties) {
326 if (disableProperty.name == newImeBundleName) {
327 hasNewIme = true;
328 break;
329 }
330 }
331 EXPECT_TRUE(hasNewIme);
332 }
333
334 /**
335 * @tc.name: testIMCListInputMethodEnable
336 * @tc.desc: IMC ListInputMethod
337 * @tc.type: FUNC
338 * @tc.require: issuesI62BHB
339 * @tc.author: chenyu
340 */
341 HWTEST_F(InputMethodSwitchTest, testIMCListInputMethodEnable, TestSize.Level0)
342 {
343 IMSA_HILOGI("IMC testIMCListInputMethodEnable Test Start");
344 std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
345 std::vector<Property> enableProperties = {};
346 auto ret = imc_->ListInputMethod(true, enableProperties);
347 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
348 EXPECT_EQ(enableProperties.size(), ENABLE_IME_NUM);
349 EXPECT_EQ(enableProperties[ENABLE_IME_NUM - 1].name, bundleName);
350 EXPECT_EQ(enableProperties[ENABLE_IME_NUM - 1].id, subName);
351 }
352
353 /**
354 * @tc.name: tesIMCtListInputMethodSubtype_001
355 * @tc.desc: ListInputMethodSubtype
356 * @tc.type: FUNC
357 * @tc.require: issuesI62BHB
358 * @tc.author: chenyu
359 */
360 HWTEST_F(InputMethodSwitchTest, tesIMCtListInputMethodSubtype_001, TestSize.Level0)
361 {
362 IMSA_HILOGI("IMC tesIMCtListInputMethodSubtype_001 Test Start");
363 Property property = { .name = newImeBundleName };
364 std::vector<SubProperty> subProps;
365 auto ret = imc_->ListInputMethodSubtype(property, subProps);
366 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
367 ASSERT_EQ(subProps.size(), NEW_IME_SUBTYPE_NUM);
368 for (uint32_t i = 0; i < NEW_IME_SUBTYPE_NUM; i++) {
369 EXPECT_EQ(subProps[i].id, newImeSubName[i]);
370 EXPECT_EQ(subProps[i].name, newImeBundleName);
371 }
372 }
373
374 /**
375 * @tc.name: tesIMCtListInputMethodSubtype_002
376 * @tc.desc: ListInputMethodSubtype
377 * @tc.type: FUNC
378 * @tc.require: issuesI62BHB
379 * @tc.author: chenyu
380 */
381 HWTEST_F(InputMethodSwitchTest, tesIMCtListInputMethodSubtype_002, TestSize.Level0)
382 {
383 IMSA_HILOGI("IMC tesIMCtListInputMethodSubtype_002 Test Start");
384 Property property = { .name = bundleName };
385 std::vector<SubProperty> subProps;
386 auto ret = imc_->ListInputMethodSubtype(property, subProps);
387 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
388 ASSERT_EQ(subProps.size(), IME_EXT_NUM);
389 for (uint32_t i = 0; i < IME_EXT_NUM; i++) {
390 EXPECT_EQ(subProps[i].id, extName[i]);
391 EXPECT_EQ(subProps[i].name, bundleName);
392 }
393 }
394
395 /**
396 * @tc.name: testIMCListInputMethodSubtypeWithErrorBundleName
397 * @tc.desc: IMC ListInputMethodSubtype
398 * @tc.type: FUNC
399 * @tc.require: issuesI62BHB
400 * @tc.author: chenyu
401 */
402 HWTEST_F(InputMethodSwitchTest, testIMCListInputMethodSubtypeWithErrorBundleName, TestSize.Level0)
403 {
404 IMSA_HILOGI("IMC testIMCListInputMethodSubtypeWitchErrorBundleName Test START");
405 std::shared_ptr<Property> property = std::make_shared<Property>();
406 std::vector<SubProperty> properties = {};
407 auto ret = imc_->ListInputMethodSubtype(*property, properties);
408 EXPECT_EQ(ret, ErrorCode::ERROR_BAD_PARAMETERS);
409 EXPECT_TRUE(properties.empty());
410 }
411
412 /**
413 * @tc.name: testShowOptionalInputMethod
414 * @tc.desc: IMC ShowOptionalInputMethod
415 * @tc.type: FUNC
416 */
417 HWTEST_F(InputMethodSwitchTest, testShowOptionalInputMethod, TestSize.Level2)
418 {
419 IMSA_HILOGI("IMC ShowOptionalInputMethod Test START");
420 int32_t ret = imc_->ShowOptionalInputMethod();
421 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
422 }
423
424 /**
425 * @tc.name: testDisplayOptionalInputMethod
426 * @tc.desc: IMC DisplayOptionalInputMethod
427 * @tc.type: FUNC
428 */
429 HWTEST_F(InputMethodSwitchTest, testDisplayOptionalInputMethod, TestSize.Level2)
430 {
431 IMSA_HILOGI("IMC DisplayOptionalInputMethod Test START");
432 sleep(2);
433 int32_t ret = imc_->DisplayOptionalInputMethod();
434 EXPECT_EQ(ret, ErrorCode::NO_ERROR);
435 }
436 } // namespace MiscServices
437 } // namespace OHOS
438