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