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 TestAttachTaskPool: 35 """ 36 测试用例:多 task 实例 attach 调试 37 测试步骤: 38 1. 连接 connect server 和主线程 debugger server 39 2. 连接子线程 debugger server,用于执行 task 任务 40 3. 所有线程使能 Runtime 和 Debugger 41 4. 主线程 Index.ts 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) 42 5. 触发点击事件,主线程命中断点 43 6. 子线程 Index.ts 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) 44 7. 子线程 resume,命中断点(Debugger.resume) 45 8. 子线程 getProperties,返回给定对象的属性(Runtime.getProperties) 46 9. 子线程 stepOut,主线程命中断点(Debugger.stepOut) 47 10. 主线程 getProperties(Runtime.getProperties) 48 11. 主线程 resume(Debugger.resume) 49 11. 子线程命中断点后 resume(Debugger.resume) 50 12. 关闭所有线程 debugger server 和 connect server 连接 51 关键代码: 52 Index.ets 53 @Concurrent 54 function add(args1, args2) { 55 return args1 + args2 56 } 57 @Concurrent 58 function sub(args1, args2) { 59 return args1 - args2 60 } 61 let taskAdd = new taskpool.Task(add, 200, 100) 62 let taskSub = new taskpool.Task(sub, 200, 100) 63 async function taskpoolTest() { 64 let valueAdd = await taskpool.execute(taskAdd) 65 let valueSub = await taskpool.execute(taskSub) 66 } 67 .OnClick(() => { 68 taskpoolTest() 69 }) 70 """ 71 72 def setup_method(self): 73 logging.info('Start running TestAttachTaskPool: setup') 74 75 self.log_path = rf'{os.path.dirname(__file__)}\..\log' 76 self.hilog_file_name = 'test_attach_task_pool.hilog.txt' 77 self.id_generator = Utils.message_id_generator() 78 79 # receive the hilog before the test start 80 Utils.clear_fault_log() 81 self.hilog_process, self.write_thread = Utils.save_hilog(log_path=self.log_path, 82 file_name=self.hilog_file_name, 83 debug_on=True) 84 85 def teardown_method(self): 86 Application.uninstall(self.config['bundle_name']) 87 88 # terminate the hilog receive process after the test done 89 time.sleep(3) 90 self.hilog_process.stdout.close() 91 self.hilog_process.terminate() 92 self.hilog_process.wait() 93 self.write_thread.join() 94 95 Utils.save_fault_log(log_path=self.log_path) 96 logging.info('TestAttachTaskPool done') 97 98 def test(self, test_suite_taskpool_01): 99 logging.info('Start running TestAttachTaskPool: test') 100 self.config = test_suite_taskpool_01 101 websocket = self.config['websocket'] 102 taskpool = self.config['taskpool'] 103 pid = self.config['pid'] 104 self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) 105 self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) 106 107 Application.attach(self.config['bundle_name']) 108 taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) 109 taskpool.await_taskpool() 110 taskpool.task_join() 111 if taskpool.task_exception: 112 raise taskpool.task_exception 113 114 async def procedure(self, websocket): 115 ################################################################################################################ 116 # main thread: connect the debugger server 117 ################################################################################################################ 118 main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) 119 logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') 120 ################################################################################################################ 121 # worker thread: connect the debugger server 122 ################################################################################################################ 123 worker_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) 124 logging.info(f'Connect to the debugger server of instance: {worker_thread.instance_id}') 125 ################################################################################################################ 126 # main thread: Runtime.enable 127 ################################################################################################################ 128 await self.runtime_impl.send("Runtime.enable", main_thread) 129 ################################################################################################################ 130 # worker thread: Runtime.enable 131 ################################################################################################################ 132 await self.runtime_impl.send("Runtime.enable", worker_thread) 133 ################################################################################################################ 134 # main thread: Debugger.enable 135 ################################################################################################################ 136 await self.debugger_impl.send("Debugger.enable", main_thread) 137 ################################################################################################################ 138 # main thread: Runtime.runIfWaitingForDebugger 139 ################################################################################################################ 140 await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) 141 ################################################################################################################ 142 # worker thread: Debugger.enable 143 ################################################################################################################ 144 await self.debugger_impl.send("Debugger.enable", worker_thread) 145 ################################################################################################################ 146 # worker thread: Runtime.runIfWaitingForDebugger 147 ################################################################################################################ 148 await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread) 149 ################################################################################################################ 150 # main thread: Debugger.removeBreakpointsByUrl 151 ################################################################################################################ 152 params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) 153 await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", main_thread, params) 154 ################################################################################################################ 155 # main thread: Debugger.getPossibleAndSetBreakpointByUrl 156 ################################################################################################################ 157 locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=10), 158 debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=17), 159 debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=25)] 160 params = debugger.SetBreakpointsLocations(locations) 161 response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", 162 main_thread, params) 163 assert response['result']['locations'][0]['id'] == 'id:10:0:' + self.config['file_path']['index'] 164 assert response['result']['locations'][1]['id'] == 'id:17:0:' + self.config['file_path']['index'] 165 assert response['result']['locations'][2]['id'] == 'id:25:0:' + self.config['file_path']['index'] 166 ################################################################################################################ 167 # main thread: click on the screen 168 ################################################################################################################ 169 Application.click_on_middle() 170 ################################################################################################################ 171 # worker thread: Debugger.scriptParsed 172 ################################################################################################################ 173 response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread) 174 assert response['params']['url'] == self.config['file_path']['index'] 175 assert response['params']['endLine'] == 0 176 # worker thread: Debugger.paused 177 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 178 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 179 assert response['params']['reason'] == 'Break on start' 180 ################################################################################################################ 181 # worker thread: Debugger.removeBreakpointsByUrl 182 ################################################################################################################ 183 params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) 184 await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread, params) 185 ################################################################################################################ 186 # worker thread: Debugger.getPossibleAndSetBreakpointByUrl 187 ################################################################################################################ 188 locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=10), 189 debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=17), 190 debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=25)] 191 params = debugger.SetBreakpointsLocations(locations) 192 response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", 193 worker_thread, params) 194 assert response['result']['locations'][0]['id'] == 'id:10:0:' + self.config['file_path']['index'] 195 assert response['result']['locations'][1]['id'] == 'id:17:0:' + self.config['file_path']['index'] 196 assert response['result']['locations'][2]['id'] == 'id:25:0:' + self.config['file_path']['index'] 197 ################################################################################################################ 198 # worker thread: Debugger.resume 199 ################################################################################################################ 200 await self.debugger_impl.send("Debugger.resume", worker_thread) 201 # worker thread: Debugger.paused 202 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 203 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 204 assert response['params']['reason'] == 'other' 205 assert response['params']['hitBreakpoints'] == ['id:10:14:' + self.config['file_path']['index']] 206 ################################################################################################################ 207 # worker thread: Runtime.getProperties 208 ################################################################################################################ 209 params = runtime.GetPropertiesParams('0') 210 response = await self.runtime_impl.send("Runtime.getProperties", worker_thread, params) 211 assert response['result']['result'][0]['name'] == 'add' 212 assert response['result']['result'][0]['value']['type'] == 'function' 213 ################################################################################################################ 214 # worker thread: Debugger.stepOut 215 ################################################################################################################ 216 await self.debugger_impl.send("Debugger.stepOut", worker_thread) 217 ################################################################################################################ 218 # main thread: Debugger.paused, hit breakpoint 219 ################################################################################################################ 220 response = await self.debugger_impl.recv("Debugger.paused", main_thread) 221 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 222 assert response['params']['hitBreakpoints'] == ['id:25:4:' + self.config['file_path']['index']] 223 ################################################################################################################ 224 # main thread: Runtime.getProperties 225 ################################################################################################################ 226 params = runtime.GetPropertiesParams('0') 227 response = await self.runtime_impl.send("Runtime.getProperties", main_thread, params) 228 assert response['result']['result'][0]['name'] == 'taskpoolTest' 229 assert response['result']['result'][0]['value']['type'] == 'function' 230 assert response['result']['result'][1]['name'] == 'valueSub' 231 assert response['result']['result'][1]['value']['type'] == 'undefined' 232 assert response['result']['result'][2]['name'] == 'valueAdd' 233 assert response['result']['result'][2]['value']['type'] == 'number' 234 assert response['result']['result'][2]['value']['description'] == '300' 235 ################################################################################################################ 236 # main thread: Debugger.resume 237 ################################################################################################################ 238 await self.debugger_impl.send("Debugger.resume", main_thread) 239 ################################################################################################################ 240 # worker thread: Debugger.paused 241 ################################################################################################################ 242 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 243 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 244 assert response['params']['hitBreakpoints'] == ['id:17:14:' + self.config['file_path']['index']] 245 ################################################################################################################ 246 # worker thread: Debugger.resume 247 ################################################################################################################ 248 await self.debugger_impl.send("Debugger.resume", worker_thread) 249 ################################################################################################################ 250 # worker thread: Debugger.disable 251 ################################################################################################################ 252 await self.debugger_impl.send("Debugger.disable", worker_thread) 253 ################################################################################################################ 254 # main thread: Debugger.disable 255 ################################################################################################################ 256 await self.debugger_impl.send("Debugger.disable", main_thread) 257 ################################################################################################################ 258 # close the websocket connections 259 ################################################################################################################ 260 await websocket.send_msg_to_debugger_server(worker_thread.instance_id, worker_thread.send_msg_queue, 'close') 261 await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') 262 await websocket.send_msg_to_connect_server('close') 263 ################################################################################################################