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 29from aw.api import debugger_api, runtime_api 30 31 32@pytest.mark.debug 33@pytest.mark.timeout(60) 34class TestWorkerConditionalBreakpoints: 35 """ 36 测试用例:多实例 debug 调试之设置条件断点 37 测试步骤: 38 1. 连接 connect server 和主线程 debugger server 39 2. 主线程使能 Runtime 和 Debugger 40 4. 触发点击事件,创建子线程,连接子线程 debugger server 41 5. 子线程使能 Runtime 和 Debugger 42 7. 子线程 Worker.ets 文件设置断点,其中包括条件断点(Debugger.getPossibleAndSetBreakpointByUrl) 43 8. 子线程 resume,停在普通断点处(Debugger.resume) 44 9. 子线程 resume,停在条件断点处(Debugger.resume) 45 7. 子线程 resume,停在普通断点处(Debugger.resume) 46 9. 子线程 resume(Debugger.resume) 47 10. 所有线程去使能 debugger(Debugger.disable) 48 10. 关闭所有线程 debugger server 和 connect server 连接 49 关键代码: 50 Index.ets 51 .OnClick(() => { 52 let myWorker = new worker.ThreadWorker("entry/ets/workers/Worker.ets") 53 myWorker.postMessage("hello world") 54 }) 55 Worker.ets 56 const workerPort: ThreadWorkerGlobalScope = worker.workerPort; 57 workerPort.onmessage = (e: MessageEvents) => { 58 let person = new Person('Tim', add(10, 11)) 59 person.introduce() // b1 60 let age = add(3, 6) + sub(4, 1) 61 } // b2 62 function add(num1, num2) { 63 let result = num1 + num2 64 return result // b3: condition = "result == 9" 65 } 66 """ 67 68 def setup_method(self): 69 logging.info('Start running TestWorkerConditionalBreakpoints: setup') 70 71 self.log_path = rf'{os.path.dirname(__file__)}\..\log' 72 self.hilog_file_name = 'test_worker_conditional_breakpoints.hilog.txt' 73 self.id_generator = Utils.message_id_generator() 74 75 # receive the hilog before the test start 76 Utils.clear_fault_log() 77 self.hilog_process, self.write_thread = Utils.save_hilog(log_path=self.log_path, 78 file_name=self.hilog_file_name, 79 debug_on=True) 80 81 def teardown_method(self): 82 Application.uninstall(self.config['bundle_name']) 83 84 # terminate the hilog receive process after the test done 85 time.sleep(3) 86 self.hilog_process.stdout.close() 87 self.hilog_process.terminate() 88 self.hilog_process.wait() 89 self.write_thread.join() 90 91 Utils.save_fault_log(log_path=self.log_path) 92 logging.info('TestWorkerConditionalBreakpoints done') 93 94 def test(self, test_suite_worker_06_debug): 95 logging.info('Start running TestWorkerConditionalBreakpoints: test') 96 self.config = test_suite_worker_06_debug 97 websocket = self.config['websocket'] 98 taskpool = self.config['taskpool'] 99 pid = self.config['pid'] 100 self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket) 101 self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket) 102 103 taskpool.submit(websocket.main_task(taskpool, self.procedure, pid)) 104 taskpool.await_taskpool() 105 taskpool.task_join() 106 if taskpool.task_exception: 107 raise taskpool.task_exception 108 109 async def procedure(self, websocket): 110 ################################################################################################################ 111 # main thread: connect the debugger server 112 ################################################################################################################ 113 main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) 114 logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}') 115 ################################################################################################################ 116 # main thread: Runtime.enable 117 ################################################################################################################ 118 await self.runtime_impl.send("Runtime.enable", main_thread) 119 ################################################################################################################ 120 # main thread: Debugger.enable 121 ################################################################################################################ 122 await self.debugger_impl.send("Debugger.enable", main_thread) 123 ################################################################################################################ 124 # main thread: Runtime.runIfWaitingForDebugger 125 ################################################################################################################ 126 await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) 127 ################################################################################################################ 128 # main thread: Debugger.scriptParsed 129 ################################################################################################################ 130 response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) 131 assert response['params']['url'] == self.config['file_path']['entry_ability'] 132 assert response['params']['endLine'] == 0 133 ################################################################################################################ 134 # main thread: Debugger.paused 135 ################################################################################################################ 136 response = await self.debugger_impl.recv("Debugger.paused", main_thread) 137 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['entry_ability'] 138 assert response['params']['reason'] == 'Break on start' 139 ################################################################################################################ 140 # main thread: Debugger.resume 141 ################################################################################################################ 142 await self.debugger_impl.send("Debugger.resume", main_thread) 143 ################################################################################################################ 144 # main thread: Debugger.scriptParsed 145 ################################################################################################################ 146 response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) 147 assert response['params']['url'] == self.config['file_path']['index'] 148 assert response['params']['endLine'] == 0 149 ################################################################################################################ 150 # main thread: Debugger.paused 151 ################################################################################################################ 152 response = await self.debugger_impl.recv("Debugger.paused", main_thread) 153 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index'] 154 assert response['params']['reason'] == 'Break on start' 155 ################################################################################################################ 156 # main thread: Debugger.resume 157 ################################################################################################################ 158 await self.debugger_impl.send("Debugger.resume", main_thread) 159 ################################################################################################################ 160 # main thread: click on the screen 161 ################################################################################################################ 162 Application.click_on_middle() 163 ################################################################################################################ 164 # worker thread: connect the debugger server 165 ################################################################################################################ 166 worker_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) 167 logging.info(f'Connect to the debugger server of instance: {worker_thread.instance_id}') 168 ################################################################################################################ 169 # worker thread: Runtime.enable 170 ################################################################################################################ 171 await self.runtime_impl.send("Runtime.enable", worker_thread) 172 ################################################################################################################ 173 # worker thread: Debugger.enable 174 ################################################################################################################ 175 await self.debugger_impl.send("Debugger.enable", worker_thread) 176 ################################################################################################################ 177 # worker thread: Runtime.runIfWaitingForDebugger 178 ################################################################################################################ 179 await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread) 180 ################################################################################################################ 181 # worker thread: Debugger.scriptParsed 182 ################################################################################################################ 183 response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread) 184 assert response['params']['url'] == self.config['file_path']['worker'] 185 assert response['params']['endLine'] == 0 186 ################################################################################################################ 187 # worker thread: Debugger.paused 188 ################################################################################################################ 189 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 190 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] 191 assert response['params']['reason'] == 'Break on start' 192 ################################################################################################################ 193 # worker thread: Debugger.removeBreakpointsByUrl 194 ################################################################################################################ 195 params = debugger.RemoveBreakpointsUrl(self.config['file_path']['worker']) 196 await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread, params) 197 ################################################################################################################ 198 # worker thread: Debugger.getPossibleAndSetBreakpointByUrl 199 ################################################################################################################ 200 RESULT_IS_9 = ( 201 'UEFOREEAAAAAAAAADAACAFQBAAAAAAAAAAAAAAIAAAA8AAAAAQAAAFABAAAAAAAARAAAAAEAAABEAAAAlgAAAMkAAAB8AAAAVAEAAAIAAA' 202 'BsAAAAAgAAAHQAAAD/////////////////////lgAAAMkAAAB8AAAAjgAAACFkZWJ1Z2dlckdldFZhbHVlAA1yZXN1bHQAM0xfRVNTbG90' 203 'TnVtYmVyQW5ub3RhdGlvbjsAAAAAAIFAAAACAAAXZnVuY19tYWluXzAAE0xfR0xPQkFMOwAAAAAAAQABAgAAAQD//7wAAACIAgETAQAAAg' 204 'AFRgEAAAYGAQAAABVTbG90TnVtYmVyAAAAAQD6AAAABQAAADcJAyoARJBEoUSybWEFYAVCAAAAYQY+AQBhBwJhCGAGKwIHCGEEYgkAAAAP' 205 'BARkC2sBDwD/////DwACACMAQQEAAA==') 206 locations = [debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=17), 207 debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=59), 208 debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=36, 209 condition=RESULT_IS_9)] 210 params = debugger.SetBreakpointsLocations(locations) 211 response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", 212 worker_thread, params) 213 assert response['result']['locations'][0]['id'] == 'id:17:0:' + self.config['file_path']['worker'] 214 assert response['result']['locations'][1]['id'] == 'id:59:0:' + self.config['file_path']['worker'] 215 assert response['result']['locations'][2]['id'] == 'id:36:0:' + self.config['file_path']['worker'] 216 ################################################################################################################ 217 # worker thread: Debugger.resume 218 ################################################################################################################ 219 await self.debugger_impl.send("Debugger.resume", worker_thread) 220 # worker thread: Debugger.paused 221 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 222 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] 223 assert response['params']['callFrames'][0]['functionName'] == 'introduce' 224 assert response['params']['reason'] == 'other' 225 assert response['params']['hitBreakpoints'] == ['id:59:8:' + self.config['file_path']['worker']] 226 ################################################################################################################ 227 # worker thread: Debugger.resume 228 ################################################################################################################ 229 await self.debugger_impl.send("Debugger.resume", worker_thread) 230 # worker thread: Debugger.paused 231 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 232 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] 233 assert response['params']['callFrames'][0]['functionName'] == 'add' 234 assert response['params']['reason'] == 'other' 235 assert response['params']['hitBreakpoints'] == ['id:36:11:' + self.config['file_path']['worker']] 236 ################################################################################################################ 237 # worker thread: Debugger.resume 238 ################################################################################################################ 239 await self.debugger_impl.send("Debugger.resume", worker_thread) 240 # worker thread: Debugger.paused 241 response = await self.debugger_impl.recv("Debugger.paused", worker_thread) 242 assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker'] 243 assert response['params']['reason'] == 'other' 244 assert response['params']['hitBreakpoints'] == ['id:17:1:' + self.config['file_path']['worker']] 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 ################################################################################################################