Skip to content

Commit

Permalink
Dev: unittest: adjust unit tests for previous changes
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholasyang2022 committed Feb 23, 2024
1 parent 4e36873 commit 9085d07
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 69 deletions.
119 changes: 50 additions & 69 deletions test/unittests/test_report_core.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import subprocess
from crmsh import config
import crmsh.report.sh
from crmsh.report import core, constants, utils, collect
import crmsh.log

Expand Down Expand Up @@ -392,7 +394,7 @@ def test_process_results_no_compress(self, mock_analyze, mock_create, mock_move,
mock_move.assert_called_once_with(mock_ctx_inst.work_dir, mock_ctx_inst.dest_dir)

@mock.patch('crmsh.report.core.finalword')
@mock.patch('crmsh.report.core.sh.cluster_shell')
@mock.patch('crmsh.sh.cluster_shell')
@mock.patch('crmsh.report.core.logger', spec=crmsh.log.DEBUG2Logger)
@mock.patch('crmsh.report.utils.create_description_template')
@mock.patch('crmsh.report.utils.analyze')
Expand Down Expand Up @@ -438,7 +440,7 @@ def test_collect_logs_and_info(self, mock_pool, mock_cpu_count, mock_getmember,
def test_collect_for_nodes(self, mock_start_collector, mock_info, mock_process):
mock_ctx_inst = mock.Mock(
node_list=["node1", "node2"],
ssh_askpw_node_list=["node2"],
passwordless_shell_for_nodes={"node1": mock.Mock(crmsh.report.sh.Shell)},
ssh_user=""
)
mock_process_inst = mock.Mock()
Expand Down Expand Up @@ -479,73 +481,52 @@ def test_process_arguments(self, mock_dest, mock_node_list):
mock_ctx_inst = mock.Mock(from_time=123, to_time=150)
core.process_arguments(mock_ctx_inst)

@mock.patch('crmsh.report.core.logger', spec=crmsh.log.DEBUG2Logger)
@mock.patch('crmsh.utils.check_ssh_passwd_need')
@mock.patch('crmsh.report.core.userdir.getuser')
@mock.patch('crmsh.report.core.userdir.get_sudoer')
def test_find_ssh_user_not_found(self, mock_get_sudoer, mock_getuser, mock_check_ssh, mock_logger):
mock_get_sudoer.return_value = ""
mock_getuser.return_value = "user2"
mock_check_ssh.return_value = True
mock_ctx_inst = mock.Mock(ssh_user="", ssh_askpw_node_list=[], node_list=["node1", "node2"], me="node1")
core.find_ssh_user(mock_ctx_inst)
mock_logger.warning.assert_called_once_with(f"passwordless ssh to node(s) ['node2'] does not work")

@mock.patch('crmsh.report.core.logger', spec=crmsh.log.DEBUG2Logger)
@mock.patch('logging.Logger.warning')
@mock.patch('logging.Logger.debug')
@mock.patch('crmsh.utils.check_ssh_passwd_need')
@mock.patch('crmsh.utils.this_node')
@mock.patch('crmsh.report.core.userdir.getuser')
@mock.patch('crmsh.report.core.userdir.get_sudoer')
def test_find_ssh_user(self, mock_get_sudoer, mock_getuser, mock_this_node, mock_check_ssh, mock_debug, mock_warn, mock_debug2):
mock_get_sudoer.return_value = "user1"
mock_getuser.return_value = "user2"
mock_this_node.return_value = "node1"
mock_check_ssh.return_value = False
mock_ctx_inst = mock.Mock(ssh_user="", ssh_askpw_node_list=[], node_list=["node1", "node2"])
core.find_ssh_user(mock_ctx_inst)
self.assertEqual("sudo", mock_ctx_inst.sudo)
self.assertEqual("user1", mock_ctx_inst.ssh_user)

@mock.patch('logging.Logger.warning')
@mock.patch('crmsh.report.core.ShellUtils')
def test_start_collector_return(self, mock_sh_utils, mock_warn):
mock_sh_utils_inst = mock.Mock()
mock_sh_utils.return_value = mock_sh_utils_inst
mock_sh_utils_inst.get_stdout_stderr.return_value = (0, '', None)
mock_ctx_inst = mock.Mock(me="node1")
core.start_collector("node1", mock_ctx_inst)
mock_sh_utils_inst.get_stdout_stderr.assert_called_once_with(f"{constants.BIN_COLLECTOR} '{mock_ctx_inst}'")

@mock.patch('logging.Logger.warning')
@mock.patch('crmsh.report.core.ShellUtils')
@mock.patch('crmsh.report.core.sh.LocalShell')
@mock.patch('crmsh.utils.this_node')
def test_start_collector_warn(self, mock_this_node, mock_sh, mock_sh_utils, mock_warn):
mock_sh_utils_inst = mock.Mock()
mock_sh_utils.return_value = mock_sh_utils_inst
mock_sh_utils_inst.get_stdout = mock.Mock()
mock_sh_inst = mock.Mock()
mock_sh.return_value = mock_sh_inst
mock_sh_inst.get_rc_stdout_stderr.return_value = (1, '', "error")
mock_ctx_inst = mock.Mock(ssh_user='', sudo='')
mock_this_node.return_value = "node2"
core.start_collector("node1", mock_ctx_inst)
mock_warn.assert_called_once_with("error")
@mock.patch('crmsh.sh.ShellUtils.get_stdout')
@mock.patch('ast.literal_eval')
def test_start_collector(self, mock_literal_eval, mock_get_stdout):
mock_shell = mock.Mock(crmsh.report.sh.Shell)
mock_context = mock.Mock(
ssh_user=None,
passwordless_shell_for_nodes={'node1': mock_shell},
__str__=mock.Mock(return_value='{"foo":"bar"}')
)
mock_shell.subprocess_run_without_input.return_value = mock.Mock(
returncode=0,
stdout=b'',
stderr=b'',
)
core.start_collector('node1', mock_context)
mock_shell.subprocess_run_without_input.assert_called_once_with(
"""/usr/sbin/crm report __collector '{"foo":"bar"}'""",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)

@mock.patch('crmsh.sh.ShellUtils.get_stdout')
@mock.patch('ast.literal_eval')
@mock.patch('crmsh.report.core.sh.LocalShell')
@mock.patch('crmsh.report.core.ShellUtils')
@mock.patch('crmsh.utils.this_node')
def test_start_collector(self, mock_this_node, mock_sh_utils, mock_sh, mock_eval):
mock_sh_utils_inst = mock.Mock()
mock_sh_utils.return_value = mock_sh_utils_inst
mock_sh_utils_inst.get_stdout = mock.Mock()
mock_sh_inst = mock.Mock()
mock_sh.return_value = mock_sh_inst
mock_sh_inst.get_rc_stdout_stderr.return_value = (0, f"line1\n{constants.COMPRESS_DATA_FLAG}data", None)
mock_ctx_inst = mock.Mock(ssh_user='', sudo='')
mock_this_node.return_value = "node2"
mock_eval.return_value = "data"
core.start_collector("node1", mock_ctx_inst)
@mock.patch('logging.Logger.warning')
def test_start_collector_warn(self, mock_warning, mock_literal_eval, mock_get_stdout):
mock_shell = mock.Mock(crmsh.report.sh.Shell)
mock_context = mock.Mock(
ssh_user=None,
passwordless_shell_for_nodes={'node1': mock_shell},
__str__=mock.Mock(return_value='{"foo":"bar"}')
)
mock_shell.subprocess_run_without_input.return_value = mock.Mock(
returncode=1,
stdout=b'',
stderr=b'asdfgh',
)
core.start_collector('node1', mock_context)
mock_shell.subprocess_run_without_input.assert_called_once_with(
"""/usr/sbin/crm report __collector '{"foo":"bar"}'""",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
mock_warning.assert_called_with(
'Failed to run collector on %s: %s: %s',
'node1', 1, 'asdfgh',
)
mock_literal_eval.assert_not_called()
mock_get_stdout.assert_not_called()
87 changes: 87 additions & 0 deletions test/unittests/test_report_sh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import unittest
from unittest import mock

import crmsh.report.sh
import crmsh.sh

import subprocess


class TestFindShell(unittest.TestCase):
def setUp(self) -> None:
self.mock_cluster_shell = mock.Mock(crmsh.sh.ClusterShell)
self.patcher_local_shell = mock.patch('crmsh.report.sh.Shell.local_shell')
self.patcher_try_create_report_shell = mock.patch('crmsh.report.sh.Shell._try_create_report_shell')
self.mock_local_shell = self.patcher_local_shell.start()
self.mock_local_shell.return_value = mock.Mock(crmsh.sh.LocalShell)
self.mock_try_create_report_shell = self.patcher_try_create_report_shell.start()

def tearDown(self) -> None:
self.patcher_local_shell.stop()
self.patcher_try_create_report_shell.stop()

def test_cluster_shell_available(self):
self.mock_cluster_shell.can_run_as.return_value = True
self.assertIsInstance(
crmsh.report.sh.Shell.find_shell(self.mock_cluster_shell, 'node1', None),
crmsh.report.sh.ClusterShellAdaptor,
)
self.assertIsInstance(
crmsh.report.sh.Shell.find_shell(self.mock_cluster_shell, 'node1', 'alice'),
crmsh.report.sh.ClusterShellAdaptor,
)

def test_specified_user_work(self):
self.mock_cluster_shell.can_run_as.return_value = False
self.mock_try_create_report_shell.return_value = mock.Mock(crmsh.report.sh.Shell)
ret = crmsh.report.sh.Shell.find_shell(self.mock_cluster_shell, 'node1', 'alice')
self.mock_local_shell.assert_called_once()
self.mock_try_create_report_shell.assert_called_once_with(
self.mock_local_shell.return_value,
'node1', 'alice',
)
self.assertIs(ret, self.mock_try_create_report_shell.return_value)

class TestTryCreateReportShell(unittest.TestCase):
def setUp(self) -> None:
self.mock_local_shell = mock.Mock(crmsh.sh.LocalShell)
self.patcher_ssh_shell = mock.patch('crmsh.sh.SSHShell')
self.mock_ssh_shell = self.patcher_ssh_shell.start().return_value

def tearDown(self) -> None:
self.patcher_ssh_shell.stop()

def test_success(self):
self.mock_ssh_shell.can_run_as.return_value = True
self.mock_ssh_shell.subprocess_run_without_input.return_value = mock.Mock(returncode=0)
ret = crmsh.report.sh.Shell._try_create_report_shell(self.mock_local_shell, 'node1', 'alice')
self.mock_ssh_shell.can_run_as.assert_called_once_with('node1', 'alice')
self.mock_ssh_shell.subprocess_run_without_input.assert_called_once_with(
'node1', 'alice',
'sudo true',
start_new_session=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
self.assertIsInstance(ret, crmsh.report.sh.Shell)

def test_failure_no_sudoer(self):
self.mock_ssh_shell.can_run_as.return_value = True
self.mock_ssh_shell.subprocess_run_without_input.return_value = mock.Mock(returncode=1)
ret = crmsh.report.sh.Shell._try_create_report_shell(self.mock_local_shell, 'node1', 'alice')
self.mock_ssh_shell.can_run_as.assert_called_once_with('node1', 'alice')
self.mock_ssh_shell.subprocess_run_without_input.assert_called_once_with(
'node1', 'alice',
'sudo true',
start_new_session=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
self.assertIsNone(ret)

def test_failure_no_ssh(self):
self.mock_ssh_shell.can_run_as.return_value = False
ret = crmsh.report.sh.Shell._try_create_report_shell(self.mock_local_shell, 'node1', 'alice')
self.mock_ssh_shell.can_run_as.assert_called_once_with('node1', 'alice')
self.mock_ssh_shell.subprocess_run_without_input.assert_not_called()
self.assertIsNone(ret)

0 comments on commit 9085d07

Please sign in to comment.