Skip to content

Commit d76f170

Browse files
authored
Merge branch 'master' into ps_fix_runtime_error_for_sharded_pubsub
2 parents 7f3cd45 + 0406e85 commit d76f170

File tree

3 files changed

+134
-4
lines changed

3 files changed

+134
-4
lines changed

redis/client.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,10 +1009,22 @@ def is_health_check_response(self, response) -> bool:
10091009
If there are no subscriptions redis responds to PING command with a
10101010
bulk response, instead of a multi-bulk with "pong" and the response.
10111011
"""
1012-
return response in [
1013-
self.health_check_response, # If there was a subscription
1014-
self.health_check_response_b, # If there wasn't
1015-
]
1012+
if self.encoder.decode_responses:
1013+
return (
1014+
response
1015+
in [
1016+
self.health_check_response, # If there is a subscription
1017+
self.HEALTH_CHECK_MESSAGE, # If there are no subscriptions and decode_responses=True
1018+
]
1019+
)
1020+
else:
1021+
return (
1022+
response
1023+
in [
1024+
self.health_check_response, # If there is a subscription
1025+
self.health_check_response_b, # If there isn't a subscription and decode_responses=False
1026+
]
1027+
)
10161028

10171029
def check_health(self) -> None:
10181030
conn = self.connection

tests/test_asyncio/test_pubsub.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,63 @@ async def test_send_pubsub_ping_message(self, r: redis.Redis):
671671
await p.aclose()
672672

673673

674+
@pytest.mark.onlynoncluster
675+
class TestPubSubHealthCheckResponse:
676+
"""Tests for health check response validation with different decode_responses settings"""
677+
678+
async def test_health_check_response_decode_false_list_format(self, r: redis.Redis):
679+
"""Test health_check_response includes list format with decode_responses=False"""
680+
p = r.pubsub()
681+
# List format: [b"pong", b"redis-py-health-check"]
682+
assert [b"pong", b"redis-py-health-check"] in p.health_check_response
683+
await p.aclose()
684+
685+
async def test_health_check_response_decode_false_bytes_format(
686+
self, r: redis.Redis
687+
):
688+
"""Test health_check_response includes bytes format with decode_responses=False"""
689+
p = r.pubsub()
690+
# Bytes format: b"redis-py-health-check"
691+
assert b"redis-py-health-check" in p.health_check_response
692+
await p.aclose()
693+
694+
async def test_health_check_response_decode_true_list_format(self, create_redis):
695+
"""Test health_check_response includes list format with decode_responses=True"""
696+
r = await create_redis(decode_responses=True)
697+
p = r.pubsub()
698+
# List format: ["pong", "redis-py-health-check"]
699+
assert ["pong", "redis-py-health-check"] in p.health_check_response
700+
await p.aclose()
701+
await r.aclose()
702+
703+
async def test_health_check_response_decode_true_string_format(self, create_redis):
704+
"""Test health_check_response includes string format with decode_responses=True"""
705+
r = await create_redis(decode_responses=True)
706+
p = r.pubsub()
707+
# String format: "redis-py-health-check" (THE FIX!)
708+
assert "redis-py-health-check" in p.health_check_response
709+
await p.aclose()
710+
await r.aclose()
711+
712+
async def test_health_check_response_decode_false_excludes_string(
713+
self, r: redis.Redis
714+
):
715+
"""Test health_check_response excludes string format with decode_responses=False"""
716+
p = r.pubsub()
717+
# String format should NOT be in the list when decode_responses=False
718+
assert "redis-py-health-check" not in p.health_check_response
719+
await p.aclose()
720+
721+
async def test_health_check_response_decode_true_excludes_bytes(self, create_redis):
722+
"""Test health_check_response excludes bytes format with decode_responses=True"""
723+
r = await create_redis(decode_responses=True)
724+
p = r.pubsub()
725+
# Bytes format should NOT be in the list when decode_responses=True
726+
assert b"redis-py-health-check" not in p.health_check_response
727+
await p.aclose()
728+
await r.aclose()
729+
730+
674731
@pytest.mark.onlynoncluster
675732
class TestPubSubConnectionKilled:
676733
@skip_if_server_version_lt("3.0.0")

tests/test_pubsub.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,67 @@ def test_send_pubsub_ping_message(self, r):
10081008
)
10091009

10101010

1011+
@pytest.mark.onlynoncluster
1012+
class TestPubSubHealthCheckResponse:
1013+
"""Tests for health check response validation with different decode_responses settings"""
1014+
1015+
def test_is_health_check_response_decode_false_list_format(self, r):
1016+
"""Test is_health_check_response recognizes list format with decode_responses=False"""
1017+
p = r.pubsub()
1018+
# List format: [b"pong", b"redis-py-health-check"]
1019+
assert p.is_health_check_response([b"pong", b"redis-py-health-check"])
1020+
1021+
def test_is_health_check_response_decode_false_bytes_format(self, r):
1022+
"""Test is_health_check_response recognizes bytes format with decode_responses=False"""
1023+
p = r.pubsub()
1024+
# Bytes format: b"redis-py-health-check"
1025+
assert p.is_health_check_response(b"redis-py-health-check")
1026+
1027+
def test_is_health_check_response_decode_false_rejects_string(self, r):
1028+
"""Test is_health_check_response rejects string format with decode_responses=False"""
1029+
p = r.pubsub()
1030+
# String format should NOT be recognized when decode_responses=False
1031+
assert not p.is_health_check_response("redis-py-health-check")
1032+
1033+
def test_is_health_check_response_decode_true_list_format(self, request):
1034+
"""Test is_health_check_response recognizes list format with decode_responses=True"""
1035+
r = _get_client(redis.Redis, request, decode_responses=True)
1036+
p = r.pubsub()
1037+
# List format: ["pong", "redis-py-health-check"]
1038+
assert p.is_health_check_response(["pong", "redis-py-health-check"])
1039+
1040+
def test_is_health_check_response_decode_true_string_format(self, request):
1041+
"""Test is_health_check_response recognizes string format with decode_responses=True"""
1042+
r = _get_client(redis.Redis, request, decode_responses=True)
1043+
p = r.pubsub()
1044+
# String format: "redis-py-health-check" (THE FIX!)
1045+
assert p.is_health_check_response("redis-py-health-check")
1046+
1047+
def test_is_health_check_response_decode_true_rejects_bytes(self, request):
1048+
"""Test is_health_check_response rejects bytes format with decode_responses=True"""
1049+
r = _get_client(redis.Redis, request, decode_responses=True)
1050+
p = r.pubsub()
1051+
# Bytes format should NOT be recognized when decode_responses=True
1052+
assert not p.is_health_check_response(b"redis-py-health-check")
1053+
1054+
def test_is_health_check_response_decode_true_rejects_invalid(self, request):
1055+
"""Test is_health_check_response rejects invalid responses with decode_responses=True"""
1056+
r = _get_client(redis.Redis, request, decode_responses=True)
1057+
p = r.pubsub()
1058+
# Invalid responses should be rejected
1059+
assert not p.is_health_check_response("invalid-response")
1060+
assert not p.is_health_check_response(["pong", "invalid-response"])
1061+
assert not p.is_health_check_response(None)
1062+
1063+
def test_is_health_check_response_decode_false_rejects_invalid(self, r):
1064+
"""Test is_health_check_response rejects invalid responses with decode_responses=False"""
1065+
p = r.pubsub()
1066+
# Invalid responses should be rejected
1067+
assert not p.is_health_check_response(b"invalid-response")
1068+
assert not p.is_health_check_response([b"pong", b"invalid-response"])
1069+
assert not p.is_health_check_response(None)
1070+
1071+
10111072
@pytest.mark.onlynoncluster
10121073
class TestPubSubConnectionKilled:
10131074
@skip_if_server_version_lt("3.0.0")

0 commit comments

Comments
 (0)