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.ProcSchedLatencyNS(), 93 ProcSimpleFileTests.ProcSchedRTPeriodUS(), 94 ProcSimpleFileTests.ProcSchedRTRuntimeUS(), 95 ProcSimpleFileTests.ProcSchedTunableScaling(), 96 ProcSimpleFileTests.ProcSchedWakeupGranularityNS(), 97 ProcShowUidStatTest.ProcShowUidStatTest(), 98 ProcSimpleFileTests.ProcSuidDumpable(), 99 ProcSimpleFileTests.ProcSysKernelRandomBootId(), 100 ProcSimpleFileTests.ProcSysRqTest(), 101 ProcSimpleFileTests.ProcUptime(), 102 ProcStatTest.ProcStatTest(), 103 ProcUidIoStatsTest.ProcUidIoStatsTest(), 104 ProcUidTimeInStateTest.ProcUidTimeInStateTest(), 105 ProcUidConcurrentTimeTests.ProcUidConcurrentActiveTimeTest(), 106 ProcUidConcurrentTimeTests.ProcUidConcurrentPolicyTimeTest(), 107 ProcUidCpuPowerTests.ProcUidCpuPowerTimeInStateTest(), 108 ProcUidCpuPowerTests.ProcUidCpuPowerConcurrentActiveTimeTest(), 109 ProcUidCpuPowerTests.ProcUidCpuPowerConcurrentPolicyTimeTest(), 110 ProcVersionTest.ProcVersionTest(), 111 ProcVmallocInfoTest.ProcVmallocInfoTest(), 112 ProcVmstatTest.ProcVmstat(), 113 ProcZoneInfoTest.ProcZoneInfoTest(), 114} 115 116TEST_OBJECTS_64 = { 117 ProcSimpleFileTests.ProcMmapRndCompatBitsTest(), 118} 119 120 121class VtsKernelProcFileApiTest(unittest.TestCase): 122 """Test cases which check content of proc files. 123 124 Attributes: 125 _PROC_SYS_ABI_SWP_FILE_PATH: the path of a file which decides behaviour of SWP instruction. 126 """ 127 128 _PROC_SYS_ABI_SWP_FILE_PATH = "/proc/sys/abi/swp" 129 130 def setUp(self): 131 """Initializes tests. 132 133 Data file path, device, remote shell instance and temporary directory 134 are initialized. 135 """ 136 serial_number = os.environ.get("ANDROID_SERIAL") 137 self.assertTrue(serial_number, "$ANDROID_SERIAL is empty.") 138 self.dut = utils.AndroidDevice(serial_number) 139 140 def testProcPagetypeinfo(self): 141 # TODO(b/109884074): make mandatory once incident_helper is in AOSP. 142 out, err, r_code = self.dut.shell.Execute("which incident_helper") 143 if r_code != 0: 144 logging.info("incident_helper not present") 145 return 146 147 filepath = "/proc/pagetypeinfo" 148 # Check that incident_helper can parse /proc/pagetypeinfo. 149 out, err, r_code = self.dut.shell.Execute( 150 "cat %s | incident_helper -s 2001" % filepath) 151 self.assertEqual( 152 r_code, 0, 153 "Failed to parse %s." % filepath) 154 155 def testProcSysrqTrigger(self): 156 filepath = "/proc/sysrq-trigger" 157 158 # This command only performs a best effort attempt to remount all 159 # filesystems. Check that it doesn't throw an error. 160 self.dut.shell.Execute("echo u > %s" % filepath) 161 162 # Reboot the device. 163 self.dut.shell.Execute("echo b > %s" % filepath) 164 self.assertTrue(self.dut.IsShutdown(10), "Device is still alive.") 165 self.assertTrue(self.dut.WaitForBootCompletion(300)) 166 self.assertTrue(self.dut.Root()) 167 168 def testProcUidProcstatSet(self): 169 170 def UidIOStats(uid): 171 """Returns I/O stats for a given uid. 172 173 Args: 174 uid, uid number. 175 176 Returns: 177 list of I/O numbers. 178 """ 179 stats_path = "/proc/uid_io/stats" 180 out, err, r_code = self.dut.shell.Execute( 181 "cat %s | grep '^%d'" % (stats_path, uid)) 182 return out.split() 183 184 def CheckStatsInState(state): 185 """Sets VTS (root uid) into a given state and checks the stats. 186 187 Args: 188 state, boolean. Use False for foreground, 189 and True for background. 190 """ 191 state = 1 if state else 0 192 filepath = "/proc/uid_procstat/set" 193 root_uid = 0 194 195 # fg write chars are at index 2, and bg write chars are at 6. 196 wchar_index = 6 if state else 2 197 old_wchar = UidIOStats(root_uid)[wchar_index] 198 self.dut.shell.Execute("echo %d %s > %s" % (root_uid, state, filepath)) 199 # This should increase the number of write syscalls. 200 self.dut.shell.Execute("echo foo") 201 self.assertLess( 202 int(old_wchar), 203 int(UidIOStats(root_uid)[wchar_index]), 204 "Number of write syscalls has not increased.") 205 206 CheckStatsInState(False) 207 CheckStatsInState(True) 208 209 def testProcPerUidTimes(self): 210 # TODO: make these files mandatory once they're in AOSP 211 try: 212 filepaths = self.dut.FindFiles('/proc/uid', 'time_in_state') 213 except: 214 logging.info("/proc/uid/ directory does not exist and is optional") 215 return 216 217 if not filepaths: 218 logging.info('per-UID time_in_state files do not exist and are optional') 219 return 220 221 for filepath in filepaths: 222 self.assertTrue(self.dut.Exists(filepath), 223 '%s does not exist.' % filepath) 224 permission = self.dut.GetPermission(filepath) 225 self.assertTrue(target_file_utils.IsReadOnly(permission)) 226 file_content = self.dut.ReadFileContent(filepath) 227 228 def testProcSysAbiSwpInstruction(self): 229 """Tests /proc/sys/abi/swp. 230 231 /proc/sys/abi/swp sets the execution behaviour for the obsoleted ARM instruction 232 SWP. As per the setting in /proc/sys/abi/swp, the usage of SWP{B} 233 can either generate an undefined instruction abort or use software emulation 234 or hardware execution. 235 """ 236 if not ('arm' in self.cpu_abi(self.dut) and self.is64Bit(self.dut)): 237 logging.info("file not present on non-ARM64 device") 238 return 239 240 filepath = '/proc/sys/abi/swp' 241 242 self.assertTrue(self.dut.Exists(filepath), '%s does not exist.' % filepath) 243 permission = self.dut.GetPermission(filepath) 244 self.assertTrue(target_file_utils.IsReadWrite(permission)) 245 246 file_content = self.dut.ReadFileContent(filepath) 247 try: 248 swp_state = int(file_content) 249 except ValueError as e: 250 self.fail("Failed to parse %s" % filepath) 251 self.assertTrue(swp_state >= 0 and swp_state <= 2, 252 "%s contains incorrect value: %d" 253 % (filepath, swp_state)) 254 255 def cpu_abi(self, dut): 256 """CPU ABI (Application Binary Interface) of the device.""" 257 out = dut._GetProp("ro.product.cpu.abi") 258 if not out: 259 return "unknown" 260 261 cpu_abi = out.lower() 262 return cpu_abi 263 264 def is64Bit(self, dut): 265 """True if device is 64 bit.""" 266 out, _, _ = dut.shell.Execute('uname -m') 267 return "64" in out 268 269 270def run_proc_file_test(test_object): 271 """Reads from the file and checks that it parses and the content is valid. 272 273 Args: 274 test_object: inherits KernelProcFileTestBase, contains the test functions 275 """ 276 def test(self): 277 if test_object in TEST_OBJECTS_64 and not self.is64Bit(self.dut): 278 logging.info("Skip test for 64-bit kernel.") 279 return 280 test_object.set_api_level(self.dut) 281 filepath = test_object.get_path() 282 if not self.dut.Exists(filepath) and test_object.file_optional(dut=self.dut): 283 logging.info("%s does not exist and is optional." % filepath) 284 return 285 self.assertTrue(self.dut.Exists(filepath), '%s does not exist.' % filepath) 286 permission = self.dut.GetPermission(filepath) 287 self.assertTrue(test_object.get_permission_checker()) 288 self.assertTrue(test_object.get_permission_checker()(permission), 289 "%s: File has invalid permissions (%s)" % (filepath, 290 permission)) 291 292 logging.info("Testing format of %s", filepath) 293 self.assertTrue( 294 test_object.prepare_test(self.dut), "Setup failed!") 295 296 if not test_object.test_format(): 297 return 298 299 file_content = self.dut.ReadFileContent(filepath) 300 try: 301 parse_result = test_object.parse_contents(file_content) 302 except (SyntaxError, ValueError, IndexError) as e: 303 self.fail("Failed to parse! " + str(e)) 304 self.assertTrue( 305 test_object.result_correct(parse_result), "Results not valid!") 306 return test 307 308 309if __name__ == "__main__": 310 try: 311 for test_object in TEST_OBJECTS.union(TEST_OBJECTS_64): 312 test_func = run_proc_file_test(test_object) 313 setattr(VtsKernelProcFileApiTest, 'test_' + 314 test_object.__class__.__name__, test_func) 315 suite = unittest.TestLoader().loadTestsFromTestCase( 316 VtsKernelProcFileApiTest) 317 results = unittest.TextTestRunner(verbosity=2).run(suite) 318 finally: 319 if results.failures: 320 sys.exit(1) 321