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(30) 34class TestDebug04: 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 53 def setup_method(self): 54 logging.info('Start running TestDebug04: setup') 55 56 self.log_path = rf'{os.path.dirname(__file__)}\..\log' 57 self.hilog_file_name = 'test_debug_04.hilog.txt' 58 self.id_generator = Utils.message_id_generator() 59 60 # receive the hilog before the test start 61 Utils.clear_fault_log() 62 self.hilog_process, self.write_thread = Utils.save_hilog(log_path=self.log_path, 63 file_name=self.hilog_file_name, 64 debug_on=True) 65 66 def teardown_method(self): 67 Application.uninstall(self.config['bundle_name']) 68 69 # terminate the hilog receive process after the test done 70 time.sleep(3) 71 self.hilog_process.stdout.close() 72 self.hilog_process.terminate() 73 self.hilog_process.wait() 74 self.write_thread.join() 75 76 Utils.save_fault_log(log_path=self.log_path) 77 logging.info('TestDebug04 done') 78 79 def test(self, test_suite_taskpool_01): 80 logging.info('Start running TestDebug04: test') 81 self.config = test_suite_taskpool_01 82 websocket = self.config['websocket'] 83 taskpool = self.config['taskpool'] 84 pid = self.config['pid'] 85 self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) 86 self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) 87 88 Application.attach(self.config['bundle_name']) 89 taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) 90 taskpool.await_taskpool() 91 taskpool.task_join() 92 if taskpool.task_exception: 93 raise taskpool.task_exception 94 95 async def procedure(self, websocket): 96 ################################################################################################################ 97 # main thread: connect the debugger server 98 ################################################################################################################ 99 main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) 100 logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') 101 ################################################################################################################ 102 # worker thread: connect the debugger server 103 ################################################################################################################ 104 worker_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) 105 logging.info(f'Connect to the debugger server of instance: {worker_thread.instance_id}') 106 ################################################################################################################ 107 # main thread: Runtime.enable 108 ################################################################################################################ 109 await self.runtime_impl.send("Runtime.enable", main_thread) 110 ################################################################################################################ 111 # worker thread: Runtime.enable 112 ################################################################################################################ 113 await self.runtime_impl.send("Runtime.enable", worker_thread) 114 ################################################################################################################ 115 # main thread: Debugger.enable 116 ################################################################################################################ 117 await self.debugger_impl.send("Debugger.enable", main_thread) 118 ################################################################################################################ 119 # main thread: Runtime.runIfWaitingForDebugger 120 ################################################################################################################ 121 await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) 122 ################################################################################################################ 123 # worker thread: Debugger.enable 124 ################################################################################################################ 125 await self.debugger_impl.send("Debugger.enable", worker_thread) 126 ################################################################################################################ 127 # worker thread: Runtime.runIfWaitingForDebugger 128 ################################################################################################################ 129 await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread) 130 ################################################################################################################ 131 # main thread: Debugger.removeBreakpointsByUrl 132 ################################################################################################################ 133 params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) 134 await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", main_thread, params) 135 ################################################################################################################ 136 # main thread: Debugger.getPossibleAndSetBreakpointByUrl 137 ################################################################################################################ 138 locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=10), 139 debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=17), 140 debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=25)] 141 params = debugger.SetBreakpointsLocations(locations) 142 response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", 143 main_thread, params) 144 assert response['result']['locations'][0]['id'] == 'id:10:0:' + self.config['file_path']['index'] 145 assert response['result']['locations'][1]['id'] == 'id:17:0:' + self.config['file_path']['index'] 146 assert response['result']['locations'][2]['id'] == 'id:25:0:' + self.config['file_path']['index'] 147 ################################################################################################################ 148 # main thread: click on the screen 149 ################################################################################################################ 150 Application.click_on_middle() 151 ################################################################################################################ 152 # worker thread: Debugger.scriptParsed 153 ################################################################################################################ 154 response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread) 155 assert response['params']['url'] == self.config['file_path']['index'] 156 assert response['params']['endLine'] == 0 157 # worker thread: Debugger.paused 158 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 159 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 160 assert response['params']['reason'] == 'Break on start' 161 ################################################################################################################ 162 # worker thread: Debugger.removeBreakpointsByUrl 163 ################################################################################################################ 164 params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) 165 await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread, params) 166 ################################################################################################################ 167 # worker thread: Debugger.getPossibleAndSetBreakpointByUrl 168 ################################################################################################################ 169 locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=10), 170 debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=17), 171 debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=25)] 172 params = debugger.SetBreakpointsLocations(locations) 173 response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", 174 worker_thread, params) 175 assert response['result']['locations'][0]['id'] == 'id:10:0:' + self.config['file_path']['index'] 176 assert response['result']['locations'][1]['id'] == 'id:17:0:' + self.config['file_path']['index'] 177 assert response['result']['locations'][2]['id'] == 'id:25:0:' + self.config['file_path']['index'] 178 ################################################################################################################ 179 # worker thread: Debugger.resume 180 ################################################################################################################ 181 await self.debugger_impl.send("Debugger.resume", worker_thread) 182 # worker thread: Debugger.paused 183 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 184 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 185 assert response['params']['reason'] == 'other' 186 assert response['params']['hitBreakpoints'] == ['id:10:14:' + self.config['file_path']['index']] 187 ################################################################################################################ 188 # worker thread: Runtime.getProperties 189 ################################################################################################################ 190 params = runtime.GetPropertiesParams('0') 191 response = await self.runtime_impl.send("Runtime.getProperties", worker_thread, params) 192 assert response['result']['result'][0]['name'] == 'add' 193 assert response['result']['result'][0]['value']['type'] == 'function' 194 ################################################################################################################ 195 # worker thread: Debugger.stepOut 196 ################################################################################################################ 197 await self.debugger_impl.send("Debugger.stepOut", worker_thread) 198 ################################################################################################################ 199 # main thread: Debugger.paused, hit breakpoint 200 ################################################################################################################ 201 response = await self.debugger_impl.recv("Debugger.paused", main_thread) 202 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 203 assert response['params']['hitBreakpoints'] == ['id:25:4:' + self.config['file_path']['index']] 204 ################################################################################################################ 205 # main thread: Runtime.getProperties 206 ################################################################################################################ 207 params = runtime.GetPropertiesParams('0') 208 response = await self.runtime_impl.send("Runtime.getProperties", main_thread, params) 209 assert response['result']['result'][0]['name'] == 'taskpoolTest' 210 assert response['result']['result'][0]['value']['type'] == 'function' 211 assert response['result']['result'][1]['name'] == 'valueSub' 212 assert response['result']['result'][1]['value']['type'] == 'undefined' 213 assert response['result']['result'][2]['name'] == 'valueAdd' 214 assert response['result']['result'][2]['value']['type'] == 'number' 215 assert response['result']['result'][2]['value']['description'] == '300' 216 ################################################################################################################ 217 # main thread: Debugger.resume 218 ################################################################################################################ 219 await self.debugger_impl.send("Debugger.resume", main_thread) 220 ################################################################################################################ 221 # worker thread: Debugger.paused 222 ################################################################################################################ 223 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 224 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 225 assert response['params']['hitBreakpoints'] == ['id:17:14:' + self.config['file_path']['index']] 226 ################################################################################################################ 227 # worker thread: Debugger.resume 228 ################################################################################################################ 229 await self.debugger_impl.send("Debugger.resume", worker_thread) 230 ################################################################################################################ 231 # worker thread: Debugger.disable 232 ################################################################################################################ 233 await self.debugger_impl.send("Debugger.disable", worker_thread) 234 ################################################################################################################ 235 # main thread: Debugger.disable 236 ################################################################################################################ 237 await self.debugger_impl.send("Debugger.disable", main_thread) 238 ################################################################################################################ 239 # close the websocket connections 240 ################################################################################################################ 241 await websocket.send_msg_to_debugger_server(worker_thread.instance_id, worker_thread.send_msg_queue, 'close') 242 await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') 243 await websocket.send_msg_to_connect_server('close') 244 ################################################################################################################