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 test_object.set_api_level(self.dut) 145 filepath = test_object.get_path() 146 asserts.skipIf(not target_file_utils.Exists(filepath, self.shell) and 147 test_object.file_optional(shell=self.shell, dut=self.dut), 148 "%s does not exist and is optional." % filepath) 149 target_file_utils.assertPermissionsAndExistence( 150 self.shell, filepath, test_object.get_permission_checker()) 151 152 logging.info("Testing format of %s", filepath) 153 154 asserts.assertTrue( 155 test_object.prepare_test(self.shell, self.dut), "Setup failed!") 156 157 if not test_object.test_format(): 158 return 159 160 file_content = self.ReadFileContent(filepath) 161 try: 162 parse_result = test_object.parse_contents(file_content) 163 except (SyntaxError, ValueError, IndexError) as e: 164 asserts.fail("Failed to parse! " + str(e)) 165 asserts.assertTrue( 166 test_object.result_correct(parse_result), "Results not valid!") 167 168 def generateProcFileTests(self): 169 """Run all proc file tests.""" 170 self.runGeneratedTests( 171 test_func=self.runProcFileTest, 172 settings=TEST_OBJECTS.union(TEST_OBJECTS_64), 173 name_func=lambda test_obj: "test" + test_obj.__class__.__name__) 174 175 def ReadFileContent(self, filepath): 176 """Read the content of a file and perform assertions. 177 178 Args: 179 filepath: string, path to file 180 181 Returns: 182 string, content of file 183 """ 184 cmd = "cat %s" % filepath 185 results = self.shell.Execute(cmd) 186 187 # checks the exit code 188 asserts.assertEqual( 189 results[const.EXIT_CODE][0], 0, 190 "%s: Error happened while reading the file." % filepath) 191 192 return results[const.STDOUT][0] 193 194 def testProcPagetypeinfo(self): 195 # TODO(b/109884074): make mandatory once incident_helper is in AOSP. 196 try: 197 self.dut.adb.shell("which incident_helper") 198 except: 199 asserts.skip("incident_helper not present") 200 201 filepath = "/proc/pagetypeinfo" 202 # Check that incident_helper can parse /proc/pagetypeinfo. 203 result = self.shell.Execute("cat %s | incident_helper -s 2001" % filepath) 204 asserts.assertEqual( 205 result[const.EXIT_CODE][0], 0, 206 "Failed to parse %s." % filepath) 207 208 def testProcSysrqTrigger(self): 209 filepath = "/proc/sysrq-trigger" 210 211 # This command only performs a best effort attempt to remount all 212 # filesystems. Check that it doesn't throw an error. 213 self.dut.adb.shell("echo u > %s" % filepath) 214 215 # Reboot the device. 216 self.dut.adb.shell("echo b > %s" % filepath) 217 asserts.assertFalse(self.dut.hasBooted(), "Device is still alive.") 218 self.dut.waitForBootCompletion() 219 self.dut.rootAdb() 220 221 def testProcUidProcstatSet(self): 222 def UidIOStats(uid): 223 """Returns I/O stats for a given uid. 224 225 Args: 226 uid, uid number. 227 228 Returns: 229 list of I/O numbers. 230 """ 231 stats_path = "/proc/uid_io/stats" 232 result = self.dut.adb.shell( 233 "cat %s | grep '^%d'" % (stats_path, uid), 234 no_except=True) 235 return result[const.STDOUT].split() 236 237 def CheckStatsInState(state): 238 """Sets VTS (root uid) into a given state and checks the stats. 239 240 Args: 241 state, boolean. Use False for foreground, 242 and True for background. 243 """ 244 state = 1 if state else 0 245 filepath = "/proc/uid_procstat/set" 246 root_uid = 0 247 248 # fg write chars are at index 2, and bg write chars are at 6. 249 wchar_index = 6 if state else 2 250 old_wchar = UidIOStats(root_uid)[wchar_index] 251 self.dut.adb.shell("echo %d %s > %s" % (root_uid, state, filepath)) 252 # This should increase the number of write syscalls. 253 self.dut.adb.shell("echo foo") 254 asserts.assertLess( 255 int(old_wchar), 256 int(UidIOStats(root_uid)[wchar_index]), 257 "Number of write syscalls has not increased.") 258 259 CheckStatsInState(False) 260 CheckStatsInState(True) 261 262 def testProcPerUidTimes(self): 263 # TODO: make these files mandatory once they're in AOSP 264 try: 265 filepaths = self.dut.adb.shell("find /proc/uid -name time_in_state") 266 except: 267 asserts.skip("/proc/uid/ directory does not exist and is optional") 268 269 asserts.skipIf(not filepaths, 270 "per-UID time_in_state files do not exist and are optional") 271 272 filepaths = filepaths.splitlines() 273 for filepath in filepaths: 274 target_file_utils.assertPermissionsAndExistence( 275 self.shell, filepath, target_file_utils.IsReadOnly 276 ) 277 file_content = self.ReadFileContent(filepath) 278 279 def testProcSysAbiSwpInstruction(self): 280 """Tests /proc/sys/abi/swp. 281 282 /proc/sys/abi/swp sets the execution behaviour for the obsoleted ARM instruction 283 SWP. As per the setting in /proc/sys/abi/swp, the usage of SWP{B} 284 can either generate an undefined instruction abort or use software emulation 285 or hardware execution. 286 """ 287 288 asserts.skipIf(not ("arm" in self.dut.cpu_abi and self.dut.is64Bit), 289 "file not present on non-ARM64 device") 290 target_file_utils.assertPermissionsAndExistence( 291 self.shell, self._PROC_SYS_ABI_SWP_FILE_PATH, target_file_utils.IsReadWrite) 292 file_content = self.ReadFileContent(self._PROC_SYS_ABI_SWP_FILE_PATH) 293 try: 294 swp_state = int(file_content) 295 except ValueError as e: 296 asserts.fail("Failed to parse %s" % self._PROC_SYS_ABI_SWP_FILE_PATH) 297 asserts.assertTrue(swp_state >= 0 and swp_state <= 2, 298 "%s contains incorrect value: %d" % (self._PROC_SYS_ABI_SWP_FILE_PATH, 299 swp_state)) 300 301if __name__ == "__main__": 302 test_runner.main() 303