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