1# Copyright 2018 - The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Tests for list.""" 15 16import unittest 17 18from unittest import mock 19 20from acloud import errors 21from acloud.internal.lib import cvd_runtime_config 22from acloud.internal.lib import driver_test_lib 23from acloud.internal.lib import utils 24from acloud.list import list as list_instance 25from acloud.list import instance 26 27 28class InstanceObject: 29 """Mock to store data of instance.""" 30 31 def __init__(self, name): 32 self.name = name 33 34 35class ListTest(driver_test_lib.BaseDriverTest): 36 """Test list.""" 37 38 def testGetInstancesFromInstanceNames(self): 39 """test get instances from instance names.""" 40 cfg = mock.MagicMock() 41 instance_names = ["alive_instance1", "alive_local_instance"] 42 43 alive_instance1 = InstanceObject("alive_instance1") 44 alive_instance2 = InstanceObject("alive_instance2") 45 alive_local_instance = InstanceObject("alive_local_instance") 46 47 self.Patch(list_instance, "GetLocalInstancesByNames", 48 return_value=[alive_local_instance]) 49 self.Patch(list_instance, "GetRemoteInstances", 50 return_value=[alive_instance1, alive_instance2]) 51 instances_list = list_instance.GetInstancesFromInstanceNames(cfg, instance_names) 52 instances_name_in_list = [instance_object.name for instance_object in instances_list] 53 self.assertEqual(instances_name_in_list.sort(), instance_names.sort()) 54 55 instance_names = ["alive_instance1", "alive_local_instance", "alive_local_instance"] 56 instances_list = list_instance.GetInstancesFromInstanceNames(cfg, instance_names) 57 instances_name_in_list = [instance_object.name for instance_object in instances_list] 58 self.assertEqual(instances_name_in_list.sort(), instance_names.sort()) 59 60 # test get instance from instance name error with invalid input. 61 instance_names = ["miss2_local_instance", "alive_instance1"] 62 miss_instance_names = ["miss2_local_instance"] 63 self.assertRaisesRegex( 64 errors.NoInstancesFound, 65 "Did not find the following instances: %s" % ' '.join(miss_instance_names), 66 list_instance.GetInstancesFromInstanceNames, 67 cfg=cfg, 68 instance_names=instance_names) 69 70 def testChooseOneRemoteInstance(self): 71 """test choose one remote instance from instance names.""" 72 cfg = mock.MagicMock() 73 74 # Test only one instance case 75 instance_names = ["cf_instance1"] 76 self.Patch(list_instance, "GetCFRemoteInstances", return_value=instance_names) 77 expected_instance = "cf_instance1" 78 self.assertEqual(list_instance.ChooseOneRemoteInstance(cfg), expected_instance) 79 80 # Test no instance case 81 self.Patch(list_instance, "GetCFRemoteInstances", return_value=[]) 82 with self.assertRaises(errors.NoInstancesFound): 83 list_instance.ChooseOneRemoteInstance(cfg) 84 85 # Test two instances case. 86 instance_names = ["cf_instance1", "cf_instance2"] 87 choose_instance = ["cf_instance2"] 88 self.Patch(list_instance, "GetCFRemoteInstances", return_value=instance_names) 89 self.Patch(utils, "GetAnswerFromList", return_value=choose_instance) 90 expected_instance = "cf_instance2" 91 self.assertEqual(list_instance.ChooseOneRemoteInstance(cfg), expected_instance) 92 93 def testGetLocalInstancesByNames(self): 94 """test GetLocalInstancesByNames.""" 95 self.Patch( 96 instance, "GetLocalInstanceIdByName", 97 side_effect=lambda name: 1 if name == "local-instance-1" else None) 98 self.Patch(instance, "GetLocalInstanceConfig", 99 return_value="path1") 100 self.Patch(instance, "GetDefaultCuttlefishConfig", 101 return_value="path2") 102 mock_cf_ins = mock.Mock() 103 mock_cf_ins.name = "local-instance-1" 104 mock_get_cf = self.Patch(list_instance, 105 "_GetLocalCuttlefishInstances", 106 return_value=[mock_cf_ins]) 107 mock_gf_ins = mock.Mock() 108 mock_gf_ins.name = "local-goldfish-instance-1" 109 self.Patch(instance.LocalGoldfishInstance, "GetExistingInstances", 110 return_value=[mock_gf_ins]) 111 112 ins_list = list_instance.GetLocalInstancesByNames([ 113 mock_cf_ins.name, "local-instance-6", mock_gf_ins.name]) 114 self.assertEqual([mock_cf_ins, mock_gf_ins], ins_list) 115 mock_get_cf.assert_called_with([(1, "path1"), (1, "path2")]) 116 117 # pylint: disable=attribute-defined-outside-init 118 def testFilterInstancesByAdbPort(self): 119 """test FilterInstancesByAdbPort.""" 120 alive_instance1 = InstanceObject("alive_instance1") 121 alive_instance1.adb_port = 1111 122 alive_instance1.fullname = "device serial: 127.0.0.1:1111 alive_instance1" 123 expected_instance = [alive_instance1] 124 # Test to find instance by adb port number. 125 self.assertEqual( 126 expected_instance, 127 list_instance.FilterInstancesByAdbPort(expected_instance, 1111)) 128 # Test for instance can't be found by adb port number. 129 with self.assertRaises(errors.NoInstancesFound): 130 list_instance.FilterInstancesByAdbPort(expected_instance, 2222) 131 132 # pylint: disable=protected-access 133 def testGetLocalCuttlefishInstances(self): 134 """test _GetLocalCuttlefishInstances.""" 135 # Test getting two instance case 136 id_cfg_pairs = [(1, "fake_path1"), (2, "fake_path2")] 137 mock_isfile = self.Patch(list_instance.os.path, "isfile", 138 return_value=True) 139 140 mock_lock = mock.Mock() 141 mock_lock.Lock.return_value = True 142 self.Patch(instance, "GetLocalInstanceLock", return_value=mock_lock) 143 144 local_ins = mock.MagicMock() 145 local_ins.CvdStatus.return_value = True 146 self.Patch(instance, "LocalInstance", return_value=local_ins) 147 148 ins_list = list_instance._GetLocalCuttlefishInstances(id_cfg_pairs) 149 self.assertEqual(2, len(ins_list)) 150 mock_isfile.assert_called() 151 local_ins.CvdStatus.assert_called() 152 self.assertEqual(2, mock_lock.Lock.call_count) 153 self.assertEqual(2, mock_lock.Unlock.call_count) 154 155 local_ins.CvdStatus.reset_mock() 156 mock_lock.Lock.reset_mock() 157 mock_lock.Lock.return_value = False 158 mock_lock.Unlock.reset_mock() 159 ins_list = list_instance._GetLocalCuttlefishInstances(id_cfg_pairs) 160 self.assertEqual(0, len(ins_list)) 161 local_ins.CvdStatus.assert_not_called() 162 self.assertEqual(2, mock_lock.Lock.call_count) 163 mock_lock.Unlock.assert_not_called() 164 165 mock_lock.Lock.reset_mock() 166 mock_lock.Lock.return_value = True 167 local_ins.CvdStatus.return_value = False 168 ins_list = list_instance._GetLocalCuttlefishInstances(id_cfg_pairs) 169 self.assertEqual(0, len(ins_list)) 170 self.assertEqual(2, mock_lock.Lock.call_count) 171 self.assertEqual(2, mock_lock.Unlock.call_count) 172 173 # pylint: disable=no-member 174 def testPrintInstancesDetails(self): 175 """test PrintInstancesDetails.""" 176 # Test instance Summary should be called if verbose 177 self.Patch(instance.Instance, "Summary") 178 cf_config = mock.MagicMock( 179 x_res=728, 180 y_res=728, 181 dpi=240, 182 instance_dir="fake_dir", 183 adb_ip_port="127.0.0.1:6520" 184 ) 185 self.Patch(cvd_runtime_config, "CvdRuntimeConfig", 186 return_value=cf_config) 187 188 ins = instance.LocalInstance("fake_cf_path") 189 list_instance.PrintInstancesDetails([ins], verbose=True) 190 instance.Instance.Summary.assert_called_once() 191 192 # Test Summary shouldn't be called if not verbose 193 self.Patch(instance.Instance, "Summary") 194 list_instance.PrintInstancesDetails([ins], verbose=False) 195 instance.Instance.Summary.assert_not_called() 196 197 # Test Summary shouldn't be called if no instance found. 198 list_instance.PrintInstancesDetails([], verbose=True) 199 instance.Instance.Summary.assert_not_called() 200 201 202if __name__ == "__main__": 203 unittest.main() 204