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 _TestNoLlndkInDirectory(self, lib_dir): 105 """Verifies that the vendor directory doesn't contain LLNDK libraries. 106 107 Args: 108 lib_dir: The path to the directory on device. 109 """ 110 if vndk_utils.IsVndkRequired(self._dut): 111 llndk_list = vndk_data.LoadVndkLibraryListsFromResources( 112 self._vndk_version, vndk_data.LL_NDK)[0] 113 else: 114 llndk_list = self._dut.GetLlndkList() 115 llndk_set = set(llndk_list).difference(self._LL_NDK_COLLIDING_NAMES) 116 logging.debug("llndk set: %s", llndk_set) 117 unexpected = [x for x in self._ListFiles(lib_dir) if 118 target_path_module.basename(x) in llndk_set] 119 if unexpected: 120 self._Fail(unexpected, 121 lib_dir + " must not contain LLNDK libraries.") 122 123 def _TestVndkCoreDirectory(self, bitness): 124 """Verifies that VNDK directory doesn't contain extra files.""" 125 if not self._dut.GetCpuAbiList(bitness): 126 logging.info("Skip the test as the device doesn't support %d-bit " 127 "ABI.", bitness) 128 return 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 if not vndk_utils.IsVndkRequired(self._dut): 134 logging.info("Skip the test as the device does not require VNDK.") 135 return 136 if vndk_utils.IsVndkInstalledInVendor(self._dut): 137 logging.info("Skip the test as VNDK %s should be installed in " 138 "vendor partition.", self._vndk_version) 139 return 140 self._TestVndkDirectory( 141 vndk_utils.GetVndkDirectory(bitness, self._vndk_version), 142 (vndk_data.VNDK, vndk_data.VNDK_PRIVATE, vndk_data.VNDK_SP, 143 vndk_data.VNDK_SP_PRIVATE,)) 144 145 def testVndkCoreDirectory32(self): 146 """Runs _TestVndkCoreDirectory for 32-bit libraries.""" 147 self._TestVndkCoreDirectory(32) 148 149 def testVndkCoreDirectory64(self): 150 """Runs _TestVndkCoreDirectory for 64-bit libraries.""" 151 self._TestVndkCoreDirectory(64) 152 153 def _TestNoLlndkInVendor(self, bitness): 154 """Verifies that vendor partition has no LL-NDK libraries.""" 155 if not self._dut.GetCpuAbiList(bitness): 156 logging.info("Skip the test as the device doesn't support %d-bit " 157 "ABI.", bitness) 158 return 159 self._TestNoLlndkInDirectory( 160 vndk_utils.FormatVndkPath(self._TARGET_VENDOR_LIB, bitness)) 161 162 def testNoLlndkInVendor32(self): 163 """Runs _TestNoLlndkInVendor for 32-bit libraries.""" 164 self._TestNoLlndkInVendor(32) 165 166 def testNoLlndkInVendor64(self): 167 """Runs _TestNoLlndkInVendor for 64-bit libraries.""" 168 self._TestNoLlndkInVendor(64) 169 170 def _TestNoLlndkInOdm(self, bitness): 171 """Verifies that odm partition has no LL-NDK libraries.""" 172 if not self._dut.GetCpuAbiList(bitness): 173 logging.info("Skip the test as the device doesn't support %d-bit " 174 "ABI.", bitness) 175 return 176 self._TestNoLlndkInDirectory( 177 vndk_utils.FormatVndkPath(self._TARGET_ODM_LIB, bitness)) 178 179 def testNoLlndkInOdm32(self): 180 """Runs _TestNoLlndkInOdm for 32-bit libraries.""" 181 self._TestNoLlndkInOdm(32) 182 183 def testNoLlndkInOdm64(self): 184 """Runs _TestNoLlndkInOdm for 64-bit libraries.""" 185 self._TestNoLlndkInOdm(64) 186 187 188if __name__ == "__main__": 189 # The logs are written to stdout so that TradeFed test runner can parse the 190 # results from stderr. 191 logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) 192 # Setting verbosity is required to generate output that the TradeFed test 193 # runner can parse. 194 unittest.main(verbosity=3) 195