1#!/usr/bin/env python3
2#
3# Copyright 2020, 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 IML class."""
18
19import os
20import shutil
21import tempfile
22import unittest
23from unittest import mock
24
25from aidegen import templates
26from aidegen.lib import common_util
27from aidegen.idea import iml
28from atest import module_info
29
30
31# pylint: disable=protected-access
32class IMLGenUnittests(unittest.TestCase):
33    """Unit tests for IMLGenerator class."""
34
35    _TEST_DIR = None
36
37    def setUp(self):
38        """Prepare the testdata related path."""
39        IMLGenUnittests._TEST_DIR = tempfile.mkdtemp()
40        module = {
41            'module_name': 'test',
42            'iml_name': 'test_iml',
43            'path': ['a/b'],
44            'srcs': ['a/b/src'],
45            'tests': ['a/b/tests'],
46            'srcjars': ['x/y.srcjar'],
47            'jars': ['s.jar'],
48            'dependencies': ['m1']
49        }
50        with mock.patch.object(common_util, 'get_android_root_dir') as obj:
51            obj.return_value = IMLGenUnittests._TEST_DIR
52            self.iml = iml.IMLGenerator(module)
53
54    def tearDown(self):
55        """Clear the testdata related path."""
56        self.iml = None
57        shutil.rmtree(IMLGenUnittests._TEST_DIR)
58
59    def test_init(self):
60        """Test initialize the attributes."""
61        self.assertEqual(self.iml._mod_info['module_name'], 'test')
62
63    @mock.patch.object(common_util, 'get_android_root_dir')
64    def test_iml_path(self, mock_root_path):
65        """Test iml_path."""
66        mock_root_path.return_value = IMLGenUnittests._TEST_DIR
67        iml_path = os.path.join(IMLGenUnittests._TEST_DIR, 'a/b/test_iml.iml')
68        self.assertEqual(self.iml.iml_path, iml_path)
69
70    @mock.patch.object(common_util, 'get_android_root_dir')
71    def test_create(self, mock_root_path):
72        """Test create."""
73        mock_root_path.return_value = IMLGenUnittests._TEST_DIR
74        module_path = os.path.join(IMLGenUnittests._TEST_DIR, 'a/b')
75        src_path = os.path.join(IMLGenUnittests._TEST_DIR, 'a/b/src')
76        test_path = os.path.join(IMLGenUnittests._TEST_DIR, 'a/b/tests')
77        srcjar_path = os.path.join(IMLGenUnittests._TEST_DIR, 'x/y.srcjar')
78        jar_path = os.path.join(IMLGenUnittests._TEST_DIR, 's.jar')
79        expected = """<?xml version="1.0" encoding="UTF-8"?>
80<module type="JAVA_MODULE" version="4">
81    <component name="NewModuleRootManager" inherit-compiler-output="true">
82        <exclude-output />
83        <content url="file://{MODULE_PATH}">
84            <sourceFolder url="file://{SRC_PATH}" isTestSource="false" />
85            <sourceFolder url="file://{TEST_PATH}" isTestSource="true" />
86        </content>
87        <orderEntry type="sourceFolder" forTests="false" />
88        <content url="jar://{SRCJAR}!/">
89            <sourceFolder url="jar://{SRCJAR}!/" isTestSource="False" />
90        </content>
91        <orderEntry type="module" module-name="m1" />
92        <orderEntry type="module-library" exported="">
93          <library>
94            <CLASSES>
95              <root url="jar://{JAR}!/" />
96            </CLASSES>
97            <JAVADOC />
98            <SOURCES />
99          </library>
100        </orderEntry>
101        <orderEntry type="inheritedJdk" />
102    </component>
103</module>
104""".format(MODULE_PATH=module_path,
105           SRC_PATH=src_path,
106           TEST_PATH=test_path,
107           SRCJAR=srcjar_path,
108           JAR=jar_path)
109        self.iml.create({'srcs': True, 'srcjars': True, 'dependencies': True,
110                         'jars': True})
111        gen_iml = os.path.join(IMLGenUnittests._TEST_DIR,
112                               self.iml._mod_info['path'][0],
113                               self.iml._mod_info['iml_name'] + '.iml')
114        result = common_util.read_file_content(gen_iml)
115        self.assertEqual(result, expected)
116
117    @mock.patch.object(common_util, 'get_android_root_dir')
118    def test_gen_dep_sources(self, mock_root_path):
119        """Test _generate_dep_srcs."""
120        mock_root_path.return_value = IMLGenUnittests._TEST_DIR
121        src_path = os.path.join(IMLGenUnittests._TEST_DIR, 'a/b/src')
122        test_path = os.path.join(IMLGenUnittests._TEST_DIR, 'a/b/tests')
123        expected = """<?xml version="1.0" encoding="UTF-8"?>
124<module type="JAVA_MODULE" version="4">
125    <component name="NewModuleRootManager" inherit-compiler-output="true">
126        <exclude-output />
127        <content url="file://{SRC_PATH}">
128            <sourceFolder url="file://{SRC_PATH}" isTestSource="false" />
129        </content>
130        <content url="file://{TEST_PATH}">
131            <sourceFolder url="file://{TEST_PATH}" isTestSource="true" />
132        </content>
133        <orderEntry type="sourceFolder" forTests="false" />
134        <orderEntry type="inheritedJdk" />
135    </component>
136</module>
137""".format(SRC_PATH=src_path,
138           TEST_PATH=test_path)
139        self.iml.create({'dep_srcs': True})
140        gen_iml = os.path.join(IMLGenUnittests._TEST_DIR,
141                               self.iml._mod_info['path'][0],
142                               self.iml._mod_info['iml_name'] + '.iml')
143        result = common_util.read_file_content(gen_iml)
144        self.assertEqual(result, expected)
145
146    @mock.patch.object(iml.IMLGenerator, '_create_iml')
147    @mock.patch.object(iml.IMLGenerator, '_generate_dependencies')
148    @mock.patch.object(iml.IMLGenerator, '_generate_srcjars')
149    def test_skip_create_iml(self, mock_gen_srcjars, mock_gen_dep,
150                             mock_create_iml):
151        """Test skipping create_iml."""
152        self.iml.create({'srcjars': False, 'dependencies': False})
153        self.assertFalse(mock_gen_srcjars.called)
154        self.assertFalse(mock_gen_dep.called)
155        self.assertFalse(mock_create_iml.called)
156
157    @mock.patch('os.path.exists')
158    def test_generate_facet(self, mock_exists):
159        """Test _generate_facet."""
160        mock_exists.return_value = False
161        self.iml._generate_facet()
162        self.assertEqual(self.iml._facet, '')
163        mock_exists.return_value = True
164        self.iml._generate_facet()
165        self.assertEqual(self.iml._facet, templates.FACET)
166
167    def test_get_uniq_iml_name(self):
168        """Test the unique name cache mechanism.
169
170        By using the path data in module info json as input, if the count of
171        name data set is the same as sub folder path count, then it means
172        there's no duplicated name, the test PASS.
173        """
174        # Add following test path
175        test_paths = {
176            'cts/tests/tests/app',
177            'cts/tests/app',
178            'cts/tests/app/app1/../app',
179            'cts/tests/app/app2/../app',
180            'cts/tests/app/app3/../app',
181            'frameworks/base/tests/xxxxxxxxxxxx/base',
182            'frameworks/base',
183            'external/xxxxx-xxx/robolectric',
184            'external/robolectric',
185        }
186        mod_info = module_info.ModuleInfo()
187        test_paths.update(mod_info._get_path_to_module_info(
188            mod_info.name_to_module_info).keys())
189        print('\n{} {}.'.format('Test_paths length:', len(test_paths)))
190
191        path_list = []
192        for path in test_paths:
193            path_list.append(path)
194        print('{} {}.'.format('path list with length:', len(path_list)))
195
196        names = [iml.IMLGenerator.get_unique_iml_name(f)
197                 for f in path_list]
198        print('{} {}.'.format('Names list with length:', len(names)))
199        self.assertEqual(len(names), len(path_list))
200        dic = {}
201        for i, path in enumerate(path_list):
202            dic[names[i]] = path
203        print('{} {}.'.format('The size of name set is:', len(dic)))
204        self.assertEqual(len(dic), len(path_list))
205
206
207if __name__ == '__main__':
208    unittest.main()
209