From 5cf109d2e588dfeaaed4e6b78db7def66ecf5e1d Mon Sep 17 00:00:00 2001 From: zhongjun Date: Fri, 29 Sep 2017 09:12:49 +0800 Subject: Add more test function and case in test_utils.py Add more test functions and test case in test_utils.py, test_daisy_server.py and test_environment.py. Change-Id: I7e4ea6993205e1d2f7cc8202820a3ada99613910 Signed-off-by: zhongjun --- tests/unit/test_daisy_server.py | 324 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 317 insertions(+), 7 deletions(-) (limited to 'tests/unit/test_daisy_server.py') diff --git a/tests/unit/test_daisy_server.py b/tests/unit/test_daisy_server.py index ada3c96d..97e0a1e2 100644 --- a/tests/unit/test_daisy_server.py +++ b/tests/unit/test_daisy_server.py @@ -1,18 +1,81 @@ import os import pytest import mock +import paramiko from deploy import daisy_server from deploy.daisy_server import ( - DaisyServer + DaisyServer, + log_from_stream, + log_scp ) +from deploy.utils import WORKSPACE -@pytest.fixture(scope="session") +@pytest.fixture(scope="module") def conf_file_dir(data_root): return os.path.join(data_root, 'lab_conf') +@pytest.fixture(scope="module") +def common_test_file_dir(data_root): + return os.path.join(data_root, 'common') + + +def ssh_test_file_dir(): + return os.path.join(WORKSPACE, 'tests/data/common') + + +def get_ssh_test_command_from_file(dir, file_name): + file_path = os.path.join(dir, file_name) + with open(file_path) as f: + return f.read() + + +data1 = get_ssh_test_command_from_file(ssh_test_file_dir(), 'ssh_stream_data1.txt') +res1 = None +expected_ret1 = None +res2 = 'test_res_commd' +data2 = get_ssh_test_command_from_file(ssh_test_file_dir(), 'ssh_stream_data2.txt') +expected_ret2 = 'test_ssh_cmd3' +data3 = get_ssh_test_command_from_file(ssh_test_file_dir(), 'ssh_stream_data3.txt') + + +@pytest.mark.parametrize('data, res, expected', [ + (data1, res1, expected_ret1), + (data1, res2, expected_ret1), + (data2, res1, expected_ret2), + (data2, res2, expected_ret2), + (data3, res1, expected_ret1), + (data3, res2, expected_ret1)]) +def test_log_from_stream(data, res, expected): + def log_func(str): + print str + pre_val = daisy_server.BLOCK_SIZE + daisy_server.BLOCK_SIZE = 16 + ret = log_from_stream(res, data, log_func) + daisy_server.BLOCK_SIZE = pre_val + assert expected == ret + + +@pytest.mark.parametrize('filename, size, send', [ + ('test_file_name', 1024, 1000), + ('test_file_name', 2048, 2048), + ('test_file_name_1234', 2097152, 2097152)]) +@mock.patch('deploy.daisy_server.LD') +def test_log_scp(mock_LD, filename, size, send): + pre_val = daisy_server.LEN_OF_NAME_PART + daisy_server.LEN_OF_NAME_PART = 24 + log_scp(filename, size, send) + daisy_server.LEN_OF_NAME_PART = pre_val + if size != send: + mock_LD.assert_not_called() + elif len(filename) <= 18: + mock_LD.assert_called_once() + else: + assert mock_LD.call_count == 2 + + daisy_server_info = { 'name': 'daisy', 'image': 'daisy.qcow2', @@ -53,6 +116,239 @@ def test_create_DaisyServer_instance(tmpdir): tmpdir.remove() +@mock.patch.object(daisy_server.paramiko.SSHClient, 'connect') +@mock.patch.object(daisy_server.DaisyServer, 'ssh_run') +def test_connect_DaisyServer(mock_ssh_run, mock_connect, tmpdir): + bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name) + mock_connect.return_value = 0 + DaisyServerInst = DaisyServer(daisy_server_info['name'], + daisy_server_info['address'], + daisy_server_info['password'], + remote_dir, + bin_file, + adapter, + scenario, + deploy_file_name, + net_file_name) + DaisyServerInst.connect() + mock_ssh_run.assert_called_once_with('ls -al', check=True) + tmpdir.remove() + + +@mock.patch.object(daisy_server.paramiko.SSHClient, 'close') +@mock.patch.object(daisy_server.paramiko.SSHClient, 'connect') +@mock.patch.object(daisy_server.DaisyServer, 'ssh_run') +def test_close_DaisyServer(mock_ssh_run, mock_connect, + mock_close, tmpdir): + bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name) + mock_connect.return_value = 0 + mock_ssh_run.return_valule = 0 + mock_close.return_value = 0 + DaisyServerInst = DaisyServer(daisy_server_info['name'], + daisy_server_info['address'], + daisy_server_info['password'], + remote_dir, + bin_file, + adapter, + scenario, + deploy_file_name, + net_file_name) + DaisyServerInst.connect() + DaisyServerInst.close() + mock_close.assert_called_once_with() + tmpdir.remove() + + +stdout1 = open(os.path.join(ssh_test_file_dir(), 'sim_stdout_file')) +stdin1 = open(os.path.join(ssh_test_file_dir(), 'sim_stdout_file')) +stderr1 = open(os.path.join(ssh_test_file_dir(), 'sim_stderr_file')) +stderr2 = open(os.path.join(ssh_test_file_dir(), 'sim_stdout_file')) + + +@pytest.mark.parametrize('stdout, stdin, stderr', [ + (stdout1, stdin1, stderr1), + (stdout1, stdin1, stderr2)]) +@mock.patch('deploy.daisy_server.err_exit') +@mock.patch.object(daisy_server.paramiko.SSHClient, 'connect') +@mock.patch.object(daisy_server.paramiko.SSHClient, 'exec_command') +@mock.patch.object(daisy_server.DaisyServer, 'ssh_run') +def test_ssh_exec_cmd_DaisyServer(mock_ssh_run, mock_exec_command, + mock_connect, mock_err_exit, + stdout, stdin, stderr, tmpdir): + bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name) + cmd = 'ls -l' + mock_connect.return_value = 0 + mock_ssh_run.return_valule = 0 + expect = 'stdout file data' + mock_exec_command.return_value = (stdin, stdout, stderr) + DaisyServerInst = DaisyServer(daisy_server_info['name'], + daisy_server_info['address'], + daisy_server_info['password'], + remote_dir, + bin_file, + adapter, + scenario, + deploy_file_name, + net_file_name) + DaisyServerInst.connect() + ret = DaisyServerInst.ssh_exec_cmd(cmd) + mock_exec_command.assert_called_once() + if stderr == stderr1: + if stdout == stdout1: + assert ret == expect + elif stderr == stderr2: + mock_err_exit.assert_called_once_with('SSH client error occurred') + tmpdir.remove() + + +@pytest.mark.parametrize('check, is_recv_exit_status, expect', [ + (False, 0, 0), + (True, 1, 1)]) +@mock.patch('deploy.daisy_server.err_exit') +@mock.patch.object(daisy_server.paramiko.SSHClient, 'get_transport') +def test_ssh_run_DaisyServer(mock_get_transport, mock_err_exit, + check, is_recv_exit_status, + expect, tmpdir): + class TestSession(): + + def __init__(self, is_recv_exit_status): + self.recv_data = 'recv_test_data' + self.recv_data_total_len = len(self.recv_data) + self.recv_data_read_index = 0 + self.recv_err_data = 'recv_test_err_data' + self.recv_err_data_total_len = len(self.recv_err_data) + self.recv_err_data_read_index = 0 + self.is_recv_exit_status = is_recv_exit_status + return None + + def exec_command(self, cmd): + return 0 + + def recv_ready(self): + return True + + def recv(self, size): + if self.recv_data_read_index < self.recv_data_total_len: + if size <= self.recv_data_total_len - self.recv_data_read_index: + cur_index = self.recv_data_read_index + self.recv_data_read_index += size + return self.recv_data[cur_index:self.recv_data_read_index] + else: + cur_index = self.recv_data_read_index + self.recv_data_read_index = self.recv_data_total_len + return self.recv_data[cur_index:] + else: + return None + + def recv_stderr_ready(self): + return True + + def recv_stderr(self, size): + if self.recv_err_data_read_index < self.recv_err_data_total_len: + if size <= self.recv_err_data_total_len - self.recv_err_data_read_index: + cur_index = self.recv_err_data_read_index + self.recv_err_data_read_index += size + return self.recv_err_data[cur_index:self.recv_err_data_read_index] + else: + cur_index = self.recv_err_data_read_index + self.recv_err_data_read_index = self.recv_err_data_total_len + return self.recv_err_data[cur_index:] + else: + return None + + def exit_status_ready(self): + return True + + def recv_exit_status(self): + return self.is_recv_exit_status + + class TestTransport(): + def __init__(self, is_recv_exit_status): + self.is_recv_exit_status = is_recv_exit_status + + def set_keepalive(self, time): + self.time = time + + def open_session(self): + return TestSession(is_recv_exit_status) + + bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name) + cmd = 'ls -l' + mock_get_transport.return_value = TestTransport(is_recv_exit_status) + DaisyServerInst = DaisyServer(daisy_server_info['name'], + daisy_server_info['address'], + daisy_server_info['password'], + remote_dir, + bin_file, + adapter, + scenario, + deploy_file_name, + net_file_name) + DaisyServerInst.ssh_client = paramiko.SSHClient() + DaisyServerInst.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ret = DaisyServerInst.ssh_run(cmd, check=check) + if check and is_recv_exit_status: + mock_err_exit.assert_called_once() + assert ret == expect + tmpdir.remove() + + +@mock.patch.object(daisy_server.scp.SCPClient, 'get') +@mock.patch.object(daisy_server.paramiko.SSHClient, 'get_transport') +@mock.patch.object(daisy_server.paramiko.SSHClient, 'connect') +@mock.patch.object(daisy_server.paramiko.SSHClient, 'exec_command') +@mock.patch.object(daisy_server.DaisyServer, 'ssh_run') +def test_scp_get_DaisyServer(mock_ssh_run, mock_exec_command, + mock_connect, mock_get_transport, + mock_get, tmpdir): + bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name) + mock_connect.return_value = 0 + mock_ssh_run.return_valule = 0 + remote = '/remote_dir' + local = '.' + DaisyServerInst = DaisyServer(daisy_server_info['name'], + daisy_server_info['address'], + daisy_server_info['password'], + remote_dir, + bin_file, + adapter, + scenario, + deploy_file_name, + net_file_name) + DaisyServerInst.connect() + DaisyServerInst.scp_get(remote, local) + mock_get.assert_called_once_with(remote, local_path=local, recursive=True) + tmpdir.remove() + + +@mock.patch.object(daisy_server.scp.SCPClient, 'put') +@mock.patch.object(daisy_server.paramiko.SSHClient, 'get_transport') +@mock.patch.object(daisy_server.paramiko.SSHClient, 'connect') +@mock.patch.object(daisy_server.paramiko.SSHClient, 'exec_command') +@mock.patch.object(daisy_server.DaisyServer, 'ssh_run') +def test_scp_put_DaisyServer(mock_ssh_run, mock_exec_command, + mock_connect, mock_get_transport, + mock_put, tmpdir): + bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name) + mock_connect.return_value = 0 + mock_ssh_run.return_valule = 0 + remote = '.' + local = '/tmp' + DaisyServerInst = DaisyServer(daisy_server_info['name'], + daisy_server_info['address'], + daisy_server_info['password'], + remote_dir, + bin_file, + adapter, + scenario, + deploy_file_name, + net_file_name) + DaisyServerInst.connect() + DaisyServerInst.scp_put(local, remote) + mock_put.assert_called_once_with(local, remote_path=remote, recursive=True) + tmpdir.remove() + + @mock.patch.object(daisy_server.DaisyServer, 'ssh_exec_cmd') def test_create_dir_DaisyServer(mock_ssh_exec_cmd, tmpdir): remote_dir_test = '/home/daisy/test' @@ -91,6 +387,13 @@ def test_delete_dir_DaisyServer(mock_ssh_exec_cmd, tmpdir): tmpdir.remove() +bin_file_path1 = os.path.join('/tmp', bin_file_name) +bin_file_path2 = os.path.join(WORKSPACE, bin_file_name) + + +@pytest.mark.parametrize('bin_file', [ + (bin_file_path1), + (bin_file_path2)]) @mock.patch.object(daisy_server.DaisyServer, 'delete_dir') @mock.patch.object(daisy_server.DaisyServer, 'scp_put') @mock.patch.object(daisy_server.DaisyServer, 'create_dir') @@ -99,8 +402,8 @@ def test_prepare_files_DaisyServer(mock_update_config, mock_create_dir, mock_scp_put, mock_delete_dir, + bin_file, tmpdir): - bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name) DaisyServerInst = DaisyServer(daisy_server_info['name'], daisy_server_info['address'], daisy_server_info['password'], @@ -113,7 +416,10 @@ def test_prepare_files_DaisyServer(mock_update_config, DaisyServerInst.prepare_files() DaisyServerInst.delete_dir.assert_called_once_with(remote_dir) DaisyServerInst.create_dir.assert_called_once_with('/home/daisy_install') - assert DaisyServerInst.scp_put.call_count == 3 + if bin_file == bin_file_path1: + assert DaisyServerInst.scp_put.call_count == 3 + else: + assert DaisyServerInst.scp_put.call_count == 2 tmpdir.remove() @@ -138,10 +444,11 @@ def test_install_daisy_DaisyServer(mock_prepare_files, mock_ssh_run, tmpdir): tmpdir.remove() +@pytest.mark.parametrize('adapter', [ + ('libvirt'), ('ipmi')]) @mock.patch.object(daisy_server.DaisyServer, 'ssh_run') -def test_prepare_configurations_DaisyServer(mock_ssh_run, tmpdir): +def test_prepare_configurations_DaisyServer(mock_ssh_run, adapter, tmpdir): bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name) - adapter = 'libvirt' DaisyServerInst = DaisyServer(daisy_server_info['name'], daisy_server_info['address'], daisy_server_info['password'], @@ -158,7 +465,10 @@ def test_prepare_configurations_DaisyServer(mock_ssh_run, tmpdir): net_file=os.path.join(remote_dir, net_file_name), is_bare=1 if adapter == 'ipmi' else 0) DaisyServerInst.prepare_configurations() - DaisyServerInst.ssh_run.assert_called_once_with(cmd) + if adapter == 'libvirt': + DaisyServerInst.ssh_run.assert_called_once_with(cmd) + else: + DaisyServerInst.ssh_run.assert_not_called() tmpdir.remove() -- cgit 1.2.3-korg