1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
# -*- coding: utf-8 -*-
# python std lib
from __future__ import with_statement
# rediscluster imports
from rediscluster.exceptions import (
RedisClusterException, ClusterDownError
)
from rediscluster.utils import (
string_keys_to_dict,
dict_merge,
blocked_command,
merge_result,
first_key,
clusterdown_wrapper,
parse_cluster_slots,
)
# 3rd party imports
import pytest
from redis._compat import unicode
def test_parse_cluster_slots():
"""
Example raw output from redis cluster. Output is form a redis 3.2.x node
that includes the id in the reponse. The test below that do not include the id
is to validate that the code is compatible with redis versions that do not contain
that value in the response from the server.
127.0.0.1:10000> cluster slots
1) 1) (integer) 5461
2) (integer) 10922
3) 1) "10.0.0.1"
2) (integer) 10000
3) "3588b4cf9fc72d57bb262a024747797ead0cf7ea"
4) 1) "10.0.0.4"
2) (integer) 10000
3) "a72c02c7d85f4ec3145ab2c411eefc0812aa96b0"
2) 1) (integer) 10923
2) (integer) 16383
3) 1) "10.0.0.2"
2) (integer) 10000
3) "ffd36d8d7cb10d813f81f9662a835f6beea72677"
4) 1) "10.0.0.5"
2) (integer) 10000
3) "5c15b69186017ddc25ebfac81e74694fc0c1a160"
3) 1) (integer) 0
2) (integer) 5460
3) 1) "10.0.0.3"
2) (integer) 10000
3) "069cda388c7c41c62abe892d9e0a2d55fbf5ffd5"
4) 1) "10.0.0.6"
2) (integer) 10000
3) "dc152a08b4cf1f2a0baf775fb86ad0938cb907dc"
"""
mock_response = [
[0, 5460, ['172.17.0.2', 7000], ['172.17.0.2', 7003]],
[5461, 10922, ['172.17.0.2', 7001], ['172.17.0.2', 7004]],
[10923, 16383, ['172.17.0.2', 7002], ['172.17.0.2', 7005]]
]
parse_cluster_slots(mock_response)
extended_mock_response = [
[0, 5460, ['172.17.0.2', 7000, 'ffd36d8d7cb10d813f81f9662a835f6beea72677'], ['172.17.0.2', 7003, '5c15b69186017ddc25ebfac81e74694fc0c1a160']],
[5461, 10922, ['172.17.0.2', 7001, '069cda388c7c41c62abe892d9e0a2d55fbf5ffd5'], ['172.17.0.2', 7004, 'dc152a08b4cf1f2a0baf775fb86ad0938cb907dc']],
[10923, 16383, ['172.17.0.2', 7002, '3588b4cf9fc72d57bb262a024747797ead0cf7ea'], ['172.17.0.2', 7005, 'a72c02c7d85f4ec3145ab2c411eefc0812aa96b0']]
]
parse_cluster_slots(extended_mock_response)
mock_binary_response = [
[0, 5460, [b'172.17.0.2', 7000], [b'172.17.0.2', 7003]],
[5461, 10922, [b'172.17.0.2', 7001], [b'172.17.0.2', 7004]],
[10923, 16383, [b'172.17.0.2', 7002], [b'172.17.0.2', 7005]]
]
parse_cluster_slots(mock_binary_response)
extended_mock_binary_response = [
[0, 5460, [b'172.17.0.2', 7000, b'ffd36d8d7cb10d813f81f9662a835f6beea72677'], [b'172.17.0.2', 7003, b'5c15b69186017ddc25ebfac81e74694fc0c1a160']],
[5461, 10922, [b'172.17.0.2', 7001, b'069cda388c7c41c62abe892d9e0a2d55fbf5ffd5'], [b'172.17.0.2', 7004, b'dc152a08b4cf1f2a0baf775fb86ad0938cb907dc']],
[10923, 16383, [b'172.17.0.2', 7002, b'3588b4cf9fc72d57bb262a024747797ead0cf7ea'], [b'172.17.0.2', 7005, b'a72c02c7d85f4ec3145ab2c411eefc0812aa96b0']]
]
extended_mock_parsed = {
(0, 5460): {'master': ('172.17.0.2', 7000), 'slaves': [('172.17.0.2', 7003)]},
(5461, 10922): {'master': ('172.17.0.2', 7001),
'slaves': [('172.17.0.2', 7004)]},
(10923, 16383): {'master': ('172.17.0.2', 7002),
'slaves': [('172.17.0.2', 7005)]}
}
assert parse_cluster_slots(extended_mock_binary_response) == extended_mock_parsed
def test_string_keys_to():
def mock_true():
return True
assert string_keys_to_dict(["FOO", "BAR"], mock_true) == {"FOO": mock_true, "BAR": mock_true}
def test_dict_merge():
a = {"a": 1}
b = {"b": 2}
c = {"c": 3}
assert dict_merge(a, b, c) == {"a": 1, "b": 2, "c": 3}
def test_dict_merge_value_error():
with pytest.raises(ValueError):
dict_merge([])
def test_blocked_command():
with pytest.raises(RedisClusterException) as ex:
blocked_command(None, "SET")
assert unicode(ex.value) == "Command: SET is blocked in redis cluster mode"
def test_merge_result():
assert merge_result("foobar", {"a": [1, 2, 3], "b": [4, 5, 6]}) == [1, 2, 3, 4, 5, 6]
assert merge_result("foobar", {"a": [1, 2, 3], "b": [1, 2, 3]}) == [1, 2, 3]
def test_merge_result_value_error():
with pytest.raises(ValueError):
merge_result("foobar", [])
def test_first_key():
assert first_key("foobar", {"foo": 1}) == 1
with pytest.raises(RedisClusterException) as ex:
first_key("foobar", {"foo": 1, "bar": 2})
assert unicode(ex.value).startswith("More then 1 result from command: foobar")
def test_first_key_value_error():
with pytest.raises(ValueError):
first_key("foobar", None)
def test_clusterdown_wrapper():
@clusterdown_wrapper
def bad_func():
raise ClusterDownError("CLUSTERDOWN")
with pytest.raises(ClusterDownError) as cex:
bad_func()
assert unicode(cex.value).startswith("CLUSTERDOWN error. Unable to rebuild the cluster")
|