1#!/usr/bin/env python3 2# 3# Copyright (C) 2020 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 19import os 20import posixpath as target_path_module 21import sys 22import unittest 23 24from vts.testcases.vndk import utils 25from vts.testcases.vndk.golden import vndk_data 26from vts.utils.python.vndk import vndk_utils 27 28 29class VtsVndkFilesTest(unittest.TestCase): 30 """A test for VNDK files and directories. 31 32 Attributes: 33 _dut: The AndroidDevice under test. 34 _vndk_version: The VNDK version of the device. 35 """ 36 # Some LL-NDK libraries may load the implementations with the same names 37 # from /vendor/lib. Since a vendor may install an implementation of an 38 # LL-NDK library with the same name, testNoLlndkInVendor doesn't raise 39 # errors on these LL-NDK libraries. 40 _LL_NDK_COLLIDING_NAMES = ("libEGL.so", "libGLESv1_CM.so", "libGLESv2.so", 41 "libGLESv3.so") 42 _TARGET_ODM_LIB = "/odm/{LIB}" 43 _TARGET_VENDOR_LIB = "/vendor/{LIB}" 44 45 def setUp(self): 46 """Initializes attributes.""" 47 serial_number = os.environ.get("ANDROID_SERIAL") 48 self.assertTrue(serial_number, "$ANDROID_SERIAL is empty.") 49 self._dut = utils.AndroidDevice(serial_number) 50 self.assertTrue(self._dut.IsRoot(), "This test requires adb root.") 51 self._vndk_version = self._dut.GetVndkVersion() 52 53 def _ListFiles(self, dir_path): 54 """Lists all files in a directory except subdirectories. 55 56 Args: 57 dir_path: A string, path to the directory on device. 58 59 Returns: 60 A list of strings, the file paths in the directory. 61 """ 62 if not self._dut.Exists(dir_path): 63 logging.info("%s not found", dir_path) 64 return [] 65 return self._dut.FindFiles(dir_path, "*", "!", "-type", "d") 66 67 def _Fail(self, unexpected_paths): 68 """Logs error and fails current test. 69 70 Args: 71 unexpected_paths: A list of strings, the paths to be shown in the 72 log message. 73 """ 74 logging.error("Unexpected files:\n%s", "\n".join(unexpected_paths)) 75 assert_lines = unexpected_paths[:20] 76 if len(unexpected_paths) > 20: 77 assert_lines.append("...") 78 assert_lines.append( 79 "Total number of errors: %d" % len(unexpected_paths)) 80 self.fail("\n".join(assert_lines)) 81 82 def _TestVndkDirectory(self, vndk_dir, vndk_list_names): 83 """Verifies that the VNDK directory doesn't contain extra files. 84 85 Args: 86 vndk_dir: The path to the VNDK directory on device. 87 vndk_list_names: Strings, the categories of the VNDK libraries 88 that can be in the directory. 89 """ 90 vndk_lists = vndk_data.LoadVndkLibraryListsFromResources( 91 self._vndk_version, *vndk_list_names) 92 self.assertTrue(vndk_lists, "Cannot load VNDK library lists.") 93 vndk_set = set().union(*vndk_lists) 94 logging.debug("vndk set: %s", vndk_set) 95 unexpected = [x for x in self._ListFiles(vndk_dir) if 96 target_path_module.basename(x) not in vndk_set] 97 if unexpected: 98 self._Fail(unexpected) 99 100 def _TestNotInVndkDirecotory(self, vndk_dir, vndk_list_names, except_libs): 101 """Verifies that VNDK directory doesn't contain specific files. 102 103 Args: 104 vndk_dir, The path to the VNDK directory on device. 105 vndk_list_names: A list of strings, the categories of the VNDK 106 libraries that should not be in the directory. 107 except_libs: A set of strings, the file names of the libraries that 108 are exceptions to this test. 109 """ 110 vndk_lists = vndk_data.LoadVndkLibraryListsFromResources( 111 self._vndk_version, *vndk_list_names) 112 self.assertTrue(vndk_lists, "Cannot load VNDK library lists.") 113 vndk_set = set().union(*vndk_lists) 114 vndk_set.difference_update(except_libs) 115 logging.debug("vndk set: %s", vndk_set) 116 unexpected = [x for x in self._ListFiles(vndk_dir) if 117 target_path_module.basename(x) in vndk_set] 118 if unexpected: 119 self._Fail(unexpected) 120 121 def _TestVndkCoreDirectory(self, bitness): 122 """Verifies that VNDK directory doesn't contain extra files.""" 123 if not vndk_utils.IsVndkRuntimeEnforced(self._dut): 124 logging.info("Skip the test as VNDK runtime is not enforced on " 125 "the device.") 126 return 127 self._TestVndkDirectory( 128 vndk_utils.GetVndkDirectory(bitness, self._vndk_version), 129 (vndk_data.VNDK, vndk_data.VNDK_PRIVATE, vndk_data.VNDK_SP, 130 vndk_data.VNDK_SP_PRIVATE,)) 131 132 def testVndkCoreDirectory32(self): 133 """Runs _TestVndkCoreDirectory for 32-bit libraries.""" 134 self._TestVndkCoreDirectory(32) 135 136 def testVndkCoreDirectory64(self): 137 """Runs _TestVndkCoreDirectory for 64-bit libraries.""" 138 if self._dut.GetCpuAbiList(64): 139 self._TestVndkCoreDirectory(64) 140 else: 141 logging.info("Skip the test as the device doesn't support 64-bit " 142 "ABI.") 143 144 def _TestNoLlndkInVendor(self, bitness): 145 """Verifies that vendor partition has no LL-NDK libraries.""" 146 self._TestNotInVndkDirecotory( 147 vndk_utils.FormatVndkPath(self._TARGET_VENDOR_LIB, bitness), 148 (vndk_data.LL_NDK,), 149 self._LL_NDK_COLLIDING_NAMES) 150 151 def testNoLlndkInVendor32(self): 152 """Runs _TestNoLlndkInVendor for 32-bit libraries.""" 153 self._TestNoLlndkInVendor(32) 154 155 def testNoLlndkInVendor64(self): 156 """Runs _TestNoLlndkInVendor for 64-bit libraries.""" 157 if self._dut.GetCpuAbiList(64): 158 self._TestNoLlndkInVendor(64) 159 else: 160 logging.info("Skip the test as the device doesn't support 64-bit " 161 "ABI.") 162 163 def _TestNoLlndkInOdm(self, bitness): 164 """Verifies that odm partition has no LL-NDK libraries.""" 165 self._TestNotInVndkDirecotory( 166 vndk_utils.FormatVndkPath(self._TARGET_ODM_LIB, bitness), 167 (vndk_data.LL_NDK,), 168 self._LL_NDK_COLLIDING_NAMES) 169 170 def testNoLlndkInOdm32(self): 171 """Runs _TestNoLlndkInOdm for 32-bit libraries.""" 172 self._TestNoLlndkInOdm(32) 173 174 def testNoLlndkInOdm64(self): 175 """Runs _TestNoLlndkInOdm for 64-bit libraries.""" 176 if self._dut.GetCpuAbiList(64): 177 self._TestNoLlndkInOdm(64) 178 else: 179 logging.info("Skip the test as the device doesn't support 64-bit " 180 "ABI.") 181 182 183if __name__ == "__main__": 184 # The logs are written to stdout so that TradeFed test runner can parse the 185 # results from stderr. 186 logging.basicConfig(stream=sys.stdout) 187 # Setting verbosity is required to generate output that the TradeFed test 188 # runner can parse. 189 unittest.main(verbosity=3) 190