1#!/usr/bin/env python 2# 3# Copyright (C) 2020 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import logging 19import os 20import sys 21import unittest 22 23import target_file_utils 24import proc_utils as utils 25 26from proc_tests import ProcAsoundTests 27from proc_tests import ProcCmdlineTest 28from proc_tests import ProcCpuFileTests 29from proc_tests import ProcFsFileTests 30from proc_tests import ProcKmsgTest 31from proc_tests import ProcMapsTest 32from proc_tests import ProcMiscTest 33from proc_tests import ProcMemInfoTest 34from proc_tests import ProcModulesTest 35from proc_tests import ProcQtaguidCtrlTest 36from proc_tests import ProcRemoveUidRangeTest 37from proc_tests import ProcSimpleFileTests 38from proc_tests import ProcShowUidStatTest 39from proc_tests import ProcStatTest 40from proc_tests import ProcUidIoStatsTest 41from proc_tests import ProcUidTimeInStateTest 42from proc_tests import ProcUidConcurrentTimeTests 43from proc_tests import ProcUidCpuPowerTests 44from proc_tests import ProcVersionTest 45from proc_tests import ProcVmallocInfoTest 46from proc_tests import ProcVmstatTest 47from proc_tests import ProcZoneInfoTest 48 49TEST_OBJECTS = { 50 ProcAsoundTests.ProcAsoundCardsTest(), 51 ProcCmdlineTest.ProcCmdlineTest(), 52 ProcCpuFileTests.ProcCpuInfoTest(), 53 ProcCpuFileTests.ProcLoadavgTest(), 54 ProcFsFileTests.ProcDiskstatsTest(), 55 ProcFsFileTests.ProcFilesystemsTest(), 56 ProcFsFileTests.ProcMountsTest(), 57 ProcFsFileTests.ProcSwapsTest(), 58 ProcKmsgTest.ProcKmsgTest(), 59 ProcMapsTest.ProcMapsTest(), 60 ProcMiscTest.ProcMisc(), 61 ProcMemInfoTest.ProcMemInfoTest(), 62 ProcModulesTest.ProcModulesTest(), 63 ProcQtaguidCtrlTest.ProcQtaguidCtrlTest(), 64 ProcRemoveUidRangeTest.ProcRemoveUidRangeTest(), 65 ProcSimpleFileTests.ProcCorePattern(), 66 ProcSimpleFileTests.ProcCorePipeLimit(), 67 ProcSimpleFileTests.ProcDirtyBackgroundBytes(), 68 ProcSimpleFileTests.ProcDirtyBackgroundRatio(), 69 ProcSimpleFileTests.ProcDirtyExpireCentisecs(), 70 ProcSimpleFileTests.ProcDmesgRestrict(), 71 ProcSimpleFileTests.ProcDomainname(), 72 ProcSimpleFileTests.ProcDropCaches(), 73 ProcSimpleFileTests.ProcExtraFreeKbytes(), 74 ProcSimpleFileTests.ProcHostname(), 75 ProcSimpleFileTests.ProcHungTaskTimeoutSecs(), 76 ProcSimpleFileTests.ProcKptrRestrictTest(), 77 ProcSimpleFileTests.ProcMaxMapCount(), 78 ProcSimpleFileTests.ProcMmapMinAddrTest(), 79 ProcSimpleFileTests.ProcMmapRndBitsTest(), 80 ProcSimpleFileTests.ProcModulesDisabled(), 81 ProcSimpleFileTests.ProcOverCommitMemoryTest(), 82 ProcSimpleFileTests.ProcPageCluster(), 83 ProcSimpleFileTests.ProcPanicOnOops(), 84 ProcSimpleFileTests.ProcPerfEventMaxSampleRate(), 85 ProcSimpleFileTests.ProcPerfEventParanoid(), 86 ProcSimpleFileTests.ProcPidMax(), 87 ProcSimpleFileTests.ProcPipeMaxSize(), 88 ProcSimpleFileTests.ProcProtectedHardlinks(), 89 ProcSimpleFileTests.ProcProtectedSymlinks(), 90 ProcSimpleFileTests.ProcRandomizeVaSpaceTest(), 91 ProcSimpleFileTests.ProcSchedChildRunsFirst(), 92 ProcSimpleFileTests.ProcSchedRTPeriodUS(), 93 ProcSimpleFileTests.ProcSchedRTRuntimeUS(), 94 ProcShowUidStatTest.ProcShowUidStatTest(), 95 ProcSimpleFileTests.ProcSuidDumpable(), 96 ProcSimpleFileTests.ProcSysKernelRandomBootId(), 97 ProcSimpleFileTests.ProcSysRqTest(), 98 ProcSimpleFileTests.ProcUptime(), 99 ProcStatTest.ProcStatTest(), 100 ProcUidIoStatsTest.ProcUidIoStatsTest(), 101 ProcUidTimeInStateTest.ProcUidTimeInStateTest(), 102 ProcUidConcurrentTimeTests.ProcUidConcurrentActiveTimeTest(), 103 ProcUidConcurrentTimeTests.ProcUidConcurrentPolicyTimeTest(), 104 ProcUidCpuPowerTests.ProcUidCpuPowerTimeInStateTest(), 105 ProcUidCpuPowerTests.ProcUidCpuPowerConcurrentActiveTimeTest(), 106 ProcUidCpuPowerTests.ProcUidCpuPowerConcurrentPolicyTimeTest(), 107 ProcVersionTest.ProcVersionTest(), 108 ProcVmallocInfoTest.ProcVmallocInfoTest(), 109 ProcVmstatTest.ProcVmstat(), 110 ProcZoneInfoTest.ProcZoneInfoTest(), 111} 112 113TEST_OBJECTS_64 = { 114 ProcSimpleFileTests.ProcMmapRndCompatBitsTest(), 115} 116 117 118class VtsKernelProcFileApiTest(unittest.TestCase): 119 """Test cases which check content of proc files. 120 121 Attributes: 122 _PROC_SYS_ABI_SWP_FILE_PATH: the path of a file which decides behaviour of SWP instruction. 123 """ 124 125 _PROC_SYS_ABI_SWP_FILE_PATH = "/proc/sys/abi/swp" 126 127 def setUp(self): 128 """Initializes tests. 129 130 Data file path, device, remote shell instance and temporary directory 131 are initialized. 132 """ 133 serial_number = os.environ.get("ANDROID_SERIAL") 134 self.assertTrue(serial_number, "$ANDROID_SERIAL is empty.") 135 self.dut = utils.AndroidDevice(serial_number) 136 137 def testProcPagetypeinfo(self): 138 # TODO(b/109884074): make mandatory once incident_helper is in AOSP. 139 out, err, r_code = self.dut.shell.Execute("which incident_helper") 140 if r_code != 0: 141 logging.info("incident_helper not present") 142 return 143 144 filepath = "/proc/pagetypeinfo" 145 # Check that incident_helper can parse /proc/pagetypeinfo. 146 out, err, r_code = self.dut.shell.Execute( 147 "cat %s | incident_helper -s 2001" % filepath) 148 self.assertEqual( 149 r_code, 0, 150 "Failed to parse %s." % filepath) 151 152 def testProcSysrqTrigger(self): 153 filepath = "/proc/sysrq-trigger" 154 155 # This command only performs a best effort attempt to remount all 156 # filesystems. Check that it doesn't throw an error. 157 self.dut.shell.Execute("echo u > %s" % filepath) 158 159 # Reboot the device. 160 self.dut.shell.Execute("echo b > %s" % filepath) 161 self.assertTrue(self.dut.IsShutdown(10), "Device is still alive.") 162 self.assertTrue(self.dut.WaitForBootCompletion(300)) 163 self.assertTrue(self.dut.Root()) 164 165 def testProcUidProcstatSet(self): 166 167 def UidIOStats(uid): 168 """Returns I/O stats for a given uid. 169 170 Args: 171 uid, uid number. 172 173 Returns: 174 list of I/O numbers. 175 """ 176 stats_path = "/proc/uid_io/stats" 177 out, err, r_code = self.dut.shell.Execute( 178 "cat %s | grep '^%d'" % (stats_path, uid)) 179 return out.split() 180 181 def CheckStatsInState(state): 182 """Sets VTS (root uid) into a given state and checks the stats. 183 184 Args: 185 state, boolean. Use False for foreground, 186 and True for background. 187 """ 188 state = 1 if state else 0 189 filepath = "/proc/uid_procstat/set" 190 root_uid = 0 191 192 # fg write chars are at index 2, and bg write chars are at 6. 193 wchar_index = 6 if state else 2 194 old_wchar = UidIOStats(root_uid)[wchar_index] 195 self.dut.shell.Execute("echo %d %s > %s" % (root_uid, state, filepath)) 196 # This should increase the number of write syscalls. 197 self.dut.shell.Execute("echo foo") 198 self.assertLess( 199 int(old_wchar), 200 int(UidIOStats(root_uid)[wchar_index]), 201 "Number of write syscalls has not increased.") 202 203 CheckStatsInState(False) 204 CheckStatsInState(True) 205 206 def testProcPerUidTimes(self): 207 # TODO: make these files mandatory once they're in AOSP 208 try: 209 filepaths = self.dut.FindFiles('/proc/uid', 'time_in_state') 210 except: 211 logging.info("/proc/uid/ directory does not exist and is optional") 212 return 213 214 if not filepaths: 215 logging.info('per-UID time_in_state files do not exist and are optional') 216 return 217 218 for filepath in filepaths: 219 self.assertTrue(self.dut.Exists(filepath), 220 '%s does not exist.' % filepath) 221 permission = self.dut.GetPermission(filepath) 222 self.assertTrue(target_file_utils.IsReadOnly(permission)) 223 file_content = self.dut.ReadFileContent(filepath) 224 225 def testProcSysAbiSwpInstruction(self): 226 """Tests /proc/sys/abi/swp. 227 228 /proc/sys/abi/swp sets the execution behaviour for the obsoleted ARM instruction 229 SWP. As per the setting in /proc/sys/abi/swp, the usage of SWP{B} 230 can either generate an undefined instruction abort or use software emulation 231 or hardware execution. 232 """ 233 if not ('arm' in self.cpu_abi(self.dut) and self.is64Bit(self.dut)): 234 logging.info("file not present on non-ARM64 device") 235 return 236 237 filepath = '/proc/sys/abi/swp' 238 239 self.assertTrue(self.dut.Exists(filepath), '%s does not exist.' % filepath) 240 permission = self.dut.GetPermission(filepath) 241 self.assertTrue(target_file_utils.IsReadWrite(permission)) 242 243 file_content = self.dut.ReadFileContent(filepath) 244 try: 245 swp_state = int(file_content) 246 except ValueError as e: 247 self.fail("Failed to parse %s" % filepath) 248 self.assertTrue(swp_state >= 0 and swp_state <= 2, 249 "%s contains incorrect value: %d" 250 % (filepath, swp_state)) 251 252 def cpu_abi(self, dut): 253 """CPU ABI (Application Binary Interface) of the device.""" 254 out = dut._GetProp("ro.product.cpu.abi") 255 if not out: 256 return "unknown" 257 258 cpu_abi = out.lower() 259 return cpu_abi 260 261 def is64Bit(self, dut): 262 """True if device is 64 bit.""" 263 out, _, _ = dut.shell.Execute('uname -m') 264 return "64" in out 265 266 267def run_proc_file_test(test_object): 268 """Reads from the file and checks that it parses and the content is valid. 269 270 Args: 271 test_object: inherits KernelProcFileTestBase, contains the test functions 272 """ 273 def test(self): 274 if test_object in TEST_OBJECTS_64 and not self.is64Bit(self.dut): 275 logging.info("Skip test for 64-bit kernel.") 276 return 277 test_object.set_api_level(self.dut) 278 filepath = test_object.get_path() 279 if not self.dut.Exists(filepath) and test_object.file_optional(dut=self.dut): 280 logging.info("%s does not exist and is optional." % filepath) 281 return 282 self.assertTrue(self.dut.Exists(filepath), '%s does not exist.' % filepath) 283 permission = self.dut.GetPermission(filepath) 284 self.assertTrue(test_object.get_permission_checker()) 285 self.assertTrue(test_object.get_permission_checker()(permission), 286 "%s: File has invalid permissions (%s)" % (filepath, 287 permission)) 288 289 logging.info("Testing format of %s", filepath) 290 self.assertTrue( 291 test_object.prepare_test(self.dut), "Setup failed!") 292 293 if not test_object.test_format(): 294 return 295 296 file_content = self.dut.ReadFileContent(filepath) 297 try: 298 parse_result = test_object.parse_contents(file_content) 299 except (SyntaxError, ValueError, IndexError) as e: 300 self.fail("Failed to parse! " + str(e)) 301 self.assertTrue( 302 test_object.result_correct(parse_result), "Results not valid!") 303 return test 304 305 306if __name__ == "__main__": 307 try: 308 for test_object in TEST_OBJECTS.union(TEST_OBJECTS_64): 309 test_func = run_proc_file_test(test_object) 310 setattr(VtsKernelProcFileApiTest, 'test_' + 311 test_object.__class__.__name__, test_func) 312 suite = unittest.TestLoader().loadTestsFromTestCase( 313 VtsKernelProcFileApiTest) 314 results = unittest.TextTestRunner(verbosity=2).run(suite) 315 finally: 316 if results.failures: 317 sys.exit(1) 318