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