From 0fd8dad7d06da56d1f72b49c588d9cd506475bd8 Mon Sep 17 00:00:00 2001 From: panmingxuan Date: Thu, 8 May 2025 10:46:44 +0800 Subject: [PATCH] =?UTF-8?q?testcases/toolchain=E6=B5=8B=E8=AF=95=E7=94=A8?= =?UTF-8?q?=E4=BE=8B=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sync testcases/toolchain from YZ to BZ Issue: https://gitee.com/openharmony/arkcompiler_toolchain/issues/IC65YJ Signed-off-by: panmingxuan --- .../toolchain/debug/TestAttachTaskPool.json | 15 + .../toolchain/debug/TestAttachTaskPool.py | 271 +++++++++++++++ .../toolchain/debug/TestAttachWorkerStep.json | 15 + .../toolchain/debug/TestAttachWorkerStep.py | 326 ++++++++++++++++++ .../debug/TestMainBreakpointSendable.json | 15 + .../debug/TestMainBreakpointSendable.py | 193 +++++++++++ .../debug/TestMainExceptionBreakpoints01.json | 15 + .../debug/TestMainExceptionBreakpoints01.py | 190 ++++++++++ 8 files changed, 1040 insertions(+) create mode 100644 test/autotest/testcases/toolchain/debug/TestAttachTaskPool.json create mode 100644 test/autotest/testcases/toolchain/debug/TestAttachTaskPool.py create mode 100644 test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.json create mode 100644 test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.py create mode 100644 test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.json create mode 100644 test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.py create mode 100644 test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.json create mode 100644 test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.py diff --git a/test/autotest/testcases/toolchain/debug/TestAttachTaskPool.json b/test/autotest/testcases/toolchain/debug/TestAttachTaskPool.json new file mode 100644 index 00000000..b5dcfa80 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestAttachTaskPool.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestAttachTaskPool", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestAttachTaskPool.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestAttachTaskPool.py b/test/autotest/testcases/toolchain/debug/TestAttachTaskPool.py new file mode 100644 index 00000000..9c9d5596 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestAttachTaskPool.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2025 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 连接子线程 debugger server,用于执行 task 任务 + 3. 所有线程使能 Runtime 和 Debugger + 4. 主线程 Index.ts 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) + 5. 触发点击事件,主线程命中断点 + 6. 子线程 Index.ts 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) + 7. 子线程 resume,命中断点(Debugger.resume) + 8. 子线程 getProperties,返回给定对象的属性(Runtime.getProperties) + 9. 子线程 stepOut,主线程命中断点(Debugger.stepOut) + 10. 主线程 getProperties(Runtime.getProperties) + 11. 主线程 resume(Debugger.resume) + 11. 子线程命中断点后 resume(Debugger.resume) + 12. 关闭所有线程 debugger server 和 connect server 连接 +#================================================================== +关键代码: + Index.ets + @Concurrent + function add(args1, args2) { + return args1 + args2 + } + @Concurrent + function sub(args1, args2) { + return args1 - args2 + } + let taskAdd = new taskpool.Task(add, 200, 100) + let taskSub = new taskpool.Task(sub, 200, 100) + async function taskpoolTest() { + let valueAdd = await taskpool.execute(taskAdd) + let valueSub = await taskpool.execute(taskSub) + } + .OnClick(() => { + taskpoolTest() + }) +#!!================================================================ +""" +import sys +from pathlib import Path + +root_path = Path(__file__).parent.parent.parent.parent +resource_path = root_path / 'resource' +sys.path.append(str(root_path / 'aw')) # add aw path to sys.path + +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from all_utils import CommonUtils, UiUtils +from cdp import debugger, runtime +from implement_api import debugger_api, runtime_api + + +class TestAttachTaskPool(TestCase): + def __init__(self, controllers): + self.TAG = self.__class__.__name__ + TestCase.__init__(self, self.TAG, controllers) + self.driver = UiDriver(self.device1) + self.ui_utils = UiUtils(self.driver) + self.common_utils = CommonUtils(self.driver) + self.id_generator = CommonUtils.message_id_generator() + self.config = { + 'start_mode': '', + 'connect_server_port': 15608, + 'debugger_server_port': 15609, + 'bundle_name': 'com.example.taskPool01', + 'hap_name': 'TaskPool01.hap', + 'hap_path': str(resource_path / 'hap' / 'TaskPool01.hap'), + 'file_path': { + 'entry_ability': 'entry|entry|1.0.0|src/main/ets/entryability/EntryAbility.ts', + 'index': 'entry|entry|1.0.0|src/main/ets/pages/Index.ts', + } + } + + def setup(self): + Step('1.下载应用') + self.driver.install_app(self.config['hap_path'], "-r") + Step('2.启动应用') + self.driver.start_app(package_name=self.config['bundle_name'], params=self.config['start_mode']) + self.config['pid'] = self.common_utils.get_pid(self.config['bundle_name']) + assert self.config['pid'] != 0, f'Failed to get pid of {self.config["bundle_name"]}' + Step('3.设置屏幕常亮') + self.ui_utils.keep_awake() + Step('4.端口映射,连接server') + self.common_utils.connect_server(self.config) + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, self.config['websocket']) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, self.config['websocket']) + Step('5.attach调试应用') + self.common_utils.attach(self.config['bundle_name']) + + def process(self): + Step('6.执行测试用例') + websocket = self.config['websocket'] + taskpool = self.config['taskpool'] + taskpool.submit(websocket.main_task(taskpool, self.test, self.config['pid'])) + taskpool.await_taskpool() + taskpool.task_join() + if taskpool.task_exception: + raise taskpool.task_exception + + def teardown(self): + Step('7.关闭应用') + self.driver.stop_app(self.config['bundle_name']) + Step('8.卸载应用') + self.driver.uninstall_app(self.config['bundle_name']) + + async def test(self, websocket): + ################################################################################################################ + # main thread: connect the debugger server + ################################################################################################################ + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + ################################################################################################################ + # worker thread: connect the debugger server + ################################################################################################################ + worker_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + ################################################################################################################ + # main thread: Runtime.enable + ################################################################################################################ + await self.runtime_impl.send("Runtime.enable", main_thread) + ################################################################################################################ + # worker thread: Runtime.enable + ################################################################################################################ + await self.runtime_impl.send("Runtime.enable", worker_thread) + ################################################################################################################ + # main thread: Debugger.enable + ################################################################################################################ + await self.debugger_impl.send("Debugger.enable", main_thread) + ################################################################################################################ + # main thread: Runtime.runIfWaitingForDebugger + ################################################################################################################ + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) + ################################################################################################################ + # worker thread: Debugger.enable + ################################################################################################################ + await self.debugger_impl.send("Debugger.enable", worker_thread) + ################################################################################################################ + # worker thread: Runtime.runIfWaitingForDebugger + ################################################################################################################ + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread) + ################################################################################################################ + # main thread: Debugger.removeBreakpointsByUrl + ################################################################################################################ + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", main_thread, params) + ################################################################################################################ + # main thread: Debugger.getPossibleAndSetBreakpointByUrl + ################################################################################################################ + locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=10), + debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=17), + debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=25)] + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", main_thread, params) + result_locations = response['result']['locations'] + self.common_utils.assert_equal(result_locations[0]['id'], 'id:10:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(result_locations[1]['id'], 'id:17:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(result_locations[2]['id'], 'id:25:0:' + self.config['file_path']['index']) + ################################################################################################################ + # main thread: click on the screen + ################################################################################################################ + self.ui_utils.click_on_middle() + ################################################################################################################ + # worker thread: Debugger.scriptParsed + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread) + self.common_utils.assert_equal(response['params']['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['endLine'], 0) + # worker thread: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", worker_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['reason'], 'Break on start') + ################################################################################################################ + # worker thread: Debugger.removeBreakpointsByUrl + ################################################################################################################ + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread, params) + ################################################################################################################ + # worker thread: Debugger.getPossibleAndSetBreakpointByUrl + ################################################################################################################ + locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=10), + debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=17), + debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=25)] + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", worker_thread, params) + result_locations = response['result']['locations'] + self.common_utils.assert_equal(result_locations[0]['id'], 'id:10:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(result_locations[1]['id'], 'id:17:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(result_locations[2]['id'], 'id:25:0:' + self.config['file_path']['index']) + ################################################################################################################ + # worker thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", worker_thread) + # worker thread: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", worker_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:10:14:' + self.config['file_path']['index']]) + ################################################################################################################ + # worker thread: Runtime.getProperties + ################################################################################################################ + params = runtime.GetPropertiesParams('0') + response = await self.runtime_impl.send("Runtime.getProperties", worker_thread, params) + self.common_utils.assert_equal(response['result']['result'][0]['name'], 'add') + self.common_utils.assert_equal(response['result']['result'][0]['value']['type'], 'function') + ################################################################################################################ + # worker thread: Debugger.stepOut + ################################################################################################################ + await self.debugger_impl.send("Debugger.stepOut", worker_thread) + ################################################################################################################ + # main thread: Debugger.paused, hit breakpoint + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:25:4:' + self.config['file_path']['index']]) + ################################################################################################################ + # main thread: Runtime.getProperties + ################################################################################################################ + params = runtime.GetPropertiesParams('0') + response = await self.runtime_impl.send("Runtime.getProperties", main_thread, params) + result = response['result']['result'] + self.common_utils.assert_equal(result[0]['name'], 'taskpoolTest') + self.common_utils.assert_equal(result[0]['value']['type'], 'function') + self.common_utils.assert_equal(result[1]['name'], 'valueSub') + self.common_utils.assert_equal(result[1]['value']['type'], 'undefined') + self.common_utils.assert_equal(result[2]['name'], 'valueAdd') + self.common_utils.assert_equal(result[2]['value']['type'], 'number') + self.common_utils.assert_equal(result[2]['value']['description'], '300') + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # worker thread: Debugger.paused + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", worker_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:17:14:' + self.config['file_path']['index']]) + ################################################################################################################ + # worker thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", worker_thread) + ################################################################################################################ + # worker thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", worker_thread) + ################################################################################################################ + # main thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", main_thread) + ################################################################################################################ + # close the websocket connections + ################################################################################################################ + await websocket.send_msg_to_debugger_server(worker_thread.instance_id, worker_thread.send_msg_queue, 'close') + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') + await websocket.send_msg_to_connect_server('close') + ################################################################################################################ \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.json b/test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.json new file mode 100644 index 00000000..b5fe9d5d --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestAttachWorkerStep", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestAttachWorkerStep.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.py b/test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.py new file mode 100644 index 00000000..a3af5d06 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.py @@ -0,0 +1,326 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2025 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 连接子线程 debugger server,用于执行 task 任务 + 3. 所有线程使能 Runtime 和 Debugger + 4. 主线程 Index.ts 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) + 5. 触发点击事件,主线程命中断点 + 6. 子线程 Index.ts 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) + 7. 子线程 resume,命中断点(Debugger.resume) + 8. 子线程 getProperties,返回给定对象的属性(Runtime.getProperties) + 9. 子线程 stepOut,主线程命中断点(Debugger.stepOut) + 10. 主线程 getProperties(Runtime.getProperties) + 11. 主线程 resume(Debugger.resume) + 11. 子线程命中断点后 resume(Debugger.resume) + 12. 关闭所有线程 debugger server 和 connect server 连接 +#================================================================== +关键代码: + Index.ets + @Concurrent + function add(args1, args2) { + return args1 + args2 + } + @Concurrent + function sub(args1, args2) { + return args1 - args2 + } + let taskAdd = new taskpool.Task(add, 200, 100) + let taskSub = new taskpool.Task(sub, 200, 100) + async function taskpoolTest() { + let valueAdd = await taskpool.execute(taskAdd) + let valueSub = await taskpool.execute(taskSub) + } + .OnClick(() => { + taskpoolTest() + }) +#!!================================================================ +""" +import sys +from pathlib import Path + +root_path = Path(__file__).parent.parent.parent.parent +resource_path = root_path / 'resource' +sys.path.append(str(root_path / 'aw')) # add aw path to sys.path + +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from all_utils import CommonUtils, UiUtils +from cdp import debugger +from implement_api import debugger_api, runtime_api + + +class TestAttachWorkerStep(TestCase): + def __init__(self, controllers): + self.TAG = self.__class__.__name__ + TestCase.__init__(self, self.TAG, controllers) + self.driver = UiDriver(self.device1) + self.ui_utils = UiUtils(self.driver) + self.common_utils = CommonUtils(self.driver) + self.id_generator = CommonUtils.message_id_generator() + self.config = { + 'start_mode': '', + 'connect_server_port': 15610, + 'debugger_server_port': 15611, + 'bundle_name': 'com.example.multiWorker01', + 'hap_name': 'MultiWorker01.hap', + 'hap_path': str(resource_path / 'hap' / 'MultiWorker01.hap'), + 'file_path': { + 'entry_ability': 'entry|entry|1.0.0|src/main/ets/entryability/EntryAbility.ts', + 'index': 'entry|entry|1.0.0|src/main/ets/pages/Index.ts', + 'worker': 'entry|entry|1.0.0|src/main/ets/workers/Worker.ts' + } + } + + def setup(self): + Step('1.下载应用') + self.driver.install_app(self.config['hap_path'], "-r") + Step('2.启动应用') + self.driver.start_app(package_name=self.config['bundle_name'], params=self.config['start_mode']) + self.config['pid'] = self.common_utils.get_pid(self.config['bundle_name']) + assert self.config['pid'] != 0, f'Failed to get pid of {self.config["bundle_name"]}' + Step('3.设置屏幕常亮') + self.ui_utils.keep_awake() + Step('4.端口映射,连接server') + self.common_utils.connect_server(self.config) + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, self.config['websocket']) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, self.config['websocket']) + Step('5.attach调试应用') + self.common_utils.attach(self.config['bundle_name']) + + def process(self): + Step('6.执行测试用例') + websocket = self.config['websocket'] + taskpool = self.config['taskpool'] + taskpool.submit(websocket.main_task(taskpool, self.test, self.config['pid'])) + taskpool.await_taskpool() + taskpool.task_join() + if taskpool.task_exception: + raise taskpool.task_exception + + def teardown(self): + Step('7.关闭应用') + self.driver.stop_app(self.config['bundle_name']) + Step('8.卸载应用') + self.driver.uninstall_app(self.config['bundle_name']) + + async def test(self, websocket): + ################################################################################################################ + # main thread: connect the debugger server + ################################################################################################################ + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + ################################################################################################################ + # worker thread: connect the debugger server + ################################################################################################################ + worker_thread_1 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + ################################################################################################################ + # worker thread: Runtime.enable + ################################################################################################################ + await self.runtime_impl.send("Runtime.enable", worker_thread_1) + await self.runtime_impl.send("Runtime.enable", worker_thread_2) + ################################################################################################################ + # worker thread: Debugger.enable + ################################################################################################################ + await self.debugger_impl.send("Debugger.enable", worker_thread_1) + await self.debugger_impl.send("Debugger.enable", worker_thread_2) + ################################################################################################################ + # worker thread: Runtime.runIfWaitingForDebugger + ################################################################################################################ + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread_1) + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread_2) + ################################################################################################################ + # main thread: Runtime.enable + ################################################################################################################ + await self.runtime_impl.send("Runtime.enable", main_thread) + ################################################################################################################ + # main thread: Debugger.enable + ################################################################################################################ + await self.debugger_impl.send("Debugger.enable", main_thread) + ################################################################################################################ + # main thread: Runtime.runIfWaitingForDebugger + ################################################################################################################ + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) + ################################################################################################################ + # main thread: Debugger.removeBreakpointsByUrl + ################################################################################################################ + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", main_thread, params) + ################################################################################################################ + # main thread: Debugger.getPossibleAndSetBreakpointByUrl + ################################################################################################################ + locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=53), + debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=57)] + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", main_thread, params) + result_locations = response['result']['locations'] + self.common_utils.assert_equal(result_locations[0]['id'], 'id:53:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(result_locations[1]['id'], 'id:57:0:' + self.config['file_path']['index']) + ################################################################################################################ + # main thread: click on the screen + ################################################################################################################ + self.ui_utils.click_on_middle() + ################################################################################################################ + # main thread: Debugger.paused, hit breakpoint + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:53:16:' + self.config['file_path']['index']]) + ################################################################################################################ + # worker thread: destroy instance + ################################################################################################################ + response = await self.debugger_impl.destroy_instance() + if response['instanceId'] == worker_thread_1.instance_id: + worker_thread_1 = worker_thread_2 + ################################################################################################################ + # worker thread: Debugger.removeBreakpointsByUrl + ################################################################################################################ + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['worker']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread_1, params) + ################################################################################################################ + # worker thread: Debugger.getPossibleAndSetBreakpointByUrl + ################################################################################################################ + locations = [debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=11)] + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", worker_thread_1, params) + self.common_utils.assert_equal(response['result']['locations'][0]['id'], + 'id:11:0:' + self.config['file_path']['worker']) + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + # main thread: Debugger.paused, hit breakpoint + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:57:20:' + self.config['file_path']['index']]) + ################################################################################################################ + # worker thread: connect the debugger server + ################################################################################################################ + worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False) + ################################################################################################################ + # worker thread: Runtime.enable + ################################################################################################################ + await self.runtime_impl.send("Runtime.enable", worker_thread_2) + ################################################################################################################ + # worker thread: Debugger.enable + ################################################################################################################ + await self.debugger_impl.send("Debugger.enable", worker_thread_2) + ################################################################################################################ + # worker thread: Runtime.runIfWaitingForDebugger + ################################################################################################################ + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread_2) + # worker thread: Debugger.scriptParsed + response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread_2) + self.common_utils.assert_equal(response['params']['url'], self.config['file_path']['worker']) + self.common_utils.assert_equal(response['params']['endLine'], 0) + # worker thread: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_2) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['worker']) + self.common_utils.assert_equal(response['params']['reason'], 'Break on start') + ################################################################################################################ + # worker thread: Debugger.removeBreakpointsByUrl + ################################################################################################################ + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['worker']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread_2, params) + ################################################################################################################ + # worker thread: Debugger.getPossibleAndSetBreakpointByUrl + ################################################################################################################ + locations = [debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=11)] + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", worker_thread_2, params) + self.common_utils.assert_equal(response['result']['locations'][0]['id'], + 'id:11:0:' + self.config['file_path']['worker']) + ################################################################################################################ + # worker thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", worker_thread_2) + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + # main thread: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:57:20:' + self.config['file_path']['index']]) + # worker thread: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_1) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['worker']) + self.common_utils.assert_equal(response['params']['reason'], 'Break on start') + self.common_utils.assert_equal(response['params']['hitBreakpoints'], []) + ################################################################################################################ + # worker thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", worker_thread_1) + # worker thread: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_1) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['worker']) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:11:4:' + self.config['file_path']['worker']]) + ################################################################################################################ + # worker thread: Debugger.stepOut + ################################################################################################################ + await self.debugger_impl.send("Debugger.stepOut", worker_thread_1) + ################################################################################################################ + # worker thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", worker_thread_1) + ################################################################################################################ + # main thread: Debugger.stepOver + ################################################################################################################ + await self.debugger_impl.send("Debugger.stepOver", main_thread) + # main thread: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], []) + # worker thread: Debugger.paused + response = await self.debugger_impl.recv("Debugger.paused", worker_thread_2) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['worker']) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:11:4:' + self.config['file_path']['worker']]) + ################################################################################################################ + # worker thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", worker_thread_2) + ################################################################################################################ + # worker thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", worker_thread_2) + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # worker thread: destroy instance + ################################################################################################################ + response = await self.debugger_impl.destroy_instance() + assert response['instanceId'] != self.config['pid'], f"Worker instanceId can not be {self.config['pid']}" + response = await self.debugger_impl.destroy_instance() + assert response['instanceId'] != self.config['pid'], f"Worker instanceId can not be {self.config['pid']}" + ################################################################################################################ + # main thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", main_thread) + ################################################################################################################ + # close the websocket connections + ################################################################################################################ + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') + await websocket.send_msg_to_connect_server('close') + ################################################################################################################ \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.json b/test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.json new file mode 100644 index 00000000..e9fb2ce5 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestMainBreakpointsSendable", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestMainBreakpointsSendable.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.py b/test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.py new file mode 100644 index 00000000..dcd518ae --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2025 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 主线程使能 Runtime 和 Debugger + 3. 主线程运行等待的调试器 + 4. 主线程解析 entry_ability 和 index 文件 + 5. 主线程 Index.ts 文件设置断点并运行 + 6. 主线程 resume 验证是否正确命中断点 + 7. 关闭主线程 debugger server 和 connect server 连接 +#================================================================== +关键代码: + Index.ets + @Sendable + class TestClass { + desc: string = "XXXXXXXX"; // 自定义设置类成员 + taskNum: number = XXXXXXXX; + get getTaskNum(): number { // 自定义设置类成员方法 + return this.taskNum; // 设置断点 + } + } + const testInstance = new TestClass(); + let taskNumber = testInstance.getTaskNum; +#!!================================================================ +""" +import sys +from pathlib import Path + +root_path = Path(__file__).parent.parent.parent.parent +resource_path = root_path / 'resource' +sys.path.append(str(root_path / 'aw')) # add aw path to sys.path + +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from all_utils import CommonUtils, UiUtils +from cdp import debugger +from implement_api import debugger_api, runtime_api + + +class TestMainBreakpointsSendable(TestCase): + def __init__(self, controllers): + self.TAG = self.__class__.__name__ + TestCase.__init__(self, self.TAG, controllers) + self.driver = UiDriver(self.device1) + self.ui_utils = UiUtils(self.driver) + self.common_utils = CommonUtils(self.driver) + self.id_generator = CommonUtils.message_id_generator() + self.config = { + 'start_mode': '-D', + 'connect_server_port': 15612, + 'debugger_server_port': 15613, + 'bundle_name': 'com.example.mainInstance02', + 'hap_name': 'MainInstance02.hap', + 'hap_path': str(resource_path / 'hap' / 'MainInstance02.hap'), + 'file_path': { + 'entry_ability': 'entry|entry|1.0.0|src/main/ets/entryability/EntryAbility.ts', + 'index': 'entry|entry|1.0.0|src/main/ets/pages/Index.ts', + } + } + + def setup(self): + Step('1.下载应用') + self.driver.install_app(self.config['hap_path'], "-r") + Step('2.启动应用') + self.driver.start_app(package_name=self.config['bundle_name'], params=self.config['start_mode']) + self.config['pid'] = self.common_utils.get_pid(self.config['bundle_name']) + assert self.config['pid'] != 0, f'Failed to get pid of {self.config["bundle_name"]}' + Step('3.设置屏幕常亮') + self.ui_utils.keep_awake() + Step('4.端口映射,连接server') + self.common_utils.connect_server(self.config) + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, self.config['websocket']) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, self.config['websocket']) + + def process(self): + Step('5.执行测试用例') + websocket = self.config['websocket'] + taskpool = self.config['taskpool'] + taskpool.submit(websocket.main_task(taskpool, self.test, self.config['pid'])) + taskpool.await_taskpool() + taskpool.task_join() + if taskpool.task_exception: + raise taskpool.task_exception + + def teardown(self): + Step('6.关闭应用') + self.driver.stop_app(self.config['bundle_name']) + Step('7.卸载应用') + self.driver.uninstall_app(self.config['bundle_name']) + + async def test(self, websocket): + ################################################################################################################ + # main thread: connect the debugger server + ################################################################################################################ + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + ################################################################################################################ + # main thread: Runtime.enable + ################################################################################################################ + await self.runtime_impl.send("Runtime.enable", main_thread) + ################################################################################################################ + # main thread: Debugger.enable + ################################################################################################################ + await self.debugger_impl.send("Debugger.enable", main_thread) + ################################################################################################################ + # main thread: Runtime.runIfWaitingForDebugger + ################################################################################################################ + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) + ################################################################################################################ + # main thread: Debugger.scriptParsed + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) + self.common_utils.assert_equal(response['params']['url'], self.config['file_path']['entry_ability']) + self.common_utils.assert_equal(response['params']['endLine'], 0) + ################################################################################################################ + # main thread: Debugger.paused + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], + self.config['file_path']['entry_ability']) + self.common_utils.assert_equal(response['params']['reason'], 'Break on start') + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # main thread: Debugger.scriptParsed + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) + self.common_utils.assert_equal(response['params']['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['endLine'], 0) + ################################################################################################################ + # main thread: Debugger.paused + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['reason'], 'Break on start') + ################################################################################################################ + # main thread: Debugger.removeBreakpointsByUrl + ################################################################################################################ + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['index']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", main_thread, params) + ################################################################################################################ + # main thread: Debugger.getPossibleAndSetBreakpointByUrl + ################################################################################################################ + locations = [debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=74)] + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", main_thread, params) + self.common_utils.assert_equal(response['result']['locations'][0]['id'], + 'id:74:0:' + self.config['file_path']['index']) + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # main thread: Debugger.paused, hit breakpoint + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:74:15:' + self.config['file_path']['index']]) + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ############################################################################################################### + # main thread: click on the screen + ################################################################################################################ + self.ui_utils.click_on_middle() + ################################################################################################################ + # main thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", main_thread) + ################################################################################################################ + # close the websocket connections + ################################################################################################################ + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') + await websocket.send_msg_to_connect_server('close') + ################################################################################################################ \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.json b/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.json new file mode 100644 index 00000000..96fe3fd8 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestMainExceptionBreakpoints01", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestMainExceptionBreakpoints01.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.py b/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.py new file mode 100644 index 00000000..4fffc1b4 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Copyright (c) 2025 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 主线程使能 Runtime 和 Debugger + 3. 主线程运行等待的调试器 + 4. 主线程解析 entry_ability 和 index 文件 + 5. 设置异常捕获状态 ALL + 6. 主线程 resume(Debugger.resume)命中异常断点,验证异常断点信息 CAUGHT 类型异常 + 7. 主线程 resume(Debugger.resume)命中异常断点,验证异常断点信息 UNCAUGHT 类型异常 + 8. 关闭主线程 debugger server 和 connect server 连接 +#================================================================== +关键代码: + Index.ets + function main() { + try { + throw new Error("This is a caught error"); + } catch (error) { + console.log("After error"); + } + throw new Error("This is a uncaught error"); + } + main(); +#!!================================================================ +""" +import sys +from pathlib import Path + +root_path = Path(__file__).parent.parent.parent.parent +resource_path = root_path / 'resource' +sys.path.append(str(root_path / 'aw')) # add aw path to sys.path + +from devicetest.core.test_case import TestCase, Step +from hypium import UiDriver +from all_utils import CommonUtils, UiUtils +from cdp import debugger +from implement_api import debugger_api, runtime_api + + +class TestMainExceptionBreakpoints01(TestCase): + def __init__(self, controllers): + self.TAG = self.__class__.__name__ + TestCase.__init__(self, self.TAG, controllers) + self.driver = UiDriver(self.device1) + self.ui_utils = UiUtils(self.driver) + self.common_utils = CommonUtils(self.driver) + self.id_generator = CommonUtils.message_id_generator() + self.config = { + 'start_mode': '-D', + 'connect_server_port': 15606, + 'debugger_server_port': 15607, + 'bundle_name': 'com.example.mainInstance04', + 'hap_name': 'MainInstance04.hap', + 'hap_path': str(resource_path / 'hap' / 'MainInstance04.hap'), + 'file_path': { + 'entry_ability': 'entry|entry|1.0.0|src/main/ets/entryability/EntryAbility.ts', + 'index': 'entry|entry|1.0.0|src/main/ets/pages/Index.ts', + } + } + + def setup(self): + Step('1.下载应用') + self.driver.install_app(self.config['hap_path'], "-r") + Step('2.启动应用') + self.driver.start_app(package_name=self.config['bundle_name'], params=self.config['start_mode']) + self.config['pid'] = self.common_utils.get_pid(self.config['bundle_name']) + assert self.config['pid'] != 0, f'Failed to get pid of {self.config["bundle_name"]}' + Step('3.设置屏幕常亮') + self.ui_utils.keep_awake() + Step('4.端口映射,连接server') + self.common_utils.connect_server(self.config) + self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, self.config['websocket']) + self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, self.config['websocket']) + + def process(self): + Step('5.执行测试用例') + websocket = self.config['websocket'] + taskpool = self.config['taskpool'] + taskpool.submit(websocket.main_task(taskpool, self.test, self.config['pid'])) + taskpool.await_taskpool() + taskpool.task_join() + if taskpool.task_exception: + raise taskpool.task_exception + + def teardown(self): + Step('6.关闭应用') + self.driver.stop_app(self.config['bundle_name']) + Step('7.卸载应用') + self.driver.uninstall_app(self.config['bundle_name']) + + async def test(self, websocket): + ################################################################################################################ + # main thread: connect the debugger server + ################################################################################################################ + main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True) + ################################################################################################################ + # main thread: Runtime.enable + ################################################################################################################ + await self.runtime_impl.send("Runtime.enable", main_thread) + ################################################################################################################ + # main thread: Debugger.enable + ################################################################################################################ + await self.debugger_impl.send("Debugger.enable", main_thread) + ################################################################################################################ + # main thread: Runtime.runIfWaitingForDebugger + ################################################################################################################ + await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread) + ################################################################################################################ + # main thread: Debugger.scriptParsed + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) + self.common_utils.assert_equal(response['params']['url'], self.config['file_path']['entry_ability']) + self.common_utils.assert_equal(response['params']['endLine'], 0) + ################################################################################################################ + # main thread: Debugger.paused + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], + self.config['file_path']['entry_ability']) + self.common_utils.assert_equal(response['params']['reason'], 'Break on start') + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # main thread: Debugger.scriptParsed + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) + self.common_utils.assert_equal(response['params']['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['endLine'], 0) + ################################################################################################################ + # main thread: Debugger.paused + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['reason'], 'Break on start') + ################################################################################################################ + # main thread: Debugger.setPauseOnExceptions + ################################################################################################################ + params = debugger.PauseOnExceptionsState.ALL + await self.debugger_impl.send("Debugger.setPauseOnExceptions", main_thread, params) + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # main thread: Debugger.paused + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['reason'], 'exception') + assert 'This is a caught error' in response['params']['data']['description'], \ + f"'caught error' is not in description: '{response['params']['data']['description']}'" + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # main thread: Debugger.paused + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['callFrames'][0]['url'], self.config['file_path']['index']) + self.common_utils.assert_equal(response['params']['reason'], 'exception') + assert 'This is a uncaught error' in response['params']['data']['description'], \ + f"'uncaught error' is not in description: '{response['params']['data']['description']}'" + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # close the websocket connections + ################################################################################################################ + await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close') + await websocket.send_msg_to_connect_server('close') + ################################################################################################################ \ No newline at end of file -- Gitee