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, message): 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 message: A string, the error message. 74 """ 75 logging.error("Unexpected files:\n%s", "\n".join(unexpected_paths)) 76 assert_lines = unexpected_paths[:20] 77 if len(unexpected_paths) > 20: 78 assert_lines.extend([ 79 "...", 80 "Total number of errors: %d" % len(unexpected_paths)]) 81 assert_lines.append(message) 82 self.fail("\n".join(assert_lines)) 83 84 def _TestVndkDirectory(self, vndk_dir, vndk_list_names): 85 """Verifies that the VNDK directory doesn't contain extra files. 86 87 Args: 88 vndk_dir: The path to the VNDK directory on device. 89 vndk_list_names: Strings, the categories of the VNDK libraries 90 that can be in the directory. 91 """ 92 vndk_lists = vndk_data.LoadVndkLibraryListsFromResources( 93 self._vndk_version, *vndk_list_names) 94 self.assertTrue(vndk_lists, "Cannot load VNDK library lists.") 95 vndk_set = set().union(*vndk_lists) 96 logging.debug("vndk set: %s", vndk_set) 97 unexpected = [x for x in self._ListFiles(vndk_dir) if 98 target_path_module.basename(x) not in vndk_set] 99 if unexpected: 100 self._Fail(unexpected, 101 "The above libraries are not %s." % 102 ", ".join(vndk_list_names)) 103 104 def _TestNotInVndkDirecotory(self, vndk_dir, vndk_list_names, except_libs): 105 """Verifies that VNDK directory doesn't contain specific files. 106 107 Args: 108 vndk_dir, The path to the VNDK directory on device. 109 vndk_list_names: A list of strings, the categories of the VNDK 110 libraries that should not be in the directory. 111 except_libs: A set of strings, the file names of the libraries that 112 are exceptions to this test. 113 """ 114 vndk_lists = vndk_data.LoadVndkLibraryListsFromResources( 115 self._vndk_version, *vndk_list_names) 116 self.assertTrue(vndk_lists, "Cannot load VNDK library lists.") 117 vndk_set = set().union(*vndk_lists) 118 vndk_set.difference_update(except_libs) 119 logging.debug("vndk set: %s", vndk_set) 120 unexpected = [x for x in self._ListFiles(vndk_dir) if 121 target_path_module.basename(x) in vndk_set] 122 if unexpected: 123 self._Fail(unexpected, 124 "%s must not contain %s libraries." % 125 (vndk_dir, ", ",join(vndk_list_names))) 126 127 def _TestVndkCoreDirectory(self, bitness): 128 """Verifies that VNDK directory doesn't contain extra files.""" 129 if not vndk_utils.IsVndkRuntimeEnforced(self._dut): 130 logging.info("Skip the test as VNDK runtime is not enforced on " 131 "the device.") 132 return 133 self._TestVndkDirectory( 134 vndk_utils.GetVndkDirectory(bitness, self._vndk_version), 135 (vndk_data.VNDK, vndk_data.VNDK_PRIVATE, vndk_data.VNDK_SP, 136 vndk_data.VNDK_SP_PRIVATE,)) 137 138 def testVndkCoreDirectory32(self): 139 """Runs _TestVndkCoreDirectory for 32-bit libraries.""" 140 self._TestVndkCoreDirectory(32) 141 142 def testVndkCoreDirectory64(self): 143 """Runs _TestVndkCoreDirectory for 64-bit libraries.""" 144 if self._dut.GetCpuAbiList(64): 145 self._TestVndkCoreDirectory(64) 146 else: 147 logging.info("Skip the test as the device doesn't support 64-bit " 148 "ABI.") 149 150 def _TestNoLlndkInVendor(self, bitness): 151 """Verifies that vendor partition has no LL-NDK libraries.""" 152 self._TestNotInVndkDirecotory( 153 vndk_utils.FormatVndkPath(self._TARGET_VENDOR_LIB, bitness), 154 (vndk_data.LL_NDK,), 155 self._LL_NDK_COLLIDING_NAMES) 156 157 def testNoLlndkInVendor32(self): 158 """Runs _TestNoLlndkInVendor for 32-bit libraries.""" 159 self._TestNoLlndkInVendor(32) 160 161 def testNoLlndkInVendor64(self): 162 """Runs _TestNoLlndkInVendor for 64-bit libraries.""" 163 if self._dut.GetCpuAbiList(64): 164 self._TestNoLlndkInVendor(64) 165 else: 166 logging.info("Skip the test as the device doesn't support 64-bit " 167 "ABI.") 168 169 def _TestNoLlndkInOdm(self, bitness): 170 """Verifies that odm partition has no LL-NDK libraries.""" 171 self._TestNotInVndkDirecotory( 172 vndk_utils.FormatVndkPath(self._TARGET_ODM_LIB, bitness), 173 (vndk_data.LL_NDK,), 174 self._LL_NDK_COLLIDING_NAMES) 175 176 def testNoLlndkInOdm32(self): 177 """Runs _TestNoLlndkInOdm for 32-bit libraries.""" 178 self._TestNoLlndkInOdm(32) 179 180 def testNoLlndkInOdm64(self): 181 """Runs _TestNoLlndkInOdm for 64-bit libraries.""" 182 if self._dut.GetCpuAbiList(64): 183 self._TestNoLlndkInOdm(64) 184 else: 185 logging.info("Skip the test as the device doesn't support 64-bit " 186 "ABI.") 187 188 189if __name__ == "__main__": 190 # The logs are written to stdout so that TradeFed test runner can parse the 191 # results from stderr. 192 logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) 193 # Setting verbosity is required to generate output that the TradeFed test 194 # runner can parse. 195 unittest.main(verbosity=3) 196