1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4Copyright (c) 2024 Huawei Device Co., Ltd.
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9    http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16
17Description: Scenario test case.
18"""
19
20import logging
21import os
22import time
23
24import pytest
25
26from aw import Utils
27from aw import Application
28from aw import profiler
29from aw.api import debugger_api, runtime_api, profiler_api
30
31
32@pytest.mark.cpu_profiler
33@pytest.mark.timeout(40)
34class TestCpuProfiler02:
35    """
36    测试用例:多实例 CPU 调优 Launch 录制
37    测试步骤:
38        1. -p 模式启动应用
39        2.  连接 connect server 和主线程 debugger server
40        3.  连接 worker 线程 debugger server
41        4.  worker 线程使能 Runtime(Runtime.enable)
42        5.  worker 线程设置采样间隔(Profiler.setSamplingInterval)
43        6.  worker 线程启动 CPU 调试(Profiler.start)
44        7.  worker 线程去使能 Debugger(Debugger.disable)
45        8.  等待 10 秒后关闭 worker 线程 CPU 调优,获取 worker 线程调优数据(Profiler.stop)
46        9.  销毁 worker 线程,对应的 debugger server 连接断开
47        10. 关闭主线程 CPU 调优,获取主线程调优数据(Profiler.stop)
48        11. 关闭主线程 debugger server 和 connect server 连接
49    """
50
51    def setup_method(self):
52        logging.info('Start running TestCpuProfiler02: setup')
53
54        self.log_path = rf'{os.path.dirname(__file__)}\..\log'
55        self.hilog_file_name = 'test_cpu_profiler_02.hilog.txt'
56        self.id_generator = Utils.message_id_generator()
57
58        # receive the hilog before the test start
59        Utils.clear_fault_log()
60        self.hilog_process, self.write_thread = Utils.save_hilog(log_path=self.log_path,
61                                                                 file_name=self.hilog_file_name,
62                                                                 debug_on=True)
63
64    def teardown_method(self):
65        Application.uninstall(self.config['bundle_name'])
66
67        # terminate the hilog receive process after the test done
68        time.sleep(3)
69        self.hilog_process.stdout.close()
70        self.hilog_process.terminate()
71        self.hilog_process.wait()
72        self.write_thread.join()
73
74        Utils.save_fault_log(log_path=self.log_path)
75        logging.info('TestCpuProfiler02 done')
76
77    def test(self, test_suite_worker_02_profile):
78        logging.info('Start running TestCpuProfiler02: test')
79        self.config = test_suite_worker_02_profile
80        websocket = self.config['websocket']
81        taskpool = self.config['taskpool']
82        pid = self.config['pid']
83        self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket)
84        self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket)
85        self.profiler_impl = profiler_api.ProfilerImpl(self.id_generator, websocket)
86
87        taskpool.submit(websocket.main_task(taskpool, self.procedure, pid))
88        taskpool.await_taskpool()
89        taskpool.task_join()
90        if taskpool.task_exception:
91            raise taskpool.task_exception
92
93    async def procedure(self, websocket):
94        ################################################################################################################
95        # main thread: connect the debugger server
96        ################################################################################################################
97        main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True)
98        logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}')
99        ################################################################################################################
100        # worker thread: connect the debugger server
101        ################################################################################################################
102        worker_thread_1 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False)
103        logging.info(f'Connect to the debugger server of instance: {worker_thread_1.instance_id}')
104        worker_thread_2 = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False)
105        logging.info(f'Connect to the debugger server of instance: {worker_thread_2.instance_id}')
106        ################################################################################################################
107        # worker thread: Runtime.enable
108        ################################################################################################################
109        await self.runtime_impl.send("Runtime.enable", worker_thread_1)
110        await self.runtime_impl.send("Runtime.enable", worker_thread_2)
111        ################################################################################################################
112        # worker thread: Profiler.setSamplingInterval
113        ################################################################################################################
114        params = profiler.SamplingInterval(500)
115        await self.profiler_impl.send("Profiler.setSamplingInterval", worker_thread_1, params)
116        await self.profiler_impl.send("Profiler.setSamplingInterval", worker_thread_2, params)
117        ################################################################################################################
118        # worker thread: Profiler.start
119        ################################################################################################################
120        await self.profiler_impl.send("Profiler.start", worker_thread_1)
121        await self.profiler_impl.send("Profiler.start", worker_thread_2)
122        ################################################################################################################
123        # worker thread: Debugger.disable
124        ################################################################################################################
125        await self.debugger_impl.send("Debugger.disable", worker_thread_1)
126        await self.debugger_impl.send("Debugger.disable", worker_thread_2)
127        ################################################################################################################
128        # all thread: sleep 10 seconds
129        ################################################################################################################
130        time.sleep(10)
131        ################################################################################################################
132        # worker thread: Profiler.stop
133        ################################################################################################################
134        await self.profiler_impl.send("Profiler.stop", worker_thread_1)
135        await self.profiler_impl.send("Profiler.stop", worker_thread_2)
136        ################################################################################################################
137        # main thread: Profiler.stop
138        ################################################################################################################
139        await self.profiler_impl.send("Profiler.stop", main_thread)
140        ################################################################################################################
141        # close the websocket connections
142        ################################################################################################################
143        await websocket.send_msg_to_debugger_server(worker_thread_1.instance_id, worker_thread_1.send_msg_queue, 'close')
144        await websocket.send_msg_to_debugger_server(worker_thread_2.instance_id, worker_thread_2.send_msg_queue, 'close')
145        await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close')
146        await websocket.send_msg_to_connect_server('close')
147        ################################################################################################################