mirror of
https://github.com/joyieldInc/predixy.git
synced 2026-02-05 01:42:24 +08:00
125 lines
5.2 KiB
Python
Executable File
125 lines
5.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# predixy - A high performance and full features proxy for redis.
|
|
# Copyright (C) 2017 Joyield, Inc. <joyield.com@gmail.com>
|
|
# All rights reserved.
|
|
|
|
import time
|
|
from test_util import parse_args, make_clients, exit_with_result
|
|
|
|
c1 = None
|
|
c2 = None
|
|
|
|
def test():
|
|
ps = c1.pubsub()
|
|
stats = [
|
|
[ps, 'subscribe', ['ch']],
|
|
[ps, 'get_message', [], {'pattern': None, 'type': 'subscribe', 'channel': 'ch', 'data': 1}],
|
|
[c2, 'publish', ['ch', 'hello'], 1],
|
|
[ps, 'get_message', [], {'pattern': None, 'type': 'message', 'channel': 'ch', 'data': 'hello'}],
|
|
[ps, 'subscribe', ['ch1', 'ch2']],
|
|
[ps, 'get_message', [], {'pattern': None, 'type': 'subscribe', 'channel': 'ch1', 'data': 2}],
|
|
[ps, 'get_message', [], {'pattern': None, 'type': 'subscribe', 'channel': 'ch2', 'data': 3}],
|
|
[c2, 'publish', ['ch1', 'channel1'], lambda x:True],
|
|
[c2, 'publish', ['ch2', 'channel2'], lambda x:True],
|
|
[ps, 'get_message', [], {'pattern': None, 'type': 'message', 'channel': 'ch1', 'data': 'channel1'}],
|
|
[ps, 'get_message', [], {'pattern': None, 'type': 'message', 'channel': 'ch2', 'data': 'channel2'}],
|
|
[ps, 'psubscribe', ['ch*']],
|
|
[ps, 'get_message', [], {'pattern': None, 'type': 'psubscribe', 'channel': 'ch*', 'data': 4}],
|
|
[c2, 'publish', ['ch', 'hello'], 2],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and (x.get('data') == 'hello' or (isinstance(x.get('data'), bytes) and x.get('data').decode('utf-8') == 'hello'))],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and (x.get('data') == 'hello' or (isinstance(x.get('data'), bytes) and x.get('data').decode('utf-8') == 'hello'))],
|
|
[ps, 'psubscribe', ['ch1*', 'ch2*']],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and x['type']=='psubscribe'],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and x['type']=='psubscribe'],
|
|
[ps, 'unsubscribe', ['ch']],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and x['type']=='unsubscribe'],
|
|
[c2, 'publish', ['ch', 'hello'], 1],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and (x.get('data') == 'hello' or (isinstance(x.get('data'), bytes) and x.get('data').decode('utf-8') == 'hello'))],
|
|
[ps, 'punsubscribe', ['ch*']],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and x['type']=='punsubscribe'],
|
|
[ps, 'unsubscribe', ['ch1', 'ch2']],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and x['type']=='unsubscribe'],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and x['type']=='unsubscribe'],
|
|
[ps, 'punsubscribe', ['ch1*', 'ch2*']],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and x['type']=='punsubscribe'],
|
|
[ps, 'get_message', [], lambda x:isinstance(x, dict) and x['type']=='punsubscribe'],
|
|
]
|
|
def normalize_value(v):
|
|
"""Convert byte strings to strings for comparison."""
|
|
if isinstance(v, bytes):
|
|
return v.decode('utf-8')
|
|
elif isinstance(v, dict):
|
|
return {normalize_value(k): normalize_value(val) for k, val in v.items()}
|
|
elif isinstance(v, (list, tuple)):
|
|
return [normalize_value(item) for item in v]
|
|
return v
|
|
|
|
def compare_values(actual, expected):
|
|
"""Compare actual and expected values, handling byte strings."""
|
|
if hasattr(expected, '__call__'):
|
|
return expected(actual)
|
|
|
|
# Normalize actual value
|
|
actual_norm = normalize_value(actual)
|
|
expected_norm = normalize_value(expected)
|
|
|
|
# Direct comparison
|
|
if actual_norm == expected_norm:
|
|
return True
|
|
|
|
# Handle dict comparison
|
|
if isinstance(actual_norm, dict) and isinstance(expected_norm, dict):
|
|
if set(actual_norm.keys()) != set(expected_norm.keys()):
|
|
return False
|
|
for key in actual_norm.keys():
|
|
if not compare_values(actual_norm[key], expected_norm.get(key)):
|
|
return False
|
|
return True
|
|
|
|
return False
|
|
|
|
def run(stat):
|
|
func = getattr(stat[0], stat[1])
|
|
r = func(*stat[2])
|
|
if len(stat) == 3:
|
|
print('EXEC %s(*%s)' % (stat[1], repr(stat[2])))
|
|
print(' =>', r)
|
|
return True
|
|
if hasattr(stat[3], '__call__'):
|
|
isPass = stat[3](r)
|
|
else:
|
|
isPass = compare_values(r, stat[3])
|
|
if isPass:
|
|
print('PASS %s(*%s):%s' % (stat[1], repr(stat[2]), repr(r)))
|
|
print(' =>', r)
|
|
return True
|
|
else:
|
|
print('FAIL %s(*%s):%s != %s' % (stat[1], repr(stat[2]), repr(r), repr(stat[3])))
|
|
print(' =>', r)
|
|
return False
|
|
|
|
succ = True
|
|
for stat in stats:
|
|
if not run(stat):
|
|
succ = False
|
|
time.sleep(0.01)
|
|
print('---------------------------------')
|
|
if succ:
|
|
print('Good! PubSub test pass')
|
|
else:
|
|
print('Oh! PubSub some case fail')
|
|
return succ
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
args = parse_args("PubSub test")
|
|
host = args.host
|
|
port = args.port
|
|
c1, c2 = make_clients(host, port, count=2)
|
|
success = test()
|
|
exit_with_result(success, "pubsub", "pubsub")
|
|
|
|
|