xref: /aosp_15_r20/tools/treble/split/manifest_split_test.py (revision 105f628577ac4ba0e277a494fbb614ed8c12a994)
1*105f6285SAndroid Build Coastguard Worker# Copyright (C) 2020 The Android Open Source Project
2*105f6285SAndroid Build Coastguard Worker#
3*105f6285SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*105f6285SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*105f6285SAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*105f6285SAndroid Build Coastguard Worker#
7*105f6285SAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
8*105f6285SAndroid Build Coastguard Worker#
9*105f6285SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*105f6285SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*105f6285SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*105f6285SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*105f6285SAndroid Build Coastguard Worker# limitations under the License.
14*105f6285SAndroid Build Coastguard Worker"""Test manifest split."""
15*105f6285SAndroid Build Coastguard Worker
16*105f6285SAndroid Build Coastguard Workerimport json
17*105f6285SAndroid Build Coastguard Workerimport os
18*105f6285SAndroid Build Coastguard Workerimport re
19*105f6285SAndroid Build Coastguard Workerimport subprocess
20*105f6285SAndroid Build Coastguard Workerimport tempfile
21*105f6285SAndroid Build Coastguard Workerimport unittest
22*105f6285SAndroid Build Coastguard Workerimport unittest.mock
23*105f6285SAndroid Build Coastguard Workerimport xml.etree.ElementTree as ET
24*105f6285SAndroid Build Coastguard Worker
25*105f6285SAndroid Build Coastguard Workerfrom treble.split import manifest_split
26*105f6285SAndroid Build Coastguard Worker
27*105f6285SAndroid Build Coastguard Worker
28*105f6285SAndroid Build Coastguard Workerclass ManifestSplitTest(unittest.TestCase):
29*105f6285SAndroid Build Coastguard Worker
30*105f6285SAndroid Build Coastguard Worker  def test_read_config(self):
31*105f6285SAndroid Build Coastguard Worker    with tempfile.NamedTemporaryFile('w+t') as test_config:
32*105f6285SAndroid Build Coastguard Worker      test_config.write("""
33*105f6285SAndroid Build Coastguard Worker        <config>
34*105f6285SAndroid Build Coastguard Worker          <add_project name="add1" />
35*105f6285SAndroid Build Coastguard Worker          <add_project name="add2" />
36*105f6285SAndroid Build Coastguard Worker          <remove_project name="remove1" />
37*105f6285SAndroid Build Coastguard Worker          <remove_project name="remove2" />
38*105f6285SAndroid Build Coastguard Worker          <path_mapping pattern="p1.*" sub="$0" />
39*105f6285SAndroid Build Coastguard Worker        </config>""")
40*105f6285SAndroid Build Coastguard Worker      test_config.flush()
41*105f6285SAndroid Build Coastguard Worker      config = manifest_split.ManifestSplitConfig.from_config_files(
42*105f6285SAndroid Build Coastguard Worker          [test_config.name])
43*105f6285SAndroid Build Coastguard Worker      self.assertEqual(config.remove_projects, {
44*105f6285SAndroid Build Coastguard Worker          'remove1': test_config.name,
45*105f6285SAndroid Build Coastguard Worker          'remove2': test_config.name
46*105f6285SAndroid Build Coastguard Worker      })
47*105f6285SAndroid Build Coastguard Worker      self.assertEqual(config.add_projects, {
48*105f6285SAndroid Build Coastguard Worker          'add1': test_config.name,
49*105f6285SAndroid Build Coastguard Worker          'add2': test_config.name
50*105f6285SAndroid Build Coastguard Worker      })
51*105f6285SAndroid Build Coastguard Worker      self.assertEqual(config.path_mappings, [
52*105f6285SAndroid Build Coastguard Worker          manifest_split.PathMappingConfig(re.compile('p1.*'), '$0'),
53*105f6285SAndroid Build Coastguard Worker      ])
54*105f6285SAndroid Build Coastguard Worker
55*105f6285SAndroid Build Coastguard Worker  def test_get_repo_projects_from_manifest(self):
56*105f6285SAndroid Build Coastguard Worker    manifest_contents = """
57*105f6285SAndroid Build Coastguard Worker      <manifest>
58*105f6285SAndroid Build Coastguard Worker        <project name="platform/project1" path="system/project1" />
59*105f6285SAndroid Build Coastguard Worker        <project name="platform/project2" path="system/project2" />
60*105f6285SAndroid Build Coastguard Worker        <project name="platform/project3" path="system/project3" />
61*105f6285SAndroid Build Coastguard Worker      </manifest>"""
62*105f6285SAndroid Build Coastguard Worker    manifest = ET.ElementTree(ET.fromstring(manifest_contents))
63*105f6285SAndroid Build Coastguard Worker    projects = manifest_split.get_repo_projects(
64*105f6285SAndroid Build Coastguard Worker        None, manifest, path_mappings=[])
65*105f6285SAndroid Build Coastguard Worker    self.assertDictEqual(
66*105f6285SAndroid Build Coastguard Worker        {
67*105f6285SAndroid Build Coastguard Worker            'system/project1': 'platform/project1',
68*105f6285SAndroid Build Coastguard Worker            'system/project2': 'platform/project2',
69*105f6285SAndroid Build Coastguard Worker            'system/project3': 'platform/project3',
70*105f6285SAndroid Build Coastguard Worker        }, projects)
71*105f6285SAndroid Build Coastguard Worker
72*105f6285SAndroid Build Coastguard Worker
73*105f6285SAndroid Build Coastguard Worker  def test_get_repo_projects(self):
74*105f6285SAndroid Build Coastguard Worker    with tempfile.NamedTemporaryFile('w+t') as repo_list_file:
75*105f6285SAndroid Build Coastguard Worker      repo_list_file.write("""
76*105f6285SAndroid Build Coastguard Worker        system/project1 : platform/project1
77*105f6285SAndroid Build Coastguard Worker        system/project2 : platform/project2""")
78*105f6285SAndroid Build Coastguard Worker      repo_list_file.flush()
79*105f6285SAndroid Build Coastguard Worker      repo_projects = manifest_split.get_repo_projects(
80*105f6285SAndroid Build Coastguard Worker          repo_list_file.name, None, path_mappings=[])
81*105f6285SAndroid Build Coastguard Worker      self.assertEqual(
82*105f6285SAndroid Build Coastguard Worker          repo_projects, {
83*105f6285SAndroid Build Coastguard Worker              'system/project1': 'platform/project1',
84*105f6285SAndroid Build Coastguard Worker              'system/project2': 'platform/project2',
85*105f6285SAndroid Build Coastguard Worker          })
86*105f6285SAndroid Build Coastguard Worker
87*105f6285SAndroid Build Coastguard Worker  def test_get_repo_projects_with_mappings(self):
88*105f6285SAndroid Build Coastguard Worker    with tempfile.NamedTemporaryFile('w+t') as repo_list_file:
89*105f6285SAndroid Build Coastguard Worker      repo_list_file.write("""
90*105f6285SAndroid Build Coastguard Worker        overlay/system/project1 : platform/project1
91*105f6285SAndroid Build Coastguard Worker        system/project2 : platform/project2
92*105f6285SAndroid Build Coastguard Worker        hide/this/one : platform/project3""")
93*105f6285SAndroid Build Coastguard Worker      repo_list_file.flush()
94*105f6285SAndroid Build Coastguard Worker      path_mappings = [
95*105f6285SAndroid Build Coastguard Worker          manifest_split.PathMappingConfig(re.compile('^overlay/(.*)'), '\\1'),
96*105f6285SAndroid Build Coastguard Worker          manifest_split.PathMappingConfig(re.compile('^hide/this/one.*'), ''),
97*105f6285SAndroid Build Coastguard Worker      ]
98*105f6285SAndroid Build Coastguard Worker
99*105f6285SAndroid Build Coastguard Worker      repo_projects = manifest_split.get_repo_projects(repo_list_file.name,
100*105f6285SAndroid Build Coastguard Worker                                                       None,
101*105f6285SAndroid Build Coastguard Worker                                                       path_mappings)
102*105f6285SAndroid Build Coastguard Worker      self.assertEqual(
103*105f6285SAndroid Build Coastguard Worker          repo_projects, {
104*105f6285SAndroid Build Coastguard Worker              'system/project1': 'platform/project1',
105*105f6285SAndroid Build Coastguard Worker              'system/project2': 'platform/project2',
106*105f6285SAndroid Build Coastguard Worker          })
107*105f6285SAndroid Build Coastguard Worker
108*105f6285SAndroid Build Coastguard Worker  def test_get_module_info(self):
109*105f6285SAndroid Build Coastguard Worker    with tempfile.NamedTemporaryFile('w+t') as module_info_file:
110*105f6285SAndroid Build Coastguard Worker      module_info_file.write("""{
111*105f6285SAndroid Build Coastguard Worker        "target1a": { "class": ["EXECUTABLES"], "path": ["system/project1"], "dependencies": ["target2"] },
112*105f6285SAndroid Build Coastguard Worker        "target1b": { "class": ["EXECUTABLES"], "path": ["system/project1"], "dependencies": ["target3", "target42"] },
113*105f6285SAndroid Build Coastguard Worker        "target2": { "class": ["SHARED_LIBRARIES"], "path": ["out/project2"], "dependencies": [] },
114*105f6285SAndroid Build Coastguard Worker        "target3": { "class": ["SHARED_LIBRARIES"], "path": ["vendor/google/project3"], "dependencies": ["x", "y", "z"] },
115*105f6285SAndroid Build Coastguard Worker        "target4a": { "class": ["APPS"], "path": ["system/project4"], "dependencies": ["out/target/common/obj/JAVA_LIBRARIES/target4b_intermediates/classes-header.jar"] },
116*105f6285SAndroid Build Coastguard Worker        "target4b": { "class": ["JAVA_LIBRARIES"],  "path": ["system/project4"], "dependencies": [] }
117*105f6285SAndroid Build Coastguard Worker      }""")
118*105f6285SAndroid Build Coastguard Worker      module_info_file.flush()
119*105f6285SAndroid Build Coastguard Worker      repo_projects = {
120*105f6285SAndroid Build Coastguard Worker          'system/project1': 'platform/project1',
121*105f6285SAndroid Build Coastguard Worker          'system/project4': 'platform/project4',
122*105f6285SAndroid Build Coastguard Worker          'vendor/google/project3': 'vendor/project3',
123*105f6285SAndroid Build Coastguard Worker      }
124*105f6285SAndroid Build Coastguard Worker      ignore_paths = set(['out/'])
125*105f6285SAndroid Build Coastguard Worker      module_info = manifest_split.ModuleInfo(module_info_file.name,
126*105f6285SAndroid Build Coastguard Worker                                              repo_projects, ignore_paths)
127*105f6285SAndroid Build Coastguard Worker      self.assertEqual(
128*105f6285SAndroid Build Coastguard Worker          module_info.project_modules, {
129*105f6285SAndroid Build Coastguard Worker              'platform/project1': set(['target1a', 'target1b']),
130*105f6285SAndroid Build Coastguard Worker              'platform/project4': set(['target4a', 'target4b']),
131*105f6285SAndroid Build Coastguard Worker              'vendor/project3': set(['target3']),
132*105f6285SAndroid Build Coastguard Worker          })
133*105f6285SAndroid Build Coastguard Worker      self.assertEqual(
134*105f6285SAndroid Build Coastguard Worker          module_info.module_project, {
135*105f6285SAndroid Build Coastguard Worker              'target1a': 'platform/project1',
136*105f6285SAndroid Build Coastguard Worker              'target1b': 'platform/project1',
137*105f6285SAndroid Build Coastguard Worker              'target3': 'vendor/project3',
138*105f6285SAndroid Build Coastguard Worker              'target4a': 'platform/project4',
139*105f6285SAndroid Build Coastguard Worker              'target4b': 'platform/project4',
140*105f6285SAndroid Build Coastguard Worker          })
141*105f6285SAndroid Build Coastguard Worker      self.assertEqual(
142*105f6285SAndroid Build Coastguard Worker          module_info.module_class, {
143*105f6285SAndroid Build Coastguard Worker              'target1a': 'EXECUTABLES',
144*105f6285SAndroid Build Coastguard Worker              'target1b': 'EXECUTABLES',
145*105f6285SAndroid Build Coastguard Worker              'target2': 'SHARED_LIBRARIES',
146*105f6285SAndroid Build Coastguard Worker              'target3': 'SHARED_LIBRARIES',
147*105f6285SAndroid Build Coastguard Worker              'target4a': 'APPS',
148*105f6285SAndroid Build Coastguard Worker              'target4b': 'JAVA_LIBRARIES',
149*105f6285SAndroid Build Coastguard Worker          })
150*105f6285SAndroid Build Coastguard Worker      self.assertEqual(
151*105f6285SAndroid Build Coastguard Worker          module_info.module_deps, {
152*105f6285SAndroid Build Coastguard Worker              'target1a': ['target2'],
153*105f6285SAndroid Build Coastguard Worker              'target1b': ['target3', 'target42'],
154*105f6285SAndroid Build Coastguard Worker              'target2': [],
155*105f6285SAndroid Build Coastguard Worker              'target3': ['x', 'y', 'z'],
156*105f6285SAndroid Build Coastguard Worker              'target4a': ['target4b'],
157*105f6285SAndroid Build Coastguard Worker              'target4b': [],
158*105f6285SAndroid Build Coastguard Worker          })
159*105f6285SAndroid Build Coastguard Worker
160*105f6285SAndroid Build Coastguard Worker  def test_get_module_info_raises_on_unknown_module_path(self):
161*105f6285SAndroid Build Coastguard Worker    with tempfile.NamedTemporaryFile('w+t') as module_info_file:
162*105f6285SAndroid Build Coastguard Worker      module_info_file.write("""{
163*105f6285SAndroid Build Coastguard Worker        "target1": { "class": ["EXECUTABLES"], "path": ["system/unknown/project1"], "dependencies": [] }
164*105f6285SAndroid Build Coastguard Worker      }""")
165*105f6285SAndroid Build Coastguard Worker      module_info_file.flush()
166*105f6285SAndroid Build Coastguard Worker      repo_projects = {}
167*105f6285SAndroid Build Coastguard Worker      ignore_paths = set()
168*105f6285SAndroid Build Coastguard Worker      with self.assertRaisesRegex(ValueError,
169*105f6285SAndroid Build Coastguard Worker                                  'Unknown module path for module target1'):
170*105f6285SAndroid Build Coastguard Worker        manifest_split.ModuleInfo(module_info_file.name, repo_projects,
171*105f6285SAndroid Build Coastguard Worker                                  ignore_paths)
172*105f6285SAndroid Build Coastguard Worker
173*105f6285SAndroid Build Coastguard Worker  @unittest.mock.patch.object(subprocess, 'check_output', autospec=True)
174*105f6285SAndroid Build Coastguard Worker  def test_get_ninja_inputs(self, mock_check_output):
175*105f6285SAndroid Build Coastguard Worker    mock_check_output.return_value = b"""
176*105f6285SAndroid Build Coastguard Worker    path/to/input1
177*105f6285SAndroid Build Coastguard Worker    path/to/input2
178*105f6285SAndroid Build Coastguard Worker    path/to/TEST_MAPPING
179*105f6285SAndroid Build Coastguard Worker    path/to/MODULE_LICENSE_GPL
180*105f6285SAndroid Build Coastguard Worker    """
181*105f6285SAndroid Build Coastguard Worker
182*105f6285SAndroid Build Coastguard Worker    inputs = manifest_split.get_ninja_inputs('unused', 'unused', ['droid'])
183*105f6285SAndroid Build Coastguard Worker    self.assertEqual(inputs, {'path/to/input1', 'path/to/input2'})
184*105f6285SAndroid Build Coastguard Worker
185*105f6285SAndroid Build Coastguard Worker  @unittest.mock.patch.object(subprocess, 'check_output', autospec=True)
186*105f6285SAndroid Build Coastguard Worker  def test_get_ninja_inputs_includes_test_mapping(self, mock_check_output):
187*105f6285SAndroid Build Coastguard Worker    mock_check_output.return_value = b"""
188*105f6285SAndroid Build Coastguard Worker    path/to/input1
189*105f6285SAndroid Build Coastguard Worker    path/to/input2
190*105f6285SAndroid Build Coastguard Worker    path/to/TEST_MAPPING
191*105f6285SAndroid Build Coastguard Worker    """
192*105f6285SAndroid Build Coastguard Worker
193*105f6285SAndroid Build Coastguard Worker    inputs = manifest_split.get_ninja_inputs('unused', 'unused',
194*105f6285SAndroid Build Coastguard Worker                                             ['droid', 'test_mapping'])
195*105f6285SAndroid Build Coastguard Worker    self.assertEqual(
196*105f6285SAndroid Build Coastguard Worker        inputs, {'path/to/input1', 'path/to/input2', 'path/to/TEST_MAPPING'})
197*105f6285SAndroid Build Coastguard Worker
198*105f6285SAndroid Build Coastguard Worker  @unittest.mock.patch.object(subprocess, 'check_output', autospec=True)
199*105f6285SAndroid Build Coastguard Worker  def test_get_kati_makefiles(self, mock_check_output):
200*105f6285SAndroid Build Coastguard Worker    with tempfile.TemporaryDirectory() as temp_dir:
201*105f6285SAndroid Build Coastguard Worker      os.chdir(temp_dir)
202*105f6285SAndroid Build Coastguard Worker
203*105f6285SAndroid Build Coastguard Worker      makefiles = [
204*105f6285SAndroid Build Coastguard Worker          'device/oem1/product1.mk',
205*105f6285SAndroid Build Coastguard Worker          'device/oem2/product2.mk',
206*105f6285SAndroid Build Coastguard Worker          'device/google/google_product.mk',
207*105f6285SAndroid Build Coastguard Worker          'overlays/oem_overlay/device/oem3/product3.mk',
208*105f6285SAndroid Build Coastguard Worker          'packages/apps/Camera/Android.mk',
209*105f6285SAndroid Build Coastguard Worker      ]
210*105f6285SAndroid Build Coastguard Worker      for makefile in makefiles:
211*105f6285SAndroid Build Coastguard Worker        os.makedirs(os.path.dirname(makefile))
212*105f6285SAndroid Build Coastguard Worker        os.mknod(makefile)
213*105f6285SAndroid Build Coastguard Worker
214*105f6285SAndroid Build Coastguard Worker      symlink_src = os.path.join(temp_dir, 'vendor/oem4/symlink_src.mk')
215*105f6285SAndroid Build Coastguard Worker      os.makedirs(os.path.dirname(symlink_src))
216*105f6285SAndroid Build Coastguard Worker      os.mknod(symlink_src)
217*105f6285SAndroid Build Coastguard Worker      symlink_dest = 'device/oem4/symlink_dest.mk'
218*105f6285SAndroid Build Coastguard Worker      os.makedirs(os.path.dirname(symlink_dest))
219*105f6285SAndroid Build Coastguard Worker      os.symlink(symlink_src, symlink_dest)
220*105f6285SAndroid Build Coastguard Worker      # Only append the symlink destination, not where the symlink points to.
221*105f6285SAndroid Build Coastguard Worker      # (The Kati stamp file does not resolve symlink sources.)
222*105f6285SAndroid Build Coastguard Worker      makefiles.append(symlink_dest)
223*105f6285SAndroid Build Coastguard Worker
224*105f6285SAndroid Build Coastguard Worker      # Mock the output of ckati --dump_stamp_tool:
225*105f6285SAndroid Build Coastguard Worker      mock_check_output.return_value = '\n'.join(makefiles).encode()
226*105f6285SAndroid Build Coastguard Worker
227*105f6285SAndroid Build Coastguard Worker      kati_makefiles = manifest_split.get_kati_makefiles(
228*105f6285SAndroid Build Coastguard Worker          'stamp-file', ['overlays/oem_overlay/'])
229*105f6285SAndroid Build Coastguard Worker      self.assertEqual(
230*105f6285SAndroid Build Coastguard Worker          kati_makefiles,
231*105f6285SAndroid Build Coastguard Worker          set([
232*105f6285SAndroid Build Coastguard Worker              # Regular product makefiles
233*105f6285SAndroid Build Coastguard Worker              'device/oem1/product1.mk',
234*105f6285SAndroid Build Coastguard Worker              'device/oem2/product2.mk',
235*105f6285SAndroid Build Coastguard Worker              # Product makefile remapped from an overlay
236*105f6285SAndroid Build Coastguard Worker              'device/oem3/product3.mk',
237*105f6285SAndroid Build Coastguard Worker              # Product makefile symlink and its source
238*105f6285SAndroid Build Coastguard Worker              'device/oem4/symlink_dest.mk',
239*105f6285SAndroid Build Coastguard Worker              'vendor/oem4/symlink_src.mk',
240*105f6285SAndroid Build Coastguard Worker          ]))
241*105f6285SAndroid Build Coastguard Worker
242*105f6285SAndroid Build Coastguard Worker  def test_scan_repo_projects(self):
243*105f6285SAndroid Build Coastguard Worker    repo_projects = {
244*105f6285SAndroid Build Coastguard Worker        'system/project1': 'platform/project1',
245*105f6285SAndroid Build Coastguard Worker        'system/project2': 'platform/project2',
246*105f6285SAndroid Build Coastguard Worker    }
247*105f6285SAndroid Build Coastguard Worker    self.assertEqual(
248*105f6285SAndroid Build Coastguard Worker        manifest_split.scan_repo_projects(repo_projects,
249*105f6285SAndroid Build Coastguard Worker                                          'system/project1/path/to/file.h'),
250*105f6285SAndroid Build Coastguard Worker        'system/project1')
251*105f6285SAndroid Build Coastguard Worker    self.assertEqual(
252*105f6285SAndroid Build Coastguard Worker        manifest_split.scan_repo_projects(
253*105f6285SAndroid Build Coastguard Worker            repo_projects, 'system/project2/path/to/another_file.cc'),
254*105f6285SAndroid Build Coastguard Worker        'system/project2')
255*105f6285SAndroid Build Coastguard Worker    self.assertIsNone(
256*105f6285SAndroid Build Coastguard Worker        manifest_split.scan_repo_projects(
257*105f6285SAndroid Build Coastguard Worker            repo_projects, 'system/project3/path/to/unknown_file.h'))
258*105f6285SAndroid Build Coastguard Worker
259*105f6285SAndroid Build Coastguard Worker  def test_get_input_projects(self):
260*105f6285SAndroid Build Coastguard Worker    repo_projects = {
261*105f6285SAndroid Build Coastguard Worker        'system/project1': 'platform/project1',
262*105f6285SAndroid Build Coastguard Worker        'system/project2': 'platform/project2',
263*105f6285SAndroid Build Coastguard Worker        'system/project4': 'platform/project4',
264*105f6285SAndroid Build Coastguard Worker    }
265*105f6285SAndroid Build Coastguard Worker    inputs = [
266*105f6285SAndroid Build Coastguard Worker        'system/project1/path/to/file.h',
267*105f6285SAndroid Build Coastguard Worker        'out/path/to/out/file.h',
268*105f6285SAndroid Build Coastguard Worker        'system/project2/path/to/another_file.cc',
269*105f6285SAndroid Build Coastguard Worker        'system/project3/path/to/unknown_file.h',
270*105f6285SAndroid Build Coastguard Worker        '/tmp/absolute/path/file.java',
271*105f6285SAndroid Build Coastguard Worker    ]
272*105f6285SAndroid Build Coastguard Worker    self.assertEqual(
273*105f6285SAndroid Build Coastguard Worker        manifest_split.get_input_projects(repo_projects, inputs), {
274*105f6285SAndroid Build Coastguard Worker            'platform/project1': ['system/project1/path/to/file.h'],
275*105f6285SAndroid Build Coastguard Worker            'platform/project2': ['system/project2/path/to/another_file.cc'],
276*105f6285SAndroid Build Coastguard Worker        })
277*105f6285SAndroid Build Coastguard Worker
278*105f6285SAndroid Build Coastguard Worker  def test_update_manifest(self):
279*105f6285SAndroid Build Coastguard Worker    manifest_contents = """
280*105f6285SAndroid Build Coastguard Worker      <manifest>
281*105f6285SAndroid Build Coastguard Worker        <project name="platform/project1" path="system/project1" />
282*105f6285SAndroid Build Coastguard Worker        <project name="platform/project2" path="system/project2" />
283*105f6285SAndroid Build Coastguard Worker        <project name="platform/project3" path="system/project3" />
284*105f6285SAndroid Build Coastguard Worker      </manifest>"""
285*105f6285SAndroid Build Coastguard Worker    input_projects = set(['platform/project1', 'platform/project3'])
286*105f6285SAndroid Build Coastguard Worker    remove_projects = set(['platform/project3'])
287*105f6285SAndroid Build Coastguard Worker    manifest = manifest_split.update_manifest(
288*105f6285SAndroid Build Coastguard Worker        ET.ElementTree(ET.fromstring(manifest_contents)), input_projects,
289*105f6285SAndroid Build Coastguard Worker        remove_projects)
290*105f6285SAndroid Build Coastguard Worker
291*105f6285SAndroid Build Coastguard Worker    projects = manifest.getroot().findall('project')
292*105f6285SAndroid Build Coastguard Worker    self.assertEqual(len(projects), 1)
293*105f6285SAndroid Build Coastguard Worker    self.assertEqual(
294*105f6285SAndroid Build Coastguard Worker        ET.tostring(projects[0]).strip().decode(),
295*105f6285SAndroid Build Coastguard Worker        '<project name="platform/project1" path="system/project1" />')
296*105f6285SAndroid Build Coastguard Worker
297*105f6285SAndroid Build Coastguard Worker  @unittest.mock.patch.object(subprocess, 'check_output', autospec=True)
298*105f6285SAndroid Build Coastguard Worker  def test_create_split_manifest(self, mock_check_output):
299*105f6285SAndroid Build Coastguard Worker    with tempfile.NamedTemporaryFile('w+t') as repo_list_file, \
300*105f6285SAndroid Build Coastguard Worker      tempfile.NamedTemporaryFile('w+t') as manifest_file, \
301*105f6285SAndroid Build Coastguard Worker      tempfile.NamedTemporaryFile('w+t') as module_info_file, \
302*105f6285SAndroid Build Coastguard Worker      tempfile.NamedTemporaryFile('w+t') as config_file, \
303*105f6285SAndroid Build Coastguard Worker      tempfile.NamedTemporaryFile('w+t') as split_manifest_file, \
304*105f6285SAndroid Build Coastguard Worker      tempfile.TemporaryDirectory() as temp_dir:
305*105f6285SAndroid Build Coastguard Worker
306*105f6285SAndroid Build Coastguard Worker      os.chdir(temp_dir)
307*105f6285SAndroid Build Coastguard Worker
308*105f6285SAndroid Build Coastguard Worker      repo_list_file.write("""
309*105f6285SAndroid Build Coastguard Worker        system/project1 : platform/project1
310*105f6285SAndroid Build Coastguard Worker        system/project2 : platform/project2
311*105f6285SAndroid Build Coastguard Worker        system/project3 : platform/project3
312*105f6285SAndroid Build Coastguard Worker        system/project4 : platform/project4
313*105f6285SAndroid Build Coastguard Worker        system/project5 : platform/project5
314*105f6285SAndroid Build Coastguard Worker        system/project6 : platform/project6
315*105f6285SAndroid Build Coastguard Worker        system/project7 : platform/project7
316*105f6285SAndroid Build Coastguard Worker        system/project8 : platform/project8
317*105f6285SAndroid Build Coastguard Worker        system/project9 : platform/project9
318*105f6285SAndroid Build Coastguard Worker        vendor/project1 : vendor/project1""")
319*105f6285SAndroid Build Coastguard Worker      repo_list_file.flush()
320*105f6285SAndroid Build Coastguard Worker
321*105f6285SAndroid Build Coastguard Worker      manifest_file.write("""
322*105f6285SAndroid Build Coastguard Worker        <manifest>
323*105f6285SAndroid Build Coastguard Worker          <project name="platform/project1" path="system/project1" />
324*105f6285SAndroid Build Coastguard Worker          <project name="platform/project2" path="system/project2" />
325*105f6285SAndroid Build Coastguard Worker          <project name="platform/project3" path="system/project3" />
326*105f6285SAndroid Build Coastguard Worker          <project name="platform/project4" path="system/project4" />
327*105f6285SAndroid Build Coastguard Worker          <project name="platform/project5" path="system/project5" />
328*105f6285SAndroid Build Coastguard Worker          <project name="platform/project6" path="system/project6" />
329*105f6285SAndroid Build Coastguard Worker          <project name="platform/project7" path="system/project7" />
330*105f6285SAndroid Build Coastguard Worker          <project name="platform/project8" path="system/project8" />
331*105f6285SAndroid Build Coastguard Worker          <project name="platform/project9" path="system/project9" />
332*105f6285SAndroid Build Coastguard Worker          <project name="vendor/project1" path="vendor/project1" />
333*105f6285SAndroid Build Coastguard Worker        </manifest>""")
334*105f6285SAndroid Build Coastguard Worker      manifest_file.flush()
335*105f6285SAndroid Build Coastguard Worker
336*105f6285SAndroid Build Coastguard Worker      module_info_file.write("""{
337*105f6285SAndroid Build Coastguard Worker        "droid": { "class": ["EXECUTABLES"], "path": ["system/project1"], "dependencies": [] },
338*105f6285SAndroid Build Coastguard Worker        "target_a": { "class": ["EXECUTABLES"], "path": ["out/project2"], "dependencies": ["unknown_module_a"] },
339*105f6285SAndroid Build Coastguard Worker        "target_b": { "class": ["EXECUTABLES"], "path": ["system/project3"], "dependencies": ["target_f", "unknown_module_b"] },
340*105f6285SAndroid Build Coastguard Worker        "target_c": { "class": ["EXECUTABLES"], "path": ["system/project4"], "dependencies": [] },
341*105f6285SAndroid Build Coastguard Worker        "target_d": { "class": ["EXECUTABLES"], "path": ["system/project5"], "dependencies": [] },
342*105f6285SAndroid Build Coastguard Worker        "target_e": { "class": ["EXECUTABLES"], "path": ["system/project6"], "dependencies": [] },
343*105f6285SAndroid Build Coastguard Worker        "target_f": { "class": ["HEADER_LIBRARIES"], "path": ["system/project7"], "dependencies": [] },
344*105f6285SAndroid Build Coastguard Worker        "target_g": { "class": ["SHARED_LIBRARIES"], "path": ["system/project8"], "dependencies": ["target_h"] },
345*105f6285SAndroid Build Coastguard Worker        "target_h": { "class": ["HEADER_LIBRARIES"], "path": ["system/project9"], "dependencies": [] }
346*105f6285SAndroid Build Coastguard Worker      }""")
347*105f6285SAndroid Build Coastguard Worker      module_info_file.flush()
348*105f6285SAndroid Build Coastguard Worker
349*105f6285SAndroid Build Coastguard Worker      # droid needs inputs from project1 and project3
350*105f6285SAndroid Build Coastguard Worker      ninja_inputs_droid = b"""
351*105f6285SAndroid Build Coastguard Worker      system/project1/file1
352*105f6285SAndroid Build Coastguard Worker      system/project1/file2
353*105f6285SAndroid Build Coastguard Worker      system/project3/file1
354*105f6285SAndroid Build Coastguard Worker      """
355*105f6285SAndroid Build Coastguard Worker
356*105f6285SAndroid Build Coastguard Worker      # target_b (indirectly included due to being in project3) needs inputs
357*105f6285SAndroid Build Coastguard Worker      # from project3 and project4
358*105f6285SAndroid Build Coastguard Worker      ninja_inputs_target_b = b"""
359*105f6285SAndroid Build Coastguard Worker      system/project3/file2
360*105f6285SAndroid Build Coastguard Worker      system/project4/file1
361*105f6285SAndroid Build Coastguard Worker      """
362*105f6285SAndroid Build Coastguard Worker
363*105f6285SAndroid Build Coastguard Worker      # target_c (indirectly included due to being in project4) needs inputs
364*105f6285SAndroid Build Coastguard Worker      # from only project4
365*105f6285SAndroid Build Coastguard Worker      ninja_inputs_target_c = b"""
366*105f6285SAndroid Build Coastguard Worker      system/project4/file2
367*105f6285SAndroid Build Coastguard Worker      system/project4/file3
368*105f6285SAndroid Build Coastguard Worker      """
369*105f6285SAndroid Build Coastguard Worker
370*105f6285SAndroid Build Coastguard Worker      product_makefile = 'vendor/project1/product.mk'
371*105f6285SAndroid Build Coastguard Worker      os.makedirs(os.path.dirname(product_makefile))
372*105f6285SAndroid Build Coastguard Worker      os.mknod(product_makefile)
373*105f6285SAndroid Build Coastguard Worker      kati_stamp_dump = product_makefile.encode()
374*105f6285SAndroid Build Coastguard Worker
375*105f6285SAndroid Build Coastguard Worker      mock_check_output.side_effect = [
376*105f6285SAndroid Build Coastguard Worker          ninja_inputs_droid,
377*105f6285SAndroid Build Coastguard Worker          kati_stamp_dump,
378*105f6285SAndroid Build Coastguard Worker          ninja_inputs_target_b,
379*105f6285SAndroid Build Coastguard Worker          ninja_inputs_target_c,
380*105f6285SAndroid Build Coastguard Worker      ]
381*105f6285SAndroid Build Coastguard Worker
382*105f6285SAndroid Build Coastguard Worker      # The config file says to manually include project6
383*105f6285SAndroid Build Coastguard Worker      config_file.write("""
384*105f6285SAndroid Build Coastguard Worker        <config>
385*105f6285SAndroid Build Coastguard Worker          <add_project name="platform/project6" />
386*105f6285SAndroid Build Coastguard Worker        </config>""")
387*105f6285SAndroid Build Coastguard Worker      config_file.flush()
388*105f6285SAndroid Build Coastguard Worker
389*105f6285SAndroid Build Coastguard Worker      debug_file = os.path.join(temp_dir, 'debug.json')
390*105f6285SAndroid Build Coastguard Worker
391*105f6285SAndroid Build Coastguard Worker      manifest_split.create_split_manifest(
392*105f6285SAndroid Build Coastguard Worker          ['droid'], manifest_file.name, split_manifest_file.name,
393*105f6285SAndroid Build Coastguard Worker          [config_file.name], repo_list_file.name, 'build-target.ninja',
394*105f6285SAndroid Build Coastguard Worker          'ninja', module_info_file.name, 'unused kati stamp',
395*105f6285SAndroid Build Coastguard Worker          ['unused overlay'], [], debug_file)
396*105f6285SAndroid Build Coastguard Worker      split_manifest = ET.parse(split_manifest_file.name)
397*105f6285SAndroid Build Coastguard Worker      split_manifest_projects = [
398*105f6285SAndroid Build Coastguard Worker          child.attrib['name']
399*105f6285SAndroid Build Coastguard Worker          for child in split_manifest.getroot().findall('project')
400*105f6285SAndroid Build Coastguard Worker      ]
401*105f6285SAndroid Build Coastguard Worker      self.assertEqual(
402*105f6285SAndroid Build Coastguard Worker          split_manifest_projects,
403*105f6285SAndroid Build Coastguard Worker          [
404*105f6285SAndroid Build Coastguard Worker              # From droid
405*105f6285SAndroid Build Coastguard Worker              'platform/project1',
406*105f6285SAndroid Build Coastguard Worker              # From droid
407*105f6285SAndroid Build Coastguard Worker              'platform/project3',
408*105f6285SAndroid Build Coastguard Worker              # From target_b (module within project3, indirect dependency)
409*105f6285SAndroid Build Coastguard Worker              'platform/project4',
410*105f6285SAndroid Build Coastguard Worker              # Manual inclusion from config file
411*105f6285SAndroid Build Coastguard Worker              'platform/project6',
412*105f6285SAndroid Build Coastguard Worker              # From target_b (depends on target_f header library)
413*105f6285SAndroid Build Coastguard Worker              'platform/project7',
414*105f6285SAndroid Build Coastguard Worker              # Inclusion from the Kati makefile stamp
415*105f6285SAndroid Build Coastguard Worker              'vendor/project1',
416*105f6285SAndroid Build Coastguard Worker          ])
417*105f6285SAndroid Build Coastguard Worker
418*105f6285SAndroid Build Coastguard Worker      with open(debug_file) as debug_fp:
419*105f6285SAndroid Build Coastguard Worker        debug_data = json.load(debug_fp)
420*105f6285SAndroid Build Coastguard Worker
421*105f6285SAndroid Build Coastguard Worker        # Dependency for droid, but no other adjacent modules
422*105f6285SAndroid Build Coastguard Worker        self.assertTrue(debug_data['platform/project1']['direct_input'])
423*105f6285SAndroid Build Coastguard Worker        self.assertFalse(debug_data['platform/project1']['adjacent_input'])
424*105f6285SAndroid Build Coastguard Worker        self.assertFalse(debug_data['platform/project1']['deps_input'])
425*105f6285SAndroid Build Coastguard Worker
426*105f6285SAndroid Build Coastguard Worker        # Dependency for droid and an adjacent module
427*105f6285SAndroid Build Coastguard Worker        self.assertTrue(debug_data['platform/project3']['direct_input'])
428*105f6285SAndroid Build Coastguard Worker        self.assertTrue(debug_data['platform/project3']['adjacent_input'])
429*105f6285SAndroid Build Coastguard Worker        self.assertFalse(debug_data['platform/project3']['deps_input'])
430*105f6285SAndroid Build Coastguard Worker
431*105f6285SAndroid Build Coastguard Worker        # Dependency only for an adjacent module
432*105f6285SAndroid Build Coastguard Worker        self.assertFalse(debug_data['platform/project4']['direct_input'])
433*105f6285SAndroid Build Coastguard Worker        self.assertTrue(debug_data['platform/project4']['adjacent_input'])
434*105f6285SAndroid Build Coastguard Worker        self.assertFalse(debug_data['platform/project4']['deps_input'])
435*105f6285SAndroid Build Coastguard Worker
436*105f6285SAndroid Build Coastguard Worker        # Included via header library
437*105f6285SAndroid Build Coastguard Worker        self.assertFalse(debug_data['platform/project7']['direct_input'])
438*105f6285SAndroid Build Coastguard Worker        self.assertFalse(debug_data['platform/project7']['adjacent_input'])
439*105f6285SAndroid Build Coastguard Worker        self.assertTrue(debug_data['platform/project7']['deps_input'])
440*105f6285SAndroid Build Coastguard Worker
441*105f6285SAndroid Build Coastguard Worker        # Included due to the config file
442*105f6285SAndroid Build Coastguard Worker        self.assertEqual(
443*105f6285SAndroid Build Coastguard Worker            debug_data['platform/project6']['manual_add_config'],
444*105f6285SAndroid Build Coastguard Worker            config_file.name)
445*105f6285SAndroid Build Coastguard Worker
446*105f6285SAndroid Build Coastguard Worker        # Included due to the Kati makefile stamp
447*105f6285SAndroid Build Coastguard Worker        self.assertEqual(debug_data['vendor/project1']['kati_makefiles'][0],
448*105f6285SAndroid Build Coastguard Worker                         product_makefile)
449*105f6285SAndroid Build Coastguard Worker
450*105f6285SAndroid Build Coastguard Worker  @unittest.mock.patch.object(manifest_split, 'get_ninja_inputs', autospec=True)
451*105f6285SAndroid Build Coastguard Worker  @unittest.mock.patch.object(manifest_split, 'get_kati_makefiles', autospec=True)
452*105f6285SAndroid Build Coastguard Worker  @unittest.mock.patch.object(manifest_split.ModuleInfo, '__init__', autospec=True)
453*105f6285SAndroid Build Coastguard Worker  def test_create_split_manifest_skip_kati_module_info(self, mock_init,
454*105f6285SAndroid Build Coastguard Worker                                                       mock_get_kati_makefiles,
455*105f6285SAndroid Build Coastguard Worker                                                       mock_get_ninja_inputs):
456*105f6285SAndroid Build Coastguard Worker    with tempfile.NamedTemporaryFile('w+t') as repo_list_file, \
457*105f6285SAndroid Build Coastguard Worker            tempfile.NamedTemporaryFile('w+t') as manifest_file, \
458*105f6285SAndroid Build Coastguard Worker            tempfile.NamedTemporaryFile('w+t') as module_info_file, \
459*105f6285SAndroid Build Coastguard Worker            tempfile.NamedTemporaryFile('w+t') as config_file, \
460*105f6285SAndroid Build Coastguard Worker            tempfile.NamedTemporaryFile('w+t') as split_manifest_file, \
461*105f6285SAndroid Build Coastguard Worker            tempfile.TemporaryDirectory() as temp_dir:
462*105f6285SAndroid Build Coastguard Worker
463*105f6285SAndroid Build Coastguard Worker      os.chdir(temp_dir)
464*105f6285SAndroid Build Coastguard Worker
465*105f6285SAndroid Build Coastguard Worker      manifest_file.write("""
466*105f6285SAndroid Build Coastguard Worker        <manifest>
467*105f6285SAndroid Build Coastguard Worker        </manifest>""")
468*105f6285SAndroid Build Coastguard Worker      manifest_file.flush()
469*105f6285SAndroid Build Coastguard Worker
470*105f6285SAndroid Build Coastguard Worker      manifest_split.create_split_manifest(
471*105f6285SAndroid Build Coastguard Worker          targets=['droid'],
472*105f6285SAndroid Build Coastguard Worker          manifest_file=manifest_file.name,
473*105f6285SAndroid Build Coastguard Worker          split_manifest_file=split_manifest_file.name,
474*105f6285SAndroid Build Coastguard Worker          config_files=[],
475*105f6285SAndroid Build Coastguard Worker          repo_list_file=repo_list_file.name,
476*105f6285SAndroid Build Coastguard Worker          ninja_build_file='build-target.ninja',
477*105f6285SAndroid Build Coastguard Worker          ninja_binary='ninja',
478*105f6285SAndroid Build Coastguard Worker          kati_stamp_file=None,
479*105f6285SAndroid Build Coastguard Worker          module_info_file=None,
480*105f6285SAndroid Build Coastguard Worker          overlays=[],
481*105f6285SAndroid Build Coastguard Worker          installed_prebuilts=[],
482*105f6285SAndroid Build Coastguard Worker          debug_file=None)
483*105f6285SAndroid Build Coastguard Worker
484*105f6285SAndroid Build Coastguard Worker    mock_get_ninja_inputs.assert_called_with(
485*105f6285SAndroid Build Coastguard Worker        'ninja', 'build-target.ninja', ['droid'])
486*105f6285SAndroid Build Coastguard Worker    mock_get_kati_makefiles.assert_not_called()
487*105f6285SAndroid Build Coastguard Worker    mock_init.assert_not_called()
488*105f6285SAndroid Build Coastguard Worker
489*105f6285SAndroid Build Coastguard Worker  @unittest.mock.patch.object(subprocess, 'check_output', autospec=True)
490*105f6285SAndroid Build Coastguard Worker  def test_create_split_manifest_installed_prebuilt(self, mock_check_output):
491*105f6285SAndroid Build Coastguard Worker
492*105f6285SAndroid Build Coastguard Worker    # The purpose of this test is to verify that create_split_manifests treats
493*105f6285SAndroid Build Coastguard Worker    # installed prebuilts as projects, even though the installed prebuilts are
494*105f6285SAndroid Build Coastguard Worker    # not in the manifest. This use case occurs when installed prebuilts
495*105f6285SAndroid Build Coastguard Worker    # contribute modules to the build, but the installed prebuilts themselves
496*105f6285SAndroid Build Coastguard Worker    # aren't sourced from the manifest.
497*105f6285SAndroid Build Coastguard Worker
498*105f6285SAndroid Build Coastguard Worker    with tempfile.NamedTemporaryFile('w+t') as repo_list_file, \
499*105f6285SAndroid Build Coastguard Worker      tempfile.NamedTemporaryFile('w+t') as manifest_file, \
500*105f6285SAndroid Build Coastguard Worker      tempfile.NamedTemporaryFile('w+t') as module_info_file, \
501*105f6285SAndroid Build Coastguard Worker      tempfile.NamedTemporaryFile('w+t') as split_manifest_file, \
502*105f6285SAndroid Build Coastguard Worker      tempfile.TemporaryDirectory() as temp_dir:
503*105f6285SAndroid Build Coastguard Worker
504*105f6285SAndroid Build Coastguard Worker      os.chdir(temp_dir)
505*105f6285SAndroid Build Coastguard Worker
506*105f6285SAndroid Build Coastguard Worker      repo_list_file.write("""
507*105f6285SAndroid Build Coastguard Worker        system/project1 : platform/project1
508*105f6285SAndroid Build Coastguard Worker        vendor/project1 : vendor/project1""")
509*105f6285SAndroid Build Coastguard Worker      repo_list_file.flush()
510*105f6285SAndroid Build Coastguard Worker
511*105f6285SAndroid Build Coastguard Worker      # Here we have small manifest that does not include "prebuilt/project3"
512*105f6285SAndroid Build Coastguard Worker      # or "prebuilt/project4".
513*105f6285SAndroid Build Coastguard Worker
514*105f6285SAndroid Build Coastguard Worker      manifest_file.write("""
515*105f6285SAndroid Build Coastguard Worker        <manifest>
516*105f6285SAndroid Build Coastguard Worker          <project name="platform/project1" path="system/project1" />
517*105f6285SAndroid Build Coastguard Worker          <project name="vendor/project1" path="vendor/project1" />
518*105f6285SAndroid Build Coastguard Worker        </manifest>""")
519*105f6285SAndroid Build Coastguard Worker      manifest_file.flush()
520*105f6285SAndroid Build Coastguard Worker
521*105f6285SAndroid Build Coastguard Worker      # Here's the module_info.json file. It contains modules whose paths are
522*105f6285SAndroid Build Coastguard Worker      # "prebuilt/project3" and "prebult/project4", which are not found in the
523*105f6285SAndroid Build Coastguard Worker      # manifest. Normally create_split_manifest doesn't tolerate a path that
524*105f6285SAndroid Build Coastguard Worker      # doesn't correspond to a manifest project. However, this test verifies
525*105f6285SAndroid Build Coastguard Worker      # that you can use these modules if you tell create_split_manifest about
526*105f6285SAndroid Build Coastguard Worker      # the installed prebuilts via a parameter.
527*105f6285SAndroid Build Coastguard Worker
528*105f6285SAndroid Build Coastguard Worker      module_info_file.write("""{
529*105f6285SAndroid Build Coastguard Worker        "droid": { "class": ["EXECUTABLES"], "path": ["system/project1"], "dependencies": [] },
530*105f6285SAndroid Build Coastguard Worker        "target_a": { "class": ["EXECUTABLES"], "path": ["system/project1"], "dependencies": ["target_b", "target_c"] },
531*105f6285SAndroid Build Coastguard Worker        "target_b": { "class": ["SHARED_LIBRARIES"], "path": ["prebuilt/project3"], "dependencies": [] },
532*105f6285SAndroid Build Coastguard Worker        "target_c": { "class": ["SHARED_LIBRARIES"], "path": ["prebuilt/project4"], "dependencies": [] }
533*105f6285SAndroid Build Coastguard Worker      }""")
534*105f6285SAndroid Build Coastguard Worker      module_info_file.flush()
535*105f6285SAndroid Build Coastguard Worker
536*105f6285SAndroid Build Coastguard Worker      # droid needs inputs from project1
537*105f6285SAndroid Build Coastguard Worker      ninja_inputs_droid = b"""
538*105f6285SAndroid Build Coastguard Worker      system/project1/file1
539*105f6285SAndroid Build Coastguard Worker      """
540*105f6285SAndroid Build Coastguard Worker
541*105f6285SAndroid Build Coastguard Worker      # target_a needs inputs from prebuilt/project3 and prebuilt/project4
542*105f6285SAndroid Build Coastguard Worker      ninja_inputs_target_a = b"""
543*105f6285SAndroid Build Coastguard Worker      prebuilt/project3/file2
544*105f6285SAndroid Build Coastguard Worker      prebuilt/project4/file3
545*105f6285SAndroid Build Coastguard Worker      """
546*105f6285SAndroid Build Coastguard Worker
547*105f6285SAndroid Build Coastguard Worker      # target_b needs inputs from prebuilt/project3
548*105f6285SAndroid Build Coastguard Worker      ninja_inputs_target_b = b"""
549*105f6285SAndroid Build Coastguard Worker      prebuilt/project3/file4
550*105f6285SAndroid Build Coastguard Worker      """
551*105f6285SAndroid Build Coastguard Worker
552*105f6285SAndroid Build Coastguard Worker      # target_c needs inputs from prebuilt/project4
553*105f6285SAndroid Build Coastguard Worker      ninja_inputs_target_c = b"""
554*105f6285SAndroid Build Coastguard Worker      prebuilt/project4/file5
555*105f6285SAndroid Build Coastguard Worker      """
556*105f6285SAndroid Build Coastguard Worker
557*105f6285SAndroid Build Coastguard Worker      product_makefile = 'vendor/project1/product.mk'
558*105f6285SAndroid Build Coastguard Worker      os.makedirs(os.path.dirname(product_makefile))
559*105f6285SAndroid Build Coastguard Worker      os.mknod(product_makefile)
560*105f6285SAndroid Build Coastguard Worker      kati_stamp_dump = product_makefile.encode()
561*105f6285SAndroid Build Coastguard Worker
562*105f6285SAndroid Build Coastguard Worker      mock_check_output.side_effect = [
563*105f6285SAndroid Build Coastguard Worker          ninja_inputs_droid,
564*105f6285SAndroid Build Coastguard Worker          kati_stamp_dump,
565*105f6285SAndroid Build Coastguard Worker          ninja_inputs_target_a,
566*105f6285SAndroid Build Coastguard Worker          ninja_inputs_target_b,
567*105f6285SAndroid Build Coastguard Worker          ninja_inputs_target_c,
568*105f6285SAndroid Build Coastguard Worker      ]
569*105f6285SAndroid Build Coastguard Worker
570*105f6285SAndroid Build Coastguard Worker      debug_file = os.path.join(temp_dir, 'debug.json')
571*105f6285SAndroid Build Coastguard Worker
572*105f6285SAndroid Build Coastguard Worker      manifest_split.create_split_manifest(
573*105f6285SAndroid Build Coastguard Worker          targets=['droid'],
574*105f6285SAndroid Build Coastguard Worker          manifest_file=manifest_file.name,
575*105f6285SAndroid Build Coastguard Worker          split_manifest_file=split_manifest_file.name,
576*105f6285SAndroid Build Coastguard Worker          config_files=[],
577*105f6285SAndroid Build Coastguard Worker          repo_list_file=repo_list_file.name,
578*105f6285SAndroid Build Coastguard Worker          ninja_build_file='build-target.ninja',
579*105f6285SAndroid Build Coastguard Worker          ninja_binary='ninja',
580*105f6285SAndroid Build Coastguard Worker          module_info_file=module_info_file.name,
581*105f6285SAndroid Build Coastguard Worker          kati_stamp_file='unused kati stamp',
582*105f6285SAndroid Build Coastguard Worker          overlays=['unused overlay'],
583*105f6285SAndroid Build Coastguard Worker
584*105f6285SAndroid Build Coastguard Worker          # This is a key part of the test. Passing these two "projects" as
585*105f6285SAndroid Build Coastguard Worker          # prebuilts allows create_split_manifest to recognize them as
586*105f6285SAndroid Build Coastguard Worker          # projects even though they are not in the manifest.
587*105f6285SAndroid Build Coastguard Worker
588*105f6285SAndroid Build Coastguard Worker          installed_prebuilts=['prebuilt/project3', 'prebuilt/project4'],
589*105f6285SAndroid Build Coastguard Worker
590*105f6285SAndroid Build Coastguard Worker          debug_file = debug_file)
591*105f6285SAndroid Build Coastguard Worker
592*105f6285SAndroid Build Coastguard Worker      split_manifest = ET.parse(split_manifest_file.name)
593*105f6285SAndroid Build Coastguard Worker
594*105f6285SAndroid Build Coastguard Worker      split_manifest_projects = [
595*105f6285SAndroid Build Coastguard Worker          child.attrib['name']
596*105f6285SAndroid Build Coastguard Worker          for child in split_manifest.getroot().findall('project')
597*105f6285SAndroid Build Coastguard Worker      ]
598*105f6285SAndroid Build Coastguard Worker
599*105f6285SAndroid Build Coastguard Worker      # Note that the installed prebuilts do not appear in the final split
600*105f6285SAndroid Build Coastguard Worker      # manfiest output because they were not in the manifest to begin with.
601*105f6285SAndroid Build Coastguard Worker
602*105f6285SAndroid Build Coastguard Worker      self.assertEqual(
603*105f6285SAndroid Build Coastguard Worker          split_manifest_projects,
604*105f6285SAndroid Build Coastguard Worker          [
605*105f6285SAndroid Build Coastguard Worker              # From droid
606*105f6285SAndroid Build Coastguard Worker              'platform/project1',
607*105f6285SAndroid Build Coastguard Worker              # Inclusion from the Kati makefile stamp
608*105f6285SAndroid Build Coastguard Worker              'vendor/project1',
609*105f6285SAndroid Build Coastguard Worker          ])
610*105f6285SAndroid Build Coastguard Worker
611*105f6285SAndroid Build Coastguard Worker      with open(debug_file) as debug_fp:
612*105f6285SAndroid Build Coastguard Worker        debug_data = json.load(debug_fp)
613*105f6285SAndroid Build Coastguard Worker
614*105f6285SAndroid Build Coastguard Worker        # Dependency for droid, but no other adjacent modules
615*105f6285SAndroid Build Coastguard Worker        self.assertTrue(debug_data['platform/project1']['direct_input'])
616*105f6285SAndroid Build Coastguard Worker        self.assertFalse(debug_data['platform/project1']['adjacent_input'])
617*105f6285SAndroid Build Coastguard Worker        self.assertFalse(debug_data['platform/project1']['deps_input'])
618*105f6285SAndroid Build Coastguard Worker
619*105f6285SAndroid Build Coastguard Worker        # Included due to the Kati makefile stamp
620*105f6285SAndroid Build Coastguard Worker        self.assertEqual(debug_data['vendor/project1']['kati_makefiles'][0],
621*105f6285SAndroid Build Coastguard Worker                         product_makefile)
622*105f6285SAndroid Build Coastguard Worker
623*105f6285SAndroid Build Coastguard Worker
624*105f6285SAndroid Build Coastguard Workerif __name__ == '__main__':
625*105f6285SAndroid Build Coastguard Worker  unittest.main()
626