• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4Copyright (c) 2024 Huawei Device Co., Ltd.
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9    http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16
17Description: Scenario test case.
18"""
19
20import logging
21import os
22import time
23
24import pytest
25
26from aw import Application
27from aw import Utils
28from aw import debugger
29from aw.api import debugger_api, runtime_api
30
31
32@pytest.mark.debug
33@pytest.mark.timeout(60)
34class TestWorkerSmartStepInto:
35    """
36    测试用例:多实例 debug 调试 smartStepInto
37    测试步骤:
38        1.  连接 connect server 和主线程 debugger server
39        2.  主线程使能 Runtime 和 Debugger
40        3.  主线程 resume(Debugger.resume)
41        4.  触发点击事件,创建子线程,连接子线程 debugger server
42        5.  子线程使能 Runtime 和 Debugger
43        6.  子线程 Worker.ets 文件设置断点(Debugger.getPossibleAndSetBreakpointByUrl)
44        7.  子线程 resume,停在断点处(Debugger.resume)
45        8.  子线程 smartStepInto 进入 introduce 方法(Debugger.smartStepInto)
46        9.  子线程 stepOut 跳出 introduce 方法(Debugger.stepOut)
47        10. 子线程 smartStepInto 进入 add 方法(Debugger.smartStepInto)
48        11. 子线程 stepOut 跳出 add 方法(Debugger.stepOut)
49        12. 子线程 smartStepInto 进入 sub 方法(Debugger.smartStepInto)
50        13. 子线程 resume(Debugger.resume)
51        14. 所有线程去使能 debugger(Debugger.disable)
52        15. 关闭所有线程 debugger server 和 connect server 连接
53    关键代码:
54        Index.ets
55            .OnClick(() => {
56                let myWorker = new worker.ThreadWorker("entry/ets/workers/Worker.ets")
57                myWorker.onmessage = (e: MessageEvents) => {}
58                myWorker.postMessage("hello world")
59            })
60        Worker.ets
61            const workerPort: ThreadWorkerGlobalScope = worker.workerPort;
62            workerPort.onmessage = (e: MessageEvents) => {
63                let person = new Person('Tim', add(10, 11))
64                person.introduce()
65                let age = add(3, 6) + sub(4, 1)
66                workerPort.postMessage(e.data)
67            }
68            function add(args1, args2) {
69                return args1 + args2
70            }
71            function sub(args1, args2) {
72                return args1 - args2
73            }
74            class Person {
75                name: string
76                age: number
77                constructor(name, age){}
78                introduce() {}
79            }
80    """
81
82    def setup_method(self):
83        logging.info('Start running TestWorkerSmartStepInto: setup')
84
85        self.log_path = rf'{os.path.dirname(__file__)}\..\log'
86        self.hilog_file_name = 'test_worker_smart_step_into.hilog.txt'
87        self.id_generator = Utils.message_id_generator()
88
89        # receive the hilog before the test start
90        Utils.clear_fault_log()
91        self.hilog_process, self.write_thread = Utils.save_hilog(log_path=self.log_path,
92                                                                 file_name=self.hilog_file_name,
93                                                                 debug_on=True)
94
95    def teardown_method(self):
96        Application.uninstall(self.config['bundle_name'])
97
98        # terminate the hilog receive process after the test done
99        time.sleep(3)
100        self.hilog_process.stdout.close()
101        self.hilog_process.terminate()
102        self.hilog_process.wait()
103        self.write_thread.join()
104
105        Utils.save_fault_log(log_path=self.log_path)
106        logging.info('TestWorkerSmartStepInto done')
107
108    def test(self, test_suite_worker_06_debug):
109        logging.info('Start running TestWorkerSmartStepInto: test')
110        self.config = test_suite_worker_06_debug
111        websocket = self.config['websocket']
112        taskpool = self.config['taskpool']
113        pid = self.config['pid']
114        self.debugger_impl = debugger_api.DebuggerImpl(self.id_generator, websocket)
115        self.runtime_impl = runtime_api.RuntimeImpl(self.id_generator, websocket)
116
117        taskpool.submit(websocket.main_task(taskpool, self.procedure, pid))
118        taskpool.await_taskpool()
119        taskpool.task_join()
120        if taskpool.task_exception:
121            raise taskpool.task_exception
122
123    async def procedure(self, websocket):
124        ################################################################################################################
125        # main thread: connect the debugger server
126        ################################################################################################################
127        main_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], True)
128        logging.info(f'Connect to the debugger server of instance: {main_thread.instance_id}')
129        ################################################################################################################
130        # main thread: Runtime.enable
131        ################################################################################################################
132        await self.runtime_impl.send("Runtime.enable", main_thread)
133        ################################################################################################################
134        # main thread: Debugger.enable
135        ################################################################################################################
136        await self.debugger_impl.send("Debugger.enable", main_thread)
137        ################################################################################################################
138        # main thread: Runtime.runIfWaitingForDebugger
139        ################################################################################################################
140        await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", main_thread)
141        ################################################################################################################
142        # main thread: Debugger.scriptParsed
143        ################################################################################################################
144        response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread)
145        assert response['params']['url'] == self.config['file_path']['entry_ability']
146        assert response['params']['endLine'] == 0
147        ################################################################################################################
148        # main thread: Debugger.paused
149        ################################################################################################################
150        response = await self.debugger_impl.recv("Debugger.paused", main_thread)
151        assert response['params']['callFrames'][0]['url'] == self.config['file_path']['entry_ability']
152        assert response['params']['reason'] == 'Break on start'
153        ################################################################################################################
154        # main thread: Debugger.resume
155        ################################################################################################################
156        await self.debugger_impl.send("Debugger.resume", main_thread)
157        ################################################################################################################
158        # main thread: Debugger.scriptParsed
159        ################################################################################################################
160        response = await self.debugger_impl.recv("Debugger.scriptParsed", main_thread)
161        assert response['params']['url'] == self.config['file_path']['index']
162        assert response['params']['endLine'] == 0
163        ################################################################################################################
164        # main thread: Debugger.paused
165        ################################################################################################################
166        response = await self.debugger_impl.recv("Debugger.paused", main_thread)
167        assert response['params']['callFrames'][0]['url'] == self.config['file_path']['index']
168        assert response['params']['reason'] == 'Break on start'
169        ################################################################################################################
170        # main thread: Debugger.resume
171        ################################################################################################################
172        await self.debugger_impl.send("Debugger.resume", main_thread)
173        ################################################################################################################
174        # main thread: click on the screen
175        ################################################################################################################
176        Application.click_on_middle()
177        ################################################################################################################
178        # worker thread: connect the debugger server
179        ################################################################################################################
180        worker_thread = await self.debugger_impl.connect_to_debugger_server(self.config['pid'], False)
181        logging.info(f'Connect to the debugger server of instance: {worker_thread.instance_id}')
182        ################################################################################################################
183        # worker thread: Runtime.enable
184        ################################################################################################################
185        await self.runtime_impl.send("Runtime.enable", worker_thread)
186        ################################################################################################################
187        # worker thread: Debugger.enable
188        ################################################################################################################
189        await self.debugger_impl.send("Debugger.enable", worker_thread)
190        ################################################################################################################
191        # worker thread: Runtime.runIfWaitingForDebugger
192        ################################################################################################################
193        await self.runtime_impl.send("Runtime.runIfWaitingForDebugger", worker_thread)
194        ################################################################################################################
195        # worker thread: Debugger.scriptParsed
196        ################################################################################################################
197        response = await self.debugger_impl.recv("Debugger.scriptParsed", worker_thread)
198        assert response['params']['url'] == self.config['file_path']['worker']
199        assert response['params']['endLine'] == 0
200        ################################################################################################################
201        # worker thread: Debugger.paused
202        ################################################################################################################
203        response = await self.debugger_impl.recv("Debugger.paused", worker_thread)
204        assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker']
205        assert response['params']['reason'] == 'Break on start'
206        ################################################################################################################
207        # worker thread: Debugger.removeBreakpointsByUrl
208        ################################################################################################################
209        params = debugger.RemoveBreakpointsUrl(self.config['file_path']['worker'])
210        await self.debugger_impl.send("Debugger.removeBreakpointsByUrl", worker_thread, params)
211        ################################################################################################################
212        # worker thread: Debugger.getPossibleAndSetBreakpointByUrl
213        ################################################################################################################
214        locations = [debugger.BreakLocationUrl(url=self.config['file_path']['worker'], line_number=12)]
215        params = debugger.SetBreakpointsLocations(locations)
216        response = await self.debugger_impl.send("Debugger.getPossibleAndSetBreakpointsByUrl",
217                                                 worker_thread, params)
218        assert response['result']['locations'][0]['id'] == 'id:12:0:' + self.config['file_path']['worker']
219        ################################################################################################################
220        # worker thread: Debugger.resume
221        ################################################################################################################
222        await self.debugger_impl.send("Debugger.resume", worker_thread)
223        # worker thread: Debugger.paused
224        response = await self.debugger_impl.recv("Debugger.paused", worker_thread)
225        assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker']
226        assert response['params']['reason'] == 'other'
227        assert response['params']['hitBreakpoints'] == ['id:12:4:' + self.config['file_path']['worker']]
228        ################################################################################################################
229        # worker thread: Debugger.smartStepInto
230        ################################################################################################################
231        params = debugger.SmartStepIntoParams(url=self.config['file_path']['worker'], line_number=59)
232        await self.debugger_impl.send("Debugger.smartStepInto", worker_thread, params)
233        ################################################################################################################
234        # worker thread: Debugger.resume
235        ################################################################################################################
236        await self.debugger_impl.send("Debugger.resume", worker_thread)
237        # worker thread: Debugger.paused
238        response = await self.debugger_impl.recv("Debugger.paused", worker_thread)
239        assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker']
240        assert response['params']['callFrames'][0]['functionName'] == 'introduce'
241        assert response['params']['reason'] == 'other'
242        assert response['params']['hitBreakpoints'] == ['id:59:8:' + self.config['file_path']['worker']]
243        ################################################################################################################
244        # worker thread: Debugger.stepOut
245        ################################################################################################################
246        await self.debugger_impl.send("Debugger.stepOut", worker_thread)
247        # worker thread: Debugger.paused
248        response = await self.debugger_impl.recv("Debugger.paused", worker_thread)
249        assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker']
250        assert response['params']['reason'] == 'other'
251        assert response['params']['hitBreakpoints'] == []
252        ################################################################################################################
253        # worker thread: Debugger.smartStepInto
254        ################################################################################################################
255        params = debugger.SmartStepIntoParams(url=self.config['file_path']['worker'], line_number=35)
256        await self.debugger_impl.send("Debugger.smartStepInto", worker_thread, params)
257        ################################################################################################################
258        # worker thread: Debugger.resume
259        ################################################################################################################
260        await self.debugger_impl.send("Debugger.resume", worker_thread)
261        # worker thread: Debugger.paused
262        response = await self.debugger_impl.recv("Debugger.paused", worker_thread)
263        assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker']
264        assert response['params']['callFrames'][0]['functionName'] == 'add'
265        assert response['params']['reason'] == 'other'
266        assert response['params']['hitBreakpoints'] == ['id:35:17:' + self.config['file_path']['worker']]
267        ################################################################################################################
268        # worker thread: Debugger.stepOut
269        ################################################################################################################
270        await self.debugger_impl.send("Debugger.stepOut", worker_thread)
271        # worker thread: Debugger.paused
272        response = await self.debugger_impl.recv("Debugger.paused", worker_thread)
273        assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker']
274        assert response['params']['reason'] == 'other'
275        assert response['params']['hitBreakpoints'] == []
276        ################################################################################################################
277        # worker thread: Debugger.smartStepInto
278        ################################################################################################################
279        params = debugger.SmartStepIntoParams(url=self.config['file_path']['worker'], line_number=39)
280        await self.debugger_impl.send("Debugger.smartStepInto", worker_thread, params)
281        ################################################################################################################
282        # worker thread: Debugger.resume
283        ################################################################################################################
284        await self.debugger_impl.send("Debugger.resume", worker_thread)
285        # worker thread: Debugger.paused
286        response = await self.debugger_impl.recv("Debugger.paused", worker_thread)
287        assert response['params']['callFrames'][0]['url'] == self.config['file_path']['worker']
288        assert response['params']['callFrames'][0]['functionName'] == 'sub'
289        assert response['params']['reason'] == 'other'
290        assert response['params']['hitBreakpoints'] == ['id:39:17:' + self.config['file_path']['worker']]
291        ################################################################################################################
292        # worker thread: Debugger.resume
293        ################################################################################################################
294        await self.debugger_impl.send("Debugger.resume", worker_thread)
295        ################################################################################################################
296        # worker thread: Debugger.disable
297        ################################################################################################################
298        await self.debugger_impl.send("Debugger.disable", worker_thread)
299        ################################################################################################################
300        # main thread: Debugger.disable
301        ################################################################################################################
302        await self.debugger_impl.send("Debugger.disable", main_thread)
303        ################################################################################################################
304        # close the websocket connections
305        ################################################################################################################
306        await websocket.send_msg_to_debugger_server(worker_thread.instance_id, worker_thread.send_msg_queue, 'close')
307        await websocket.send_msg_to_debugger_server(main_thread.instance_id, main_thread.send_msg_queue, 'close')
308        await websocket.send_msg_to_connect_server('close')
309        ################################################################################################################