1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3""" 4Copyright (c) 2024 Huawei Device Co., Ltd. 5Licensed under the Apache License, Version 2.0 (the "License"); 6you may not use this file except in compliance with the License. 7You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11Unless required by applicable law or agreed to in writing, software 12distributed under the License is distributed on an "AS IS" BASIS, 13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14See the License for the specific language governing permissions and 15limitations under the License. 16 17Description: Scenario test case. 18""" 19 20import logging 21import os 22import time 23 24import pytest 25 26from aw import Application 27from aw import Utils 28from aw import debugger, runtime 29from aw.api import debugger_api, runtime_api 30 31 32@pytest.mark.debug 33@pytest.mark.timeout(60) 34class TestTaskPoolSendable: 35 """ 36 测试用例:跨线程传递 Sendable 对象 37 测试步骤: 38 1. 连接 connect server 和主线程 debugger server 39 2. 主线程使能 Runtime 和 Debugger 40 3. 主线程 resume(Debugger.resume) 41 4. 创建子线程,连接子线程 debugger server 42 5. 子线程使能 Runtime 和 Debugger 43 6. 主线程 Index.ets 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) 44 7. 触发点击事件,子线程 Index.ets 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) 45 8. 子线程 resume,停在断点处(Debugger.resume) 46 9. 子线程 getProperties,获取 Sendable 对象方法(Debugger.getProperties) 47 10. 子线程 resume,停在下一断点处(Debugger.resume) 48 11. 子线程 getProperties,获取 Sendable 对象方法(Debugger.getProperties) 49 12. 子线程 resume(Debugger.resume) 50 13. 所有线程去使能 debugger(Debugger.disable) 51 14. 关闭所有线程 debugger server 和 connect server 连接 52 关键代码; 53 Index.ets 54 @Concurrent 55 async function taskFunc(person: Person) { 56 let ans = person.calculate(21, 50) 57 person.setScore(100) 58 } 59 async function sendableTest() { 60 let p = new Person('Tony', 9) 61 let task: taskpool.Task = new taskpool.Task(taskFunc, p) 62 await taskpool.execute(task) 63 } 64 .OnClick(() => { 65 sendableTest() 66 }) 67 @Sendable 68 class Person { 69 name: string 70 age: number 71 score: number = 0 72 constructor(name: string, age: number) { 73 this.name = name 74 this.age = age 75 } 76 setScore(score: number) { 77 this.score = score // b1 78 } 79 addNumber(num1: number, num2: number) { 80 let result = num1 + num2 // b2 81 return result 82 } 83 } 84 """ 85 86 def setup_method(self): 87 logging.info('Start running TestTaskPoolSendable: setup') 88 89 self.log_path = rf'{os.path.dirname(__file__)}\..\log' 90 self.hilog_file_name = 'test_task_pool_sendable.hilog.txt' 91 self.id_generator = Utils.message_id_generator() 92 93 # receive the hilog before the test start 94 Utils.clear_fault_log() 95 self.hilog_process, self.write_thread = Utils.save_hilog(log_path=self.log_path, 96 file_name=self.hilog_file_name, 97 debug_on=True) 98 99 def teardown_method(self): 100 Application.uninstall(self.config['bundle_name']) 101 102 # terminate the hilog receive process after the test done 103 time.sleep(3) 104 self.hilog_process.stdout.close() 105 self.hilog_process.terminate() 106 self.hilog_process.wait() 107 self.write_thread.join() 108 109 Utils.save_fault_log(log_path=self.log_path) 110 logging.info('TestTaskPoolSendable done') 111 112 def test(self, test_suite_taskpool_02_debug): 113 logging.info('Start running TestTaskPoolSendable: test') 114 self.config = test_suite_taskpool_02_debug 115 websocket = self.config['websocket'] 116 taskpool = self.config['taskpool'] 117 pid = self.config['pid'] 118 self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) 119 self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) 120 121 taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) 122 taskpool.await_taskpool() 123 taskpool.task_join() 124 if taskpool.task_exception: 125 raise taskpool.task_exception 126 127 async def procedure(self, websocket): 128 ################################################################################################################ 129 # main thread: connect the debugger server 130 ################################################################################################################ 131 main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) 132 logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') 133 ################################################################################################################ 134 # main thread: Runtime.enable 135 ################################################################################################################ 136 await self.runtime_impl.send("Runtime.enable", main_thread) 137 ################################################################################################################ 138 # main thread: Debugger.enable 139 ################################################################################################################ 140 await self.debugger_impl.send("Debugger.enable", main_thread) 141 ################################################################################################################ 142 # main thread: Runtime.runIfWaitingForDebugger 143 ################################################################################################################ 144 await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) 145 ################################################################################################################ 146 # main thread: Debugger.scriptParsed 147 ################################################################################################################ 148 response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) 149 assert response['params']['url'] == self.config['file_path']['entry_ability'] 150 assert response['params']['endLine'] == 0 151 ################################################################################################################ 152 # main thread: Debugger.paused 153 ################################################################################################################ 154 response = await self.debugger_impl.recv("Debugger.paused", main_thread) 155 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['entry_ability'] 156 assert response['params']['reason'] == 'Break on start' 157 ################################################################################################################ 158 # main thread: Debugger.resume 159 ################################################################################################################ 160 await self.debugger_impl.send("Debugger.resume", main_thread) 161 ################################################################################################################ 162 # main thread: Debugger.scriptParsed 163 ################################################################################################################ 164 response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) 165 assert response['params']['url'] == self.config['file_path']['index'] 166 assert response['params']['endLine'] == 0 167 ################################################################################################################ 168 # main thread: Debugger.paused 169 ################################################################################################################ 170 response = await self.debugger_impl.recv("Debugger.paused", main_thread) 171 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 172 assert response['params']['reason'] == 'Break on start' 173 ################################################################################################################ 174 # main thread: Debugger.resume 175 ################################################################################################################ 176 await self.debugger_impl.send("Debugger.resume", main_thread) 177 ################################################################################################################ 178 # worker thread: connect the debugger server 179 ################################################################################################################ 180 worker_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) 181 logging.info(f'Connect to the debugger server of instance: {worker_thread.instance_id}') 182 ################################################################################################################ 183 # worker thread: Runtime.enable 184 ################################################################################################################ 185 await self.runtime_impl.send("Runtime.enable", worker_thread) 186 ################################################################################################################ 187 # worker thread: Debugger.enable 188 ################################################################################################################ 189 await self.debugger_impl.send("Debugger.enable", worker_thread) 190 ################################################################################################################ 191 # worker thread: Runtime.runIfWaitingForDebugger 192 ################################################################################################################ 193 await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread) 194 ################################################################################################################ 195 # main thread: click on the screen 196 ################################################################################################################ 197 Application.click_on_middle() 198 ################################################################################################################ 199 # worker thread: Debugger.scriptParsed 200 ################################################################################################################ 201 response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread) 202 assert response['params']['url'] == self.config['file_path']['index'] 203 assert response['params']['endLine'] == 0 204 # worker thread: Debugger.paused 205 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 206 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 207 assert response['params']['reason'] == 'Break on start' 208 ################################################################################################################ 209 # worker thread: Debugger.removeBreakpointsByUrl 210 ################################################################################################################ 211 params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) 212 await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread, params) 213 ################################################################################################################ 214 # worker thread: Debugger.getPossibleAndSetBreakpointByUrl 215 ################################################################################################################ 216 locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=95), 217 debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=98)] 218 params = debugger.SetBreakpointsLocations(locations) 219 response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", 220 worker_thread, params) 221 assert response['result']['locations'][0]['id'] == 'id:95:0:' + self.config['file_path']['index'] 222 assert response['result']['locations'][1]['id'] == 'id:98:0:' + self.config['file_path']['index'] 223 ################################################################################################################ 224 # worker thread: Debugger.resume 225 ################################################################################################################ 226 await self.debugger_impl.send("Debugger.resume", worker_thread) 227 # worker thread: Debugger.paused 228 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 229 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 230 assert response['params']['callFrames'][0]['functionName'] == 'addNumber' 231 assert response['params']['reason'] == 'other' 232 assert response['params']['hitBreakpoints'] == ['id:98:21:' + self.config['file_path']['index']] 233 ################################################################################################################ 234 # worker thread: Runtime.getProperties 235 ################################################################################################################ 236 params = runtime.GetPropertiesParams('0') 237 response = await self.runtime_impl.send("Runtime.getProperties", worker_thread, params) 238 assert response['result']['result'][0]['name'] == 'addNumber' 239 assert response['result']['result'][0]['value']['description'].endswith('[Sendable]') 240 ################################################################################################################ 241 # worker thread: Debugger.resume 242 ################################################################################################################ 243 await self.debugger_impl.send("Debugger.resume", worker_thread) 244 # worker thread: Debugger.paused 245 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 246 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 247 assert response['params']['callFrames'][0]['functionName'] == 'setScore' 248 assert response['params']['reason'] == 'other' 249 assert response['params']['hitBreakpoints'] == ['id:95:8:' + self.config['file_path']['index']] 250 ################################################################################################################ 251 # worker thread: Runtime.getProperties 252 ################################################################################################################ 253 params = runtime.GetPropertiesParams('0') 254 response = await self.runtime_impl.send("Runtime.getProperties", worker_thread, params) 255 assert response['result']['result'][0]['name'] == 'setScore' 256 assert response['result']['result'][0]['value']['description'].endswith('[Sendable]') 257 ################################################################################################################ 258 # worker thread: Debugger.resume 259 ################################################################################################################ 260 await self.debugger_impl.send("Debugger.resume", worker_thread) 261 ################################################################################################################ 262 # worker thread: Debugger.disable 263 ################################################################################################################ 264 await self.debugger_impl.send("Debugger.disable", worker_thread) 265 ################################################################################################################ 266 # main thread: Debugger.disable 267 ################################################################################################################ 268 await self.debugger_impl.send("Debugger.disable", main_thread) 269 ################################################################################################################ 270 # close the websocket connections 271 ################################################################################################################ 272 await websocket.send_msg_to_debugger_server(worker_thread.instance_id, worker_thread.send_msg_queue, 'close') 273 await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') 274 await websocket.send_msg_to_connect_server('close') 275 ################################################################################################################