Skip to content

Commit d842821

Browse files
authored
Merge branch 'master' into ps_fix_runtime_error_for_sharded_pubsub
2 parents 50f8ab3 + 0406e85 commit d842821

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
@@ -1006,6 +1006,67 @@ def test_send_pubsub_ping_message(self, r):
10061006
)
10071007

10081008

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

0 commit comments

Comments
 (0)