summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-03-13 03:10:13 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-03-13 03:10:13 +0000
commit632440a17283f144d92586f6a35d9b6bb26ebf79 (patch)
tree57b3d133046d2b4f5147c43ae392d2661e3e0f70
parent45aa2463e66b3e836671d99c37bc992e2cf6e846 (diff)
parentea547f5c6fcf461a68ee5e1ed268021f1b2d7d42 (diff)
downloadvndk-632440a17283f144d92586f6a35d9b6bb26ebf79.tar.gz
Add vts_vndk_files_test am: a0805f0b0f am: ea547f5c6f
Change-Id: I96a10a99c6e55d8db7248c204a47b4afb484840c
-rw-r--r--Android.bp13
-rw-r--r--files/vts_vndk_files_test.py183
-rw-r--r--files/vts_vndk_files_test.xml24
-rw-r--r--utils.py29
4 files changed, 249 insertions, 0 deletions
diff --git a/Android.bp b/Android.bp
index df43d92..90cc368 100644
--- a/Android.bp
+++ b/Android.bp
@@ -58,3 +58,16 @@ python_test_host {
"dependency/vts_vndk_dependency_test.py",
]
}
+
+python_test_host {
+ name: "vts_vndk_files_test",
+ defaults: ["vts_vndk_default"],
+ main: "files/vts_vndk_files_test.py",
+ srcs: [
+ "files/vts_vndk_files_test.py",
+ ],
+ test_suites: [
+ "vts-core",
+ ],
+ test_config: "files/vts_vndk_files_test.xml",
+}
diff --git a/files/vts_vndk_files_test.py b/files/vts_vndk_files_test.py
new file mode 100644
index 0000000..bcab2b7
--- /dev/null
+++ b/files/vts_vndk_files_test.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import logging
+import os
+import posixpath as target_path_module
+import unittest
+
+from vts.testcases.vndk import utils
+from vts.testcases.vndk.golden import vndk_data
+from vts.utils.python.vndk import vndk_utils
+
+
+class VtsVndkFilesTest(unittest.TestCase):
+ """A test for VNDK files and directories.
+
+ Attributes:
+ _dut: The AndroidDevice under test.
+ _vndk_version: The VNDK version of the device.
+ """
+ # Some LL-NDK libraries may load the implementations with the same names
+ # from /vendor/lib. Since a vendor may install an implementation of an
+ # LL-NDK library with the same name, testNoLlndkInVendor doesn't raise
+ # errors on these LL-NDK libraries.
+ _LL_NDK_COLLIDING_NAMES = ("libEGL.so", "libGLESv1_CM.so", "libGLESv2.so",
+ "libGLESv3.so")
+ _TARGET_ODM_LIB = "/odm/{LIB}"
+ _TARGET_VENDOR_LIB = "/vendor/{LIB}"
+
+ def setUp(self):
+ """Initializes attributes."""
+ serial_number = os.environ.get("ANDROID_SERIAL")
+ self.assertTrue(serial_number, "$ANDROID_SERIAL is empty.")
+ self._dut = utils.AndroidDevice(serial_number)
+ self.assertTrue(self._dut.IsRoot(), "This test requires adb root.")
+ self._vndk_version = self._dut.GetVndkVersion()
+
+ def _ListFiles(self, dir_path):
+ """Lists all files in a directory except subdirectories.
+
+ Args:
+ dir_path: A string, path to the directory on device.
+
+ Returns:
+ A list of strings, the file paths in the directory.
+ """
+ if not self._dut.Exists(dir_path):
+ logging.info("%s not found", dir_path)
+ return []
+ return self._dut.FindFiles(dir_path, "*", "!", "-type", "d")
+
+ def _Fail(self, unexpected_paths):
+ """Logs error and fails current test.
+
+ Args:
+ unexpected_paths: A list of strings, the paths to be shown in the
+ log message.
+ """
+ logging.error("Unexpected files:\n%s", "\n".join(unexpected_paths))
+ assert_lines = unexpected_paths[:20]
+ if len(unexpected_paths) > 20:
+ assert_lines.append("...")
+ assert_lines.append(
+ "Total number of errors: %d" % len(unexpected_paths))
+ self.fail("\n".join(assert_lines))
+
+ def _TestVndkDirectory(self, vndk_dir, vndk_list_names):
+ """Verifies that the VNDK directory doesn't contain extra files.
+
+ Args:
+ vndk_dir: The path to the VNDK directory on device.
+ vndk_list_names: Strings, the categories of the VNDK libraries
+ that can be in the directory.
+ """
+ vndk_lists = vndk_data.LoadVndkLibraryListsFromResources(
+ self._vndk_version, *vndk_list_names)
+ self.assertTrue(vndk_lists, "Cannot load VNDK library lists.")
+ vndk_set = set().union(*vndk_lists)
+ logging.debug("vndk set: %s", vndk_set)
+ unexpected = [x for x in self._ListFiles(vndk_dir) if
+ target_path_module.basename(x) not in vndk_set]
+ if unexpected:
+ self._Fail(unexpected)
+
+ def _TestNotInVndkDirecotory(self, vndk_dir, vndk_list_names, except_libs):
+ """Verifies that VNDK directory doesn't contain specific files.
+
+ Args:
+ vndk_dir, The path to the VNDK directory on device.
+ vndk_list_names: A list of strings, the categories of the VNDK
+ libraries that should not be in the directory.
+ except_libs: A set of strings, the file names of the libraries that
+ are exceptions to this test.
+ """
+ vndk_lists = vndk_data.LoadVndkLibraryListsFromResources(
+ self._vndk_version, *vndk_list_names)
+ self.assertTrue(vndk_lists, "Cannot load VNDK library lists.")
+ vndk_set = set().union(*vndk_lists)
+ vndk_set.difference_update(except_libs)
+ logging.debug("vndk set: %s", vndk_set)
+ unexpected = [x for x in self._ListFiles(vndk_dir) if
+ target_path_module.basename(x) in vndk_set]
+ if unexpected:
+ self._Fail(unexpected)
+
+ def _TestVndkCoreDirectory(self, bitness):
+ """Verifies that VNDK directory doesn't contain extra files."""
+ if not vndk_utils.IsVndkRuntimeEnforced(self._dut):
+ logging.info("Skip the test as VNDK runtime is not enforced on "
+ "the device.")
+ return
+ self._TestVndkDirectory(
+ vndk_utils.GetVndkDirectory(bitness, self._vndk_version),
+ (vndk_data.VNDK, vndk_data.VNDK_PRIVATE, vndk_data.VNDK_SP,
+ vndk_data.VNDK_SP_PRIVATE,))
+
+ def testVndkCoreDirectory32(self):
+ """Runs _TestVndkCoreDirectory for 32-bit libraries."""
+ self._TestVndkCoreDirectory(32)
+
+ def testVndkCoreDirectory64(self):
+ """Runs _TestVndkCoreDirectory for 64-bit libraries."""
+ if self._dut.GetCpuAbiList(64):
+ self._TestVndkCoreDirectory(64)
+ else:
+ logging.info("Skip the test as the device doesn't support 64-bit "
+ "ABI.")
+
+ def _TestNoLlndkInVendor(self, bitness):
+ """Verifies that vendor partition has no LL-NDK libraries."""
+ self._TestNotInVndkDirecotory(
+ vndk_utils.FormatVndkPath(self._TARGET_VENDOR_LIB, bitness),
+ (vndk_data.LL_NDK,),
+ self._LL_NDK_COLLIDING_NAMES)
+
+ def testNoLlndkInVendor32(self):
+ """Runs _TestNoLlndkInVendor for 32-bit libraries."""
+ self._TestNoLlndkInVendor(32)
+
+ def testNoLlndkInVendor64(self):
+ """Runs _TestNoLlndkInVendor for 64-bit libraries."""
+ if self._dut.GetCpuAbiList(64):
+ self._TestNoLlndkInVendor(64)
+ else:
+ logging.info("Skip the test as the device doesn't support 64-bit "
+ "ABI.")
+
+ def _TestNoLlndkInOdm(self, bitness):
+ """Verifies that odm partition has no LL-NDK libraries."""
+ self._TestNotInVndkDirecotory(
+ vndk_utils.FormatVndkPath(self._TARGET_ODM_LIB, bitness),
+ (vndk_data.LL_NDK,),
+ self._LL_NDK_COLLIDING_NAMES)
+
+ def testNoLlndkInOdm32(self):
+ """Runs _TestNoLlndkInOdm for 32-bit libraries."""
+ self._TestNoLlndkInOdm(32)
+
+ def testNoLlndkInOdm64(self):
+ """Runs _TestNoLlndkInOdm for 64-bit libraries."""
+ if self._dut.GetCpuAbiList(64):
+ self._TestNoLlndkInOdm(64)
+ else:
+ logging.info("Skip the test as the device doesn't support 64-bit "
+ "ABI.")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/files/vts_vndk_files_test.xml b/files/vts_vndk_files_test.xml
new file mode 100644
index 0000000..4813916
--- /dev/null
+++ b/files/vts_vndk_files_test.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for vts_vndk_files_test">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+ <option name="test-suite-tag" value="vts-core" />
+ <test class="com.android.tradefed.testtype.python.PythonBinaryHostTest">
+ <option name="par-file-name" value="vts_vndk_files_test" />
+ <option name="test-timeout" value="2m" />
+ </test>
+</configuration>
+
diff --git a/utils.py b/utils.py
index 45a5951..0592bfa 100644
--- a/utils.py
+++ b/utils.py
@@ -156,6 +156,10 @@ class AndroidDevice(object):
(args, out, err))
return return_code == 0
+ def Exists(self, path):
+ """Returns whether a path on the device exists."""
+ return self._Test("-e", path)
+
def IsDirectory(self, path):
"""Returns whether a path on the device is a directory."""
return self._Test("-d", path)
@@ -172,3 +176,28 @@ class AndroidDevice(object):
def IsExecutable(self, path):
"""Returns if execute permission is granted to a path on the device."""
return "x" in self._Stat("%A", path)
+
+ def FindFiles(self, path, name_pattern, *options):
+ """Executes find command.
+
+ Args:
+ path: A string, the path on the device.
+ name_pattern: A string, the pattern of the file name.
+ options: Strings, extra options passed to the command.
+
+ Returns:
+ A list of strings, the paths to the found files.
+
+ Raises:
+ ValueError if the pattern contains quotes.
+ IOError if the path does not exist.
+ """
+ if '"' in name_pattern or "'" in name_pattern:
+ raise ValueError("File name pattern contains quotes.")
+ out, err, return_code = self._ExecuteCommand("find", path, "-name",
+ "'" + name_pattern + "'",
+ *options)
+ if return_code != 0 or err.strip():
+ raise IOError("`find %s -name '%s' %s` stdout: %s\nstderr: %s" %
+ (path, name_pattern, " ".join(options), out, err))
+ return out.strip().split("\n")