* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include <sys/time.h>
#include <unistd.h>
#include <condition_variable>
#include <string>
#include <vector>
#include "global.h"
#include "ime_event_monitor_manager_impl.h"
#include "ime_setting_listener_test_impl.h"
#include "input_method_controller.h"
#include "input_method_property.h"
#include "tdd_util.h"
using namespace testing::ext;
namespace OHOS {
namespace MiscServices {
class InputMethodSwitchTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
void SetUp();
void TearDown();
static void CheckCurrentProp(const std::string &extName);
static void CheckCurrentSubProp(const std::string &extName);
static void CheckCurrentSubProps();
static sptr<InputMethodController> imc_;
static std::string newImeBundleName;
static std::vector<std::string> newImeSubName;
static std::string newExtName;
static std::string bundleName;
static std::vector<std::string> extName;
static std::vector<std::string> language;
static std::vector<std::string> locale;
};
sptr<InputMethodController> InputMethodSwitchTest::imc_;
std::string InputMethodSwitchTest::newImeBundleName = "com.example.newTestIme";
std::string InputMethodSwitchTest::newExtName = "InputMethodExtAbility";
std::vector<std::string> InputMethodSwitchTest::newImeSubName { "lowerInput", "upperInput", "chineseInput" };
std::string InputMethodSwitchTest::bundleName = "com.example.testIme";
std::vector<std::string> InputMethodSwitchTest::extName { "InputMethodExtAbility", "InputMethodExtAbility2" };
std::vector<std::string> InputMethodSwitchTest::language { "chinese", "english" };
std::vector<std::string> InputMethodSwitchTest::locale { "zh-CN", "en-US" };
constexpr uint32_t IME_EXT_NUM = 2;
constexpr uint32_t NEW_IME_SUBTYPE_NUM = 3;
constexpr uint32_t TOTAL_IME_MIN_NUM = 2;
constexpr uint32_t ENABLE_IME_NUM = 1;
constexpr uint32_t WAIT_IME_READY_TIME = 1;
void InputMethodSwitchTest::SetUpTestCase(void)
{
IMSA_HILOGI("InputMethodSwitchTest::SetUpTestCase");
TddUtil::StorageSelfTokenID();
TddUtil::SetTestTokenID(TddUtil::AllocTestTokenID(true, "ohos.inputMethod.test",
{ "ohos.permission.CONNECT_IME_ABILITY", "ohos.permission.INJECT_INPUT_EVENT" }));
TddUtil::EnabledAllIme();
imc_ = InputMethodController::GetInstance();
auto listener = std::make_shared<ImeSettingListenerTestImpl>();
ImeEventMonitorManagerImpl::GetInstance().RegisterImeEventListener(EVENT_IME_CHANGE_MASK, listener);
}
void InputMethodSwitchTest::TearDownTestCase(void)
{
IMSA_HILOGI("InputMethodSwitchTest::TearDownTestCase");
InputMethodController::GetInstance()->Close();
TddUtil::RestoreSelfTokenID();
}
void InputMethodSwitchTest::SetUp(void)
{
IMSA_HILOGI("InputMethodSwitchTest::SetUp");
}
void InputMethodSwitchTest::TearDown(void)
{
IMSA_HILOGI("InputMethodSwitchTest::TearDown");
}
void InputMethodSwitchTest::CheckCurrentProp(const std::string &extName)
{
std::shared_ptr<Property> property = imc_->GetCurrentInputMethod();
ASSERT_TRUE(property != nullptr);
EXPECT_EQ(property->name, bundleName);
EXPECT_EQ(property->id, extName);
}
void InputMethodSwitchTest::CheckCurrentSubProp(const std::string &extName)
{
auto subProperty = imc_->GetCurrentInputMethodSubtype();
ASSERT_TRUE(subProperty != nullptr);
EXPECT_EQ(subProperty->id, extName);
EXPECT_EQ(subProperty->name, bundleName);
}
void InputMethodSwitchTest::CheckCurrentSubProps()
{
std::vector<SubProperty> subProps;
auto ret = imc_->ListCurrentInputMethodSubtype(subProps);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
ASSERT_EQ(subProps.size(), IME_EXT_NUM);
for (uint32_t i = 0; i < IME_EXT_NUM; i++) {
EXPECT_EQ(subProps[i].id, extName[i]);
EXPECT_EQ(subProps[i].name, bundleName);
EXPECT_EQ(subProps[i].language, language[i]);
EXPECT_EQ(subProps[i].locale, locale[i]);
}
}
* @tc.name: testImeSwitch
* @tc.desc: switch to testIme
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testImeSwitch, TestSize.Level0)
{
IMSA_HILOGI("oldIme testImeSwitch Test START");
ImeSettingListenerTestImpl::ResetParam();
auto ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
CheckCurrentProp(extName[0]);
CheckCurrentSubProp(extName[0]);
CheckCurrentSubProps();
sleep(WAIT_IME_READY_TIME);
}
* @tc.name: testSubTypeSwitch_001
* @tc.desc: switch subtype with extName1
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testSubTypeSwitch_001, TestSize.Level0)
{
IMSA_HILOGI("oldIme testSubTypeSwitch_001 Test START");
ImeSettingListenerTestImpl::ResetParam();
int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName, extName[0]);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
CheckCurrentProp(extName[0]);
CheckCurrentSubProp(extName[0]);
CheckCurrentSubProps();
}
* @tc.name: testSubTypeSwitch_002
* @tc.desc: switch subtype with extName2
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testSubTypeSwitch_002, TestSize.Level0)
{
IMSA_HILOGI("oldIme testSubTypeSwitch_002 Test START");
ImeSettingListenerTestImpl::ResetParam();
int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName, extName[1]);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
CheckCurrentProp(extName[0]);
CheckCurrentSubProp(extName[1]);
CheckCurrentSubProps();
}
* @tc.name: testSubTypeSwitch_003
* @tc.desc: switch subtype with extName1
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testSubTypeSwitch_003, TestSize.Level0)
{
IMSA_HILOGI("oldIme testSubTypeSwitch_003 Test START");
ImeSettingListenerTestImpl::ResetParam();
int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName, extName[0]);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
CheckCurrentProp(extName[0]);
CheckCurrentSubProp(extName[0]);
CheckCurrentSubProps();
}
* @tc.name: testSubTypeSwitchWithErrorSubName
* @tc.desc: switch subtype with error subName.
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testSubTypeSwitchWithErrorSubName, TestSize.Level0)
{
IMSA_HILOGI("oldIme testSubTypeSwitchWithErrorSubName Test START");
std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName, "error subName");
EXPECT_EQ(ret, ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED);
CheckCurrentProp(subName);
CheckCurrentSubProp(subName);
CheckCurrentSubProps();
}
* @tc.name: testSwitchToCurrentImeWithEmptySubName
* @tc.desc: switch to currentIme witch empty subName.
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testSwitchToCurrentImeWithEmptySubName, TestSize.Level0)
{
IMSA_HILOGI("oldIme testSwitchToCurrentImeWithEmptySubName Test START");
ImeSettingListenerTestImpl::ResetParam();
std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, bundleName);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
CheckCurrentProp(subName);
CheckCurrentSubProp(subName);
CheckCurrentSubProps();
}
* @tc.name: testSwitchImeWithErrorBundleName
* @tc.desc: switch ime witch error bundleName
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testSwitchImeWithErrorBundleName, TestSize.Level0)
{
IMSA_HILOGI("oldIme testSwitchImeWithErrorBundleName Test START");
std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, "error bundleName", extName[0]);
EXPECT_TRUE(ret == ErrorCode::ERROR_ENABLE_IME || ret == ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED);
CheckCurrentProp(subName);
CheckCurrentSubProp(subName);
CheckCurrentSubProps();
}
* @tc.name: testSwitchImeWithErrorBundleNameWitchEmptySubName
* @tc.desc: switch ime witch error bundleName and empty subName
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testSwitchImeWithErrorBundleNameWitchEmptySubName, TestSize.Level0)
{
IMSA_HILOGI("oldIme testSwitchImeWithErrorBundleNameWitchEmptySubName Test START");
std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
int32_t ret = imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, "error bundleName", " ");
EXPECT_TRUE(ret == ErrorCode::ERROR_ENABLE_IME || ret == ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED);
CheckCurrentProp(subName);
CheckCurrentSubProp(subName);
CheckCurrentSubProps();
}
* @tc.name: testIMCListInputMethod
* @tc.desc: IMC ListInputMethod
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testIMCListInputMethod, TestSize.Level0)
{
IMSA_HILOGI("IMC testIMCListInputMethod Test Start");
std::vector<Property> properties = {};
auto ret = imc_->ListInputMethod(properties);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_TRUE(properties.size() >= TOTAL_IME_MIN_NUM);
bool hasIme = false;
bool hasNewIme = false;
for (const auto &property : properties) {
if (property.name == bundleName) {
hasIme = true;
}
if (property.name == newImeBundleName) {
hasNewIme = true;
}
}
EXPECT_TRUE(hasIme && hasNewIme);
}
* @tc.name: testIMCListInputMethodDisable
* @tc.desc: IMC ListInputMethod
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testIMCListInputMethodDisable, TestSize.Level0)
{
IMSA_HILOGI("IMC testIMCListInputMethodDisable Test Start");
std::vector<Property> disableProperties = {};
auto ret = imc_->ListInputMethod(false, disableProperties);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_GE(disableProperties.size(), 0);
}
* @tc.name: testIMCListInputMethodEnable
* @tc.desc: IMC ListInputMethod
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testIMCListInputMethodEnable, TestSize.Level0)
{
IMSA_HILOGI("IMC testIMCListInputMethodEnable Test Start");
std::string subName = InputMethodSwitchTest::imc_->GetCurrentInputMethodSubtype()->id;
std::vector<Property> enableProperties = {};
auto ret = imc_->ListInputMethod(true, enableProperties);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_GE(enableProperties.size(), ENABLE_IME_NUM);
}
* @tc.name: tesIMCtListInputMethodSubtype_001
* @tc.desc: ListInputMethodSubtype
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, tesIMCtListInputMethodSubtype_001, TestSize.Level0)
{
IMSA_HILOGI("IMC tesIMCtListInputMethodSubtype_001 Test Start");
Property property;
property.name = newImeBundleName;
std::vector<SubProperty> subProps;
auto ret = imc_->ListInputMethodSubtype(property, subProps);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
ASSERT_EQ(subProps.size(), NEW_IME_SUBTYPE_NUM);
for (uint32_t i = 0; i < NEW_IME_SUBTYPE_NUM; i++) {
EXPECT_EQ(subProps[i].id, newImeSubName[i]);
EXPECT_EQ(subProps[i].name, newImeBundleName);
}
}
* @tc.name: tesIMCtListInputMethodSubtype_002
* @tc.desc: ListInputMethodSubtype
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, tesIMCtListInputMethodSubtype_002, TestSize.Level0)
{
IMSA_HILOGI("IMC tesIMCtListInputMethodSubtype_002 Test Start");
Property property;
property.name = bundleName;
std::vector<SubProperty> subProps;
auto ret = imc_->ListInputMethodSubtype(property, subProps);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
ASSERT_EQ(subProps.size(), IME_EXT_NUM);
for (uint32_t i = 0; i < IME_EXT_NUM; i++) {
EXPECT_EQ(subProps[i].id, extName[i]);
EXPECT_EQ(subProps[i].name, bundleName);
}
}
* @tc.name: testIMCListInputMethodSubtypeWithErrorBundleName
* @tc.desc: IMC ListInputMethodSubtype
* @tc.type: FUNC
* @tc.require: issuesI62BHB
* @tc.author: chenyu
*/
HWTEST_F(InputMethodSwitchTest, testIMCListInputMethodSubtypeWithErrorBundleName, TestSize.Level0)
{
IMSA_HILOGI("IMC testIMCListInputMethodSubtypeWitchErrorBundleName Test START");
std::shared_ptr<Property> property = std::make_shared<Property>();
std::vector<SubProperty> properties = {};
auto ret = imc_->ListInputMethodSubtype(*property, properties);
EXPECT_EQ(ret, ErrorCode::ERROR_BAD_PARAMETERS);
EXPECT_TRUE(properties.empty());
}
* @tc.name: testShowOptionalInputMethod
* @tc.desc: IMC ShowOptionalInputMethod
* @tc.type: FUNC
*/
HWTEST_F(InputMethodSwitchTest, testShowOptionalInputMethod, TestSize.Level2)
{
IMSA_HILOGI("IMC ShowOptionalInputMethod Test START");
int32_t ret = imc_->ShowOptionalInputMethod();
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
}
* @tc.name: testDisplayOptionalInputMethod
* @tc.desc: IMC DisplayOptionalInputMethod
* @tc.type: FUNC
*/
HWTEST_F(InputMethodSwitchTest, testDisplayOptionalInputMethod, TestSize.Level2)
{
IMSA_HILOGI("IMC DisplayOptionalInputMethod Test START");
sleep(2);
int32_t ret = imc_->DisplayOptionalInputMethod();
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
}
* @tc.name: testCombinationKeySwitchIme_001
* @tc.desc: switch ime by combination key.
* @tc.type: FUNC
* @tc.require: issuesI8RPP3
* @tc.author: mashaoyin
*/
HWTEST_F(InputMethodSwitchTest, testCombinationKeySwitchIme_001, TestSize.Level0)
{
IMSA_HILOGI("testCombinationKeySwitchIme_001 Test START");
ImeSettingListenerTestImpl::ResetParam();
std::shared_ptr<Property> property = imc_->GetCurrentInputMethod();
std::string result;
static std::string cmd = "uinput -K -d 2076 -d 2050";
auto ret = TddUtil::ExecuteCmd(cmd, result);
EXPECT_TRUE(ret);
EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, property->name, "");
}
* @tc.name: testCombinationKeySwitchIme_002
* @tc.desc: switch ime by combination key.
* @tc.type: FUNC
* @tc.require: issuesI8RPP3
* @tc.author: mashaoyin
*/
HWTEST_F(InputMethodSwitchTest, testCombinationKeySwitchIme_002, TestSize.Level0)
{
IMSA_HILOGI("testCombinationKeySwitchIme_002 Test START");
ImeSettingListenerTestImpl::ResetParam();
std::shared_ptr<Property> property = imc_->GetCurrentInputMethod();
std::string result;
static std::string cmd = "uinput -K -d 2077 -d 2050";
auto ret = TddUtil::ExecuteCmd(cmd, result);
EXPECT_TRUE(ret);
EXPECT_TRUE(ImeSettingListenerTestImpl::WaitImeChange());
imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, property->name, "");
}
* @tc.name: testCombinationKeySwitchIme_003
* @tc.desc: switch ime by combination key.
* @tc.type: FUNC
* @tc.require: issuesI8RPP3
* @tc.author: mashaoyin
*/
HWTEST_F(InputMethodSwitchTest, testCombinationKeySwitchIme_003, TestSize.Level0)
{
IMSA_HILOGI("testCombinationKeySwitchIme_003 Test START");
ImeSettingListenerTestImpl::ResetParam();
std::shared_ptr<Property> property = imc_->GetCurrentInputMethod();
std::vector<Property> props;
imc_->ListInputMethod(true, props);
std::string result;
static std::string cmd = "uinput -K -d 2077 -d 2050 -u 2050 -u 2077";
for (auto iter = 0; iter < props.size(); ++iter) {
auto ret = TddUtil::ExecuteCmd(cmd, result);
EXPECT_TRUE(ret);
}
EXPECT_TRUE(ImeSettingListenerTestImpl::WaitTargetImeChange(property->name));
std::shared_ptr<Property> curProperty = imc_->GetCurrentInputMethod();
EXPECT_EQ(property->name, curProperty->name);
imc_->SwitchInputMethod(SwitchTrigger::CURRENT_IME, property->name, "");
}
}
}