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