From 2cd318218b67fcf6e1590bccfa6031d282fff61a Mon Sep 17 00:00:00 2001 From: panmingxuan Date: Mon, 26 May 2025 09:33:05 +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=A53?= 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/ICAEF4 Signed-off-by: panmingxuan --- .../toolchain/debug/TestAttachTaskPool.py | 3 + .../toolchain/debug/TestAttachWorkerStep.py | 3 + .../debug/TestMainBreakpointSendable.py | 3 + .../toolchain/debug/TestMainDropFrame.py | 3 + .../debug/TestMainExceptionBreakpoints01.py | 3 + .../debug/TestMainExceptionBreakpoints02.py | 3 + .../debug/TestMainExceptionBreakpoints03.py | 3 + .../debug/TestMainLaunchAccelerate.json | 15 + .../debug/TestMainLaunchAccelerate.py | 260 +++++++++++++++ .../toolchain/debug/TestMainMixedDebug.json | 15 + .../toolchain/debug/TestMainMixedDebug.py | 231 +++++++++++++ .../debug/TestMainSendableClass.json | 15 + .../toolchain/debug/TestMainSendableClass.py | 204 ++++++++++++ .../debug/TestMainSmartStepInto.json | 15 + .../toolchain/debug/TestMainSmartStepInto.py | 214 ++++++++++++ .../toolchain/debug/TestTaskPool.json | 15 + .../testcases/toolchain/debug/TestTaskPool.py | 310 ++++++++++++++++++ .../toolchain/debug/TestTaskPoolSendable.json | 15 + .../toolchain/debug/TestTaskPoolSendable.py | 286 ++++++++++++++++ .../TestWorkerConditionalBreakpoints.json | 15 + .../debug/TestWorkerConditionalBreakpoints.py | 277 ++++++++++++++++ 21 files changed, 1908 insertions(+) create mode 100644 test/autotest/testcases/toolchain/debug/TestMainLaunchAccelerate.json create mode 100644 test/autotest/testcases/toolchain/debug/TestMainLaunchAccelerate.py create mode 100644 test/autotest/testcases/toolchain/debug/TestMainMixedDebug.json create mode 100644 test/autotest/testcases/toolchain/debug/TestMainMixedDebug.py create mode 100644 test/autotest/testcases/toolchain/debug/TestMainSendableClass.json create mode 100644 test/autotest/testcases/toolchain/debug/TestMainSendableClass.py create mode 100644 test/autotest/testcases/toolchain/debug/TestMainSmartStepInto.json create mode 100644 test/autotest/testcases/toolchain/debug/TestMainSmartStepInto.py create mode 100644 test/autotest/testcases/toolchain/debug/TestTaskPool.json create mode 100644 test/autotest/testcases/toolchain/debug/TestTaskPool.py create mode 100644 test/autotest/testcases/toolchain/debug/TestTaskPoolSendable.json create mode 100644 test/autotest/testcases/toolchain/debug/TestTaskPoolSendable.py create mode 100644 test/autotest/testcases/toolchain/debug/TestWorkerConditionalBreakpoints.json create mode 100644 test/autotest/testcases/toolchain/debug/TestWorkerConditionalBreakpoints.py diff --git a/test/autotest/testcases/toolchain/debug/TestAttachTaskPool.py b/test/autotest/testcases/toolchain/debug/TestAttachTaskPool.py index 9c9d5596..ed62e81f 100644 --- a/test/autotest/testcases/toolchain/debug/TestAttachTaskPool.py +++ b/test/autotest/testcases/toolchain/debug/TestAttachTaskPool.py @@ -14,6 +14,9 @@ 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. +#================================================================== +#文 件 名: TestAttachTaskPool.py +#文件说明: 多 task 实例 attach 调试 #================================================================== 测试步骤: 1. 连接 connect server 和主线程 debugger server diff --git a/test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.py b/test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.py index a3af5d06..760a0fd0 100644 --- a/test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.py +++ b/test/autotest/testcases/toolchain/debug/TestAttachWorkerStep.py @@ -14,6 +14,9 @@ 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. +#================================================================== +#文 件 名: TestAttachWorkerStep.py +#文件说明: 多实例 attach 调试,执行单步操作进行跨线程通信 #================================================================== 测试步骤: 1. 连接 connect server 和主线程 debugger server diff --git a/test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.py b/test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.py index dcd518ae..0c61306b 100644 --- a/test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.py +++ b/test/autotest/testcases/toolchain/debug/TestMainBreakpointSendable.py @@ -14,6 +14,9 @@ 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. +#================================================================== +#文 件 名: TestMainBreakpointsSendable.py +#文件说明: 主线程 Sendable 对象成员方法上普通断点的设置/取消 #================================================================== 测试步骤: 1. 连接 connect server 和主线程 debugger server diff --git a/test/autotest/testcases/toolchain/debug/TestMainDropFrame.py b/test/autotest/testcases/toolchain/debug/TestMainDropFrame.py index 0ef07531..21f89158 100644 --- a/test/autotest/testcases/toolchain/debug/TestMainDropFrame.py +++ b/test/autotest/testcases/toolchain/debug/TestMainDropFrame.py @@ -14,6 +14,9 @@ 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. +#================================================================== +#文 件 名: TestMainBreakpoints.py +#文件说明: 主线程 debug 调试之 drop frame #================================================================== 测试步骤: 1. 连接 connect server 和主线程 debugger server diff --git a/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.py b/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.py index 4fffc1b4..7c1aaa2b 100644 --- a/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.py +++ b/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints01.py @@ -14,6 +14,9 @@ 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. +#================================================================== +#文 件 名: TestMainExceptionBreakpoints01.py +#文件说明: 主线程 debug 调试异常断点 ALL 模式 #================================================================== 测试步骤: 1. 连接 connect server 和主线程 debugger server diff --git a/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints02.py b/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints02.py index 761060f1..0bdf88b4 100644 --- a/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints02.py +++ b/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints02.py @@ -14,6 +14,9 @@ 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. +#================================================================== +#文 件 名: TestMainExceptionBreakpoints02.py +#文件说明: 主线程 debug 调试异常断点 UNCAUGHT 模式 #================================================================== 测试步骤: 1. 连接 connect server 和主线程 debugger server diff --git a/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints03.py b/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints03.py index 8af33f61..92b708c0 100644 --- a/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints03.py +++ b/test/autotest/testcases/toolchain/debug/TestMainExceptionBreakpoints03.py @@ -14,6 +14,9 @@ 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. +#================================================================== +#文 件 名: TestMainExceptionBreakpoints03.py +#文件说明: 主线程 debug 调试异常断点 NONE 模式 #================================================================== 测试步骤: 1. 连接 connect server 和主线程 debugger server diff --git a/test/autotest/testcases/toolchain/debug/TestMainLaunchAccelerate.json b/test/autotest/testcases/toolchain/debug/TestMainLaunchAccelerate.json new file mode 100644 index 00000000..f4e7f1ca --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainLaunchAccelerate.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestMainLaunchAccelerate", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestMainLaunchAccelerate.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestMainLaunchAccelerate.py b/test/autotest/testcases/toolchain/debug/TestMainLaunchAccelerate.py new file mode 100644 index 00000000..b24025bf --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainLaunchAccelerate.py @@ -0,0 +1,260 @@ +#!/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. + +#================================================================== +#文 件 名: TestMainLaunchAccelerate.py +#文件说明: 主线程冷启性能优化测试 +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 主线程使能 Runtime 和 Debugger + 3. 主线程设置所有断点(Debugger.saveAllPossibleBreakpoints) + 4. 主线程 scriptParsed 加载文件(Debugger.scriptPaused) + 5. 主线程多次 resume, 程序停在设置的断点处(Debugger.resume) + 6. 主线程在 params.ets 文件中设置断点(Debugger.getPossibleAndSetBreakpointsByUrl) + 7. 主线程 resume,命中断点(Debugger.resume) + 8. 主线程 resume(Debugger.resume) + 9. 关闭所有线程 debugger server 和 connect server 连接 +#!!================================================================ +""" +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 TestMainLaunchAccelerate(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': 15618, + 'debugger_server_port': 15619, + 'bundle_name': 'com.example.multiWorker09', + 'hap_name': 'MultiWorker09.hap', + 'hap_path': str(resource_path / 'hap' / 'MultiWorker09.hap'), + 'file_path': { + 'entry_ability': 'entry|entry|1.0.0|src/main/ets/entryability/EntryAbility.ts', + 'params': 'entry|entry|1.0.0|src/main/ets/resources/Params.ts', + 'index': 'entry|entry|1.0.0|src/main/ets/pages/Index.ts', + 'sendable': 'entry|entry|1.0.0|src/main/ets/resources/Sendable.ts', + 'person': 'entry|entry|1.0.0|src/main/ets/resources/Person.ts', + 'drop_frame': 'entry|entry|1.0.0|src/main/ets/resources/DropFrame.ts', + 'step': 'entry|entry|1.0.0|src/main/ets/resources/Step.ts', + 'calculate': 'entry|entry|1.0.0|src/main/ets/resources/Calculate.ts', + 'sleep': 'entry|entry|1.0.0|src/main/ets/resources/Sleep.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']) + + 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, debugger.EnableAccelerateLaunchParams()) + ################################################################################################################ + # main thread: Debugger.saveAllPossibleBreakpoints + ################################################################################################################ + locations = { + self.config['file_path']['step']: [3], + self.config['file_path']['index']: [76, 78, 1000], + self.config['file_path']['params']: [77, 79, 83] + } + params = debugger.SaveAllPossibleBreakpointsParams(locations) + await self.debugger_impl.send("Debugger.saveAllPossibleBreakpoints", main_thread, params) + ################################################################################################################ + # 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']) + ################################################################################################################ + # 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']['sendable']) + ################################################################################################################ + # 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']['person']) + ################################################################################################################ + # 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']['params']) + ################################################################################################################ + # 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']['drop_frame']) + ################################################################################################################ + # 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']['calculate']) + ################################################################################################################ + # 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']['step']) + ################################################################################################################ + # 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']) + ################################################################################################################ + # main thread: Debugger.paused + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.paused", main_thread) + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:76:0:' + self.config['file_path']['index']]) + ################################################################################################################ + # 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']['hitBreakpoints'], + ['id:3:19:' + self.config['file_path']['step']]) + ################################################################################################################ + # main thread: Debugger.removeBreakpointsByUrl + ################################################################################################################ + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['step']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", 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']['hitBreakpoints'], + ['id:78:0:' + self.config['file_path']['index']]) + ################################################################################################################ + # 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']['hitBreakpoints'], + ['id:77:4:' + self.config['file_path']['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']['hitBreakpoints'], + ['id:79:4:' + self.config['file_path']['params']]) + ################################################################################################################ + # main thread: Debugger.removeBreakpointsByUrl + ################################################################################################################ + params = debugger.RemoveBreakpointsUrl(self.config['file_path']['params']) + await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", main_thread, params) + ################################################################################################################ + # main thread: Debugger.getPossibleAndSetBreakpointByUrl + ################################################################################################################ + locations = [debugger.BreakLocationUrl(url=self.config['file_path']['params'], line_number=84)] + 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:84:0:' + self.config['file_path']['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']['hitBreakpoints'], + ['id:84:4:' + self.config['file_path']['params']]) + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_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(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/TestMainMixedDebug.json b/test/autotest/testcases/toolchain/debug/TestMainMixedDebug.json new file mode 100644 index 00000000..f68a2121 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainMixedDebug.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestMainMixedDebug", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestMainMixedDebug.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestMainMixedDebug.py b/test/autotest/testcases/toolchain/debug/TestMainMixedDebug.py new file mode 100644 index 00000000..0bb29eaa --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainMixedDebug.py @@ -0,0 +1,231 @@ +#!/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. + +#================================================================== +#文 件 名: TestMainMixedDebug.py +#文件说明: 主线程 debug 混合调试 +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 主线程使能 Runtime 和 Debugger + 3. 主线程使能混合调试(Debugger.setMixedDebugEnabled) + 4. 主线程 Index.ets 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) + 5. 触发点击事件,主线程暂停在断点处 + 6. 主线程 stepInto,进入 native 调试(Debugger.stepInto) + 7. 主线程收到 native 返回的消息后应答,停在下一断点处(Debugger.replyNativeCalling) + 8. 主线程 stepOver,停在下一行(Debugger.stepOver) + 9. 主线程 resume(Debugger.resume) + 10. 主线程去使能 debugger(Debugger.disable) + 11. 关闭主线程 debugger server 和 connect server 连接 +#================================================================== +关键代码: + Index.ets + import testNapi from 'libentry.so'; + .OnClick(() => { + let num = testNapi.add(1, 2) + let ans = testNapi.add(num, 3) + console.log("testNapi.add run successfully, ans = ", ans) + }) +#!!================================================================ +""" +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 TestMainMixedDebug(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': 15620, + 'debugger_server_port': 15621, + 'bundle_name': 'com.example.native01', + 'hap_name': 'Native01.hap', + 'hap_path': str(resource_path / 'hap' / 'Native01.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: Debugger.setMixedDebugEnabled + ################################################################################################################ + params = debugger.SetMixedDebugEnabledParams(enabled=True, mixed_stack_enabled=False) + await self.debugger_impl.send("Debugger.setMixedDebugEnabled", main_thread, params) + ################################################################################################################ + # 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=62), + debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=63)] + 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:62:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(response['result']['locations'][1]['id'], + 'id:63:0:' + 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.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:62:26:' + self.config['file_path']['index']]) + ################################################################################################################ + # main thread: Debugger.stepInto + ################################################################################################################ + await self.debugger_impl.send("Debugger.stepInto", main_thread) + ################################################################################################################ + # main thread: Debugger.nativeCalling + ################################################################################################################ + response = await self.debugger_impl.recv("Debugger.nativeCalling", main_thread) + assert response['params']['isStepInto'] is True + ################################################################################################################ + # main thread: Debugger.replyNativeCalling + ################################################################################################################ + params = debugger.ReplyNativeCallingParams() + await self.debugger_impl.send("Debugger.replyNativeCalling", main_thread, params) + # 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:63:26:' + self.config['file_path']['index']]) + ################################################################################################################ + # 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'], []) + ################################################################################################################ + # main thread: Debugger.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_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(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/TestMainSendableClass.json b/test/autotest/testcases/toolchain/debug/TestMainSendableClass.json new file mode 100644 index 00000000..904836af --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainSendableClass.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestMainSendableClass", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestMainSendableClass.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestMainSendableClass.py b/test/autotest/testcases/toolchain/debug/TestMainSendableClass.py new file mode 100644 index 00000000..c1196695 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainSendableClass.py @@ -0,0 +1,204 @@ +#!/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. + +#================================================================== +#文 件 名: TestMainSendableClass.py +#文件说明: 主线程 Sendable 变量信息查看 +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 主线程使能 Runtime 和 Debugger + 3. 主线程运行等待的调试器 + 4. 主线程解析 entry_ability 和 index 文件 + 5. 主线程 Index.ts 文件设置断点 + 6. 主线程 resume 验证是否正确命中断点 + 7. 主线程查询类对象并验证是否携带 Sendable 标签 + 8. 关闭主线程 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 TestMainSendableClass(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': 15622, + 'debugger_server_port': 15623, + '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=78)] + 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:78: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:78:17:' + self.config['file_path']['index']]) + ################################################################################################################ + # main thread: Runtime.getProperties and check sendable + ################################################################################################################ + params = debugger.EvaluateOnCallFrameParams('testInstance') + response = await self.debugger_impl.send("Debugger.evaluateOnCallFrame", main_thread, params) + assert '[Sendable]' in response['result']['result']['description'], \ + f"[Sendable] is not in description: {response['result']['result']['description']}" + ################################################################################################################ + # 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/TestMainSmartStepInto.json b/test/autotest/testcases/toolchain/debug/TestMainSmartStepInto.json new file mode 100644 index 00000000..fa86ca98 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainSmartStepInto.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestMainSmartStepInto", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestMainSmartStepInto.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestMainSmartStepInto.py b/test/autotest/testcases/toolchain/debug/TestMainSmartStepInto.py new file mode 100644 index 00000000..6a99fe9f --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestMainSmartStepInto.py @@ -0,0 +1,214 @@ +#!/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. + +#================================================================== +#文 件 名: TestMainSmartStepInto.py +#文件说明: 主线程 debug 调试 smartStepinto +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 主线程使能 Runtime 和 Debugger + 3. 主线程运行等待的调试器 + 4. 主线程解析 entry_ability 和 index 文件 + 5. 主线程 Index.ts 文件设置断点并运行 + 6. 主线程 resume 验证是否正确命中断点 + 7. 主线程 smartStepInto 验证传回的函数信息 + 8. 关闭主线程 debugger server 和 connect server 连接 +#================================================================== +关键代码: + Index.ets + function test1() { + return taskNumber; + } + function test2() { + return taskNumber + 5; + } + function main() { + test1(); + taskNumber = test1() + test2(); // 设置断点 + } + 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 TestMainSmartStepInto(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': 15624, + 'debugger_server_port': 15625, + 'bundle_name': 'com.example.mainInstance03', + 'hap_name': 'MainInstance03.hap', + 'hap_path': str(resource_path / 'hap' / 'MainInstance03.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=73)] + 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:73: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:73:17:' + self.config['file_path']['index']]) + ################################################################################################################ + # main thread: Debugger.smartStepInto + ################################################################################################################ + params = debugger.SmartStepIntoParams(url=self.config['file_path']['index'], line_number=69) + await self.debugger_impl.send("Debugger.smartStepInto", 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']['callFrames'][0]['functionName'], 'test2') + self.common_utils.assert_equal(response['params']['reason'], 'other') + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:69:11:' + 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/TestTaskPool.json b/test/autotest/testcases/toolchain/debug/TestTaskPool.json new file mode 100644 index 00000000..8b8bdce1 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestTaskPool.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestTaskPool", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestTaskPool.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestTaskPool.py b/test/autotest/testcases/toolchain/debug/TestTaskPool.py new file mode 100644 index 00000000..776b0587 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestTaskPool.py @@ -0,0 +1,310 @@ +#!/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. + +#================================================================== +#文 件 名: TestTaskPool.py +#文件说明: 多 task 实例 debug 调试 +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 主线程使能 Runtime 和 Debugger + 3. 连接子线程 debugger server,用于执行 task 任务 + 4. 子线程使能 Runtime 和 Debugger + 5. 主线程 Index.ts 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) + 6. 触发点击事件,主线程命中断点 + 7. 子线程 Index.ts 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) + 8. 子线程 resume,命中断点(Debugger.resume) + 9. 子线程 getProperties,返回给定对象的属性(Runtime.getProperties) + 10. 子线程 stepOut,主线程命中断点(Debugger.stepOut) + 11. 主线程 getProperties(Runtime.getProperties) + 12. 主线程 resume(Debugger.resume) + 13. 子线程命中断点后 resume(Debugger.resume) + 14. 关闭所有线程 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 TestTaskPool(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': 15626, + 'debugger_server_port': 15627, + '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']) + + 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.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # worker thread: connect the debugger server + ################################################################################################################ + worker_thread = 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) + ################################################################################################################ + # 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) + self.common_utils.assert_equal(response['result']['locations'][0]['id'], + 'id:10:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(response['result']['locations'][1]['id'], + 'id:17:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(response['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) + self.common_utils.assert_equal(response['result']['locations'][0]['id'], + 'id:10:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(response['result']['locations'][1]['id'], + 'id:17:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(response['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']['reason'], 'other') + 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) + self.common_utils.assert_equal(response['result']['result'][0]['name'], 'taskpoolTest') + self.common_utils.assert_equal(response['result']['result'][0]['value']['type'], 'function') + self.common_utils.assert_equal(response['result']['result'][1]['name'], 'valueSub') + self.common_utils.assert_equal(response['result']['result'][1]['value']['type'], 'undefined') + self.common_utils.assert_equal(response['result']['result'][2]['name'], 'valueAdd') + self.common_utils.assert_equal(response['result']['result'][2]['value']['type'], 'number') + self.common_utils.assert_equal(response['result']['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/TestTaskPoolSendable.json b/test/autotest/testcases/toolchain/debug/TestTaskPoolSendable.json new file mode 100644 index 00000000..ad2194eb --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestTaskPoolSendable.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestTaskPoolSendable", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestTaskPoolSendable.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestTaskPoolSendable.py b/test/autotest/testcases/toolchain/debug/TestTaskPoolSendable.py new file mode 100644 index 00000000..c2a4a815 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestTaskPoolSendable.py @@ -0,0 +1,286 @@ +#!/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. + +#================================================================== +#文 件 名: TestTaskPoolSendable.py +#文件说明: 跨线程传递 Sendable 对象 +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 主线程使能 Runtime 和 Debugger + 3. 主线程 resume(Debugger.resume) + 4. 创建子线程,连接子线程 debugger server + 5. 子线程使能 Runtime 和 Debugger + 6. 主线程 Index.ets 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) + 7. 触发点击事件,子线程 Index.ets 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl) + 8. 子线程 resume,停在断点处(Debugger.resume) + 9. 子线程 getProperties,获取 Sendable 对象方法(Debugger.getProperties) + 10. 子线程 resume,停在下一断点处(Debugger.resume) + 11. 子线程 getProperties,获取 Sendable 对象方法(Debugger.getProperties) + 12. 子线程 resume(Debugger.resume) + 13. 所有线程去使能 debugger(Debugger.disable) + 14. 关闭所有线程 debugger server 和 connect server 连接 +#================================================================== +关键代码: + Index.ets + @Concurrent + async function taskFunc(person: Person) { + let ans = person.calculate(21, 50) + person.setScore(100) + } + async function sendableTest() { + let p = new Person('Tony', 9) + let task: taskpool.Task = new taskpool.Task(taskFunc, p) + await taskpool.execute(task) + } + .OnClick(() => { + sendableTest() + }) + @Sendable + class Person { + name: string + age: number + score: number = 0 + constructor(name: string, age: number) { + this.name = name + this.age = age + } + setScore(score: number) { + this.score = score // b1 + } + addNumber(num1: number, num2: number) { + let result = num1 + num2 // b2 + return result + } + } +#!!================================================================ +""" +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 TestTaskPoolSendable(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': 15628, + 'debugger_server_port': 15629, + 'bundle_name': 'com.example.taskPool02', + 'hap_name': 'TaskPool02.hap', + 'hap_path': str(resource_path / 'hap' / 'TaskPool02.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.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # worker thread: connect the debugger server + ################################################################################################################ + worker_thread = 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) + ################################################################################################################ + # 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: 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=95), + debugger.BreakLocationUrl(url=self.config['file_path']['index'], line_number=98)] + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", worker_thread, params) + self.common_utils.assert_equal(response['result']['locations'][0]['id'], + 'id:95:0:' + self.config['file_path']['index']) + self.common_utils.assert_equal(response['result']['locations'][1]['id'], + 'id:98: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']['callFrames'][0]['functionName'], 'addNumber') + self.common_utils.assert_equal(response['params']['reason'], 'other') + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:98:21:' + 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'], 'addNumber') + assert response['result']['result'][0]['value']['description'].endswith('[Sendable]') + ################################################################################################################ + # 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']['callFrames'][0]['functionName'], 'setScore') + self.common_utils.assert_equal(response['params']['reason'], 'other') + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:95:8:' + 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'], 'setScore') + assert response['result']['result'][0]['value']['description'].endswith('[Sendable]') + ################################################################################################################ + # 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/TestWorkerConditionalBreakpoints.json b/test/autotest/testcases/toolchain/debug/TestWorkerConditionalBreakpoints.json new file mode 100644 index 00000000..98388a88 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestWorkerConditionalBreakpoints.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestWorkerConditionalBreakpoints", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/debug/TestWorkerConditionalBreakpoints.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/debug/TestWorkerConditionalBreakpoints.py b/test/autotest/testcases/toolchain/debug/TestWorkerConditionalBreakpoints.py new file mode 100644 index 00000000..fefc3027 --- /dev/null +++ b/test/autotest/testcases/toolchain/debug/TestWorkerConditionalBreakpoints.py @@ -0,0 +1,277 @@ +#!/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. + +#================================================================== +#文 件 名: TestWorkerConditionalBreakpoints.py +#文件说明: 多实例 debug 调试之设置条件断点 +#================================================================== +测试步骤: + 1. 连接 connect server 和主线程 debugger server + 2. 主线程使能 Runtime 和 Debugger + 4. 触发点击事件,创建子线程,连接子线程 debugger server + 5. 子线程使能 Runtime 和 Debugger + 7. 子线程 Worker.ets 文件设置断点,其中包括条件断点(Debugger.getPossibleAndSetBreakpointByUrl) + 8. 子线程 resume,停在普通断点处(Debugger.resume) + 9. 子线程 resume,停在条件断点处(Debugger.resume) + 7. 子线程 resume,停在普通断点处(Debugger.resume) + 9. 子线程 resume(Debugger.resume) + 10. 所有线程去使能 debugger(Debugger.disable) + 10. 关闭所有线程 debugger server 和 connect server 连接 +#================================================================== +关键代码: + Index.ets + .OnClick(() => { + let myWorker = new worker.ThreadWorker("entry/ets/workers/Worker.ets") + myWorker.postMessage("hello world") + }) + Worker.ets + const workerPort: ThreadWorkerGlobalScope = worker.workerPort; + workerPort.onmessage = (e: MessageEvents) => { + let person = new Person('Tim', add(10, 11)) + person.introduce() // b1 + let age = add(3, 6) + sub(4, 1) + } // b2 + function add(num1, num2) { + let result = num1 + num2 + return result // b3: condition = "result == 9" + } +#!!================================================================ +""" +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 TestWorkerConditionalBreakpoints(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': 15630, + 'debugger_server_port': 15631, + 'bundle_name': 'com.example.multiWorker06', + 'hap_name': 'MultiWorker06.hap', + 'hap_path': str(resource_path / 'hap' / 'MultiWorker06.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']) + + 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.resume + ################################################################################################################ + await self.debugger_impl.send("Debugger.resume", main_thread) + ################################################################################################################ + # main thread: click on the screen + ################################################################################################################ + self.ui_utils.click_on_middle() + ################################################################################################################ + # worker thread: connect the debugger server + ################################################################################################################ + worker_thread = 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) + ################################################################################################################ + # 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) + ################################################################################################################ + # 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']['worker']) + 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']['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, params) + ################################################################################################################ + # worker thread: Debugger.getPossibleAndSetBreakpointByUrl + ################################################################################################################ + RESULT_IS_9 = ( + 'UEFOREEAAAAAAAAADAACAFQBAAAAAAAAAAAAAAIAAAA8AAAAAQAAAFABAAAAAAAARAAAAAEAAABEAAAAlgAAAMkAAAB8AAAAVAEAAAIAAA' + 'BsAAAAAgAAAHQAAAD/////////////////////lgAAAMkAAAB8AAAAjgAAACFkZWJ1Z2dlckdldFZhbHVlAA1yZXN1bHQAM0xfRVNTbG90' + 'TnVtYmVyQW5ub3RhdGlvbjsAAAAAAIFAAAACAAAXZnVuY19tYWluXzAAE0xfR0xPQkFMOwAAAAAAAQABAgAAAQD//7wAAACIAgETAQAAAg' + 'AFRgEAAAYGAQAAABVTbG90TnVtYmVyAAAAAQD6AAAABQAAADcJAyoARJBEoUSybWEFYAVCAAAAYQY+AQBhBwJhCGAGKwIHCGEEYgkAAAAP' + 'BARkC2sBDwD/////DwACACMAQQEAAA==') + locations = [debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=19), + debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=61), + debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=38, + condition=RESULT_IS_9)] + params = debugger.SetBreakpointsLocations(locations) + response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl", worker_thread, params) + self.common_utils.assert_equal(response['result']['locations'][0]['id'], + 'id:19:0:' + self.config['file_path']['worker']) + self.common_utils.assert_equal(response['result']['locations'][1]['id'], + 'id:61:0:' + self.config['file_path']['worker']) + self.common_utils.assert_equal(response['result']['locations'][2]['id'], + 'id:38:0:' + self.config['file_path']['worker']) + ################################################################################################################ + # 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']['worker']) + self.common_utils.assert_equal(response['params']['callFrames'][0]['functionName'], 'introduce') + self.common_utils.assert_equal(response['params']['reason'], 'other') + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:61:8:' + self.config['file_path']['worker']]) + ################################################################################################################ + # 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']['worker']) + self.common_utils.assert_equal(response['params']['callFrames'][0]['functionName'], 'add') + self.common_utils.assert_equal(response['params']['reason'], 'other') + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:38:11:' + self.config['file_path']['worker']]) + ################################################################################################################ + # 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']['worker']) + self.common_utils.assert_equal(response['params']['reason'], 'other') + self.common_utils.assert_equal(response['params']['hitBreakpoints'], + ['id:19:1:' + self.config['file_path']['worker']]) + ################################################################################################################ + # 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 -- Gitee