#!/usr/bin/env python
|
#
|
# Copyright (C) 2017 The Android Open Source Project
|
#
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
# you may not use this file except in compliance with the License.
|
# You may obtain a copy of the License at
|
#
|
# http://www.apache.org/licenses/LICENSE-2.0
|
#
|
# Unless required by applicable law or agreed to in writing, software
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# See the License for the specific language governing permissions and
|
# limitations under the License.
|
#
|
|
import logging
|
|
from vts.runners.host import asserts
|
from vts.runners.host import base_test
|
from vts.runners.host import const
|
from vts.runners.host import test_runner
|
|
from vts.testcases.kernel.api.proc import ProcAsoundTests
|
from vts.testcases.kernel.api.proc import ProcCmdlineTest
|
from vts.testcases.kernel.api.proc import ProcCpuFileTests
|
from vts.testcases.kernel.api.proc import ProcFsFileTests
|
from vts.testcases.kernel.api.proc import ProcKmsgTest
|
from vts.testcases.kernel.api.proc import ProcMapsTest
|
from vts.testcases.kernel.api.proc import ProcMiscTest
|
from vts.testcases.kernel.api.proc import ProcMemInfoTest
|
from vts.testcases.kernel.api.proc import ProcModulesTest
|
from vts.testcases.kernel.api.proc import ProcQtaguidCtrlTest
|
from vts.testcases.kernel.api.proc import ProcRemoveUidRangeTest
|
from vts.testcases.kernel.api.proc import ProcSimpleFileTests
|
from vts.testcases.kernel.api.proc import ProcShowUidStatTest
|
from vts.testcases.kernel.api.proc import ProcStatTest
|
from vts.testcases.kernel.api.proc import ProcUidIoStatsTest
|
from vts.testcases.kernel.api.proc import ProcUidTimeInStateTest
|
from vts.testcases.kernel.api.proc import ProcUidConcurrentTimeTests
|
from vts.testcases.kernel.api.proc import ProcUidCpuPowerTests
|
from vts.testcases.kernel.api.proc import ProcVersionTest
|
from vts.testcases.kernel.api.proc import ProcVmallocInfoTest
|
from vts.testcases.kernel.api.proc import ProcVmstatTest
|
from vts.testcases.kernel.api.proc import ProcZoneInfoTest
|
|
from vts.utils.python.controllers import android_device
|
from vts.utils.python.file import target_file_utils
|
|
TEST_OBJECTS = {
|
ProcAsoundTests.ProcAsoundCardsTest(),
|
ProcCmdlineTest.ProcCmdlineTest(),
|
ProcCpuFileTests.ProcCpuInfoTest(),
|
ProcCpuFileTests.ProcLoadavgTest(),
|
ProcFsFileTests.ProcDiskstatsTest(),
|
ProcFsFileTests.ProcFilesystemsTest(),
|
ProcFsFileTests.ProcMountsTest(),
|
ProcFsFileTests.ProcSwapsTest(),
|
ProcKmsgTest.ProcKmsgTest(),
|
ProcMapsTest.ProcMapsTest(),
|
ProcMiscTest.ProcMisc(),
|
ProcMemInfoTest.ProcMemInfoTest(),
|
ProcModulesTest.ProcModulesTest(),
|
ProcQtaguidCtrlTest.ProcQtaguidCtrlTest(),
|
ProcRemoveUidRangeTest.ProcRemoveUidRangeTest(),
|
ProcSimpleFileTests.ProcCorePattern(),
|
ProcSimpleFileTests.ProcCorePipeLimit(),
|
ProcSimpleFileTests.ProcDirtyBackgroundBytes(),
|
ProcSimpleFileTests.ProcDirtyBackgroundRatio(),
|
ProcSimpleFileTests.ProcDirtyExpireCentisecs(),
|
ProcSimpleFileTests.ProcDmesgRestrict(),
|
ProcSimpleFileTests.ProcDomainname(),
|
ProcSimpleFileTests.ProcDropCaches(),
|
ProcSimpleFileTests.ProcExtraFreeKbytes(),
|
ProcSimpleFileTests.ProcHostname(),
|
ProcSimpleFileTests.ProcHungTaskTimeoutSecs(),
|
ProcSimpleFileTests.ProcKptrRestrictTest(),
|
ProcSimpleFileTests.ProcMaxMapCount(),
|
ProcSimpleFileTests.ProcMmapMinAddrTest(),
|
ProcSimpleFileTests.ProcMmapRndBitsTest(),
|
ProcSimpleFileTests.ProcModulesDisabled(),
|
ProcSimpleFileTests.ProcOverCommitMemoryTest(),
|
ProcSimpleFileTests.ProcPageCluster(),
|
ProcSimpleFileTests.ProcPanicOnOops(),
|
ProcSimpleFileTests.ProcPerfEventMaxSampleRate(),
|
ProcSimpleFileTests.ProcPerfEventParanoid(),
|
ProcSimpleFileTests.ProcPidMax(),
|
ProcSimpleFileTests.ProcPipeMaxSize(),
|
ProcSimpleFileTests.ProcProtectedHardlinks(),
|
ProcSimpleFileTests.ProcProtectedSymlinks(),
|
ProcSimpleFileTests.ProcRandomizeVaSpaceTest(),
|
ProcSimpleFileTests.ProcSchedChildRunsFirst(),
|
ProcSimpleFileTests.ProcSchedLatencyNS(),
|
ProcSimpleFileTests.ProcSchedRTPeriodUS(),
|
ProcSimpleFileTests.ProcSchedRTRuntimeUS(),
|
ProcSimpleFileTests.ProcSchedTunableScaling(),
|
ProcSimpleFileTests.ProcSchedWakeupGranularityNS(),
|
ProcShowUidStatTest.ProcShowUidStatTest(),
|
ProcSimpleFileTests.ProcSuidDumpable(),
|
ProcSimpleFileTests.ProcSysKernelRandomBootId(),
|
ProcSimpleFileTests.ProcSysRqTest(),
|
ProcSimpleFileTests.ProcUptime(),
|
ProcStatTest.ProcStatTest(),
|
ProcUidIoStatsTest.ProcUidIoStatsTest(),
|
ProcUidTimeInStateTest.ProcUidTimeInStateTest(),
|
ProcUidConcurrentTimeTests.ProcUidConcurrentActiveTimeTest(),
|
ProcUidConcurrentTimeTests.ProcUidConcurrentPolicyTimeTest(),
|
ProcUidCpuPowerTests.ProcUidCpuPowerTimeInStateTest(),
|
ProcUidCpuPowerTests.ProcUidCpuPowerConcurrentActiveTimeTest(),
|
ProcUidCpuPowerTests.ProcUidCpuPowerConcurrentPolicyTimeTest(),
|
ProcVersionTest.ProcVersionTest(),
|
ProcVmallocInfoTest.ProcVmallocInfoTest(),
|
ProcVmstatTest.ProcVmstat(),
|
ProcZoneInfoTest.ProcZoneInfoTest(),
|
}
|
|
TEST_OBJECTS_64 = {
|
ProcSimpleFileTests.ProcMmapRndCompatBitsTest(),
|
}
|
|
|
class VtsKernelProcFileApiTest(base_test.BaseTestClass):
|
"""Test cases which check content of proc files.
|
|
Attributes:
|
_PROC_SYS_ABI_SWP_FILE_PATH: the path of a file which decides behaviour of SWP instruction.
|
"""
|
|
_PROC_SYS_ABI_SWP_FILE_PATH = "/proc/sys/abi/swp"
|
|
def setUpClass(self):
|
self.dut = self.android_devices[0]
|
self.shell = self.dut.shell
|
|
def runProcFileTest(self, test_object):
|
"""Reads from the file and checks that it parses and the content is valid.
|
|
Args:
|
test_object: inherits KernelProcFileTestBase, contains the test functions
|
"""
|
asserts.skipIf(test_object in TEST_OBJECTS_64 and not self.dut.is64Bit,
|
"Skip test for 64-bit kernel.")
|
filepath = test_object.get_path()
|
asserts.skipIf(not target_file_utils.Exists(filepath, self.shell) and
|
test_object.file_optional(shell=self.shell, dut=self.dut),
|
"%s does not exist and is optional." % filepath)
|
target_file_utils.assertPermissionsAndExistence(
|
self.shell, filepath, test_object.get_permission_checker())
|
|
logging.info("Testing format of %s", filepath)
|
|
asserts.assertTrue(
|
test_object.prepare_test(self.shell, self.dut), "Setup failed!")
|
|
if not test_object.test_format():
|
return
|
|
file_content = self.ReadFileContent(filepath)
|
try:
|
parse_result = test_object.parse_contents(file_content)
|
except (SyntaxError, ValueError, IndexError) as e:
|
asserts.fail("Failed to parse! " + str(e))
|
asserts.assertTrue(
|
test_object.result_correct(parse_result), "Results not valid!")
|
|
def generateProcFileTests(self):
|
"""Run all proc file tests."""
|
self.runGeneratedTests(
|
test_func=self.runProcFileTest,
|
settings=TEST_OBJECTS.union(TEST_OBJECTS_64),
|
name_func=lambda test_obj: "test" + test_obj.__class__.__name__)
|
|
def ReadFileContent(self, filepath):
|
"""Read the content of a file and perform assertions.
|
|
Args:
|
filepath: string, path to file
|
|
Returns:
|
string, content of file
|
"""
|
cmd = "cat %s" % filepath
|
results = self.shell.Execute(cmd)
|
|
# checks the exit code
|
asserts.assertEqual(
|
results[const.EXIT_CODE][0], 0,
|
"%s: Error happened while reading the file." % filepath)
|
|
return results[const.STDOUT][0]
|
|
def testProcPagetypeinfo(self):
|
# TODO(b/109884074): make mandatory once incident_helper is in AOSP.
|
try:
|
self.dut.adb.shell("which incident_helper")
|
except:
|
asserts.skip("incident_helper not present")
|
|
filepath = "/proc/pagetypeinfo"
|
# Check that incident_helper can parse /proc/pagetypeinfo.
|
result = self.shell.Execute("cat %s | incident_helper -s 2001" % filepath)
|
asserts.assertEqual(
|
result[const.EXIT_CODE][0], 0,
|
"Failed to parse %s." % filepath)
|
|
def testProcSysrqTrigger(self):
|
filepath = "/proc/sysrq-trigger"
|
|
# This command only performs a best effort attempt to remount all
|
# filesystems. Check that it doesn't throw an error.
|
self.dut.adb.shell("echo u > %s" % filepath)
|
|
# Reboot the device.
|
self.dut.adb.shell("echo b > %s" % filepath)
|
asserts.assertFalse(self.dut.hasBooted(), "Device is still alive.")
|
self.dut.waitForBootCompletion()
|
self.dut.rootAdb()
|
|
def testProcUidProcstatSet(self):
|
def UidIOStats(uid):
|
"""Returns I/O stats for a given uid.
|
|
Args:
|
uid, uid number.
|
|
Returns:
|
list of I/O numbers.
|
"""
|
stats_path = "/proc/uid_io/stats"
|
result = self.dut.adb.shell(
|
"cat %s | grep '^%d'" % (stats_path, uid),
|
no_except=True)
|
return result[const.STDOUT].split()
|
|
def CheckStatsInState(state):
|
"""Sets VTS (root uid) into a given state and checks the stats.
|
|
Args:
|
state, boolean. Use False for foreground,
|
and True for background.
|
"""
|
state = 1 if state else 0
|
filepath = "/proc/uid_procstat/set"
|
root_uid = 0
|
|
# fg write chars are at index 2, and bg write chars are at 6.
|
wchar_index = 6 if state else 2
|
old_wchar = UidIOStats(root_uid)[wchar_index]
|
self.dut.adb.shell("echo %d %s > %s" % (root_uid, state, filepath))
|
# This should increase the number of write syscalls.
|
self.dut.adb.shell("echo foo")
|
asserts.assertLess(
|
old_wchar,
|
UidIOStats(root_uid)[wchar_index],
|
"Number of write syscalls has not increased.")
|
|
CheckStatsInState(False)
|
CheckStatsInState(True)
|
|
def testProcPerUidTimes(self):
|
# TODO: make these files mandatory once they're in AOSP
|
try:
|
filepaths = self.dut.adb.shell("find /proc/uid -name time_in_state")
|
except:
|
asserts.skip("/proc/uid/ directory does not exist and is optional")
|
|
asserts.skipIf(not filepaths,
|
"per-UID time_in_state files do not exist and are optional")
|
|
filepaths = filepaths.splitlines()
|
for filepath in filepaths:
|
target_file_utils.assertPermissionsAndExistence(
|
self.shell, filepath, target_file_utils.IsReadOnly
|
)
|
file_content = self.ReadFileContent(filepath)
|
|
def testProcSysAbiSwpInstruction(self):
|
"""Tests /proc/sys/abi/swp.
|
|
/proc/sys/abi/swp sets the execution behaviour for the obsoleted ARM instruction
|
SWP. As per the setting in /proc/sys/abi/swp, the usage of SWP{B}
|
can either generate an undefined instruction abort or use software emulation
|
or hardware execution.
|
"""
|
|
asserts.skipIf(not ("arm" in self.dut.cpu_abi and self.dut.is64Bit),
|
"file not present on non-ARM64 device")
|
target_file_utils.assertPermissionsAndExistence(
|
self.shell, self._PROC_SYS_ABI_SWP_FILE_PATH, target_file_utils.IsReadWrite)
|
file_content = self.ReadFileContent(self._PROC_SYS_ABI_SWP_FILE_PATH)
|
try:
|
swp_state = int(file_content)
|
except ValueError as e:
|
asserts.fail("Failed to parse %s" % self._PROC_SYS_ABI_SWP_FILE_PATH)
|
asserts.assertTrue(swp_state >= 0 and swp_state <= 2,
|
"%s contains incorrect value: %d" % (self._PROC_SYS_ABI_SWP_FILE_PATH,
|
swp_state))
|
|
if __name__ == "__main__":
|
test_runner.main()
|