• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright 2018, 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 module_info_utils."""
18
19import copy
20import os
21import subprocess
22import unittest
23from unittest import mock
24
25import aidegen.unittest_constants as uc
26from aidegen.lib import errors
27from aidegen.lib import module_info_util
28from atest import module_info
29
30
31_TEST_CLASS_DICT = {'class': ['JAVA_LIBRARIES']}
32_TEST_SRCS_BAR_DICT = {'srcs': ['Bar']}
33_TEST_SRCS_BAZ_DICT = {'srcs': ['Baz']}
34_TEST_DEP_FOO_DIST = {'dependencies': ['Foo']}
35_TEST_DEP_SRC_DICT = {'dependencies': ['Foo'], 'srcs': ['Bar']}
36_TEST_DEP_SRC_MORE_DICT = {'dependencies': ['Foo'], 'srcs': ['Baz', 'Bar']}
37_TEST_MODULE_A_DICT = {
38    'module_a': {
39        'class': ['JAVA_LIBRARIES'],
40        'path': ['path_a'],
41        'installed': ['out/path_a/a.jar'],
42        'dependencies': ['Foo'],
43        'srcs': ['Bar']
44    }
45}
46_TEST_MODULE_A_DICT_HAS_NONEED_ITEMS = {
47    'module_a': {
48        'class': ['JAVA_LIBRARIES'],
49        'path': ['path_a'],
50        'installed': ['out/path_a/a.jar'],
51        'dependencies': ['Foo'],
52        'srcs': ['Bar'],
53        'compatibility_suites': ['null-suite'],
54        'module_name': ['ltp_fstat03_64']
55    }
56}
57_TEST_MODULE_A_JOIN_PATH_DICT = {
58    'module_a': {
59        'class': ['JAVA_LIBRARIES'],
60        'path': ['path_a'],
61        'installed': ['out/path_a/a.jar'],
62        'dependencies': ['Foo'],
63        'srcs': ['path_a/Bar']
64    }
65}
66
67
68# pylint: disable=protected-access
69# pylint: disable=invalid-name
70class AidegenModuleInfoUtilUnittests(unittest.TestCase):
71    """Unit tests for moduole_info_utils.py"""
72
73    def test_merge_module_keys_with_empty_dict(self):
74        """Test _merge_module_keys with an empty dictionary."""
75        test_b_dict = {}
76        test_m_dict = copy.deepcopy(_TEST_DEP_SRC_DICT)
77        module_info_util._merge_module_keys(test_m_dict, test_b_dict)
78        self.assertEqual(_TEST_DEP_SRC_DICT, test_m_dict)
79
80    def test_merge_module_keys_with_key_not_in_orginial_dict(self):
81        """Test _merge_module_keys with the key does not exist in the dictionary
82        to be merged into.
83        """
84        test_b_dict = _TEST_SRCS_BAR_DICT
85        test_m_dict = copy.deepcopy(_TEST_DEP_FOO_DIST)
86        module_info_util._merge_module_keys(test_m_dict, test_b_dict)
87        self.assertEqual(_TEST_DEP_SRC_DICT, test_m_dict)
88
89    def test_merge_module_keys_with_key_in_orginial_dict(self):
90        """Test _merge_module_keys with with the key exists in the dictionary
91        to be merged into.
92        """
93        test_b_dict = _TEST_SRCS_BAZ_DICT
94        test_m_dict = copy.deepcopy(_TEST_DEP_SRC_DICT)
95        module_info_util._merge_module_keys(test_m_dict, test_b_dict)
96        self.assertEqual(
97            set(_TEST_DEP_SRC_MORE_DICT['srcs']), set(test_m_dict['srcs']))
98        self.assertEqual(
99            set(_TEST_DEP_SRC_MORE_DICT['dependencies']),
100            set(test_m_dict['dependencies']))
101
102    def test_merge_module_keys_with_duplicated_item_dict(self):
103        """Test _merge_module_keys with with the key exists in the dictionary
104        to be merged into.
105        """
106        test_b_dict = _TEST_CLASS_DICT
107        test_m_dict = copy.deepcopy(_TEST_CLASS_DICT)
108        module_info_util._merge_module_keys(test_m_dict, test_b_dict)
109        self.assertEqual(_TEST_CLASS_DICT, test_m_dict)
110
111    def test_copy_needed_items_from_empty_dict(self):
112        """Test _copy_needed_items_from an empty dictionary."""
113        test_mk_dict = {}
114        want_dict = {}
115        self.assertEqual(want_dict,
116                         module_info_util._copy_needed_items_from(test_mk_dict))
117
118    def test_copy_needed_items_from_all_needed_items_dict(self):
119        """Test _copy_needed_items_from a dictionary with all needed items."""
120        self.assertEqual(
121            _TEST_MODULE_A_DICT,
122            module_info_util._copy_needed_items_from(_TEST_MODULE_A_DICT))
123
124    def test_copy_needed_items_from_some_needed_items_dict(self):
125        """Test _copy_needed_items_from a dictionary with some needed items."""
126        self.assertEqual(
127            _TEST_MODULE_A_DICT,
128            module_info_util._copy_needed_items_from(
129                _TEST_MODULE_A_DICT_HAS_NONEED_ITEMS))
130
131    @mock.patch('subprocess.check_call')
132    @mock.patch('os.environ.copy')
133    def test_build_target_normal(self, mock_copy, mock_check_call):
134        """Test _build_target with verbose true and false."""
135        mock_copy.return_value = ''
136        amodule_info = module_info.ModuleInfo()
137        cmd = [module_info_util._GENERATE_JSON_COMMAND]
138        module_info_util._build_target(cmd, uc.TEST_MODULE, amodule_info, True)
139        self.assertTrue(mock_copy.called)
140        self.assertTrue(mock_check_call.called)
141        mock_check_call.assert_called_with(
142            cmd,
143            stderr=subprocess.STDOUT,
144            env=mock_copy.return_value,
145            shell=True)
146        module_info_util._build_target(cmd, uc.TEST_MODULE, amodule_info, False)
147        self.assertTrue(mock_check_call.called)
148        mock_check_call.assert_called_with(cmd, shell=True)
149
150    @mock.patch('os.path.getmtime')
151    @mock.patch('os.path.isfile')
152    def test_is_new_json_file_generated(self, mock_isfile, mock_getmtime):
153        """Test _is_new_json_file_generated with different situations."""
154        jfile = 'path/test.json'
155        mock_isfile.return_value = True
156        self.assertEqual(
157            mock_isfile.return_value,
158            module_info_util._is_new_json_file_generated(jfile, None))
159        mock_isfile.return_value = False
160        self.assertEqual(
161            mock_isfile.return_value,
162            module_info_util._is_new_json_file_generated(jfile, None))
163        original_file_mtime = 1000
164        mock_getmtime.return_value = original_file_mtime
165        self.assertEqual(
166            False,
167            module_info_util._is_new_json_file_generated(
168                jfile, original_file_mtime))
169        mock_getmtime.return_value = 1001
170        self.assertEqual(
171            True,
172            module_info_util._is_new_json_file_generated(
173                jfile, original_file_mtime))
174
175    @mock.patch('builtins.input')
176    @mock.patch('glob.glob')
177    def test_build_failed_handle(self, mock_glob, mock_input):
178        """Test _build_failed_handle with different situations."""
179        mock_glob.return_value = ['project/file.iml']
180        mock_input.return_value = 'N'
181        with self.assertRaises(SystemExit) as cm:
182            module_info_util._build_failed_handle(uc.TEST_MODULE)
183        self.assertEqual(cm.exception.code, 1)
184        mock_glob.return_value = []
185        with self.assertRaises(errors.BuildFailureError):
186            module_info_util._build_failed_handle(uc.TEST_MODULE)
187
188    @mock.patch('builtins.open')
189    def test_get_soong_build_json_dict_failed(self, mock_open):
190        """Test _get_soong_build_json_dict failure and raise error."""
191        mock_open.side_effect = IOError
192        with self.assertRaises(errors.JsonFileNotExistError):
193            module_info_util._get_soong_build_json_dict()
194
195    @mock.patch('aidegen.lib.module_info_util._build_failed_handle')
196    @mock.patch('aidegen.lib.module_info_util._is_new_json_file_generated')
197    @mock.patch('subprocess.check_call')
198    def test_build_target(self, mock_call, mock_new, mock_handle):
199        """Test _build_target with different arguments."""
200        cmd = [module_info_util._GENERATE_JSON_COMMAND]
201        main_project = ''
202        amodule_info = {}
203        verbose = False
204        module_info_util._build_target(cmd, main_project, amodule_info, verbose)
205        mock_call.assert_called_with(cmd, shell=True)
206        verbose = True
207        full_env_vars = os.environ.copy()
208        module_info_util._build_target(cmd, main_project, amodule_info, verbose)
209        mock_call.assert_called_with(cmd, stderr=subprocess.STDOUT,
210                                     env=full_env_vars, shell=True)
211        mock_call.side_effect = subprocess.CalledProcessError(1, '')
212        mock_new.return_value = False
213        module_info_util._build_target(cmd, main_project, amodule_info, verbose)
214        self.assertTrue(mock_new.called)
215        self.assertFalse(mock_handle.called)
216        mock_new.return_value = True
217        module_info_util._build_target(cmd, main_project, amodule_info, verbose)
218        self.assertTrue(mock_new.called)
219        self.assertTrue(mock_handle.called)
220
221
222if __name__ == '__main__':
223    unittest.main()
224