• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright (C) 2025 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import pytest
17import re
18import time
19import subprocess
20from utils import *
21
22PSS_INDEX = 2
23SWAP_PSS_INDEX = 8
24
25def ParseSmapsOutput(output):
26    memory_data = {}
27    for line in output.split("\n"):
28        if re.search(r"\d", line) is None:
29            continue
30        key = re.search(r'(/|\[|[a-zA-Z])(.*$)', line)
31        key = key.group().strip()
32        memory_data[key] = [int(val) for val in re.findall(r'\d+', line)]
33    return memory_data
34
35@print_check_result
36def CheckSmapsTotalPss(memory_data):
37    PSS_SUMMARY = memory_data["Summary"][PSS_INDEX]
38    SWAPPSS_SUMMARY = memory_data["Summary"][SWAP_PSS_INDEX]
39    return sum([val[PSS_INDEX] for key, val in memory_data.items() if key != "Summary"]) + SWAPPSS_SUMMARY == PSS_SUMMARY
40
41@print_check_result
42def CheckMemAddrss(output):
43    ret = re.search(r"\s([a-zA-Z0-9]{8,})\s", output)
44    return ret is not None
45
46@print_check_result
47def CheckPseft(output):
48    result = re.search("UID\s+PID\s+TID  PPID TCNT STIME TTY\s+TIME CMD\n([^\n]+\n){1,}", output)
49    return result is not None
50
51@print_check_result
52def CheckMountInfo(output):
53    result = re.search("/proc/\d+/mountinfo\n\n([^\n]+\n){4,}", output)
54    return result is not None
55
56def CheckSmaps(output):
57    result = re.search(r"/proc/\d+/maps", output)
58    return result is not None
59
60def CheckMemSmapsWithRoot(output):
61    memory_data = ParseSmapsOutput(output)
62    ret = all(check(memory_data) for check in [CheckSmapsTotalPss])
63    return ret
64
65def CheckMemSmapsVWithRoot(output):
66    memory_data = ParseSmapsOutput(output)
67    return CheckSmapsTotalPss(memory_data) and CheckMemAddrss(output)
68
69def CheckHelpOutput(output):
70    return "usage:" in output
71
72
73class TestHidumperPermission:
74    @classmethod
75    def setup_class(cls):
76        if not IsRootVersion():
77            subprocess.check_call("hdc shell aa start -a EntryAbility -b com.example.jsleakwatcher", shell=True)
78
79    @classmethod
80    def teardown_class(cls):
81        if not IsRootVersion():
82            subprocess.check_call("hdc shell aa force-stop -b com.example.jsleakwatcher", shell=True)
83
84    @pytest.mark.L0
85    def test_mem_smaps(self):
86        processName = "render_service"
87        pid = GetPidByProcessName(processName)
88        if (IsRootVersion()):
89            CheckFunc = CheckMemSmapsWithRoot
90        else:
91            CheckFunc = CheckHelpOutput
92        command = f"hidumper --mem-smaps {pid}"
93        hidumperTmpCmd = "OPT:mem-smaps SUB_OPT:"
94        # 校验命令行输出
95        CheckCmd(command, CheckFunc, hidumperTmpCmd)
96        # 校验命令行重定向输出
97        CheckCmdRedirect(command, CheckFunc, None, hidumperTmpCmd)
98        # 校验命令行输出到zip文件
99        if IsRootVersion():
100            CheckCmdZip(command, CheckFunc)
101
102    @pytest.mark.L0
103    def test_mem_smaps_v(self):
104        processName = "render_service"
105        pid = GetPidByProcessName(processName)
106        if (IsRootVersion()):
107            CheckFunc = CheckMemSmapsVWithRoot
108        else:
109            CheckFunc = CheckHelpOutput
110        command = f"hidumper --mem-smaps {pid} -v"
111        hidumperTmpCmd = "OPT:mem-smaps SUB_OPT:v"
112        # 校验命令行输出
113        CheckCmd(command, CheckFunc, hidumperTmpCmd)
114        # 校验命令行重定向输出
115        CheckCmdRedirect(command, CheckFunc, None, hidumperTmpCmd)
116        # 校验命令行输出到zip文件
117        if IsRootVersion():
118            CheckCmdZip(command, CheckFunc)
119
120    @pytest.mark.L3
121    def test_mem_smaps_error_pid(self):
122        command = f"hidumper --mem-smaps 2147483647;hidumper --mem-smaps -2147483647"
123        hidumperTmpCmd = "OPT:mem-smaps SUB_OPT:"
124        # 校验命令行输出
125        CheckCmd(command, lambda output : "hidumper: No such process: 2147483647\nhidumper: invalid arg: -2147483647" in output, hidumperTmpCmd)
126        command = f"hidumper --mem-smaps 2147483648;hidumper --mem-smaps -2147483648"
127        CheckCmd(command, lambda output : "hidumper: invalid arg: -2147483648" in output, hidumperTmpCmd)
128
129    @pytest.mark.L3
130    def test_mem_smaps_error_option(self):
131        command = "hdc shell \"hidumper -v --mem-smaps 1\""
132        output = subprocess.check_output(command, shell=True, encoding="utf-8", text=True)
133        assert "hidumper: invalid arg: --mem-smaps" in output
134
135
136
137