File: test_utils.py

package info (click to toggle)
redis-py-cluster 2.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 748 kB
  • sloc: python: 5,888; ruby: 1,045; makefile: 542
file content (151 lines) | stat: -rw-r--r-- 5,237 bytes parent folder | download | duplicates (2)
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")