Skip to content

Commit

Permalink
Dev: unittest: Add unit test for previous changes
Browse files Browse the repository at this point in the history
  • Loading branch information
liangxin1300 committed Nov 5, 2021
1 parent d726b51 commit 685c93a
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 44 deletions.
21 changes: 18 additions & 3 deletions test/unittests/test_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,21 @@ def tearDownClass(cls):
Global tearDown.
"""

@mock.patch('crmsh.log.LoggerUtils.status_long')
@mock.patch('crmsh.utils.start_service')
@mock.patch('crmsh.sbd.SBDManager.get_suitable_sbd_systemd_timeout')
@mock.patch('crmsh.sbd.SBDManager.is_delay_start')
@mock.patch('crmsh.utils.service_is_enabled')
@mock.patch('crmsh.utils.package_is_installed')
def test_start_pacemaker(self, mock_installed, mock_enabled, mock_delay_start, mock_timeout, mock_start, mock_long):
mock_installed.return_value = True
mock_enabled.return_value = True
mock_delay_start.return_value = True
mock_timeout.return_value = 60
bootstrap.start_pacemaker()
mock_long.assert_called_once_with('Starting pacemaker(waiting for sbd 60s)')
mock_start.assert_called_once_with('pacemaker.service', enable=True, node_list=[])

@mock.patch('crmsh.bootstrap.configure_local_ssh_key')
@mock.patch('crmsh.utils.start_service')
def test_init_ssh(self, mock_start_service, mock_config_ssh):
Expand Down Expand Up @@ -1049,7 +1064,7 @@ def test_invokerc(self, mock_invoke):
self.assertEqual(res, True)
mock_invoke.assert_called_once_with("cmd")

@mock.patch('crmsh.utils.is_quorate')
@mock.patch('crmsh.utils.calculate_quorate_status')
@mock.patch('crmsh.utils.get_quorum_votes_dict')
def test_evaluate_qdevice_quorum_effect_reload(self, mock_get_dict, mock_quorate):
mock_get_dict.return_value = {'Expected': '2', 'Total': '2'}
Expand All @@ -1060,7 +1075,7 @@ def test_evaluate_qdevice_quorum_effect_reload(self, mock_get_dict, mock_quorate
mock_quorate.assert_called_once_with(3, 2)

@mock.patch('crmsh.utils.has_resource_running')
@mock.patch('crmsh.utils.is_quorate')
@mock.patch('crmsh.utils.calculate_quorate_status')
@mock.patch('crmsh.utils.get_quorum_votes_dict')
def test_evaluate_qdevice_quorum_effect_reload(self, mock_get_dict, mock_quorate, mock_ra_running):
mock_get_dict.return_value = {'Expected': '2', 'Total': '2'}
Expand All @@ -1073,7 +1088,7 @@ def test_evaluate_qdevice_quorum_effect_reload(self, mock_get_dict, mock_quorate
mock_ra_running.assert_called_once_with()

@mock.patch('crmsh.utils.has_resource_running')
@mock.patch('crmsh.utils.is_quorate')
@mock.patch('crmsh.utils.calculate_quorate_status')
@mock.patch('crmsh.utils.get_quorum_votes_dict')
def test_evaluate_qdevice_quorum_effect(self, mock_get_dict, mock_quorate, mock_ra_running):
mock_get_dict.return_value = {'Expected': '2', 'Total': '2'}
Expand Down
65 changes: 46 additions & 19 deletions test/unittests/test_ui_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,48 +38,75 @@ def tearDownClass(cls):

@mock.patch('logging.Logger.info')
@mock.patch('crmsh.utils.service_is_active')
def test_do_start_already_started(self, mock_active, mock_info):
@mock.patch('crmsh.ui_cluster.parse_option_for_nodes')
def test_do_start_already_started(self, mock_parse_nodes, mock_active, mock_info):
context_inst = mock.Mock()
mock_active.return_value = True
self.ui_cluster_inst.do_start(context_inst)
mock_active.assert_called_once_with("pacemaker.service")
mock_info.assert_called_once_with("Cluster services already started")
mock_parse_nodes.return_value = ["node1", "node2"]
mock_active.side_effect = [True, True]
self.ui_cluster_inst.do_start(context_inst, "node1", "node2")
mock_parse_nodes.assert_called_once_with(context_inst, "node1", "node2")
mock_active.assert_has_calls([
mock.call("pacemaker.service", remote_addr="node1"),
mock.call("pacemaker.service", remote_addr="node2")
])
mock_info.assert_has_calls([
mock.call("Cluster services already started on node1"),
mock.call("Cluster services already started on node2")
])

@mock.patch('crmsh.bootstrap.start_pacemaker')
@mock.patch('logging.Logger.info')
@mock.patch('crmsh.utils.is_qdevice_configured')
@mock.patch('crmsh.utils.start_service')
@mock.patch('crmsh.utils.service_is_active')
def test_do_start(self, mock_active, mock_start, mock_qdevice_configured, mock_info, mock_start_pacemaker):
@mock.patch('crmsh.ui_cluster.parse_option_for_nodes')
def test_do_start(self, mock_parse_nodes, mock_active, mock_start, mock_qdevice_configured, mock_info, mock_start_pacemaker):
context_inst = mock.Mock()
mock_parse_nodes.return_value = ["node1"]
mock_active.return_value = False
mock_qdevice_configured.return_value = True

self.ui_cluster_inst.do_start(context_inst)
self.ui_cluster_inst.do_start(context_inst, "node1")

mock_active.assert_called_once_with("pacemaker.service")
mock_start.assert_has_calls([mock.call("corosync-qdevice")])
mock_active.assert_called_once_with("pacemaker.service", remote_addr="node1")
mock_start.assert_called_once_with("corosync-qdevice", node_list=["node1"])
mock_qdevice_configured.assert_called_once_with()
mock_info.assert_called_once_with("Cluster services started")
mock_info.assert_called_once_with("Cluster services started on node1")

@mock.patch('logging.Logger.info')
@mock.patch('crmsh.utils.service_is_active')
def test_do_stop_already_stopped(self, mock_active, mock_info):
@mock.patch('crmsh.ui_cluster.parse_option_for_nodes')
def test_do_stop_already_stopped(self, mock_parse_nodes, mock_active, mock_info):
context_inst = mock.Mock()
mock_parse_nodes.return_value = ["node1"]
mock_active.return_value = False
self.ui_cluster_inst.do_stop(context_inst)
mock_active.assert_called_once_with("corosync.service")
mock_info.assert_called_once_with("Cluster services already stopped")
self.ui_cluster_inst.do_stop(context_inst, "node1")
mock_active.assert_called_once_with("corosync.service", remote_addr="node1")
mock_info.assert_called_once_with("Cluster services already stopped on node1")

@mock.patch('logging.Logger.info')
@mock.patch('crmsh.utils.stop_service')
@mock.patch('crmsh.utils.set_dlm_option')
@mock.patch('crmsh.utils.is_quorate')
@mock.patch('crmsh.utils.is_dlm_configured')
@mock.patch('crmsh.utils.service_is_active')
def test_do_stop(self, mock_active, mock_stop, mock_info):
@mock.patch('crmsh.ui_cluster.parse_option_for_nodes')
def test_do_stop(self, mock_parse_nodes, mock_active, mock_dlm_configured, mock_is_quorate, mock_set_dlm, mock_stop, mock_info):
context_inst = mock.Mock()
mock_parse_nodes.return_value = ["node1"]
mock_active.side_effect = [True, True]
mock_dlm_configured.return_value = True
mock_is_quorate.return_value = False

self.ui_cluster_inst.do_stop(context_inst)
self.ui_cluster_inst.do_stop(context_inst, "node1")

mock_active.assert_has_calls([mock.call("corosync.service"), mock.call("corosync-qdevice")])
mock_stop.assert_has_calls([mock.call("corosync-qdevice"), mock.call("corosync")])
mock_info.assert_called_once_with("Cluster services stopped")
mock_active.assert_has_calls([
mock.call("corosync.service", remote_addr="node1"),
mock.call("corosync-qdevice.service")
])
mock_stop.assert_has_calls([
mock.call("pacemaker", node_list=["node1"]),
mock.call("corosync-qdevice.service", node_list=["node1"]),
mock.call("corosync", node_list=["node1"])
])
mock_info.assert_called_once_with("Cluster services stopped on node1")
152 changes: 130 additions & 22 deletions test/unittests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,24 +188,6 @@ def test_get_member_iplist():
mock_get_stdout_stderr.assert_called_once_with('corosync-cmapctl -b runtime.totem.pg.mrp.srp.members')


def test_list_cluster_nodes_pacemaker_running():
with mock.patch('crmsh.utils.stdout2list') as mock_stdout2list:
crm_node_value= ["336860211 15sp1-1 member", "336860212 15sp1-2 member"]
mock_stdout2list.return_value = (0, crm_node_value)
assert utils.list_cluster_nodes() == ['15sp1-1', '15sp1-2']
mock_stdout2list.assert_called_once_with(['crm_node', '-l'], shell=False, stderr_on=False)


@mock.patch('crmsh.utils.stdout2list')
@mock.patch('crmsh.utils.get_member_iplist')
def test_list_cluster_nodes_corosync_running(mock_get_member_iplist, mock_stdout2list):
mock_stdout2list.return_value = (1, None)
mock_get_member_iplist.return_value = ["node1", "node2"]
assert utils.list_cluster_nodes() == ["node1", "node2"]
mock_stdout2list.assert_called_once_with(['crm_node', '-l'], shell=False, stderr_on=False)
mock_get_member_iplist.assert_called_once_with()


@mock.patch('crmsh.utils.list_cluster_nodes')
def test_cluster_run_cmd_exception(mock_list_nodes):
mock_list_nodes.return_value = None
Expand Down Expand Up @@ -1203,9 +1185,9 @@ def test_ping_node(mock_run):
mock_run.assert_called_once_with("ping -c 1 node_unreachable")


def test_is_quorate():
assert utils.is_quorate(3, 2) is True
assert utils.is_quorate(3, 1) is False
def test_calculate_quorate_status():
assert utils.calculate_quorate_status(3, 2) is True
assert utils.calculate_quorate_status(3, 1) is False


@mock.patch("crmsh.utils.get_stdout_stderr")
Expand Down Expand Up @@ -1238,7 +1220,7 @@ def test_get_quorum_votes_dict(mock_run):
"""
res = utils.get_quorum_votes_dict()
assert res == {'Expected': '1', 'Total': '1'}
mock_run.assert_called_once_with("corosync-quorumtool -s", remote=None)
mock_run.assert_called_once_with("corosync-quorumtool -s", remote=None, success_val_list=[0, 2])


@mock.patch("crmsh.utils.get_stdout_or_raise_error")
Expand Down Expand Up @@ -1495,3 +1477,129 @@ def test_detect_virt(mock_run):
mock_run.return_value = (0, None, None)
assert utils.detect_virt() is True
mock_run.assert_called_once_with("systemd-detect-virt")


@mock.patch('crmsh.utils.get_stdout_or_raise_error')
def test_is_standby(mock_run):
mock_run.return_value = """
Node List:
* Node 15sp2-1: standby
"""
assert utils.is_standby("15sp2-1") is True
mock_run.assert_called_once_with("crm_mon -1")


@mock.patch('crmsh.utils.get_stdout_or_raise_error')
def test_get_dlm_option_dict(mock_run):
mock_run.return_value = """
key1=value1
key2=value2
"""
res_dict = utils.get_dlm_option_dict()
assert res_dict == {
"key1": "value1",
"key2": "value2"
}
mock_run.assert_called_once_with("dlm_tool dump_config")


@mock.patch('crmsh.utils.get_dlm_option_dict')
def test_set_dlm_option_exception(mock_get_dict):
mock_get_dict.return_value = {
"key1": "value1",
"key2": "value2"
}
with pytest.raises(ValueError) as err:
utils.set_dlm_option(name="xin")
assert str(err.value) == '"name" is not dlm config option'


@mock.patch('crmsh.utils.get_stdout_or_raise_error')
@mock.patch('crmsh.utils.get_dlm_option_dict')
def test_set_dlm_option(mock_get_dict, mock_run):
mock_get_dict.return_value = {
"key1": "value1",
"key2": "value2"
}
utils.set_dlm_option(key2="test")
mock_run.assert_called_once_with('dlm_tool set_config "key2=test"')


@mock.patch('crmsh.utils.has_resource_configured')
def test_is_dlm_configured(mock_configured):
mock_configured.return_value = True
assert utils.is_dlm_configured() is True
mock_configured.assert_called_once_with("ocf::pacemaker:controld")


@mock.patch('crmsh.utils.get_stdout_or_raise_error')
def test_is_quorate_exception(mock_run):
mock_run.return_value = "data"
with pytest.raises(ValueError) as err:
utils.is_quorate()
assert str(err.value) == "Failed to get quorate status from corosync-quorumtool"
mock_run.assert_called_once_with("corosync-quorumtool -s", success_val_list=[0, 2])


@mock.patch('crmsh.utils.get_stdout_or_raise_error')
def test_is_quorate(mock_run):
mock_run.return_value = """
Ring ID: 1084783297/440
Quorate: Yes
"""
assert utils.is_quorate() is True
mock_run.assert_called_once_with("corosync-quorumtool -s", success_val_list=[0, 2])


@mock.patch('crmsh.utils.etree.fromstring')
@mock.patch('crmsh.utils.get_stdout_stderr')
def test_list_cluster_nodes_none(mock_run, mock_etree):
mock_run.return_value = (0, "data", None)
mock_etree.return_value = None
res = utils.list_cluster_nodes()
assert res is None
mock_run.assert_called_once_with(constants.CIB_QUERY)
mock_etree.assert_called_once_with("data")


@mock.patch('os.path.isfile')
@mock.patch('os.getenv')
@mock.patch('crmsh.utils.get_stdout_stderr')
def test_list_cluster_nodes_cib_not_exist(mock_run, mock_env, mock_isfile):
mock_run.return_value = (1, None, None)
mock_env.return_value = constants.CIB_RAW_FILE
mock_isfile.return_value = False
res = utils.list_cluster_nodes()
assert res is None
mock_run.assert_called_once_with(constants.CIB_QUERY)
mock_env.assert_called_once_with("CIB_file", constants.CIB_RAW_FILE)
mock_isfile.assert_called_once_with(constants.CIB_RAW_FILE)


@mock.patch('crmsh.xmlutil.file2cib_elem')
@mock.patch('os.path.isfile')
@mock.patch('os.getenv')
@mock.patch('crmsh.utils.get_stdout_stderr')
def test_list_cluster_nodes(mock_run, mock_env, mock_isfile, mock_file2elem):
mock_run.return_value = (1, None, None)
mock_env.return_value = constants.CIB_RAW_FILE
mock_isfile.return_value = True
mock_cib_inst = mock.Mock()
mock_file2elem.return_value = mock_cib_inst
mock_node_inst1 = mock.Mock()
mock_node_inst2 = mock.Mock()
mock_node_inst1.get.side_effect = ["node1", "remote"]
mock_node_inst2.get.side_effect = ["node2", "member"]
mock_cib_inst.xpath.side_effect = [[mock_node_inst1, mock_node_inst2], "data"]

res = utils.list_cluster_nodes()
assert res == ["node2"]

mock_run.assert_called_once_with(constants.CIB_QUERY)
mock_env.assert_called_once_with("CIB_file", constants.CIB_RAW_FILE)
mock_isfile.assert_called_once_with(constants.CIB_RAW_FILE)
mock_file2elem.assert_called_once_with(constants.CIB_RAW_FILE)
mock_cib_inst.xpath.assert_has_calls([
mock.call(constants.XML_NODE_PATH),
mock.call("//primitive[@id='node1']/instance_attributes/nvpair[@name='server']")
])

0 comments on commit 685c93a

Please sign in to comment.