1# 2# Copyright (C) 2019 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the 'License'); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an 'AS IS' BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17import os.path 18import shutil 19 20import common 21import test_utils 22from check_target_files_vintf import CheckVintf 23 24# A skeleton target files directory structure. This is VINTF compatible. 25SKELETON_TARGET_FILE_STRUCTURE = { 26 # Empty files 27 'PRODUCT/build.prop': '', 28 'PRODUCT/etc/build.prop': '', 29 'VENDOR/etc/build.prop': '', 30 'ODM/build.prop': '', 31 'ODM/etc/build.prop': '', 32 'RECOVERY/RAMDISK/etc/recovery.fstab': '', 33 'SYSTEM/build.prop': '', 34 'SYSTEM/etc/build.prop': '', 35 'SYSTEM_EXT/build.prop': '', 36 'SYSTEM_EXT/etc/build.prop': '', 37 38 # Non-empty files 39 'SYSTEM/etc/vintf/compatibility_matrix.1.xml':""" 40 <compatibility-matrix version="1.0" level="1" type="framework"> 41 <sepolicy> 42 <sepolicy-version>0.0</sepolicy-version> 43 <kernel-sepolicy-version>0</kernel-sepolicy-version> 44 </sepolicy> 45 </compatibility-matrix>""", 46 'SYSTEM/manifest.xml': 47 '<manifest version="1.0" type="framework"/>', 48 'VENDOR/build.prop': 'ro.product.first_api_level=29\n', 49 'VENDOR/compatibility_matrix.xml': 50 '<compatibility-matrix version="1.0" type="device" />', 51 'VENDOR/etc/vintf/manifest.xml': 52 '<manifest version="1.0" target-level="1" type="device"/>', 53 'META/misc_info.txt': 54 'recovery_api_version=3\nfstab_version=2\nvintf_enforce=true\n', 55} 56 57 58def write_string_to_file(content, path, mode='w'): 59 if not os.path.isdir(os.path.dirname(path)): 60 os.makedirs(os.path.dirname(path)) 61 with open(path, mode=mode) as f: 62 f.write(content) 63 64 65class CheckTargetFilesVintfTest(test_utils.ReleaseToolsTestCase): 66 67 def setUp(self): 68 self.testdata_dir = test_utils.get_testdata_dir() 69 70 def prepare_test_dir(self, test_delta_rel_path): 71 test_delta_dir = os.path.join(self.testdata_dir, test_delta_rel_path) 72 test_dir = common.MakeTempDir(prefix='check_target_files_vintf') 73 74 # Create a skeleton directory structure of target files 75 for rel_path, content in SKELETON_TARGET_FILE_STRUCTURE.items(): 76 write_string_to_file(content, os.path.join(test_dir, rel_path)) 77 78 # Overwrite with files from test_delta_rel_path 79 for root, _, files in os.walk(test_delta_dir): 80 rel_root = os.path.relpath(root, test_delta_dir) 81 for f in files: 82 if not f.endswith('.xml'): 83 continue 84 output_file = os.path.join(test_dir, rel_root, f) 85 with open(os.path.join(root, f)) as inp: 86 write_string_to_file(inp.read(), output_file) 87 88 return test_dir 89 90 # Prepare test dir with required HAL for APEX testing 91 def prepare_apex_test_dir(self, test_delta_rel_path): 92 test_dir = self.prepare_test_dir(test_delta_rel_path) 93 write_string_to_file( 94 """<compatibility-matrix version="1.0" level="1" type="framework"> 95 <hal format="aidl" optional="false" updatable-via-apex="true"> 96 <name>android.apex.foo</name> 97 <version>1</version> 98 <interface> 99 <name>IApex</name> 100 <instance>default</instance> 101 </interface> 102 </hal> 103 <sepolicy> 104 <sepolicy-version>0.0</sepolicy-version> 105 <kernel-sepolicy-version>0</kernel-sepolicy-version> 106 </sepolicy> 107 </compatibility-matrix>""", 108 os.path.join(test_dir, 'SYSTEM/etc/vintf/compatibility_matrix.1.xml')) 109 110 return test_dir 111 112 @test_utils.SkipIfExternalToolsUnavailable() 113 def test_CheckVintf_skeleton(self): 114 msg = 'vintf check with skeleton target files failed.' 115 test_dir = self.prepare_test_dir('does-not-exist') 116 self.assertTrue(CheckVintf(test_dir), msg=msg) 117 118 @test_utils.SkipIfExternalToolsUnavailable() 119 def test_CheckVintf_matrix_incompat(self): 120 msg = 'vintf/matrix_incompat should be incompatible because sepolicy ' \ 121 'version fails to match' 122 test_dir = self.prepare_test_dir('vintf/matrix_incompat') 123 self.assertFalse(CheckVintf(test_dir), msg=msg) 124 125 @test_utils.SkipIfExternalToolsUnavailable() 126 def test_CheckVintf_kernel_compat(self): 127 msg = 'vintf/kernel with 4.14.1 kernel version should be compatible' 128 test_dir = self.prepare_test_dir('vintf/kernel') 129 write_string_to_file('', os.path.join(test_dir, 'META/kernel_configs.txt')) 130 write_string_to_file('4.14.1', 131 os.path.join(test_dir, 'META/kernel_version.txt')) 132 self.assertTrue(CheckVintf(test_dir), msg=msg) 133 134 @test_utils.SkipIfExternalToolsUnavailable() 135 def test_CheckVintf_kernel_incompat(self): 136 msg = 'vintf/kernel with 4.14.0 kernel version should be incompatible ' \ 137 'because 4.14.1 kernel version is required' 138 test_dir = self.prepare_test_dir('vintf/kernel') 139 write_string_to_file('', os.path.join(test_dir, 'META/kernel_configs.txt')) 140 write_string_to_file('4.14.0', 141 os.path.join(test_dir, 'META/kernel_version.txt')) 142 self.assertFalse(CheckVintf(test_dir), msg=msg) 143 144 @test_utils.SkipIfExternalToolsUnavailable() 145 def test_CheckVintf_sku_compat(self): 146 msg = 'vintf/sku_compat should be compatible because ' \ 147 'ODM/etc/vintf/manifest_sku.xml has the required HALs' 148 test_dir = self.prepare_test_dir('vintf/sku_compat') 149 write_string_to_file('vintf_odm_manifest_skus=sku', 150 os.path.join(test_dir, 'META/misc_info.txt'), mode='a') 151 self.assertTrue(CheckVintf(test_dir), msg=msg) 152 153 @test_utils.SkipIfExternalToolsUnavailable() 154 def test_CheckVintf_sku_incompat(self): 155 msg = 'vintf/sku_compat should be compatible because ' \ 156 'ODM/etc/vintf/manifest_sku.xml does not have the required HALs' 157 test_dir = self.prepare_test_dir('vintf/sku_incompat') 158 write_string_to_file('vintf_odm_manifest_skus=sku', 159 os.path.join(test_dir, 'META/misc_info.txt'), mode='a') 160 self.assertFalse(CheckVintf(test_dir), msg=msg) 161 162 @test_utils.SkipIfExternalToolsUnavailable() 163 def test_CheckVintf_bad_xml(self): 164 test_dir = self.prepare_test_dir('does-not-exist') 165 write_string_to_file('not an XML', 166 os.path.join(test_dir, 'VENDOR/etc/vintf/manifest.xml')) 167 # Should raise an error because a file has invalid format. 168 self.assertRaises(common.ExternalError, CheckVintf, test_dir) 169 170 @test_utils.SkipIfExternalToolsUnavailable() 171 def test_CheckVintf_apex_compat(self): 172 apex_file_name = 'com.android.apex.vendor.foo.with_vintf.apex' 173 msg = 'vintf/apex_compat should be compatible because ' \ 174 'APEX %s has the required HALs' % (apex_file_name) 175 test_dir = self.prepare_apex_test_dir('vintf/apex_compat') 176 # Copy APEX under VENDOR/apex 177 apex_file = os.path.join(test_utils.get_current_dir(), apex_file_name) 178 apex_dir = os.path.join(test_dir, 'VENDOR/apex') 179 os.makedirs(apex_dir) 180 shutil.copy(apex_file, apex_dir) 181 # Should find required HAL via APEX 182 self.assertTrue(CheckVintf(test_dir), msg=msg) 183 184 @test_utils.SkipIfExternalToolsUnavailable() 185 def test_CheckVintf_apex_incompat(self): 186 msg = 'vintf/apex_incompat should be incompatible because ' \ 187 'no APEX data' 188 test_dir = self.prepare_apex_test_dir('vintf/apex_incompat') 189 # Should not find required HAL 190 self.assertFalse(CheckVintf(test_dir), msg=msg) 191