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 "basic_tdd_test.h"
16 #include <cstring>
17 #include <sys/prctl.h>
18 #include "async_task_manager.h"
19 #include "common/graphic_startup.h"
20 #include "common/task_manager.h"
21 #include "component_utils.h"
22 #include "core/render_manager.h"
23 #include "descriptor_utils.h"
24 #include "dock/screen_device_proxy.h"
25 #include "event_injector.h"
26 #include "js_app_context.h"
27 #include "js_app_environment.h"
28 #include "module_manager.h"
29 #include "root_view.h"
30
31 namespace OHOS {
32 namespace ACELite {
BasicTddTest()33 BasicTddTest::BasicTddTest() : rootComponent_(nullptr) {}
~BasicTddTest()34 BasicTddTest::~BasicTddTest() {}
35
36 ScreenDevice *BasicTddTest::display_ = nullptr;
37 Window *BasicTddTest::window_ = nullptr;
38 pthread_t BasicTddTest::tickThread_ = -1;
39 bool BasicTddTest::isTickTaskRunning_ = false;
40
41 // 10ms a tick
42 constexpr uint16_t TICK = 10000;
43 constexpr uint32_t SWIPE_TIME = 100;
44
45 constexpr uint8_t NUMBER_TWO = 2;
46
SetUpTestCase(void)47 void BasicTddTest::SetUpTestCase(void)
48 {
49 GraphicStartUp::Init();
50 isTickTaskRunning_ = true;
51
52 display_ = new ScreenDevice();
53 ScreenDeviceProxy::GetInstance()->SetDevice(display_);
54 ScreenDeviceProxy::GetInstance()->SetScreenSize(HORIZONTAL_RESOLUTION, VERTICAL_RESOLUTION);
55
56 WindowConfig config = {};
57 uint16_t width = GetHorizontalResolution();
58 uint16_t height = GetVerticalResolution();
59 config.rect.SetRect(0, 0, width - 1, height - 1);
60 window_ = Window::CreateWindow(config);
61 RootView *rootView = RootView::GetInstance();
62 rootView->SetPosition(0, 0);
63 rootView->SetWidth(width);
64 rootView->SetHeight(height);
65 window_->BindRootView(rootView);
66 TaskManager::GetInstance()->Remove(&RenderManager::GetInstance());
67 if (pthread_create(&tickThread_, nullptr, TickHandler, nullptr) == 0) {
68 pthread_detach(tickThread_);
69 HILOG_DEBUG(HILOG_MODULE_ACE, "[BasicTddTest::SetUpTestCase]: Success to fork tick thread.");
70 } else {
71 HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::SetUpTestCase]: Failed to fork tick thread.");
72 }
73 }
74
TearDownTestCase(void)75 void BasicTddTest::TearDownTestCase(void)
76 {
77 isTickTaskRunning_ = false;
78 if (window_ != nullptr) {
79 Window::DestroyWindow(window_);
80 window_ = nullptr;
81 }
82 if (display_ != nullptr) {
83 delete display_;
84 display_ = nullptr;
85 }
86 }
87
SetUp()88 void BasicTddTest::SetUp()
89 {
90 JsAppContext *appContext = JsAppContext::GetInstance();
91 const int32_t apiVersion = 6;
92 appContext->SetCompatibleApi(apiVersion);
93 appContext->SetTargetApi(apiVersion);
94 JsAppEnvironment::GetInstance()->InitJsFramework();
95 EventInjector *injector = EventInjector::GetInstance();
96 if (!injector->IsEventInjectorRegistered(EventDataType::POINT_TYPE)) {
97 injector->RegisterEventInjector(EventDataType::POINT_TYPE);
98 }
99 injector->SetWindowId(window_->GetWindowId());
100 AsyncTaskManager::GetInstance().SetFront(true);
101 }
102
TearDown()103 void BasicTddTest::TearDown()
104 {
105 ModuleManager::GetInstance()->CleanUpModule();
106 JsAppEnvironment::GetInstance()->Cleanup();
107
108 EventInjector *injector = EventInjector::GetInstance();
109 if (injector->IsEventInjectorRegistered(EventDataType::POINT_TYPE)) {
110 injector->UnregisterEventInjector(EventDataType::POINT_TYPE);
111 }
112 AsyncTaskManager::GetInstance().SetFront(false);
113 }
114
RunJS(const char * bundle,const uint32_t size) const115 JSValue BasicTddTest::RunJS(const char *bundle, const uint32_t size) const
116 {
117 return jerry_eval(reinterpret_cast<const jerry_char_t *>(bundle), size, JERRY_PARSE_NO_OPTS);
118 }
119
CreatePage(const char * bundle,const uint32_t size)120 JSValue BasicTddTest::CreatePage(const char *bundle, const uint32_t size)
121 {
122 JSValue page = RunJS(bundle, size);
123 if (JSError::Is(page)) {
124 return JSUndefined::Create();
125 }
126 JSGlobal::Set("$root", page);
127 CallLifecycle(page, "onInit");
128 JSValue rootEl = JSObject::Call(page, "$render");
129 if (JSUndefined::Is(rootEl) || JSError::Is(rootEl)) {
130 HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::CreatePage]: Failed to render page.");
131 JSRelease(rootEl);
132 JSRelease(page);
133 return JSUndefined::Create();
134 }
135 CallLifecycle(page, "onReady");
136 rootComponent_ = ComponentUtils::GetComponentFromBindingObject(rootEl);
137 if (rootComponent_ == nullptr) {
138 HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::CreatePage]: Failed to get root component.");
139 JSRelease(rootEl);
140 JSRelease(page);
141 return JSUndefined::Create();
142 }
143 uint16_t horizontalResolution = GetHorizontalResolution();
144 uint16_t verticalResolution = GetVerticalResolution();
145 ConstrainedParameter rootViewParam(horizontalResolution, verticalResolution);
146 Component::BuildViewTree(rootComponent_, nullptr, rootViewParam);
147 rootComponent_->OnViewAttached();
148 UIView *view = rootComponent_->GetComponentRootView();
149 if (view == nullptr) {
150 HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::CreatePage]: Failed to get page root view.");
151 JSRelease(rootEl);
152 JSRelease(page);
153 return JSUndefined::Create();
154 }
155 RootView *rootView = RootView::GetInstance();
156 rootView->Add(view);
157 rootView->Invalidate();
158 CallLifecycle(page, "onShow");
159 return page;
160 }
161
DestroyPage(JSValue page)162 void BasicTddTest::DestroyPage(JSValue page)
163 {
164 RootView *rootView = RootView::GetInstance();
165 rootView->RemoveAll();
166 rootView->Invalidate();
167 CallLifecycle(page, "onHide");
168 CallLifecycle(page, "onDestroy");
169 ComponentUtils::ReleaseComponents(rootComponent_);
170 rootComponent_ = nullptr;
171 JsAppContext::GetInstance()->ReleaseStyles();
172 JSGlobal::Del("$root");
173 JSRelease(page);
174 }
175
GetViewByRef(JSValue page,const char * ref) const176 UIView *BasicTddTest::GetViewByRef(JSValue page, const char *ref) const
177 {
178 JSValue refs = JSObject::Get(page, "$refs");
179 if (JSUndefined::Is(refs)) {
180 JSRelease(refs);
181 return nullptr;
182 }
183 JSValue dom = JSObject::Get(refs, ref);
184 if (JSUndefined::Is(dom)) {
185 JSRelease(refs);
186 JSRelease(dom);
187 return nullptr;
188 }
189 UIView *view = ComponentUtils::GetViewFromBindingObject(dom);
190 JSRelease(refs);
191 JSRelease(dom);
192 return view;
193 }
194
ClickByRef(JSValue page,const char * ref,uint8_t sleepTicks) const195 void BasicTddTest::ClickByRef(JSValue page, const char *ref, uint8_t sleepTicks) const
196 {
197 return Click(GetViewByRef(page, ref), sleepTicks);
198 }
199
LongPressByRef(JSValue page,const char * ref,uint8_t sleepTicks) const200 void BasicTddTest::LongPressByRef(JSValue page, const char *ref, uint8_t sleepTicks) const
201 {
202 return LongPress(GetViewByRef(page, ref), sleepTicks);
203 }
204
Click(const UIView * view,uint8_t sleepTicks) const205 void BasicTddTest::Click(const UIView *view, uint8_t sleepTicks) const
206 {
207 if (view == nullptr) {
208 HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::Click]: Failed to click because view is nullptr");
209 return;
210 }
211 Rect rect = view->GetOrigRect();
212 int16_t x = rect.GetLeft() + rect.GetWidth() / NUMBER_TWO;
213 int16_t y = rect.GetTop() + rect.GetHeight() / NUMBER_TWO;
214 return Click(x, y, sleepTicks);
215 }
216
LongPress(const UIView * view,uint8_t sleepTicks) const217 void BasicTddTest::LongPress(const UIView *view, uint8_t sleepTicks) const
218 {
219 if (view == nullptr) {
220 HILOG_ERROR(HILOG_MODULE_ACE, "[BasicTddTest::LongPress]: Failed to long press because view is nullptr");
221 return;
222 }
223 Rect rect = view->GetOrigRect();
224 int16_t x = rect.GetLeft() + rect.GetWidth() / NUMBER_TWO;
225 int16_t y = rect.GetTop() + rect.GetHeight() / NUMBER_TWO;
226 return LongPress(x, y, sleepTicks);
227 }
228
Click(int16_t x,int16_t y,uint8_t sleepTicks) const229 void BasicTddTest::Click(int16_t x, int16_t y, uint8_t sleepTicks) const
230 {
231 Point point = {x, y};
232 EventInjector *injector = EventInjector::GetInstance();
233 if (injector->SetClickEvent(point)) {
234 HILOG_DEBUG(HILOG_MODULE_ACE,
235 "[BasicTddTest::Click]: Success to inject CLICK event on (%{public}d, %{public}d)\n", x, y);
236 } else {
237 HILOG_ERROR(HILOG_MODULE_ACE,
238 "[BasicTddTest::Click]: Failed to inject CLICK event on (%{public}d, %{public}d)\n", x, y);
239 }
240 // Waiting for tick breath.
241 usleep(sleepTicks * TICK);
242 }
243
LongPress(int16_t x,int16_t y,uint8_t sleepTicks) const244 void BasicTddTest::LongPress(int16_t x, int16_t y, uint8_t sleepTicks) const
245 {
246 Point point = {x, y};
247 EventInjector *injector = EventInjector::GetInstance();
248 if (injector->SetLongPressEvent(point)) {
249 HILOG_DEBUG(HILOG_MODULE_ACE,
250 "[BasicTddTest::LongPress]: Success to inject LONGPRESS event on (%{public}d, %{public}d)\n", x, y);
251 } else {
252 HILOG_ERROR(HILOG_MODULE_ACE,
253 "[BasicTddTest::LongPress]: Failed to inject LONGPRESS event on (%{public}d, %{public}d)\n", x, y);
254 }
255 // Waiting for tick breath.
256 usleep(sleepTicks * TICK);
257 }
258
Swipe(int16_t startX,int16_t startY,int16_t endX,int16_t endY,uint8_t sleepTicks) const259 void BasicTddTest::Swipe(int16_t startX, int16_t startY, int16_t endX, int16_t endY, uint8_t sleepTicks) const
260 {
261 Point startPoint = {startX, startY};
262 Point endPoint = {endX, endY};
263 EventInjector *injector = EventInjector::GetInstance();
264 if (injector->SetDragEvent(startPoint, endPoint, SWIPE_TIME)) {
265 HILOG_DEBUG(HILOG_MODULE_ACE,
266 "[BasicTddTest::Swipe]: Success to inject SWIPE event from (%{public}d, %{public}d) to "
267 "(%{public}d, %{public}d)\n",
268 startX, startY, endX, endY);
269 } else {
270 HILOG_ERROR(
271 HILOG_MODULE_ACE,
272 "[BasicTddTest::Swipe]: Failed to inject SWIPE from (%{public}d, %{public}d) to (%{public}d, %{public}d)\n",
273 startX, startY, endX, endY);
274 }
275
276 // Waiting for tick breath.
277 usleep(sleepTicks * TICK);
278 }
279
GetChildrenSize(const UIViewGroup & grop) const280 uint8_t BasicTddTest::GetChildrenSize(const UIViewGroup &grop) const
281 {
282 UIView *child = grop.GetChildrenHead();
283 uint8_t size = 0;
284 while (child != nullptr) {
285 ++size;
286 child = child->GetNextSibling();
287 }
288 return size;
289 }
290
TickHandler(void * args)291 void *BasicTddTest::TickHandler(void *args)
292 {
293 (void)args;
294 prctl(PR_SET_NAME, "TickTask");
295 while (isTickTaskRunning_) {
296 // Periodically call TaskHandler(). It could be done in a timer interrupt or an OS task too.
297 TaskManager::GetInstance()->TaskHandler();
298 // Just to let the system breathe
299 usleep(TICK);
300 }
301 return nullptr;
302 }
303
CallLifecycle(JSValue page,const char * lifecycle) const304 void BasicTddTest::CallLifecycle(JSValue page, const char *lifecycle) const
305 {
306 JSValue func = JSObject::Get(page, lifecycle);
307 if (JSFunction::Is(func)) {
308 JSRelease(JSFunction::Call(func, page, nullptr, 0));
309 }
310 JSRelease(func);
311 }
312 } // namespace ACELite
313 } // namespace OHOS
314