1# 2# Copyright (C) 2017 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 18 19import common 20import merge_target_files 21import merge_utils 22import test_utils 23 24 25class MergeUtilsTest(test_utils.ReleaseToolsTestCase): 26 27 def setUp(self): 28 self.OPTIONS = merge_target_files.OPTIONS 29 30 def test_CopyItems_CopiesItemsMatchingPatterns(self): 31 32 def createEmptyFile(path): 33 if not os.path.exists(os.path.dirname(path)): 34 os.makedirs(os.path.dirname(path)) 35 open(path, 'a').close() 36 return path 37 38 def createEmptyFolder(path): 39 os.makedirs(path) 40 return path 41 42 def createSymLink(source, dest): 43 os.symlink(source, dest) 44 return dest 45 46 def getRelPaths(start, filepaths): 47 return set( 48 os.path.relpath(path=filepath, start=start) 49 for filepath in filepaths) 50 51 input_dir = common.MakeTempDir() 52 output_dir = common.MakeTempDir() 53 expected_copied_items = [] 54 actual_copied_items = [] 55 patterns = ['*.cpp', 'subdir/*.txt', 'subdir/empty_dir'] 56 57 # Create various files and empty directories that we expect to get copied 58 # because they match one of the patterns. 59 expected_copied_items.extend([ 60 createEmptyFile(os.path.join(input_dir, 'a.cpp')), 61 createEmptyFile(os.path.join(input_dir, 'b.cpp')), 62 createEmptyFile(os.path.join(input_dir, 'subdir', 'c.txt')), 63 createEmptyFile(os.path.join(input_dir, 'subdir', 'd.txt')), 64 createEmptyFile( 65 os.path.join(input_dir, 'subdir', 'subsubdir', 'e.txt')), 66 createEmptyFolder(os.path.join(input_dir, 'subdir', 'empty_dir')), 67 createSymLink('a.cpp', os.path.join(input_dir, 'a_link.cpp')), 68 ]) 69 # Create some more files that we expect to not get copied. 70 createEmptyFile(os.path.join(input_dir, 'a.h')) 71 createEmptyFile(os.path.join(input_dir, 'b.h')) 72 createEmptyFile(os.path.join(input_dir, 'subdir', 'subsubdir', 'f.gif')) 73 createSymLink('a.h', os.path.join(input_dir, 'a_link.h')) 74 75 # Copy items. 76 merge_utils.CopyItems(input_dir, output_dir, patterns) 77 78 # Assert the actual copied items match the ones we expected. 79 for root_dir, dirs, files in os.walk(output_dir): 80 actual_copied_items.extend( 81 os.path.join(root_dir, filename) for filename in files) 82 for dirname in dirs: 83 dir_path = os.path.join(root_dir, dirname) 84 if not os.listdir(dir_path): 85 actual_copied_items.append(dir_path) 86 self.assertEqual( 87 getRelPaths(output_dir, actual_copied_items), 88 getRelPaths(input_dir, expected_copied_items)) 89 self.assertEqual( 90 os.readlink(os.path.join(output_dir, 'a_link.cpp')), 'a.cpp') 91 92 def test_ValidateConfigLists_ReturnsFalseIfSharedExtractedPartition(self): 93 self.OPTIONS.system_item_list = [ 94 'SYSTEM/*', 95 ] 96 self.OPTIONS.vendor_item_list = [ 97 'SYSTEM/my_system_file', 98 'VENDOR/*', 99 ] 100 self.OPTIONS.vendor_item_list.append('SYSTEM/my_system_file') 101 self.assertFalse(merge_utils.ValidateConfigLists()) 102 103 def test_ValidateConfigLists_ReturnsFalseIfSharedExtractedPartitionImage( 104 self): 105 self.OPTIONS.system_item_list = [ 106 'SYSTEM/*', 107 ] 108 self.OPTIONS.vendor_item_list = [ 109 'IMAGES/system.img', 110 'VENDOR/*', 111 ] 112 self.assertFalse(merge_utils.ValidateConfigLists()) 113 114 def test_ValidateConfigLists_ReturnsFalseIfBadSystemMiscInfoKeys(self): 115 for bad_key in ['dynamic_partition_list', 'super_partition_groups']: 116 self.OPTIONS.framework_misc_info_keys = [bad_key] 117 self.assertFalse(merge_utils.ValidateConfigLists()) 118 119 def test_ItemListToPartitionSet(self): 120 item_list = [ 121 'IMAGES/system_ext.img', 122 'META/apexkeys.txt', 123 'META/apkcerts.txt', 124 'META/filesystem_config.txt', 125 'PRODUCT/*', 126 'SYSTEM/*', 127 'SYSTEM/system_ext/*', 128 ] 129 partition_set = merge_utils.ItemListToPartitionSet(item_list) 130 self.assertEqual(set(['product', 'system', 'system_ext']), partition_set) 131 132 def test_InferItemList_Framework(self): 133 zip_namelist = [ 134 'IMAGES/product.img', 135 'IMAGES/product.map', 136 'IMAGES/system.img', 137 'IMAGES/system.map', 138 'SYSTEM/my_system_file', 139 'PRODUCT/my_product_file', 140 # Device does not use a separate system_ext partition. 141 'SYSTEM/system_ext/system_ext_file', 142 ] 143 144 item_list = merge_utils.InferItemList(zip_namelist, framework=True) 145 146 expected_framework_item_list = [ 147 'IMAGES/product.img', 148 'IMAGES/product.map', 149 'IMAGES/system.img', 150 'IMAGES/system.map', 151 'META/filesystem_config.txt', 152 'META/liblz4.so', 153 'META/postinstall_config.txt', 154 'META/product_filesystem_config.txt', 155 'META/zucchini_config.txt', 156 'PRODUCT/*', 157 'SYSTEM/*', 158 ] 159 160 self.assertEqual(item_list, expected_framework_item_list) 161 162 def test_InferItemList_Vendor(self): 163 zip_namelist = [ 164 'VENDOR/my_vendor_file', 165 'ODM/my_odm_file', 166 'IMAGES/odm.img', 167 'IMAGES/odm.map', 168 'IMAGES/vendor.img', 169 'IMAGES/vendor.map', 170 'IMAGES/my_custom_image.img', 171 'IMAGES/my_custom_file.txt', 172 'IMAGES/vbmeta.img', 173 'CUSTOM_PARTITION/my_custom_file', 174 # Leftover framework pieces that shouldn't be grabbed. 175 'IMAGES/system.img', 176 'SYSTEM/system_file', 177 ] 178 179 item_list = merge_utils.InferItemList(zip_namelist, framework=False) 180 181 expected_vendor_item_list = [ 182 'CUSTOM_PARTITION/*', 183 'IMAGES/my_custom_file.txt', 184 'IMAGES/my_custom_image.img', 185 'IMAGES/odm.img', 186 'IMAGES/odm.map', 187 'IMAGES/vendor.img', 188 'IMAGES/vendor.map', 189 'META/custom_partition_filesystem_config.txt', 190 'META/kernel_configs.txt', 191 'META/kernel_version.txt', 192 'META/odm_filesystem_config.txt', 193 'META/otakeys.txt', 194 'META/pack_radioimages.txt', 195 'META/releasetools.py', 196 'META/vendor_filesystem_config.txt', 197 'ODM/*', 198 'VENDOR/*', 199 ] 200 self.assertEqual(item_list, expected_vendor_item_list) 201 202 def test_InferFrameworkMiscInfoKeys(self): 203 zip_namelist = [ 204 'PRODUCT/', 205 'SYSTEM/', 206 'SYSTEM/system_ext/', 207 ] 208 209 keys = merge_utils.InferFrameworkMiscInfoKeys(zip_namelist) 210 211 expected_keys = [ 212 'ab_update', 213 'avb_product_add_hashtree_footer_args', 214 'avb_product_hashtree_enable', 215 'avb_system_add_hashtree_footer_args', 216 'avb_system_ext_add_hashtree_footer_args', 217 'avb_system_ext_hashtree_enable', 218 'avb_system_hashtree_enable', 219 'avb_vbmeta_system', 220 'avb_vbmeta_system_algorithm', 221 'avb_vbmeta_system_key_path', 222 'avb_vbmeta_system_rollback_index_location', 223 'building_product_image', 224 'building_system_ext_image', 225 'building_system_image', 226 'default_system_dev_certificate', 227 'fs_type', 228 'product_disable_sparse', 229 'product_fs_type', 230 'system_disable_sparse', 231 'system_ext_disable_sparse', 232 'system_ext_fs_type', 233 ] 234 self.assertEqual(keys, expected_keys) 235