diff --git a/src/Subscribe.cpp b/src/Subscribe.cpp index 47c2b60..4fe4c9c 100644 --- a/src/Subscribe.cpp +++ b/src/Subscribe.cpp @@ -41,14 +41,18 @@ SubscribeParser::Status SubscribeParser::parse(const Segment& body, int& chs) st = String; } if (chs < 0) { - if (!str.complete()) { - Segment tmp(body); - tmp.rewind(); - tmp.cut(body.length() - 12); - str.set(tmp); + int len = body.length(); + int tailLen = len < 64 ? len : 64; + Segment tmp(body); + tmp.rewind(); + if (len > tailLen) { + tmp.use(len - tailLen); } - const char* p = str.data() + str.length(); - for (int i = 0; i < str.length(); ++i) { + char buf[64 + 1]; + int n = tmp.dump(buf, tailLen); + buf[n] = '\0'; + const char* p = buf + n; + while (p > buf) { if (*--p == ':') { chs = atoi(p + 1); break; diff --git a/test/pubsub_long_name.py b/test/pubsub_long_name.py new file mode 100644 index 0000000..7e7ac58 --- /dev/null +++ b/test/pubsub_long_name.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# +# Verify subscribe/psubscribe confirmation with long channel/pattern names +# + +import argparse +import sys +import redis + + +def normalize_bytes(value): + if isinstance(value, bytes): + return value.decode("utf-8") + return value + + +def run_test(host, port): + long_name = "ch_" + ("x" * 200) + pattern = long_name + "*" + + c1 = redis.StrictRedis(host=host, port=port) + ps = c1.pubsub() + + ps.subscribe(long_name) + msg = ps.get_message(timeout=1.0) + if not msg or msg.get("type") != "subscribe": + print("FAIL: subscribe confirmation missing:", msg) + return False + + if normalize_bytes(msg.get("channel")) != long_name: + print("FAIL: subscribe channel mismatch:", msg) + return False + + if msg.get("data") != 1: + print("FAIL: subscribe count mismatch:", msg) + return False + + ps.psubscribe(pattern) + msg = ps.get_message(timeout=1.0) + if not msg or msg.get("type") != "psubscribe": + print("FAIL: psubscribe confirmation missing:", msg) + return False + + if normalize_bytes(msg.get("channel")) != pattern: + print("FAIL: psubscribe channel mismatch:", msg) + return False + + if msg.get("data") != 2: + print("FAIL: psubscribe count mismatch:", msg) + return False + + return True + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(conflict_handler='resolve', description="Long pubsub name test") + parser.add_argument("-h", "--host", default="127.0.0.1") + parser.add_argument("-p", "--port", type=int, default=7617) + args = parser.parse_args() + + if run_test(args.host, args.port): + print("PASS: long pubsub name") + sys.exit(0) + print("FAIL: long pubsub name") + sys.exit(1) diff --git a/test/run.sh b/test/run.sh index 82306d8..9ec4b1f 100755 --- a/test/run.sh +++ b/test/run.sh @@ -63,6 +63,7 @@ PUBSUB_MESSAGE_EXIT=0 PUBSUB_ORDER_EXIT=0 PUBSUB_RESET_EXIT=0 NULL_RESPONSE_EXIT=0 +PUBSUB_LONG_EXIT=0 uv run python3 test/basic.py || BASIC_EXIT=$? uv run python3 test/pubsub_minimal.py -p 7617 || PUBSUB_REDIS_EXIT=$? @@ -70,8 +71,9 @@ uv run python3 test/pubsub_minimal.py -p 6379 || PUBSUB_MINIMAL_EXIT=$? uv run python3 test/pubsub.py || PUBSUB_EXIT=$? uv run python3 test/pubsub_subscription_order.py -p 7617 || PUBSUB_ORDER_EXIT=$? uv run python3 test/pubsub_parser_reset.py -p 7617 || PUBSUB_RESET_EXIT=$? +uv run python3 test/pubsub_long_name.py -p 7617 || PUBSUB_LONG_EXIT=$? uv run python3 test/null_response_handling.py -p 7617 || NULL_RESPONSE_EXIT=$? uv run python3 test/pubsub_message_response.py -p 7617 || PUBSUB_MESSAGE_EXIT=$? -TEST_EXIT=$((BASIC_EXIT + PUBSUB_REDIS_EXIT + PUBSUB_MINIMAL_EXIT + PUBSUB_EXIT + PUBSUB_MESSAGE_EXIT + PUBSUB_ORDER_EXIT + PUBSUB_RESET_EXIT + NULL_RESPONSE_EXIT)) +TEST_EXIT=$((BASIC_EXIT + PUBSUB_REDIS_EXIT + PUBSUB_MINIMAL_EXIT + PUBSUB_EXIT + PUBSUB_MESSAGE_EXIT + PUBSUB_ORDER_EXIT + PUBSUB_RESET_EXIT + NULL_RESPONSE_EXIT + PUBSUB_LONG_EXIT)) exit $TEST_EXIT