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