• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright 2019, The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""Unittests for native_util."""
18
19import os
20import unittest
21from unittest import mock
22
23from aidegen import unittest_constants
24from aidegen.lib import common_util
25from aidegen.lib import native_module_info
26from aidegen.lib import native_util
27from aidegen.lib import project_info
28
29
30# pylint: disable=protected-access
31# pylint: disable=too-many-arguments
32class AidegenNativeUtilUnittests(unittest.TestCase):
33    """Unit tests for native_util.py"""
34
35    @mock.patch.object(native_util, '_check_native_project_exists')
36    @mock.patch.object(common_util, 'check_java_or_kotlin_file_exists')
37    @mock.patch.object(common_util, 'get_related_paths')
38    def test_analyze_native_and_java_projects(
39            self, mock_get_related, mock_check_java, mock_check_native):
40        """Test analyze_native_and_java_projects function."""
41        mock_get_related.return_value = None, None
42        mock_check_java.return_value = True
43        mock_check_native.return_value = True
44        targets = ['a']
45        self.assertEqual((targets, targets),
46                         native_util._analyze_native_and_java_projects(
47                             None, None, targets))
48        mock_check_native.return_value = False
49        self.assertEqual((targets, []),
50                         native_util._analyze_native_and_java_projects(
51                             None, None, targets))
52        mock_check_java.return_value = False
53        mock_check_native.return_value = True
54        self.assertEqual(([], targets),
55                         native_util._analyze_native_and_java_projects(
56                             None, None, targets))
57
58    def test_check_native_project_exists(self):
59        """Test _check_native_project_exists function."""
60        rel_path = 'a/b'
61        path_to_module_info = {'a/b/c': {}}
62        self.assertTrue(
63            native_util._check_native_project_exists(path_to_module_info,
64                                                     rel_path))
65        rel_path = 'a/b/c/d'
66        self.assertFalse(
67            native_util._check_native_project_exists(path_to_module_info,
68                                                     rel_path))
69
70    def test_find_parent(self):
71        """Test _find_parent function with conditions."""
72        current_parent = None
73        abs_path = 'a/b/c/d'
74        expected = abs_path
75        result = native_util._find_parent(abs_path, current_parent)
76        self.assertEqual(result, expected)
77        current_parent = 'a/b/c/d/e'
78        result = native_util._find_parent(abs_path, current_parent)
79        self.assertEqual(result, expected)
80        current_parent = 'a/b/c'
81        expected = current_parent
82        result = native_util._find_parent(abs_path, current_parent)
83        self.assertEqual(result, expected)
84        current_parent = 'a/b/f'
85        expected = 'a/b'
86        result = native_util._find_parent(abs_path, current_parent)
87        self.assertEqual(result, expected)
88
89    @mock.patch.object(native_module_info.NativeModuleInfo,
90                       '_load_module_info_file')
91    @mock.patch.object(native_util, '_find_parent')
92    @mock.patch.object(common_util, 'get_related_paths')
93    def test_get_merged_native_target_is_module(
94            self, mock_get_related, mock_find_parent, mock_load_info):
95        """Test _get_merged_native_target function if the target is a module."""
96        mock_get_related.return_value = 'c/d', 'a/b/c/d'
97        parent = 'a/b'
98        mock_find_parent.return_value = parent
99        targets = ['multiarch']
100        expected = (parent, targets)
101        mock_load_info.return_value = (
102            None, unittest_constants.CC_NAME_TO_MODULE_INFO)
103        cc_mod_info = native_module_info.NativeModuleInfo()
104        new_parent, new_targets = native_util._get_merged_native_target(
105            cc_mod_info, targets)
106        result = (new_parent, new_targets)
107        self.assertEqual(result, expected)
108
109    @mock.patch.object(native_module_info.NativeModuleInfo,
110                       '_load_module_info_file')
111    @mock.patch.object(native_util, '_find_parent')
112    @mock.patch.object(common_util, 'get_related_paths')
113    def test_get_merged_native_target_is_path(self, mock_get_related,
114                                              mock_find_parent, mock_load_info):
115        """Test _get_merged_native_target function if the target is a path."""
116        parent = 'a/b'
117        rel_path = 'shared/path/to/be/used2'
118        mock_get_related.return_value = rel_path, os.path.join(parent, rel_path)
119        mock_find_parent.return_value = parent
120        mock_load_info.return_value = (
121            None, unittest_constants.CC_NAME_TO_MODULE_INFO)
122        targets = [rel_path]
123        result_targets = unittest_constants.TESTABLE_MODULES_WITH_SHARED_PATH
124        expected = (parent, result_targets)
125        cc_mod_info = native_module_info.NativeModuleInfo()
126        new_parent, new_targets = native_util._get_merged_native_target(
127            cc_mod_info, targets)
128        result = (new_parent, new_targets)
129        self.assertEqual(result, expected)
130
131    def test_filter_out_modules(self):
132        """Test _filter_out_modules with conditions."""
133        targets = ['shared/path/to/be/used2']
134        result = ([], targets)
135        self.assertEqual(
136            result, native_util._filter_out_modules(targets, lambda x: False))
137        targets = ['multiarch']
138        result = (targets, [])
139        self.assertEqual(
140            result, native_util._filter_out_modules(targets, lambda x: True))
141
142    @mock.patch.object(native_util, '_filter_out_rust_projects')
143    @mock.patch.object(native_util, '_analyze_native_and_java_projects')
144    @mock.patch.object(native_util, '_filter_out_modules')
145    def test_get_java_cc_and_rust_projects(self, mock_fil, mock_ana,
146                                           mock_fil_rust):
147        """Test get_java_cc_and_rust_projects handling."""
148        targets = ['multiarch']
149        mock_fil_rust.return_value = []
150        mock_fil.return_value = [], targets
151        cc_mod_info = mock.Mock()
152        cc_mod_info.is_module = mock.Mock()
153        cc_mod_info.is_module.return_value = True
154        at_mod_info = mock.Mock()
155        at_mod_info.is_module = mock.Mock()
156        at_mod_info.is_module.return_value = True
157        mock_ana.return_value = [], targets
158        native_util.get_java_cc_and_rust_projects(
159            at_mod_info, cc_mod_info, targets)
160        self.assertEqual(mock_fil.call_count, 2)
161        self.assertEqual(mock_ana.call_count, 1)
162
163    @mock.patch.object(native_util, '_get_rust_targets')
164    @mock.patch.object(common_util, 'get_json_dict')
165    @mock.patch('builtins.print')
166    @mock.patch('os.path.isfile')
167    @mock.patch('os.path.join')
168    @mock.patch.object(common_util, 'get_blueprint_json_path')
169    @mock.patch.object(common_util, 'get_android_root_dir')
170    def test_filter_out_rust_projects(self, mock_get_root, mock_get_json,
171                                      mock_join, mock_is_file, mock_print,
172                                      mock_get_dict, mock_get_rust):
173        """Test _filter_out_rust_projects with conditions."""
174        mock_is_file.return_value = False
175        native_util._filter_out_rust_projects(['a/b/rust'])
176        self.assertTrue(mock_get_root.called)
177        self.assertTrue(mock_get_json.called)
178        self.assertTrue(mock_join.called)
179        self.assertTrue(mock_print.called)
180        self.assertFalse(mock_get_dict.called)
181        self.assertFalse(mock_get_rust.called)
182
183        mock_get_root.mock_reset()
184        mock_get_json.mock_reset()
185        mock_join.mock_reset()
186        mock_print.mock_reset()
187        mock_get_dict.mock_reset()
188        mock_get_rust.mock_reset()
189        mock_is_file.return_value = True
190        mock_get_dict.return_value = {}
191        native_util._filter_out_rust_projects(['a/b/rust'])
192        self.assertTrue(mock_get_root.called)
193        self.assertTrue(mock_get_json.called)
194        self.assertTrue(mock_join.called)
195        self.assertTrue(mock_print.called)
196        self.assertFalse(mock_get_rust.called)
197
198        mock_get_root.mock_reset()
199        mock_get_json.mock_reset()
200        mock_join.mock_reset()
201        mock_print.mock_reset()
202        mock_get_rust.mock_reset()
203        mock_is_file.return_value = True
204        crates = [{native_util._ROOT_MODULE: 'a/b/rust/src'}]
205        mock_get_dict.return_value = {native_util._CRATES_KEY: crates}
206        mock_get_root.return_value = 'a/b'
207        native_util._filter_out_rust_projects(['a/b/rust'])
208        self.assertTrue(mock_get_json.called)
209        self.assertTrue(mock_join.called)
210        self.assertTrue(mock_get_rust.called)
211        mock_get_rust.assert_called_with(['a/b/rust'], crates, 'a/b')
212
213    @mock.patch.object(project_info, 'batch_build_dependencies')
214    @mock.patch.object(common_util, 'is_source_under_relative_path')
215    @mock.patch('os.path.isdir')
216    def test_get_rust_targets(self, mock_is_dir, mock_is_under, mock_rebuilds):
217        """Test _get_rust_targets with conditions."""
218        mock_is_dir.return_value = True
219        mock_is_under.return_value = True
220        display_name = 'rust_module'
221        mod_info = [
222            {
223                native_util._DISPLAY_NAME: display_name,
224                native_util._ROOT_MODULE: 'a/b/rust/src'
225            }
226        ]
227        targets = ['a/b/rust']
228        self.assertEqual(
229            targets,
230            native_util._get_rust_targets(targets, mod_info, 'a/b'))
231        mock_rebuilds.assert_called_with({display_name})
232
233    def test_get_relative_path(self):
234        """Test _get_relative_path with conditions."""
235        root = common_util.get_android_root_dir()
236        cwd = os.getcwd()
237        rel_target = os.path.relpath(cwd, root)
238        self.assertEqual(rel_target, native_util._get_relative_path('.', root))
239
240        root = 'a/b'
241        target = 'a/b/rust'
242        rel_target = 'rust'
243        self.assertEqual(
244            rel_target, native_util._get_relative_path(target, root))
245
246    def test_is_target_relative_module(self):
247        """Test _is_target_relative_module with conditions."""
248        path = 'a/b'
249        target = 'a/b'
250        self.assertTrue(
251            native_util._is_target_relative_module(path, target))
252
253        path = 'a/b/c'
254        self.assertTrue(
255            native_util._is_target_relative_module(path, target))
256
257        path = 'out/a/b/c'
258        self.assertTrue(
259            native_util._is_target_relative_module(path, target))
260
261        target = 'a/bc'
262        self.assertFalse(
263            native_util._is_target_relative_module(path, target))
264
265
266if __name__ == '__main__':
267    unittest.main()
268