diff --git a/test/autotest/aw/all_utils.py b/test/autotest/aw/all_utils.py index 287108a94aa421850d119625a83901efdffc603f..6106357d47739cdc2e3a0b6817c27b8718ad5496 100644 --- a/test/autotest/aw/all_utils.py +++ b/test/autotest/aw/all_utils.py @@ -22,14 +22,13 @@ import os import re import subprocess import threading -import time from typing import Union from hypium import SystemUI, BY, MatchPattern from fport import Fport from taskpool import TaskPool -from websocket import WebSocket +from toolchain_websocket import ToolchainWebSocket class TimeRecord: @@ -161,8 +160,8 @@ class CommonUtils(object): config['bundle_name']) assert connect_server_port > 0, 'Failed to fport connect server for 3 times, the port is very likely occupied' config['connect_server_port'] = connect_server_port - config['websocket'] = WebSocket(self.driver, config['connect_server_port'], config['debugger_server_port'], - config.get('print_protocol', True)) + config['websocket'] = ToolchainWebSocket(self.driver, config['connect_server_port'], + config['debugger_server_port'], config.get('print_protocol', True)) config['taskpool'] = TaskPool() def hot_reload(self, hqf_path: Union[str, list]): diff --git a/test/autotest/aw/implement_api/heap_profiler_api.py b/test/autotest/aw/implement_api/heap_profiler_api.py index dd062608d8be6616f5346c62baf7665a5994d25a..2575116565a1eddd0bded263f1e8e8133738a5c3 100644 --- a/test/autotest/aw/implement_api/heap_profiler_api.py +++ b/test/autotest/aw/implement_api/heap_profiler_api.py @@ -49,14 +49,16 @@ class HeapProfilerImpl(ProtocolImpl): async def stop_tracking_heap_objects(self, message_id, connection, params): response = await comm_with_debugger_server(self.websocket, connection, heap_profiler.stop_tracking_heap_objects(), message_id) - while response.startswith('{"method":"HeapProfiler.lastSeenObjectId"'): + while response.startswith('{"method":"HeapProfiler.lastSeenObjectId"') \ + or response.startswith('{"method":"HeapProfiler.heapStatsUpdate"'): response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, connection.received_msg_queue) assert r'\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]' in response, \ f'\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"] not in {response}' pre_response = response while response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"') \ - or response.startswith('{"method":"HeapProfiler.lastSeenObjectId"'): + or response.startswith('{"method":"HeapProfiler.lastSeenObjectId"') \ + or response.startswith('{"method":"HeapProfiler.heapStatsUpdate"'): if response.startswith('{"method":"HeapProfiler.addHeapSnapshotChunk"'): pre_response = response response = await self.websocket.recv_msg_of_debugger_server(connection.instance_id, diff --git a/test/autotest/aw/websocket.py b/test/autotest/aw/toolchain_websocket.py similarity index 99% rename from test/autotest/aw/websocket.py rename to test/autotest/aw/toolchain_websocket.py index 0e5f6b5f4ef0fb6716f99117ac9d646874b6cabe..10d3513f64a07bd024464005dceb22b0a5a00ea5 100644 --- a/test/autotest/aw/websocket.py +++ b/test/autotest/aw/toolchain_websocket.py @@ -21,14 +21,14 @@ import asyncio import json from install_lib import install +from fport import Fport install('websockets') import websockets.protocol from websockets import connect, ConnectionClosed -from fport import Fport -class WebSocket(object): +class ToolchainWebSocket(object): def __init__(self, driver, connect_server_port, debugger_server_port, print_protocol=True): self.driver = driver self.connect_server_port = connect_server_port @@ -54,12 +54,12 @@ class WebSocket(object): await queue.put(message) self.log(f'[==>] Instance {instance_id} send message: {message}') return True - + async def get_instance(self): instance_id = await self.debugger_server_instance.get() self.debugger_server_instance.task_done() return instance_id - + def no_more_instance(self): self.new_instance_flag = False diff --git a/test/autotest/testcases/toolchain/performance/TestAllocationMassiveMoveNode.json b/test/autotest/testcases/toolchain/performance/TestAllocationMassiveMoveNode.json new file mode 100644 index 0000000000000000000000000000000000000000..d06cfc754995ef978e8fa07b80b3b2f3f2888d83 --- /dev/null +++ b/test/autotest/testcases/toolchain/performance/TestAllocationMassiveMoveNode.json @@ -0,0 +1,15 @@ +{ + "description": "Config for TestAllocationMassiveMoveNode", + "environment": [ + { + "type": "device", + "label": "phone" + } + ], + "driver": { + "type": "DeviceTest", + "py_file": [ + "toolchain/performance/TestAllocationMassiveMoveNode.py" + ] + } +} \ No newline at end of file diff --git a/test/autotest/testcases/toolchain/performance/TestAllocationMassiveMoveNode.py b/test/autotest/testcases/toolchain/performance/TestAllocationMassiveMoveNode.py new file mode 100644 index 0000000000000000000000000000000000000000..61a728d9f44d2b1a4cf2fb7c20655e7cdbeb768f --- /dev/null +++ b/test/autotest/testcases/toolchain/performance/TestAllocationMassiveMoveNode.py @@ -0,0 +1,149 @@ +#!/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. + +#================================================================== +#文 件 名: TestAllocationMassiveMoveNode.py +#文件说明: Allocation 录制中大量创建string类型数据并打印 +#!!================================================================ +""" +import sys +import time +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, PerformanceUtils +from cdp import heap_profiler +from implement_api import debugger_api, runtime_api, heap_profiler_api + + +class TestAllocationMassiveMoveNode(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.performance_utils = PerformanceUtils(self.driver) + self.id_generator = CommonUtils.message_id_generator() + self.config = { + 'start_mode': '', + 'connect_server_port': 15810, + 'debugger_server_port': 15811, + 'bundle_name': 'com.example.performance03', + 'hap_name': 'Performance03.hap', + 'hap_path': str(resource_path / 'hap' / 'Performance03.hap'), + 'print_protocol': False # 表示不会打印测试时用到的调试协议 + } + + def setup(self): + Step('1.锁频锁核') + self.performance_utils.lock_for_performance() + Step('2.下载应用') + self.driver.install_app(self.config['hap_path'], "-r") + Step('3.启动设置应用') + 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('4.设置屏幕常亮') + self.ui_utils.keep_awake() + Step('5.关闭位置信息') + self.ui_utils.disable_location() + Step('6.端口映射,连接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']) + self.heap_profiler_impl = heap_profiler_api.HeapProfilerImpl(self.id_generator, self.config['websocket']) + Step('7.attach调试应用') + self.common_utils.attach(self.config['bundle_name']) + Step('8.开启线程用于获取日志中的性能数据') + self.hilog_process, self.perf_records_thread = self.performance_utils.get_perf_data_from_hilog() + + + def process(self): + Step('9.初始化websocket和taskpool') + websocket = self.config['websocket'] + taskpool = self.config['taskpool'] + Step('10.执行测试用例') + 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 + Step('11.导出数据') + time.sleep(3) + time_data = self.driver.UiTree.find_component_by_path('/root/RelativeContainer/Text') + print("time_data: ", time_data.text) + for t in time_data.text.split(): + self.performance_utils.add_time_data("AllocationMassiveMoveNode", 3500, int(t)) + self.hilog_process.stdout.close() + self.hilog_process.terminate() + self.hilog_process.wait() + self.perf_records_thread.join() + self.performance_utils.show_performance_data_in_html() + + def teardown(self): + Step('12.关闭设置应用') + self.driver.stop_app(self.config['bundle_name']) + Step('13.卸载设置应用') + 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: Runtime.getHeapUsage + ################################################################################################################ + await self.runtime_impl.send("Runtime.getHeapUsage", main_thread) + ################################################################################################################ + # main thread: HeapProfiler.startTrackingHeapObjects + ################################################################################################################ + params = heap_profiler.TrackingHeapObjectsParams(False) + await self.heap_profiler_impl.send("HeapProfiler.startTrackingHeapObjects", main_thread, params) + ################################################################################################################ + # main thread: Debugger.disable + ################################################################################################################ + await self.debugger_impl.send("Debugger.disable", main_thread) + ################################################################################################################ + # main thread: Execute Method + ################################################################################################################ + for i in range(10): + self.ui_utils.click_on_middle() + time.sleep(2) + ################################################################################################################ + # main thread: Runtime.getHeapUsage + ################################################################################################################ + await self.runtime_impl.send("Runtime.getHeapUsage", main_thread) + ################################################################################################################ + # main thread: HeapProfiler.stopTrackingHeapObjects + ################################################################################################################ + await self.heap_profiler_impl.send("HeapProfiler.stopTrackingHeapObjects", 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') + ################################################################################################################ diff --git a/test/autotest/testcases/toolchain/performance/TestMainBasicFuncWithGPSOn.py b/test/autotest/testcases/toolchain/performance/TestMainBasicFuncWithGPSOn.py index 28c37914308205ab2436e3a65574b7b49423f1b3..bafaa8e8a2fde5cda506de4a787e99e1ea131b47 100644 --- a/test/autotest/testcases/toolchain/performance/TestMainBasicFuncWithGPSOn.py +++ b/test/autotest/testcases/toolchain/performance/TestMainBasicFuncWithGPSOn.py @@ -134,7 +134,7 @@ class TestMainBasicFuncWithGPSOn(TestCase): await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) response = await self.debugger_impl.recv("Debugger.paused", main_thread) end_time = datetime.now() - self.performance_utils.add_time_data("ScriptParsed", 40, (end_time - start_time).microseconds // 1000) + self.performance_utils.add_time_data("ScriptParsed", 65, (end_time - start_time).microseconds // 1000) 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') diff --git a/test/autotest/testcases/toolchain/performance/TestWorkerBasicFuncWithGPSOn.py b/test/autotest/testcases/toolchain/performance/TestWorkerBasicFuncWithGPSOn.py index a8f8fc57562c81514af6d9305fbd718e6baf5c00..c2b0f1fe75130ba402ee05ab8db1cd86691be33e 100644 --- a/test/autotest/testcases/toolchain/performance/TestWorkerBasicFuncWithGPSOn.py +++ b/test/autotest/testcases/toolchain/performance/TestWorkerBasicFuncWithGPSOn.py @@ -134,7 +134,7 @@ class TestWorkerBasicFuncWithGPSOn(TestCase): await self.debugger_impl.recv("Debugger.scriptParsed", main_thread) response = await self.debugger_impl.recv("Debugger.paused", main_thread) end_time = datetime.now() - self.performance_utils.add_time_data("ScriptParsed", 40, (end_time - start_time).microseconds // 1000) + self.performance_utils.add_time_data("ScriptParsed", 65, (end_time - start_time).microseconds // 1000) 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')