1#!/usr/bin/env python 2# 3# Copyright 2016 - 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"""Tests for acloud.public.config.""" 18import unittest 19import os 20import tempfile 21import mock 22 23import six 24 25# pylint: disable=no-name-in-module,import-error 26from acloud import errors 27from acloud.internal.proto import internal_config_pb2 28from acloud.internal.proto import user_config_pb2 29from acloud.public import config 30 31 32class AcloudConfigManagerTest(unittest.TestCase): 33 """Test acloud configuration manager.""" 34 35 USER_CONFIG = """ 36service_account_name: "fake@developer.gserviceaccount.com" 37service_account_private_key_path: "/path/to/service/account/key" 38service_account_json_private_key_path: "/path/to/service/account/json_key" 39project: "fake-project" 40zone: "us-central1-f" 41machine_type: "n1-standard-1" 42network: "default" 43ssh_private_key_path: "/path/to/ssh/key" 44storage_bucket_name: "fake_bucket" 45orientation: "portrait" 46resolution: "1200x1200x1200x1200" 47client_id: "fake_client_id" 48client_secret: "fake_client_secret" 49extra_args_ssh_tunnel: "fake_extra_args_ssh_tunnel" 50metadata_variable { 51 key: "metadata_1" 52 value: "metadata_value_1" 53} 54hw_property: "cpu:3,resolution:1080x1920,dpi:480,memory:4g,disk:10g" 55extra_scopes: "scope1" 56extra_scopes: "scope2" 57""" 58 59 INTERNAL_CONFIG = """ 60min_machine_size: "n1-standard-1" 61disk_image_name: "avd-system.tar.gz" 62disk_image_mime_type: "application/x-tar" 63disk_image_extension: ".tar.gz" 64disk_raw_image_name: "disk.raw" 65disk_raw_image_extension: ".img" 66creds_cache_file: ".fake_oauth2.dat" 67user_agent: "fake_user_agent" 68kernel_build_target: "kernel" 69emulator_build_target: "sdk_tools_linux" 70 71default_usr_cfg { 72 machine_type: "n1-standard-1" 73 network: "default" 74 stable_host_image_name: "fake_stable_host_image_name" 75 stable_host_image_project: "fake_stable_host_image_project" 76 stable_goldfish_host_image_name: "fake_stable_goldfish_host_image_name" 77 stable_goldfish_host_image_project: "fake_stable_goldfish_host_image_project" 78 instance_name_pattern: "fake_instance_name_pattern" 79 stable_cheeps_host_image_name: "fake_stable_cheeps_host_image_name" 80 stable_cheeps_host_image_project: "fake_stable_cheeps_host_image_project" 81 metadata_variable { 82 key: "metadata_1" 83 value: "metadata_value_1" 84 } 85 86 metadata_variable { 87 key: "metadata_2" 88 value: "metadata_value_2" 89 } 90} 91 92device_resolution_map { 93 key: "nexus5" 94 value: "1080x1920x32x480" 95} 96 97device_default_orientation_map { 98 key: "nexus5" 99 value: "portrait" 100} 101 102valid_branch_and_min_build_id { 103 key: "aosp-master" 104 value: 0 105} 106 107common_hw_property_map { 108 key: "phone" 109 value: "cpu:2,resolution:1080x1920,dpi:420,memory:4g,disk:8g" 110} 111""" 112 113 def setUp(self): 114 self.config_file = mock.MagicMock() 115 116 # pylint: disable=no-member 117 def testLoadUserConfig(self): 118 """Test loading user config.""" 119 self.config_file.read.return_value = self.USER_CONFIG 120 cfg = config.AcloudConfigManager.LoadConfigFromProtocolBuffer( 121 self.config_file, user_config_pb2.UserConfig) 122 self.assertEqual(cfg.service_account_name, 123 "fake@developer.gserviceaccount.com") 124 self.assertEqual(cfg.service_account_private_key_path, 125 "/path/to/service/account/key") 126 self.assertEqual(cfg.service_account_json_private_key_path, 127 "/path/to/service/account/json_key") 128 self.assertEqual(cfg.project, "fake-project") 129 self.assertEqual(cfg.zone, "us-central1-f") 130 self.assertEqual(cfg.machine_type, "n1-standard-1") 131 self.assertEqual(cfg.network, "default") 132 self.assertEqual(cfg.ssh_private_key_path, "/path/to/ssh/key") 133 self.assertEqual(cfg.storage_bucket_name, "fake_bucket") 134 self.assertEqual(cfg.orientation, "portrait") 135 self.assertEqual(cfg.resolution, "1200x1200x1200x1200") 136 self.assertEqual(cfg.client_id, "fake_client_id") 137 self.assertEqual(cfg.client_secret, "fake_client_secret") 138 self.assertEqual(cfg.extra_args_ssh_tunnel, "fake_extra_args_ssh_tunnel") 139 self.assertEqual( 140 {key: val for key, val in six.iteritems(cfg.metadata_variable)}, 141 {"metadata_1": "metadata_value_1"}) 142 self.assertEqual(cfg.hw_property, 143 "cpu:3,resolution:1080x1920,dpi:480,memory:4g," 144 "disk:10g") 145 self.assertEqual(cfg.extra_scopes, ["scope1", "scope2"]) 146 147 # pylint: disable=protected-access 148 @mock.patch("os.makedirs") 149 @mock.patch("os.path.exists") 150 def testLoadUserConfigLogic(self, mock_file_exist, _mock_makedirs): 151 """Test load user config logic. 152 153 Load user config with some special design. 154 1. User specified user config: 155 If user config didn't exist: Raise exception. 156 2. User didn't specify user config, use default config: 157 If default config didn't exist: Initialize empty data. 158 """ 159 config_specify = config.AcloudConfigManager(self.config_file) 160 self.config_file.read.return_value = self.USER_CONFIG 161 self.assertEqual(config_specify.user_config_path, self.config_file) 162 mock_file_exist.return_value = False 163 with self.assertRaises(errors.ConfigError): 164 config_specify.Load() 165 # Test default config 166 config_unspecify = config.AcloudConfigManager(None) 167 cfg = config_unspecify.Load() 168 self.assertEqual(config_unspecify.user_config_path, 169 config.GetDefaultConfigFile()) 170 self.assertEqual(cfg.project, "") 171 self.assertEqual(cfg.zone, "") 172 173 # Test default user config exist 174 mock_file_exist.return_value = True 175 # Write the config data into a tmp file and have GetDefaultConfigFile 176 # return that. 177 _, temp_cfg_file_path = tempfile.mkstemp() 178 with open(temp_cfg_file_path, "w") as cfg_file: 179 cfg_file.writelines(self.USER_CONFIG) 180 default_patcher = mock.patch.object(config, "GetDefaultConfigFile", 181 return_value=temp_cfg_file_path) 182 default_patcher.start() 183 try: 184 config_exist = config.AcloudConfigManager(None) 185 cfg = config_exist.Load() 186 self.assertEqual(cfg.project, "fake-project") 187 self.assertEqual(cfg.zone, "us-central1-f") 188 self.assertEqual(cfg.client_id, "fake_client_id") 189 self.assertEqual(cfg.client_secret, "fake_client_secret") 190 finally: 191 # Delete tmp file 192 os.remove(temp_cfg_file_path) 193 default_patcher.stop() 194 195 def testLoadInternalConfig(self): 196 """Test loading internal config.""" 197 self.config_file.read.return_value = self.INTERNAL_CONFIG 198 cfg = config.AcloudConfigManager.LoadConfigFromProtocolBuffer( 199 self.config_file, internal_config_pb2.InternalConfig) 200 self.assertEqual(cfg.min_machine_size, "n1-standard-1") 201 self.assertEqual(cfg.disk_image_name, "avd-system.tar.gz") 202 self.assertEqual(cfg.disk_image_mime_type, "application/x-tar") 203 self.assertEqual(cfg.disk_image_extension, ".tar.gz") 204 self.assertEqual(cfg.disk_raw_image_name, "disk.raw") 205 self.assertEqual(cfg.disk_raw_image_extension, ".img") 206 self.assertEqual(cfg.creds_cache_file, ".fake_oauth2.dat") 207 self.assertEqual(cfg.user_agent, "fake_user_agent") 208 self.assertEqual(cfg.default_usr_cfg.machine_type, "n1-standard-1") 209 self.assertEqual(cfg.default_usr_cfg.network, "default") 210 self.assertEqual({ 211 key: val 212 for key, val in six.iteritems(cfg.default_usr_cfg.metadata_variable) 213 }, { 214 "metadata_1": "metadata_value_1", 215 "metadata_2": "metadata_value_2" 216 }) 217 self.assertEqual( 218 {key: val for key, val in six.iteritems(cfg.device_resolution_map)}, 219 {"nexus5": "1080x1920x32x480"}) 220 device_resolution = { 221 key: val 222 for key, val in six.iteritems(cfg.device_default_orientation_map) 223 } 224 self.assertEqual(device_resolution, {"nexus5": "portrait"}) 225 valid_branch_and_min_build_id = { 226 key: val 227 for key, val in six.iteritems(cfg.valid_branch_and_min_build_id) 228 } 229 self.assertEqual(valid_branch_and_min_build_id, {"aosp-master": 0}) 230 self.assertEqual(cfg.default_usr_cfg.stable_host_image_name, 231 "fake_stable_host_image_name") 232 self.assertEqual(cfg.default_usr_cfg.stable_host_image_project, 233 "fake_stable_host_image_project") 234 self.assertEqual(cfg.kernel_build_target, "kernel") 235 236 # Emulator related 237 self.assertEqual(cfg.default_usr_cfg.stable_goldfish_host_image_name, 238 "fake_stable_goldfish_host_image_name") 239 self.assertEqual(cfg.default_usr_cfg.stable_goldfish_host_image_project, 240 "fake_stable_goldfish_host_image_project") 241 self.assertEqual(cfg.emulator_build_target, "sdk_tools_linux") 242 self.assertEqual(cfg.default_usr_cfg.instance_name_pattern, 243 "fake_instance_name_pattern") 244 245 # Cheeps related 246 self.assertEqual(cfg.default_usr_cfg.stable_cheeps_host_image_name, 247 "fake_stable_cheeps_host_image_name") 248 self.assertEqual(cfg.default_usr_cfg.stable_cheeps_host_image_project, 249 "fake_stable_cheeps_host_image_project") 250 251 # hw property 252 self.assertEqual( 253 {key: val for key, val in six.iteritems(cfg.common_hw_property_map)}, 254 {"phone": "cpu:2,resolution:1080x1920,dpi:420,memory:4g,disk:8g"}) 255 256 def testLoadConfigFails(self): 257 """Test loading a bad file.""" 258 self.config_file.read.return_value = "malformed text" 259 with self.assertRaises(errors.ConfigError): 260 config.AcloudConfigManager.LoadConfigFromProtocolBuffer( 261 self.config_file, internal_config_pb2.InternalConfig) 262 263 def testOverrideWithHWProperty(self): 264 """Test override hw property by flavor type.""" 265 # initial config with test config. 266 self.config_file.read.return_value = self.INTERNAL_CONFIG 267 internal_cfg = config.AcloudConfigManager.LoadConfigFromProtocolBuffer( 268 self.config_file, internal_config_pb2.InternalConfig) 269 self.config_file.read.return_value = self.USER_CONFIG 270 usr_cfg = config.AcloudConfigManager.LoadConfigFromProtocolBuffer( 271 self.config_file, user_config_pb2.UserConfig) 272 cfg = config.AcloudConfig(usr_cfg, internal_cfg) 273 274 # test override with an exist flavor. 275 cfg.hw_property = None 276 args = mock.MagicMock() 277 args.flavor = "phone" 278 args.which = "create" 279 cfg.OverrideWithArgs(args) 280 self.assertEqual(cfg.hw_property, 281 "cpu:2,resolution:1080x1920,dpi:420,memory:4g,disk:8g") 282 283 # test override with a nonexistent flavor. 284 cfg.hw_property = None 285 args = mock.MagicMock() 286 args.flavor = "non-exist-flavor" 287 args.which = "create" 288 cfg.OverrideWithArgs(args) 289 self.assertEqual(cfg.hw_property, "") 290 291 292if __name__ == "__main__": 293 unittest.main() 294