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