1# Copyright 2019 - 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 pull.""" 15import unittest 16 17import os 18import tempfile 19 20from unittest import mock 21 22from acloud import errors 23from acloud.internal import constants 24from acloud.internal.lib import driver_test_lib 25from acloud.internal.lib import ssh 26from acloud.internal.lib import utils 27from acloud.list import list as list_instances 28from acloud.public import config 29from acloud.pull import pull 30 31 32class PullTest(driver_test_lib.BaseDriverTest): 33 """Test pull.""" 34 35 # pylint: disable=no-member 36 def testPullFileFromInstance(self): 37 """test PullFileFromInstance.""" 38 cfg = mock.MagicMock() 39 cfg.ssh_private_key_path = "fake_ssh_path" 40 cfg.extra_args_ssh_tunnel = "" 41 instance = mock.MagicMock() 42 instance.ip = "1.1.1.1" 43 # Multiple selected files case. 44 selected_files = ["file1.log", "file2.log"] 45 self.Patch(pull, "SelectLogFileToPull", return_value=selected_files) 46 self.Patch(pull, "PullLogs") 47 self.Patch(pull, "DisplayLog") 48 pull.PullFileFromInstance(cfg, instance) 49 self.assertEqual(pull.DisplayLog.call_count, 0) 50 51 # Only one file selected case. 52 selected_files = ["file1.log"] 53 self.Patch(pull, "SelectLogFileToPull", return_value=selected_files) 54 pull.PullFileFromInstance(cfg, instance) 55 self.assertEqual(pull.DisplayLog.call_count, 1) 56 57 def testPullLogs(self): 58 """test PullLogs.""" 59 self.Patch(tempfile, "gettempdir", return_value="/tmp") 60 self.Patch(os.path, "exists", return_value=False) 61 mock_makedirs = self.Patch(os, "makedirs") 62 _ssh = mock.MagicMock() 63 self.Patch(utils, "PrintColorString") 64 65 log_files = ["file1.log", "file2.log"] 66 download_folder = pull.PullLogs(_ssh, log_files, "instance") 67 self.assertEqual(download_folder, "/tmp/instance") 68 mock_makedirs.assert_called_once_with("/tmp/instance") 69 self.assertEqual(_ssh.ScpPullFile.call_count, 2) 70 utils.PrintColorString.assert_called_once() 71 72 @mock.patch.object(ssh.Ssh, "Run") 73 def testDisplayLog(self, mock_ssh_run): 74 """Test DisplayLog.""" 75 fake_ip = ssh.IP(external="1.1.1.1", internal="10.1.1.1") 76 _ssh = ssh.Ssh(ip=fake_ip, 77 user=constants.GCE_USER, 78 ssh_private_key_path="/fake/acloud_rea") 79 self.Patch(utils, "GetUserAnswerYes", return_value="Y") 80 log_file = "file1.log" 81 pull.DisplayLog(_ssh, log_file) 82 expected_cmd = "tail -f -n +1 %s" % log_file 83 mock_ssh_run.assert_has_calls([ 84 mock.call(expected_cmd, show_output=True)]) 85 86 def testSelectLogFileToPull(self): 87 """test choose log files from the remote instance.""" 88 _ssh = mock.MagicMock() 89 90 # Test only one log file case 91 log_files = ["file1.log"] 92 self.Patch(pull, "GetAllLogFilePaths", return_value=log_files) 93 expected_result = ["file1.log"] 94 self.assertEqual(pull.SelectLogFileToPull(_ssh), expected_result) 95 96 # Test no log files case 97 self.Patch(pull, "GetAllLogFilePaths", return_value=[]) 98 with self.assertRaises(errors.CheckPathError): 99 pull.SelectLogFileToPull(_ssh) 100 101 # Test two log files case. 102 log_files = ["file1.log", "file2.log"] 103 choose_log = ["file2.log"] 104 self.Patch(pull, "GetAllLogFilePaths", return_value=log_files) 105 self.Patch(utils, "GetAnswerFromList", return_value=choose_log) 106 expected_result = ["file2.log"] 107 self.assertEqual(pull.SelectLogFileToPull(_ssh), expected_result) 108 109 # Test user provided file name exist. 110 log_files = ["cuttlefish_runtime/file1.log", 111 "cuttlefish_runtime/file2.log"] 112 input_file = "file1.log" 113 self.Patch(pull, "GetAllLogFilePaths", return_value=log_files) 114 expected_result = ["cuttlefish_runtime/file1.log"] 115 self.assertEqual(pull.SelectLogFileToPull(_ssh, input_file), expected_result) 116 117 # Test user provided file name not exist. 118 log_files = ["cuttlefish_runtime/file1.log", 119 "cuttlefish_runtime/file2.log"] 120 input_file = "not_exist.log" 121 self.Patch(pull, "GetAllLogFilePaths", return_value=log_files) 122 with self.assertRaises(errors.CheckPathError): 123 pull.SelectLogFileToPull(_ssh, input_file) 124 125 def testGetAllLogFilePaths(self): 126 """test that GetAllLogFilePaths can filter logs.""" 127 mock_find = self.Patch(utils, "FindRemoteFiles", 128 return_value=["kernel.log", "logcat", "kernel"]) 129 # Filter out file name is "kernel". 130 expected_result = ["kernel.log", "logcat"] 131 self.assertEqual(pull.GetAllLogFilePaths(mock.Mock(), "unit/test"), 132 expected_result) 133 mock_find.assert_called_with(mock.ANY, ["unit/test"]) 134 135 # Filter out file extension is ".img". 136 mock_find.return_value = ["kernel.log", "system.img", "userdata.img", 137 "launcher.log"] 138 expected_result = ["kernel.log", "launcher.log"] 139 self.assertEqual(pull.GetAllLogFilePaths(mock.Mock(), "unit/test"), 140 expected_result) 141 142 @mock.patch.object(pull, "PullFileFromInstance") 143 def testRun(self, mock_pull_file): 144 """test Run.""" 145 cfg = mock.MagicMock() 146 args = mock.MagicMock() 147 instance_obj = mock.MagicMock() 148 # Test case with provided instance name. 149 args.instance_name = "instance_1" 150 args.file_name = "file1.log" 151 args.no_prompt = True 152 self.Patch(config, "GetAcloudConfig", return_value=cfg) 153 self.Patch(list_instances, "GetInstancesFromInstanceNames", 154 return_value=[instance_obj]) 155 pull.Run(args) 156 mock_pull_file.assert_has_calls([ 157 mock.call(cfg, instance_obj, args.file_name, args.no_prompt)]) 158 159 # Test case for user select one instance to pull log. 160 selected_instance = mock.MagicMock() 161 self.Patch(list_instances, "ChooseOneRemoteInstance", 162 return_value=selected_instance) 163 args.instance_name = None 164 pull.Run(args) 165 mock_pull_file.assert_has_calls([ 166 mock.call(cfg, selected_instance, args.file_name, args.no_prompt)]) 167 168 169if __name__ == '__main__': 170 unittest.main() 171