1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright (C) 2024 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 72def CheckNetCmd(output): 73 cmds = ["iptables -L -nvx", "ip6tables -L -nvx", "iptables -t nat -L -nvx", "iptables -t mangle -L -nvx", 74 "ip6tables -t mangle -L -nvx", "iptables -t raw -L -nvx", "ip6tables -t raw -L -nvx", 75 "ip link", "ip -4 addr show", "ip -6 addr show", "ip rule show", "ip -6 rule show"] 76 ret = all([item in output for item in cmds]) 77 return ret 78 79class TestHidumperPermission: 80 @classmethod 81 def setup_class(cls): 82 if not IsRootVersion(): 83 subprocess.check_call("hdc shell aa start -a EntryAbility -b com.example.myapplication", shell=True) 84 85 @classmethod 86 def teardown_class(cls): 87 if not IsRootVersion(): 88 subprocess.check_call("hdc shell aa force-stop -b com.example.myapplication", shell=True) 89 90 @pytest.mark.L0 91 def test_mem_smaps(self): 92 processName = "render_service" 93 pid = GetPidByProcessName(processName) 94 if (IsRootVersion()): 95 CheckFunc = CheckMemSmapsWithRoot 96 else: 97 CheckFunc = CheckHelpOutput 98 command = f"hidumper --mem-smaps {pid}" 99 # 校验命令行输出 100 CheckCmd(command, CheckFunc) 101 # 校验命令行重定向输出 102 CheckCmdRedirect(command, CheckFunc) 103 # 校验命令行输出到zip文件 104 if IsRootVersion(): 105 CheckCmdZip(command, CheckFunc) 106 107 @pytest.mark.L0 108 def test_mem_smaps_v(self): 109 processName = "render_service" 110 pid = GetPidByProcessName(processName) 111 if (IsRootVersion()): 112 CheckFunc = CheckMemSmapsVWithRoot 113 else: 114 CheckFunc = CheckHelpOutput 115 command = f"hidumper --mem-smaps {pid} -v" 116 # 校验命令行输出 117 CheckCmd(command, CheckFunc) 118 # 校验命令行重定向输出 119 CheckCmdRedirect(command, CheckFunc) 120 # 校验命令行输出到zip文件 121 if IsRootVersion(): 122 CheckCmdZip(command, CheckFunc) 123 124 @pytest.mark.L0 125 def test_process_all(self): 126 if IsRootVersion(): 127 CheckFunc = lambda x : all([CheckSmaps(x), CheckPseft(x), CheckMountInfo(x)]) 128 else: 129 CheckFunc = lambda x : all([not CheckSmaps(x), CheckPseft(x), CheckMountInfo(x)]) 130 pid = GetPidByProcessName("com.example.myapplication") 131 if pid == "": 132 pytest.skip("test application not found") 133 command = f"hidumper -p" 134 # 校验命令行输出 135 CheckCmd(command, CheckFunc) 136 # 校验命令行重定向输出 137 CheckCmdRedirect(command, CheckFunc) 138 # 校验命令行输出到zip文件 139 CheckCmdZip(command, CheckFunc) 140 141 @pytest.mark.L0 142 def test_process_pid(self): 143 command = None 144 pid = 1 145 if IsRootVersion(): 146 CheckFunc = lambda x : all([CheckSmaps(x), CheckPseft(x), CheckMountInfo(x)]) 147 else: 148 CheckFunc = lambda x : all([not CheckSmaps(x), CheckPseft(x), CheckMountInfo(x)]) 149 pid = GetPidByProcessName("com.example.myapplication") 150 if pid == "": 151 pytest.skip("test application not found") 152 command = f"hidumper -p {pid}" 153 # 校验命令行输出 154 CheckCmd(command, CheckFunc) 155 # 校验命令行重定向输出 156 CheckCmdRedirect(command, CheckFunc) 157 # 校验命令行输出到zip文件 158 CheckCmdZip(command, CheckFunc) 159 160 @pytest.mark.L0 161 def test_hidumper_help(self): 162 if not IsRootVersion(): 163 output = subprocess.check_output("hdc shell \"hidumper -h |grep mem\"", shell=True, text=True, encoding="utf-8") 164 assert "--mem [pid]" in output 165 166 @pytest.mark.L0 167 def test_process_with_non_debug_pid(self): 168 if not IsRootVersion(): 169 output = subprocess.check_output("hdc shell \"hidumper -p 1\"", shell=True, text=True, encoding="utf-8") 170 assert "only support debug application" in output 171 172 @pytest.mark.L0 173 def test_output_append(self): 174 if IsRootVersion(): 175 command = "hdc shell \"hidumper --mem 1 >> /data/log/hidumper.log\"" 176 # 校验命令行输出到zip文件 177 subprocess.check_call(command, shell=True) 178 output = subprocess.check_output("hdc shell ls -l /data/log/hidumper.log", shell=True).decode() 179 assert int(output.strip().split()[4]) > 0 180 else: 181 pytest.skip("test only in root mode") 182 183 @pytest.mark.L0 184 def test_net(self): 185 if IsRootVersion(): 186 command = "hdc shell \"hidumper --net\"" 187 subprocess.check_call(command, shell=True) 188 output = subprocess.check_output("hdc shell ls -l /data/log/hidumper.log", shell=True).decode() 189 assert int(output.strip().split()[4]) > 0 190 else: 191 pytest.skip("test only in root mode") 192