Skip to content

Commit

Permalink
feat: added UT to cover the scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
a-spiker committed Jan 23, 2025
1 parent a163da5 commit 70c9212
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 7 deletions.
19 changes: 13 additions & 6 deletions lib/live_cluster/manage_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -2755,8 +2755,15 @@ async def _check_ns_is_strong_consistency(self, ns):
"""
try:
namespace_stats = await self.cluster.info_namespace_statistics(ns, nodes='all')
if isinstance(namespace_stats, Exception):
raise namespace_stats

if not namespace_stats:
logger.error("namespace {} not found".format(ns))
return False

namespace_stats = list(namespace_stats.values())[0] if len(namespace_stats.values()) > 0 else None
if not namespace_stats or namespace_stats is None:
if not namespace_stats:
logger.error("namespace {} not does not exist".format(ns))
return False

Expand All @@ -2767,7 +2774,7 @@ async def _check_ns_is_strong_consistency(self, ns):

except Exception as e:
logger.error("Error while checking namespace strong consistency mode: {}".format(e))
raise ASInfoError("Error while checking namespace strong consistency mode", e)
raise e

return strong_consistency

Expand Down Expand Up @@ -2814,7 +2821,7 @@ async def _do_default(self, line):

# to be run against a SC namespace only
ns_strong_consistency = await self._check_ns_is_strong_consistency(ns)
if isinstance(ns_strong_consistency, ASInfoError):
if isinstance(ns_strong_consistency, Exception):
return
elif not ns_strong_consistency:
return
Expand Down Expand Up @@ -2896,7 +2903,7 @@ async def _do_default(self, line):

# to be run against a SC namespace only
ns_strong_consistency = await self._check_ns_is_strong_consistency(ns)
if isinstance(ns_strong_consistency, ASInfoError):
if isinstance(ns_strong_consistency, Exception):
return
elif not ns_strong_consistency:
return
Expand Down Expand Up @@ -2996,7 +3003,7 @@ async def _do_default(self, line):

# to be run against a SC namespace only
ns_strong_consistency = await self._check_ns_is_strong_consistency(ns)
if isinstance(ns_strong_consistency, ASInfoError):
if isinstance(ns_strong_consistency, Exception):
return
elif not ns_strong_consistency:
return
Expand Down Expand Up @@ -3061,7 +3068,7 @@ async def _do_default(self, line):

# to be run against a SC namespace only
ns_strong_consistency = await self._check_ns_is_strong_consistency(ns)
if isinstance(ns_strong_consistency, ASInfoError):
if isinstance(ns_strong_consistency, Exception):
return
elif not ns_strong_consistency:
return
Expand Down
117 changes: 116 additions & 1 deletion test/unit/live_cluster/test_manage_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

from lib.live_cluster.client import (
ASINFO_RESPONSE_OK,
ASInfoClusterStableError,
ASInfoError,
ASInfoResponseError,
ASProtocolError,
ASResponse,
Expand Down Expand Up @@ -2712,6 +2712,16 @@ def __init__(self, input, output):
self.logger_mock.warning.assert_called_with(
"The cluster is unstable. It is advised that you do not manage the roster. Run 'info network' for more information."
)

self.assertRaises(
ASInfoError,
self.controller._check_and_log_cluster_stable,
{
"1.1.1.1": "ABC",
"2.2.2.2": "ABC",
"3.3.3.3": ASInfoError("", "foo"),
},
)

def test_check_and_log_nodes_in_observed(self):
class test_case:
Expand Down Expand Up @@ -2813,6 +2823,7 @@ async def test_logs_error_from_roster(self):

self.logger_mock.error.assert_called_once_with(error)
self.cluster_mock.info_roster_set.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()
self.view_mock.print_result.assert_not_called()

async def test_logs_error_from_roster_set(self):
Expand All @@ -2830,8 +2841,91 @@ async def test_logs_error_from_roster_set(self):

self.logger_mock.error.assert_called_once_with(error)
self.cluster_mock.info_roster_set.assert_called_once()
self.cluster_mock.info_namespace_statistics.assert_called_once()
self.view_mock.print_result.assert_not_called()

async def test_raises_warn_from_none_ns(self):
line = "nodes ABC@rack1 DEF@rack2 ns test --no-warn"
self.cluster_mock.info_namespace_statistics.return_value = None

await self.controller.execute(line.split())

self.logger_mock.error.assert_called()
self.cluster_mock.info_namespace_statistics.assert_called()
self.cluster_mock.info_roster_set.assert_not_called()
self.view_mock.print_result.assert_not_called()
self.logger_mock.error.assert_any_call(
'namespace test not found'
)

async def test_raises_warn_from_invalid_ns(self):
error = Exception("test exception")
line = "nodes ABC@rack1 DEF@rack2 ns test --no-warn"
self.cluster_mock.info_roster.return_value = {"1.1.1.1": {}}
self.cluster_mock.info_namespace_statistics.return_value = {"1.1.1.1": {}}

await self.controller.execute(line.split())

self.logger_mock.error.assert_called()
self.cluster_mock.info_namespace_statistics.assert_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()
self.cluster_mock.info_roster_set.assert_not_called()
self.view_mock.print_result.assert_not_called()
self.logger_mock.error.assert_any_call(
'namespace test not does not exist'
)

async def test_raises_warn_from_ap_ns(self):
error = Exception("test exception")
line = "nodes ABC@rack1 DEF@rack2 ns test --no-warn"
self.cluster_mock.info_roster.return_value = {"1.1.1.1": {}}
self.cluster_mock.info_namespace_statistics.return_value = {
"1.1.1.1": { "strong-consistency": "false" }
}

await self.controller.execute(line.split())

self.logger_mock.error.assert_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()
self.cluster_mock.info_roster_set.assert_not_called()
self.view_mock.print_result.assert_not_called()
self.logger_mock.error.assert_any_call(
'namespace test is not in strong consistency mode'
)

async def test_raises_warn_from_malformed_ns(self):
error = Exception("test exception")
line = "nodes ABC@rack1 DEF@rack2 ns test --no-warn"
self.cluster_mock.info_roster.return_value = {"1.1.1.1": {}}
self.cluster_mock.info_namespace_statistics.return_value = {
"1.1.1.1": { "disable-mrt-writes": "false" }
}

await self.controller.execute(line.split())

self.logger_mock.error.assert_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()
self.cluster_mock.info_roster_set.assert_not_called()
self.view_mock.print_result.assert_not_called()
self.logger_mock.error.assert_any_call(
'namespace test is not in strong consistency mode'
)

async def test_raises_error_from_ns_stats(self):
error = Exception("test exception")
line = "nodes ABC@rack1 DEF@rack2 ns test --no-warn"
self.cluster_mock.info_roster.return_value = {"1.1.1.1": error}
self.cluster_mock.info_namespace_statistics.return_value = error

await test_util.assert_exception_async(
self, Exception, "test exception", self.controller.execute, line.split()
)
self.logger_mock.error.assert_called()
self.cluster_mock.info_roster_set.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()
self.view_mock.print_result.assert_not_called()


async def test_raises_error_from_roster(self):
error = Exception("test exception")
line = "nodes ABC@rack1 DEF@rack2 ns test --no-warn"
Expand Down Expand Up @@ -2862,6 +2956,7 @@ async def test_raises_error_from_roster_set(self):
self, Exception, "test exception", self.controller.execute, line.split()
)
self.logger_mock.error.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()
self.cluster_mock.info_roster_set.assert_called_once()
self.view_mock.print_result.assert_not_called()

Expand Down Expand Up @@ -2889,6 +2984,7 @@ async def test_warn_returns_false(self):
"You are about to set the pending-roster for namespace test to: GHI, ABC@rack1, DEF@rack2"
)
self.cluster_mock.info_roster_set.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_warn_returns_true(self):
line = "nodes ABC@rack1 DEF@rack2 ns test"
Expand All @@ -2915,6 +3011,7 @@ async def test_warn_returns_true(self):
"You are about to set the pending-roster for namespace test to: GHI, ABC@rack1, DEF@rack2"
)
self.cluster_mock.info_roster_set.assert_called_once()
self.cluster_mock.info_namespace_statistics.assert_called_once()


@asynctest.fail_on(active_handles=True)
Expand Down Expand Up @@ -2957,6 +3054,7 @@ async def test_success(self):
self.view_mock.print_result.assert_any_call(
'Run "manage recluster" for your changes to take effect.'
)
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_logs_error_from_roster(self):
line = "nodes ABC@rack1 DEF@rack2 ns test --no-warn"
Expand All @@ -2971,6 +3069,7 @@ async def test_logs_error_from_roster(self):
self.logger_mock.error.assert_called_once_with(error)
self.cluster_mock.info_roster_set.assert_not_called()
self.view_mock.print_result.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_logs_error_from_roster_set(self):
error = ASInfoResponseError("blah", "error::foo")
Expand All @@ -2991,6 +3090,7 @@ async def test_logs_error_from_roster_set(self):
self.logger_mock.error.assert_called_once_with(error)
self.cluster_mock.info_roster_set.assert_called_once()
self.view_mock.print_result.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_logs_error_when_node_not_in_pending(self):
line = "nodes GHI ns test"
Expand All @@ -3014,6 +3114,7 @@ async def test_logs_error_when_node_not_in_pending(self):
)
self.cluster_mock.info_roster_set.assert_not_called()
self.view_mock.print_result.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_raises_error_from_roster(self):
error = Exception("test exception")
Expand All @@ -3027,6 +3128,7 @@ async def test_raises_error_from_roster(self):
self, Exception, "test exception", self.controller.execute, line.split()
)
self.logger_mock.error.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()
self.cluster_mock.info_roster_set.assert_not_called()
self.view_mock.print_result.assert_not_called()

Expand All @@ -3048,6 +3150,7 @@ async def test_raises_error_from_roster_set(self):
self, Exception, "test exception", self.controller.execute, line.split()
)
self.logger_mock.error.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()
self.cluster_mock.info_roster_set.assert_called_once()
self.view_mock.print_result.assert_not_called()

Expand All @@ -3074,6 +3177,7 @@ async def test_warn_returns_false(self):
self.check_and_log_cluster_stable_mock.assert_called_once_with(
{"1.1.1.1": "ABCDEF"}
)
self.cluster_mock.info_namespace_statistics.assert_called_once()
self.cluster_mock.info_roster_set.assert_not_called()

async def test_warn_returns_true(self):
Expand Down Expand Up @@ -3101,6 +3205,7 @@ async def test_warn_returns_true(self):
{"1.1.1.1": "ABCDEF"}
)
self.cluster_mock.info_roster_set.assert_called_once()
self.cluster_mock.info_namespace_statistics.assert_called_once()


@asynctest.fail_on(active_handles=True)
Expand Down Expand Up @@ -3144,6 +3249,7 @@ async def test_success(self):
self.view_mock.print_result.assert_any_call(
'Run "manage recluster" for your changes to take effect.'
)
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_logs_error_from_roster_set(self):
line = "ABC@rack1 DEF@rack2 ns test --no-warn"
Expand All @@ -3159,6 +3265,7 @@ async def test_logs_error_from_roster_set(self):
"test", ["ABC@rack1", "DEF@rack2"], nodes="principal"
)

self.cluster_mock.info_namespace_statistics.assert_called_once()
self.logger_mock.error.assert_called_once_with(error)
self.view_mock.print_result.assert_not_called()

Expand All @@ -3185,6 +3292,7 @@ async def test_raises_error_from_roster_set(self):
)
self.logger_mock.error.assert_not_called()
self.view_mock.print_result.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_warn_returns_false(self):
line = "ABC@rack1 DEF@rack2 ns test"
Expand Down Expand Up @@ -3212,6 +3320,7 @@ async def test_warn_returns_false(self):
[], ["ABC@rack1", "DEF@rack2"]
)
self.cluster_mock.info_roster_set.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_warn_returns_true(self):
line = "ABC@rack1 DEF@rack2 ns test"
Expand Down Expand Up @@ -3240,6 +3349,7 @@ async def test_warn_returns_true(self):
"You are about to set the pending-roster for namespace test to: ABC@rack1, DEF@rack2"
)
self.cluster_mock.info_roster_set.assert_called_once()
self.cluster_mock.info_namespace_statistics.assert_called_once()


@asynctest.fail_on(active_handles=True)
Expand Down Expand Up @@ -3299,6 +3409,7 @@ async def test_logs_error_from_roster(self):
self.logger_mock.error.assert_called_once_with(error)
self.cluster_mock.info_roster_set.assert_not_called()
self.view_mock.print_result.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_logs_error_from_roster_set(self):
line = "ns test"
Expand All @@ -3318,6 +3429,7 @@ async def test_logs_error_from_roster_set(self):
)
self.logger_mock.error.assert_called_once_with(error)
self.view_mock.print_result.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_raises_error_from_roster(self):
error = Exception("test exception")
Expand All @@ -3333,6 +3445,7 @@ async def test_raises_error_from_roster(self):
self.logger_mock.error.assert_not_called()
self.cluster_mock.info_roster_set.assert_not_called()
self.view_mock.print_result.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_raises_error_from_roster_set(self):
error = Exception("test exception")
Expand Down Expand Up @@ -3373,6 +3486,7 @@ async def test_warn_returns_false(self):
"You are about to set the pending-roster for namespace test to: GHI, ABC@rack1, DEF@rack2"
)
self.cluster_mock.info_roster_set.assert_not_called()
self.cluster_mock.info_namespace_statistics.assert_called_once()

async def test_warn_returns_true(self):
line = "nodes ABC@rack1 DEF@rack2 ns test"
Expand All @@ -3397,3 +3511,4 @@ async def test_warn_returns_true(self):
)
self.cluster_mock.info_roster_set.assert_called_once()
self.cluster_mock.info_namespace_statistics.assert_called_once()

0 comments on commit 70c9212

Please sign in to comment.