1#!/usr/bin/env python 2# 3# Copyright (C) 2017 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 19 20from vts.runners.host import asserts 21from vts.runners.host import base_test 22from vts.runners.host import const 23from vts.runners.host import test_runner 24 25from vts.testcases.kernel.api.proc import ProcAsoundTests 26from vts.testcases.kernel.api.proc import ProcCmdlineTest 27from vts.testcases.kernel.api.proc import ProcCpuFileTests 28from vts.testcases.kernel.api.proc import ProcFsFileTests 29from vts.testcases.kernel.api.proc import ProcKmsgTest 30from vts.testcases.kernel.api.proc import ProcMapsTest 31from vts.testcases.kernel.api.proc import ProcMiscTest 32from vts.testcases.kernel.api.proc import ProcMemInfoTest 33from vts.testcases.kernel.api.proc import ProcModulesTest 34from vts.testcases.kernel.api.proc import ProcQtaguidCtrlTest 35from vts.testcases.kernel.api.proc import ProcRemoveUidRangeTest 36from vts.testcases.kernel.api.proc import ProcSimpleFileTests 37from vts.testcases.kernel.api.proc import ProcShowUidStatTest 38from vts.testcases.kernel.api.proc import ProcStatTest 39from vts.testcases.kernel.api.proc import ProcUidIoStatsTest 40from vts.testcases.kernel.api.proc import ProcUidTimeInStateTest 41from vts.testcases.kernel.api.proc import ProcUidConcurrentTimeTests 42from vts.testcases.kernel.api.proc import ProcUidCpuPowerTests 43from vts.testcases.kernel.api.proc import ProcVersionTest 44from vts.testcases.kernel.api.proc import ProcVmallocInfoTest 45from vts.testcases.kernel.api.proc import ProcVmstatTest 46from vts.testcases.kernel.api.proc import ProcZoneInfoTest 47 48from vts.utils.python.controllers import android_device 49from vts.utils.python.file import target_file_utils 50 51TEST_OBJECTS = { 52 ProcAsoundTests.ProcAsoundCardsTest(), 53 ProcCmdlineTest.ProcCmdlineTest(), 54 ProcCpuFileTests.ProcCpuInfoTest(), 55 ProcCpuFileTests.ProcLoadavgTest(), 56 ProcFsFileTests.ProcDiskstatsTest(), 57 ProcFsFileTests.ProcFilesystemsTest(), 58 ProcFsFileTests.ProcMountsTest(), 59 ProcFsFileTests.ProcSwapsTest(), 60 ProcKmsgTest.ProcKmsgTest(), 61 ProcMapsTest.ProcMapsTest(), 62 ProcMiscTest.ProcMisc(), 63 ProcMemInfoTest.ProcMemInfoTest(), 64 ProcModulesTest.ProcModulesTest(), 65 ProcQtaguidCtrlTest.ProcQtaguidCtrlTest(), 66 ProcRemoveUidRangeTest.ProcRemoveUidRangeTest(), 67 ProcSimpleFileTests.ProcCorePattern(), 68 ProcSimpleFileTests.ProcCorePipeLimit(), 69 ProcSimpleFileTests.ProcDirtyBackgroundBytes(), 70 ProcSimpleFileTests.ProcDirtyBackgroundRatio(), 71 ProcSimpleFileTests.ProcDirtyExpireCentisecs(), 72 ProcSimpleFileTests.ProcDmesgRestrict(), 73 ProcSimpleFileTests.ProcDomainname(), 74 ProcSimpleFileTests.ProcDropCaches(), 75 ProcSimpleFileTests.ProcExtraFreeKbytes(), 76 ProcSimpleFileTests.ProcHostname(), 77 ProcSimpleFileTests.ProcHungTaskTimeoutSecs(), 78 ProcSimpleFileTests.ProcKptrRestrictTest(), 79 ProcSimpleFileTests.ProcMaxMapCount(), 80 ProcSimpleFileTests.ProcMmapMinAddrTest(), 81 ProcSimpleFileTests.ProcMmapRndBitsTest(), 82 ProcSimpleFileTests.ProcModulesDisabled(), 83 ProcSimpleFileTests.ProcOverCommitMemoryTest(), 84 ProcSimpleFileTests.ProcPageCluster(), 85 ProcSimpleFileTests.ProcPanicOnOops(), 86 ProcSimpleFileTests.ProcPerfEventMaxSampleRate(), 87 ProcSimpleFileTests.ProcPerfEventParanoid(), 88 ProcSimpleFileTests.ProcPidMax(), 89 ProcSimpleFileTests.ProcPipeMaxSize(), 90 ProcSimpleFileTests.ProcProtectedHardlinks(), 91 ProcSimpleFileTests.ProcProtectedSymlinks(), 92 ProcSimpleFileTests.ProcRandomizeVaSpaceTest(), 93 ProcSimpleFileTests.ProcSchedChildRunsFirst(), 94 ProcSimpleFileTests.ProcSchedLatencyNS(), 95 ProcSimpleFileTests.ProcSchedRTPeriodUS(), 96 ProcSimpleFileTests.ProcSchedRTRuntimeUS(), 97 ProcSimpleFileTests.ProcSchedTunableScaling(), 98 ProcSimpleFileTests.ProcSchedWakeupGranularityNS(), 99 ProcShowUidStatTest.ProcShowUidStatTest(), 100 ProcSimpleFileTests.ProcSuidDumpable(), 101 ProcSimpleFileTests.ProcSysKernelRandomBootId(), 102 ProcSimpleFileTests.ProcSysRqTest(), 103 ProcSimpleFileTests.ProcUptime(), 104 ProcStatTest.ProcStatTest(), 105 ProcUidIoStatsTest.ProcUidIoStatsTest(), 106 ProcUidTimeInStateTest.ProcUidTimeInStateTest(), 107 ProcUidConcurrentTimeTests.ProcUidConcurrentActiveTimeTest(), 108 ProcUidConcurrentTimeTests.ProcUidConcurrentPolicyTimeTest(), 109 ProcUidCpuPowerTests.ProcUidCpuPowerTimeInStateTest(), 110 ProcUidCpuPowerTests.ProcUidCpuPowerConcurrentActiveTimeTest(), 111 ProcUidCpuPowerTests.ProcUidCpuPowerConcurrentPolicyTimeTest(), 112 ProcVersionTest.ProcVersionTest(), 113 ProcVmallocInfoTest.ProcVmallocInfoTest(), 114 ProcVmstatTest.ProcVmstat(), 115 ProcZoneInfoTest.ProcZoneInfoTest(), 116} 117 118TEST_OBJECTS_64 = { 119 ProcSimpleFileTests.ProcMmapRndCompatBitsTest(), 120} 121 122 123class VtsKernelProcFileApiTest(base_test.BaseTestClass): 124 """Test cases which check content of proc files. 125 126 Attributes: 127 _PROC_SYS_ABI_SWP_FILE_PATH: the path of a file which decides behaviour of SWP instruction. 128 """ 129 130 _PROC_SYS_ABI_SWP_FILE_PATH = "/proc/sys/abi/swp" 131 132 def setUpClass(self): 133 self.dut = self.android_devices[0] 134 self.shell = self.dut.shell 135 136 def runProcFileTest(self, test_object): 137 """Reads from the file and checks that it parses and the content is valid. 138 139 Args: 140 test_object: inherits KernelProcFileTestBase, contains the test functions 141 """ 142 asserts.skipIf(test_object in TEST_OBJECTS_64 and not self.dut.is64Bit, 143 "Skip test for 64-bit kernel.") 144 filepath = test_object.get_path() 145 asserts.skipIf(not target_file_utils.Exists(filepath, self.shell) and 146 test_object.file_optional(shell=self.shell, dut=self.dut), 147 "%s does not exist and is optional." % filepath) 148 target_file_utils.assertPermissionsAndExistence( 149 self.shell, filepath, test_object.get_permission_checker()) 150 151 logging.info("Testing format of %s", filepath) 152 153 asserts.assertTrue( 154 test_object.prepare_test(self.shell, self.dut), "Setup failed!") 155 156 if not test_object.test_format(): 157 return 158 159 file_content = self.ReadFileContent(filepath) 160 try: 161 parse_result = test_object.parse_contents(file_content) 162 except (SyntaxError, ValueError, IndexError) as e: 163 asserts.fail("Failed to parse! " + str(e)) 164 asserts.assertTrue( 165 test_object.result_correct(parse_result), "Results not valid!") 166 167 def generateProcFileTests(self): 168 """Run all proc file tests.""" 169 self.runGeneratedTests( 170 test_func=self.runProcFileTest, 171 settings=TEST_OBJECTS.union(TEST_OBJECTS_64), 172 name_func=lambda test_obj: "test" + test_obj.__class__.__name__) 173 174 def ReadFileContent(self, filepath): 175 """Read the content of a file and perform assertions. 176 177 Args: 178 filepath: string, path to file 179 180 Returns: 181 string, content of file 182 """ 183 cmd = "cat %s" % filepath 184 results = self.shell.Execute(cmd) 185 186 # checks the exit code 187 asserts.assertEqual( 188 results[const.EXIT_CODE][0], 0, 189 "%s: Error happened while reading the file." % filepath) 190 191 return results[const.STDOUT][0] 192 193 def testProcPagetypeinfo(self): 194 # TODO(b/109884074): make mandatory once incident_helper is in AOSP. 195 try: 196 self.dut.adb.shell("which incident_helper") 197 except: 198 asserts.skip("incident_helper not present") 199 200 filepath = "/proc/pagetypeinfo" 201 # Check that incident_helper can parse /proc/pagetypeinfo. 202 result = self.shell.Execute("cat %s | incident_helper -s 2001" % filepath) 203 asserts.assertEqual( 204 result[const.EXIT_CODE][0], 0, 205 "Failed to parse %s." % filepath) 206 207 def testProcSysrqTrigger(self): 208 filepath = "/proc/sysrq-trigger" 209 210 # This command only performs a best effort attempt to remount all 211 # filesystems. Check that it doesn't throw an error. 212 self.dut.adb.shell("echo u > %s" % filepath) 213 214 # Reboot the device. 215 self.dut.adb.shell("echo b > %s" % filepath) 216 asserts.assertFalse(self.dut.hasBooted(), "Device is still alive.") 217 self.dut.waitForBootCompletion() 218 self.dut.rootAdb() 219 220 def testProcUidProcstatSet(self): 221 def UidIOStats(uid): 222 """Returns I/O stats for a given uid. 223 224 Args: 225 uid, uid number. 226 227 Returns: 228 list of I/O numbers. 229 """ 230 stats_path = "/proc/uid_io/stats" 231 result = self.dut.adb.shell( 232 "cat %s | grep '^%d'" % (stats_path, uid), 233 no_except=True) 234 return result[const.STDOUT].split() 235 236 def CheckStatsInState(state): 237 """Sets VTS (root uid) into a given state and checks the stats. 238 239 Args: 240 state, boolean. Use False for foreground, 241 and True for background. 242 """ 243 state = 1 if state else 0 244 filepath = "/proc/uid_procstat/set" 245 root_uid = 0 246 247 # fg write chars are at index 2, and bg write chars are at 6. 248 wchar_index = 6 if state else 2 249 old_wchar = UidIOStats(root_uid)[wchar_index] 250 self.dut.adb.shell("echo %d %s > %s" % (root_uid, state, filepath)) 251 # This should increase the number of write syscalls. 252 self.dut.adb.shell("echo foo") 253 asserts.assertLess( 254 old_wchar, 255 UidIOStats(root_uid)[wchar_index], 256 "Number of write syscalls has not increased.") 257 258 CheckStatsInState(False) 259 CheckStatsInState(True) 260 261 def testProcPerUidTimes(self): 262 # TODO: make these files mandatory once they're in AOSP 263 try: 264 filepaths = self.dut.adb.shell("find /proc/uid -name time_in_state") 265 except: 266 asserts.skip("/proc/uid/ directory does not exist and is optional") 267 268 asserts.skipIf(not filepaths, 269 "per-UID time_in_state files do not exist and are optional") 270 271 filepaths = filepaths.splitlines() 272 for filepath in filepaths: 273 target_file_utils.assertPermissionsAndExistence( 274 self.shell, filepath, target_file_utils.IsReadOnly 275 ) 276 file_content = self.ReadFileContent(filepath) 277 278 def testProcSysAbiSwpInstruction(self): 279 """Tests /proc/sys/abi/swp. 280 281 /proc/sys/abi/swp sets the execution behaviour for the obsoleted ARM instruction 282 SWP. As per the setting in /proc/sys/abi/swp, the usage of SWP{B} 283 can either generate an undefined instruction abort or use software emulation 284 or hardware execution. 285 """ 286 287 asserts.skipIf(not ("arm" in self.dut.cpu_abi and self.dut.is64Bit), 288 "file not present on non-ARM64 device") 289 target_file_utils.assertPermissionsAndExistence( 290 self.shell, self._PROC_SYS_ABI_SWP_FILE_PATH, target_file_utils.IsReadWrite) 291 file_content = self.ReadFileContent(self._PROC_SYS_ABI_SWP_FILE_PATH) 292 try: 293 swp_state = int(file_content) 294 except ValueError as e: 295 asserts.fail("Failed to parse %s" % self._PROC_SYS_ABI_SWP_FILE_PATH) 296 asserts.assertTrue(swp_state >= 0 and swp_state <= 2, 297 "%s contains incorrect value: %d" % (self._PROC_SYS_ABI_SWP_FILE_PATH, 298 swp_state)) 299 300if __name__ == "__main__": 301 test_runner.main() 302