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 JDKTableXML class.""" 18 19import os 20import shutil 21import tempfile 22import unittest 23 24from unittest import mock 25from xml.etree import ElementTree 26 27from aidegen.lib import aidegen_metrics 28from aidegen.lib import common_util 29from aidegen.lib import xml_util 30from aidegen.sdk import android_sdk 31from aidegen.sdk import jdk_table 32 33 34# pylint: disable=protected-access 35# pylint: disable=too-many-arguments 36class JDKTableXMLUnittests(unittest.TestCase): 37 """Unit tests for JDKTableXML class.""" 38 39 _JDK_TABLE_XML = 'jdk.table.xml' 40 _CONFIG_FILE = '/path/to/jdk.table.xml' 41 _JDK_CONTENT = '<jdk />' 42 _JDK_PATH = '/path/to/JDK' 43 _DEFULAT_ANDROID_SDK_PATH = '/path/to/Android/SDK' 44 45 def setUp(self): 46 """Prepare the JDKTableXML class.""" 47 JDKTableXMLUnittests._TEST_DIR = tempfile.mkdtemp() 48 self.jdk_table_xml = jdk_table.JDKTableXML( 49 self._CONFIG_FILE, self._JDK_CONTENT, self._JDK_PATH, 50 self._DEFULAT_ANDROID_SDK_PATH) 51 52 def tearDown(self): 53 """Clear the JDKTableXML class.""" 54 self.jdk_table_xml = None 55 shutil.rmtree(JDKTableXMLUnittests._TEST_DIR) 56 57 @mock.patch.object(common_util, 'file_generate') 58 @mock.patch('os.path.exists') 59 @mock.patch.object(ElementTree, 'parse') 60 def test_init(self, mock_parse, mock_exists, mock_gen_file): 61 """Test initialize the attributes.""" 62 self.assertEqual(self.jdk_table_xml._platform_version, None) 63 self.assertEqual(self.jdk_table_xml._android_sdk_version, None) 64 self.assertEqual(self.jdk_table_xml._modify_config, False) 65 mock_exists.return_value = True 66 mock_parse.return_value = None 67 jdk_table.JDKTableXML(None, None, None, None) 68 self.assertTrue(mock_parse.called) 69 mock_exists.return_value = False 70 jdk_table.JDKTableXML(None, None, None, None) 71 self.assertTrue(mock_parse.called) 72 self.assertTrue(mock_gen_file.called) 73 74 def test_android_sdk_version(self): 75 """Test android_sdk_version.""" 76 self.assertEqual(self.jdk_table_xml.android_sdk_version, None) 77 78 def test_check_structure(self): 79 """Test _check_structure.""" 80 tmp_file = os.path.join(self._TEST_DIR, self._JDK_TABLE_XML) 81 xml_str = ('<application>\n</application>') 82 with open(tmp_file, 'w') as tmp_jdk_xml: 83 tmp_jdk_xml.write(xml_str) 84 self.jdk_table_xml._xml = ElementTree.parse(tmp_file) 85 self.assertFalse(self.jdk_table_xml._check_structure()) 86 xml_str = ('<application>\n' 87 ' <component>\n' 88 ' </component>\n' 89 '</application>') 90 with open(tmp_file, 'w') as tmp_jdk_xml: 91 tmp_jdk_xml.write(xml_str) 92 self.jdk_table_xml._xml = ElementTree.parse(tmp_file) 93 self.assertFalse(self.jdk_table_xml._check_structure()) 94 xml_str = ('<application>\n' 95 ' <component name="ProjectJdkTable">\n' 96 ' </component>\n' 97 '</application>') 98 with open(tmp_file, 'w') as tmp_jdk_xml: 99 tmp_jdk_xml.write(xml_str) 100 self.jdk_table_xml._xml = ElementTree.parse(tmp_file) 101 self.assertTrue(self.jdk_table_xml._check_structure()) 102 103 @mock.patch.object(jdk_table.JDKTableXML, '_check_jdk18_in_xml') 104 def test_generate_jdk_config_string(self, mock_jdk_exists): 105 """Test _generate_jdk_config_string.""" 106 mock_jdk_exists.return_value = True 107 self.jdk_table_xml._generate_jdk_config_string() 108 self.assertFalse(self.jdk_table_xml._modify_config) 109 mock_jdk_exists.return_value = False 110 expected_result = (b'<application>\n' 111 b' <component name="ProjectJdkTable">\n' 112 b' <jdk />\n' 113 b' </component>\n' 114 b'</application>') 115 self.jdk_table_xml._generate_jdk_config_string() 116 test_result = ElementTree.tostring(self.jdk_table_xml._xml.getroot()) 117 self.assertTrue(self.jdk_table_xml._modify_config) 118 self.assertEqual(test_result, expected_result) 119 xml_str = ('<application>\n' 120 ' <component name="ProjectJdkTable">\n' 121 ' <jdk>\n' 122 ' <name value="test" />\n' 123 ' <type value="JavaSDK" />\n' 124 ' </jdk>\n' 125 ' </component>\n' 126 '</application>') 127 expected_result = (b'<application>\n' 128 b' <component name="ProjectJdkTable">\n' 129 b' <jdk>\n' 130 b' <name value="test" />\n' 131 b' <type value="JavaSDK" />\n' 132 b' </jdk>\n' 133 b' <jdk />\n' 134 b' </component>\n' 135 b'</application>') 136 tmp_file = os.path.join(self._TEST_DIR, self._JDK_TABLE_XML) 137 with open(tmp_file, 'w') as tmp_jdk_xml: 138 tmp_jdk_xml.write(xml_str) 139 self.jdk_table_xml._xml = ElementTree.parse(tmp_file) 140 self.jdk_table_xml._generate_jdk_config_string() 141 test_result = ElementTree.tostring(self.jdk_table_xml._xml.getroot()) 142 self.assertEqual(test_result, expected_result) 143 144 @mock.patch.object(jdk_table.JDKTableXML, '_override_xml') 145 @mock.patch.object(ElementTree.ElementTree, 'write') 146 @mock.patch('os.path.exists') 147 @mock.patch.object(jdk_table.JDKTableXML, '_generate_sdk_config_string') 148 @mock.patch.object(jdk_table.JDKTableXML, '_generate_jdk_config_string') 149 @mock.patch.object(jdk_table.JDKTableXML, '_check_structure') 150 def test_config_jdk_table_xml(self, mock_check_structure, mock_gen_jdk, 151 mock_gen_sdk, mock_exist, mock_xml_write, 152 mock_override): 153 """Test config_jdk_table_xml.""" 154 mock_check_structure.return_value = True 155 mock_exist.return_value = True 156 self.jdk_table_xml.config_jdk_table_xml() 157 self.assertTrue(mock_gen_jdk.called) 158 self.assertTrue(mock_gen_sdk.called) 159 self.jdk_table_xml._modify_config = False 160 self.jdk_table_xml.config_jdk_table_xml() 161 self.assertFalse(mock_xml_write.called) 162 self.jdk_table_xml._modify_config = True 163 self.jdk_table_xml._android_sdk_version = 'test' 164 self.jdk_table_xml.config_jdk_table_xml() 165 self.assertTrue(mock_xml_write.called) 166 mock_check_structure.return_value = False 167 mock_override.return_value = False 168 self.assertFalse(self.jdk_table_xml.config_jdk_table_xml()) 169 mock_check_structure.return_value = False 170 mock_override.return_value = True 171 self.assertTrue(mock_gen_jdk.called) 172 173 def test_check_jdk18_in_xml(self): 174 """Test _check_jdk18_in_xml.""" 175 xml_str = ('<test><jdk><name value="JDK18" /><type value="JavaSDK" />' 176 '</jdk></test>') 177 self.jdk_table_xml._xml = ElementTree.fromstring(xml_str) 178 self.assertTrue(self.jdk_table_xml._check_jdk18_in_xml()) 179 xml_str = ('<test><jdk><name value="test" /><type value="JavaSDK" />' 180 '</jdk></test>') 181 self.jdk_table_xml._xml = ElementTree.fromstring(xml_str) 182 self.assertFalse(self.jdk_table_xml._check_jdk18_in_xml()) 183 xml_str = ('<test><jdk><name value="test" /></jdk></test>') 184 self.jdk_table_xml._xml = ElementTree.fromstring(xml_str) 185 self.assertFalse(self.jdk_table_xml._check_jdk18_in_xml()) 186 187 @mock.patch.object(android_sdk.AndroidSDK, 'is_android_sdk_path') 188 def test_check_android_sdk_in_xml(self, mock_is_android_sdk): 189 """Test _check_android_sdk_in_xml.""" 190 self.jdk_table_xml._sdk._platform_mapping = { 191 'android-29': { 192 'api_level': 29, 193 'code_name': '29', 194 }, 195 } 196 mock_is_android_sdk.return_value = True 197 xml_str = ('<test><jdk><name value="JDK18" /><type value="JavaSDK" />' 198 '</jdk></test>') 199 self.jdk_table_xml._xml = ElementTree.fromstring(xml_str) 200 self.assertFalse(self.jdk_table_xml._check_android_sdk_in_xml()) 201 xml_str = ('<test><jdk><name value="Android SDK 29 platform" />' 202 '<type value="Android SDK" />' 203 '<additional jdk="JDK18" sdk="android-29" />' 204 '</jdk></test>') 205 self.jdk_table_xml._xml = ElementTree.fromstring(xml_str) 206 self.assertFalse(self.jdk_table_xml._check_android_sdk_in_xml()) 207 xml_str = ('<test><jdk><name value="Android SDK 28 platform" />' 208 '<type value="Android SDK" />' 209 '<homePath value="/path/to/Android/SDK" />' 210 '<additional jdk="JDK18" sdk="android-28" />' 211 '</jdk></test>') 212 self.jdk_table_xml._xml = ElementTree.fromstring(xml_str) 213 self.assertFalse(self.jdk_table_xml._check_android_sdk_in_xml()) 214 xml_str = ('<test><jdk><name value="Android SDK 29 platform" />' 215 '<type value="Android SDK" />' 216 '<homePath value="/path/to/Android/SDK" />' 217 '<additional jdk="JDK18" sdk="android-29" />' 218 '</jdk></test>') 219 self.jdk_table_xml._xml = ElementTree.fromstring(xml_str) 220 self.assertTrue(self.jdk_table_xml._check_android_sdk_in_xml()) 221 mock_is_android_sdk.return_value = False 222 self.jdk_table_xml._xml = ElementTree.fromstring(xml_str) 223 self.assertFalse(self.jdk_table_xml._check_android_sdk_in_xml()) 224 225 @mock.patch.object(aidegen_metrics, 'send_exception_metrics') 226 @mock.patch.object(android_sdk.AndroidSDK, 'path_analysis') 227 @mock.patch.object(common_util, 'read_file_content') 228 @mock.patch.object(jdk_table.JDKTableXML, '_check_android_sdk_in_xml') 229 def test_generate_sdk_config_string(self, mock_sdk_in_xml, mock_read_file, 230 mock_path_analysis, mock_metrics): 231 """Test _generate_sdk_config_string.""" 232 mock_sdk_in_xml.return_value = True 233 self.jdk_table_xml._generate_sdk_config_string() 234 self.assertFalse(self.jdk_table_xml._modify_config) 235 mock_sdk_in_xml.return_value = False 236 mock_path_analysis.return_value = False 237 self.jdk_table_xml._generate_sdk_config_string() 238 self.assertTrue(mock_metrics.called) 239 mock_path_analysis.return_value = True 240 mock_read_file.return_value = '' 241 self.jdk_table_xml._generate_sdk_config_string() 242 self.assertTrue(self.jdk_table_xml._modify_config) 243 244 @mock.patch.object(aidegen_metrics, 'send_exception_metrics') 245 @mock.patch('builtins.input') 246 def test_override_xml(self, mock_input, mock_metrics): 247 """Test _override_xml.""" 248 mock_input.side_effect = ['1', 'n'] 249 self.assertFalse(self.jdk_table_xml._override_xml()) 250 self.assertEqual(mock_input.call_count, 2) 251 mock_input.side_effect = ['n'] 252 result = self.jdk_table_xml._override_xml() 253 self.assertFalse(result) 254 mock_input.side_effect = ['y'] 255 expected_result = (b'<application>\n' 256 b' <component name="ProjectJdkTable">\n' 257 b' </component>\n' 258 b'</application>') 259 self.jdk_table_xml._override_xml() 260 test_result = ElementTree.tostring(self.jdk_table_xml._xml.getroot()) 261 self.assertEqual(test_result, expected_result) 262 self.assertTrue(mock_metrics.called) 263 264 @mock.patch.object(xml_util, 'parse_xml') 265 @mock.patch.object(aidegen_metrics, 'send_exception_metrics') 266 @mock.patch('builtins.input') 267 def test_skip_send_metrics(self, mock_input, mock_metrics, mock_parse): 268 """Test _override_xml.""" 269 mock_input.side_effect = ['y'] 270 self.jdk_table_xml._xml = None 271 self.jdk_table_xml._override_xml() 272 self.assertFalse(mock_metrics.called) 273 self.assertTrue(mock_parse.called) 274 275 276if __name__ == '__main__': 277 unittest.main() 278