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 test_utils
21from merge_target_files import (validate_config_lists,
22                                DEFAULT_FRAMEWORK_ITEM_LIST,
23                                DEFAULT_VENDOR_ITEM_LIST,
24                                DEFAULT_FRAMEWORK_MISC_INFO_KEYS, copy_items,
25                                item_list_to_partition_set,
26                                process_apex_keys_apk_certs_common)
27
28
29class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase):
30
31  def setUp(self):
32    self.testdata_dir = test_utils.get_testdata_dir()
33
34  def test_copy_items_CopiesItemsMatchingPatterns(self):
35
36    def createEmptyFile(path):
37      if not os.path.exists(os.path.dirname(path)):
38        os.makedirs(os.path.dirname(path))
39      open(path, 'a').close()
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) for filepath in filepaths)
49
50    input_dir = common.MakeTempDir()
51    output_dir = common.MakeTempDir()
52    expected_copied_items = []
53    actual_copied_items = []
54    patterns = ['*.cpp', 'subdir/*.txt']
55
56    # Create various files that we expect to get copied because they
57    # match one of the patterns.
58    expected_copied_items.extend([
59        createEmptyFile(os.path.join(input_dir, 'a.cpp')),
60        createEmptyFile(os.path.join(input_dir, 'b.cpp')),
61        createEmptyFile(os.path.join(input_dir, 'subdir', 'c.txt')),
62        createEmptyFile(os.path.join(input_dir, 'subdir', 'd.txt')),
63        createEmptyFile(
64            os.path.join(input_dir, 'subdir', 'subsubdir', 'e.txt')),
65        createSymLink('a.cpp', os.path.join(input_dir, 'a_link.cpp')),
66    ])
67    # Create some more files that we expect to not get copied.
68    createEmptyFile(os.path.join(input_dir, 'a.h'))
69    createEmptyFile(os.path.join(input_dir, 'b.h'))
70    createEmptyFile(os.path.join(input_dir, 'subdir', 'subsubdir', 'f.gif'))
71    createSymLink('a.h', os.path.join(input_dir, 'a_link.h'))
72
73    # Copy items.
74    copy_items(input_dir, output_dir, patterns)
75
76    # Assert the actual copied items match the ones we expected.
77    for dirpath, _, filenames in os.walk(output_dir):
78      actual_copied_items.extend(
79          os.path.join(dirpath, filename) for filename in filenames)
80    self.assertEqual(
81        getRelPaths(output_dir, actual_copied_items),
82        getRelPaths(input_dir, expected_copied_items))
83    self.assertEqual(
84        os.readlink(os.path.join(output_dir, 'a_link.cpp')), 'a.cpp')
85
86  def test_validate_config_lists_ReturnsFalseIfMissingDefaultItem(self):
87    framework_item_list = list(DEFAULT_FRAMEWORK_ITEM_LIST)
88    framework_item_list.remove('SYSTEM/*')
89    self.assertFalse(
90        validate_config_lists(framework_item_list,
91                              DEFAULT_FRAMEWORK_MISC_INFO_KEYS,
92                              DEFAULT_VENDOR_ITEM_LIST))
93
94  def test_validate_config_lists_ReturnsTrueIfDefaultItemInDifferentList(self):
95    framework_item_list = list(DEFAULT_FRAMEWORK_ITEM_LIST)
96    framework_item_list.remove('ROOT/*')
97    vendor_item_list = list(DEFAULT_VENDOR_ITEM_LIST)
98    vendor_item_list.append('ROOT/*')
99    self.assertTrue(
100        validate_config_lists(framework_item_list,
101                              DEFAULT_FRAMEWORK_MISC_INFO_KEYS,
102                              vendor_item_list))
103
104  def test_validate_config_lists_ReturnsTrueIfExtraItem(self):
105    framework_item_list = list(DEFAULT_FRAMEWORK_ITEM_LIST)
106    framework_item_list.append('MY_NEW_PARTITION/*')
107    self.assertTrue(
108        validate_config_lists(framework_item_list,
109                              DEFAULT_FRAMEWORK_MISC_INFO_KEYS,
110                              DEFAULT_VENDOR_ITEM_LIST))
111
112  def test_validate_config_lists_ReturnsFalseIfSharedExtractedPartition(self):
113    vendor_item_list = list(DEFAULT_VENDOR_ITEM_LIST)
114    vendor_item_list.append('SYSTEM/my_system_file')
115    self.assertFalse(
116        validate_config_lists(DEFAULT_FRAMEWORK_ITEM_LIST,
117                              DEFAULT_FRAMEWORK_MISC_INFO_KEYS,
118                              vendor_item_list))
119
120  def test_validate_config_lists_ReturnsFalseIfBadSystemMiscInfoKeys(self):
121    for bad_key in ['dynamic_partition_list', 'super_partition_groups']:
122      framework_misc_info_keys = list(DEFAULT_FRAMEWORK_MISC_INFO_KEYS)
123      framework_misc_info_keys.append(bad_key)
124      self.assertFalse(
125          validate_config_lists(DEFAULT_FRAMEWORK_ITEM_LIST,
126                                framework_misc_info_keys,
127                                DEFAULT_VENDOR_ITEM_LIST))
128
129  def test_process_apex_keys_apk_certs_ReturnsTrueIfNoConflicts(self):
130    output_dir = common.MakeTempDir()
131    os.makedirs(os.path.join(output_dir, 'META'))
132
133    framework_dir = common.MakeTempDir()
134    os.makedirs(os.path.join(framework_dir, 'META'))
135    os.symlink(
136        os.path.join(self.testdata_dir, 'apexkeys_framework.txt'),
137        os.path.join(framework_dir, 'META', 'apexkeys.txt'))
138
139    vendor_dir = common.MakeTempDir()
140    os.makedirs(os.path.join(vendor_dir, 'META'))
141    os.symlink(
142        os.path.join(self.testdata_dir, 'apexkeys_vendor.txt'),
143        os.path.join(vendor_dir, 'META', 'apexkeys.txt'))
144
145    process_apex_keys_apk_certs_common(framework_dir, vendor_dir, output_dir,
146                                       set(['product', 'system', 'system_ext']),
147                                       set(['odm', 'vendor']),
148                                       'apexkeys.txt')
149
150    merged_entries = []
151    merged_path = os.path.join(self.testdata_dir, 'apexkeys_merge.txt')
152
153    with open(merged_path) as f:
154      merged_entries = f.read().split('\n')
155
156    output_entries = []
157    output_path = os.path.join(output_dir, 'META', 'apexkeys.txt')
158
159    with open(output_path) as f:
160      output_entries = f.read().split('\n')
161
162    return self.assertEqual(merged_entries, output_entries)
163
164  def test_process_apex_keys_apk_certs_ReturnsFalseIfConflictsPresent(self):
165    output_dir = common.MakeTempDir()
166    os.makedirs(os.path.join(output_dir, 'META'))
167
168    framework_dir = common.MakeTempDir()
169    os.makedirs(os.path.join(framework_dir, 'META'))
170    os.symlink(
171        os.path.join(self.testdata_dir, 'apexkeys_framework.txt'),
172        os.path.join(framework_dir, 'META', 'apexkeys.txt'))
173
174    conflict_dir = common.MakeTempDir()
175    os.makedirs(os.path.join(conflict_dir, 'META'))
176    os.symlink(
177        os.path.join(self.testdata_dir, 'apexkeys_framework_conflict.txt'),
178        os.path.join(conflict_dir, 'META', 'apexkeys.txt'))
179
180    self.assertRaises(ValueError, process_apex_keys_apk_certs_common,
181                      framework_dir, conflict_dir, output_dir,
182                      set(['product', 'system', 'system_ext']),
183                      set(['odm', 'vendor']),
184                      'apexkeys.txt')
185
186  def test_process_apex_keys_apk_certs_HandlesApkCertsSyntax(self):
187    output_dir = common.MakeTempDir()
188    os.makedirs(os.path.join(output_dir, 'META'))
189
190    framework_dir = common.MakeTempDir()
191    os.makedirs(os.path.join(framework_dir, 'META'))
192    os.symlink(
193        os.path.join(self.testdata_dir, 'apkcerts_framework.txt'),
194        os.path.join(framework_dir, 'META', 'apkcerts.txt'))
195
196    vendor_dir = common.MakeTempDir()
197    os.makedirs(os.path.join(vendor_dir, 'META'))
198    os.symlink(
199        os.path.join(self.testdata_dir, 'apkcerts_vendor.txt'),
200        os.path.join(vendor_dir, 'META', 'apkcerts.txt'))
201
202    process_apex_keys_apk_certs_common(framework_dir, vendor_dir, output_dir,
203                                       set(['product', 'system', 'system_ext']),
204                                       set(['odm', 'vendor']),
205                                       'apkcerts.txt')
206
207    merged_entries = []
208    merged_path = os.path.join(self.testdata_dir, 'apkcerts_merge.txt')
209
210    with open(merged_path) as f:
211      merged_entries = f.read().split('\n')
212
213    output_entries = []
214    output_path = os.path.join(output_dir, 'META', 'apkcerts.txt')
215
216    with open(output_path) as f:
217      output_entries = f.read().split('\n')
218
219    return self.assertEqual(merged_entries, output_entries)
220
221  def test_item_list_to_partition_set(self):
222    item_list = [
223        'META/apexkeys.txt',
224        'META/apkcerts.txt',
225        'META/filesystem_config.txt',
226        'PRODUCT/*',
227        'SYSTEM/*',
228        'SYSTEM_EXT/*',
229    ]
230    partition_set = item_list_to_partition_set(item_list)
231    self.assertEqual(set(['product', 'system', 'system_ext']), partition_set)
232