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