1#!/usr/bin/env python 2# 3# Copyright (C) 2016 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 keys 24from vts.runners.host import test_runner 25from vts.utils.python.controllers import android_device 26from vts.utils.python.os import path_utils 27 28from vts.testcases.kernel.linux_kselftest import kselftest_config as config 29 30class LinuxKselftestTest(base_test.BaseTestClass): 31 """Runs Linux Kselftest test cases against Android OS kernel. 32 33 Attributes: 34 _dut: AndroidDevice, the device under test as config 35 _shell: ShellMirrorObject, shell mirror 36 _testcases: string list, list of testcases to run 37 """ 38 _32BIT = 32 39 _64BIT = 64 40 41 def setUpClass(self): 42 """Creates a remote shell instance, and copies data files.""" 43 required_params = [ 44 keys.ConfigKeys.IKEY_DATA_FILE_PATH, 45 config.ConfigKeys.TEST_TYPE 46 ] 47 self.getUserParams(required_params) 48 49 logging.info("%s: %s", keys.ConfigKeys.IKEY_DATA_FILE_PATH, 50 self.data_file_path) 51 52 self._dut = self.android_devices[0] 53 self._shell = self._dut.shell 54 55 if self.test_type == "presubmit": 56 self._testcases = config.KSFT_CASES_PRESUBMIT 57 elif self.test_type == "stable": 58 self._testcases = config.KSFT_CASES_STABLE 59 elif self.test_type == "staging": 60 self._testcases = config.KSFT_CASES_STAGING 61 else: 62 asserts.fail("Test config is incorrect!") 63 64 def tearDownClass(self): 65 """Deletes all copied data.""" 66 self._shell.Execute("rm -rf %s" % config.KSFT_DIR) 67 68 def PushFiles(self, n_bit): 69 """adb pushes related file to target. 70 71 Args: 72 n_bit: _32BIT or 32 for 32-bit tests; 73 _64BIT or 64 for 64-bit tests; 74 """ 75 self._shell.Execute("mkdir %s -p" % config.KSFT_DIR) 76 test_bit = 'nativetest' 77 if n_bit == self._64BIT: 78 test_bit += '64' 79 self._dut.adb.push("%s/DATA/%s/linux-kselftest/. %s" % 80 (self.data_file_path, test_bit, config.KSFT_DIR)) 81 82 def PreTestSetup(self): 83 """Sets up test before running.""" 84 # This sed command makes shell scripts compatible wiht android shell. 85 sed_pattern = [ 86 's?/bin/echo?echo?', 87 's?#!/bin/sh?#!/system/bin/sh?', 88 's?#!/bin/bash?#!/system/bin/sh?' 89 ] 90 sed_cmd = 'sed %s' % ' '.join( 91 ['-i -e ' + ('"%s"' % p) for p in sed_pattern]) 92 93 # This grep command is used to identify shell scripts. 94 grep_pattern = [ 95 'bin/sh', 96 'bin/bash' 97 ] 98 grep_cmd = 'grep -l %s' % ' '.join( 99 ['-e ' + ('"%s"' % p) for p in grep_pattern]) 100 101 # This applies sed_cmd to every shell script. 102 cmd = 'find %s -type f | xargs %s | xargs %s' % ( 103 config.KSFT_DIR, grep_cmd, sed_cmd) 104 result = self._shell.Execute(cmd) 105 106 asserts.assertFalse( 107 any(result[const.EXIT_CODE]), 108 "Error: pre-test setup failed.") 109 110 def RunTestcase(self, testcase): 111 """Runs the given testcase and asserts the result. 112 113 Args: 114 testcase: a LinuxKselftestTestcase object, specifies which 115 test case to run. 116 """ 117 if not testcase: 118 asserts.skip("Test is not supported on this abi.") 119 120 chmod_cmd = "chmod -R 755 %s" % path_utils.JoinTargetPath( 121 config.KSFT_DIR, testcase.testsuite) 122 cd_cmd = "cd %s" % path_utils.JoinTargetPath( 123 config.KSFT_DIR, testcase.testsuite) 124 125 cmd = [ 126 chmod_cmd, 127 "%s && %s" % (cd_cmd, testcase.test_cmd) 128 ] 129 logging.info("Executing: %s", cmd) 130 131 result = self._shell.Execute(cmd) 132 logging.info("EXIT_CODE: %s:", result[const.EXIT_CODE]) 133 134 asserts.assertFalse( 135 any(result[const.EXIT_CODE]), 136 "%s failed." % testcase.testname) 137 138 def TestNBits(self, n_bit): 139 """Runs all 32-bit or all 64-bit tests. 140 141 Args: 142 n_bit: _32BIT or 32 for 32-bit tests; 143 _64BIT or 64 for 64-bit tests; 144 """ 145 self.PushFiles(n_bit) 146 self.PreTestSetup() 147 148 cpu_abi = self._dut.cpu_abi 149 relevant_testcases = filter( 150 lambda x: x.IsRelevant(cpu_abi, n_bit), 151 self._testcases) 152 153 self.runGeneratedTests( 154 test_func=self.RunTestcase, 155 settings=relevant_testcases, 156 name_func=lambda testcase: "%s_%sbit" % ( 157 testcase.testname.replace('/','_'), n_bit)) 158 159 def generate32BitTests(self): 160 """Runs all 32-bit tests.""" 161 self.TestNBits(self._32BIT) 162 163 def generate64BitTests(self): 164 """Runs all 64-bit tests.""" 165 if self._dut.is64Bit: 166 self.TestNBits(self._64BIT) 167 168if __name__ == "__main__": 169 test_runner.main() 170