* 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 "basic_tdd_test.h"
#include <cstring>
#include <sys/prctl.h>
#include "async_task_manager.h"
#include "common/graphic_startup.h"
#include "common/task_manager.h"
#include "component_utils.h"
#include "core/render_manager.h"
#include "descriptor_utils.h"
#include "dock/screen_device_proxy.h"
#include "event_injector.h"
#include "js_app_context.h"
#include "js_app_environment.h"
#include "module_manager.h"
#include "root_view.h"
namespace OHOS {
namespace ACELite {
BasicTddTest::BasicTddTest() : rootComponent_(nullptr) {}
BasicTddTest::~BasicTddTest() {}
ScreenDevice *BasicTddTest::display_ = nullptr;
Window *BasicTddTest::window_ = nullptr;
pthread_t BasicTddTest::tickThread_ = -1;
bool BasicTddTest::isTickTaskRunning_ = false;
constexpr uint16_t TICK = 10000;
constexpr uint32_t SWIPE_TIME = 100;
constexpr uint8_t NUMBER_TWO = 2;
void BasicTddTest::SetUpTestCase(void)
{
GraphicStartUp::Init();
isTickTaskRunning_ = true;
display_ = new ScreenDevice();
ScreenDeviceProxy::GetInstance()->SetDevice(display_);
ScreenDeviceProxy::GetInstance()->SetScreenSize(HORIZONTAL_RESOLUTION, VERTICAL_RESOLUTION);
WindowConfig config = {};
uint16_t width = GetHorizontalResolution();
uint16_t height = GetVerticalResolution();
config.rect.SetRect(0, 0, width - 1, height - 1);
window_ = Window::CreateWindow(config);
RootView *rootView = RootView::GetInstance();
rootView->SetPosition(0, 0);
rootView->SetWidth(width);
rootView->SetHeight(height);
window_->BindRootView(rootView);
TaskManager::GetInstance()->Remove(&RenderManager::GetInstance());
if (pthread_create(&tickThread_, nullptr, TickHandler, nullptr) == 0) {
pthread_detach(tickThread_);
HILOG_DEBUG(HILOG_MODULE_ACE, "[BasicTddTest::SetUpTestCase]: Success to fork tick thread.");
} else {
HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::SetUpTestCase]: Failed to fork tick thread.");
}
}
void BasicTddTest::TearDownTestCase(void)
{
isTickTaskRunning_ = false;
if (window_ != nullptr) {
Window::DestroyWindow(window_);
window_ = nullptr;
}
if (display_ != nullptr) {
delete display_;
display_ = nullptr;
}
}
void BasicTddTest::SetUp()
{
JsAppContext *appContext = JsAppContext::GetInstance();
const int32_t apiVersion = 6;
appContext->SetCompatibleApi(apiVersion);
appContext->SetTargetApi(apiVersion);
JsAppEnvironment::GetInstance()->InitJsFramework();
EventInjector *injector = EventInjector::GetInstance();
if (!injector->IsEventInjectorRegistered(EventDataType::POINT_TYPE)) {
injector->RegisterEventInjector(EventDataType::POINT_TYPE);
}
injector->SetWindowId(window_->GetWindowId());
AsyncTaskManager::GetInstance().SetFront(true);
}
void BasicTddTest::TearDown()
{
ModuleManager::GetInstance()->CleanUpModule();
JsAppEnvironment::GetInstance()->Cleanup();
EventInjector *injector = EventInjector::GetInstance();
if (injector->IsEventInjectorRegistered(EventDataType::POINT_TYPE)) {
injector->UnregisterEventInjector(EventDataType::POINT_TYPE);
}
AsyncTaskManager::GetInstance().SetFront(false);
}
JSValue BasicTddTest::RunJS(const char *bundle, const uint32_t size) const
{
return jerry_eval(reinterpret_cast<const jerry_char_t *>(bundle), size, JERRY_PARSE_NO_OPTS);
}
JSValue BasicTddTest::CreatePage(const char *bundle, const uint32_t size)
{
JSValue page = RunJS(bundle, size);
if (JSError::Is(page)) {
return JSUndefined::Create();
}
JSGlobal::Set("$root", page);
CallLifecycle(page, "onInit");
JSValue rootEl = JSObject::Call(page, "$render");
if (JSUndefined::Is(rootEl) || JSError::Is(rootEl)) {
HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::CreatePage]: Failed to render page.");
JSRelease(rootEl);
JSRelease(page);
return JSUndefined::Create();
}
CallLifecycle(page, "onReady");
rootComponent_ = ComponentUtils::GetComponentFromBindingObject(rootEl);
if (rootComponent_ == nullptr) {
HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::CreatePage]: Failed to get root component.");
JSRelease(rootEl);
JSRelease(page);
return JSUndefined::Create();
}
uint16_t horizontalResolution = GetHorizontalResolution();
uint16_t verticalResolution = GetVerticalResolution();
ConstrainedParameter rootViewParam(horizontalResolution, verticalResolution);
Component::BuildViewTree(rootComponent_, nullptr, rootViewParam);
rootComponent_->OnViewAttached();
UIView *view = rootComponent_->GetComponentRootView();
if (view == nullptr) {
HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::CreatePage]: Failed to get page root view.");
JSRelease(rootEl);
JSRelease(page);
return JSUndefined::Create();
}
RootView *rootView = RootView::GetInstance();
rootView->Add(view);
rootView->Invalidate();
CallLifecycle(page, "onShow");
return page;
}
void BasicTddTest::DestroyPage(JSValue page)
{
RootView *rootView = RootView::GetInstance();
rootView->RemoveAll();
rootView->Invalidate();
CallLifecycle(page, "onHide");
CallLifecycle(page, "onDestroy");
ComponentUtils::ReleaseComponents(rootComponent_);
rootComponent_ = nullptr;
JsAppContext::GetInstance()->ReleaseStyles();
JSGlobal::Del("$root");
JSRelease(page);
}
UIView *BasicTddTest::GetViewByRef(JSValue page, const char *ref) const
{
JSValue refs = JSObject::Get(page, "$refs");
if (JSUndefined::Is(refs)) {
JSRelease(refs);
return nullptr;
}
JSValue dom = JSObject::Get(refs, ref);
if (JSUndefined::Is(dom)) {
JSRelease(refs);
JSRelease(dom);
return nullptr;
}
UIView *view = ComponentUtils::GetViewFromBindingObject(dom);
JSRelease(refs);
JSRelease(dom);
return view;
}
void BasicTddTest::ClickByRef(JSValue page, const char *ref, uint8_t sleepTicks) const
{
return Click(GetViewByRef(page, ref), sleepTicks);
}
void BasicTddTest::LongPressByRef(JSValue page, const char *ref, uint8_t sleepTicks) const
{
return LongPress(GetViewByRef(page, ref), sleepTicks);
}
void BasicTddTest::Click(const UIView *view, uint8_t sleepTicks) const
{
if (view == nullptr) {
HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::Click]: Failed to click because view is nullptr");
return;
}
Rect rect = view->GetOrigRect();
int16_t x = rect.GetLeft() + rect.GetWidth() / NUMBER_TWO;
int16_t y = rect.GetTop() + rect.GetHeight() / NUMBER_TWO;
return Click(x, y, sleepTicks);
}
void BasicTddTest::LongPress(const UIView *view, uint8_t sleepTicks) const
{
if (view == nullptr) {
HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::LongPress]: Failed to long press because view is nullptr");
return;
}
Rect rect = view->GetOrigRect();
int16_t x = rect.GetLeft() + rect.GetWidth() / NUMBER_TWO;
int16_t y = rect.GetTop() + rect.GetHeight() / NUMBER_TWO;
return LongPress(x, y, sleepTicks);
}
void BasicTddTest::Click(int16_t x, int16_t y, uint8_t sleepTicks) const
{
Point point = {x, y};
EventInjector *injector = EventInjector::GetInstance();
if (injector->SetClickEvent(point)) {
HILOG_DEBUG(HILOG_MODULE_ACE,
"[BasicTddTest::Click]: Success to inject CLICK event on (%{public}d, %{public}d)\n", x, y);
} else {
HILOG_ERROR(HILOG_MODULE_ACE,
"[BasicTddTest::Click]: Failed to inject CLICK event on (%{public}d, %{public}d)\n", x, y);
}
usleep(sleepTicks * TICK);
}
void BasicTddTest::LongPress(int16_t x, int16_t y, uint8_t sleepTicks) const
{
Point point = {x, y};
EventInjector *injector = EventInjector::GetInstance();
if (injector->SetLongPressEvent(point)) {
HILOG_DEBUG(HILOG_MODULE_ACE,
"[BasicTddTest::LongPress]: Success to inject LONGPRESS event on (%{public}d, %{public}d)\n", x, y);
} else {
HILOG_ERROR(HILOG_MODULE_ACE,
"[BasicTddTest::LongPress]: Failed to inject LONGPRESS event on (%{public}d, %{public}d)\n", x, y);
}
usleep(sleepTicks * TICK);
}
void BasicTddTest::Swipe(int16_t startX, int16_t startY, int16_t endX, int16_t endY, uint8_t sleepTicks) const
{
Point startPoint = {startX, startY};
Point endPoint = {endX, endY};
EventInjector *injector = EventInjector::GetInstance();
if (injector->SetDragEvent(startPoint, endPoint, SWIPE_TIME)) {
HILOG_DEBUG(HILOG_MODULE_ACE,
"[BasicTddTest::Swipe]: Success to inject SWIPE event from (%{public}d, %{public}d) to "
"(%{public}d, %{public}d)\n",
startX, startY, endX, endY);
} else {
HILOG_ERROR(
HILOG_MODULE_ACE,
"[BasicTddTest::Swipe]: Failed to inject SWIPE from (%{public}d, %{public}d) to (%{public}d, %{public}d)\n",
startX, startY, endX, endY);
}
usleep(sleepTicks * TICK);
}
uint8_t BasicTddTest::GetChildrenSize(const UIViewGroup &grop) const
{
UIView *child = grop.GetChildrenHead();
uint8_t size = 0;
while (child != nullptr) {
++size;
child = child->GetNextSibling();
}
return size;
}
void *BasicTddTest::TickHandler(void *args)
{
(void)args;
prctl(PR_SET_NAME, "TickTask");
while (isTickTaskRunning_) {
TaskManager::GetInstance()->TaskHandler();
usleep(TICK);
}
return nullptr;
}
void BasicTddTest::CallLifecycle(JSValue page, const char *lifecycle) const
{
JSValue func = JSObject::Get(page, lifecycle);
if (JSFunction::Is(func)) {
JSRelease(JSFunction::Call(func, page, nullptr, 0));
}
JSRelease(func);
}
}
}