-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathtest_osstats.py
More file actions
188 lines (150 loc) · 6.13 KB
/
test_osstats.py
File metadata and controls
188 lines (150 loc) · 6.13 KB
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import pytest
import redis
from unittest.mock import Mock, patch, MagicMock
import configparser
import asyncio
from osstats import (
get_value,
native_str,
parse_response,
create_workbook,
get_command_by_args,
get_redis_client,
process_node,
process_database,
main,
)
class TestGetValue:
def test_get_value_int(self):
assert get_value("123") == 123
def test_get_value_float(self):
assert get_value("123.45") == 123.45
def test_get_value_string(self):
assert get_value("hello") == "hello"
def test_get_value_dict(self):
result = get_value("key1=val1,key2=val2")
assert result == {"key1": "val1", "key2": "val2"}
def test_get_value_nested_dict(self):
result = get_value("key1=123,key2=45.6")
assert result == {"key1": 123, "key2": 45.6}
class TestNativeStr:
def test_native_str_string(self):
assert native_str("hello") == "hello"
def test_native_str_bytes(self):
assert native_str(b"hello") == "hello"
def test_native_str_bytes_with_encoding_error(self):
# Test with invalid UTF-8 bytes
result = native_str(b"\xff\xfe")
assert isinstance(result, str)
class TestParseResponse:
def test_parse_response_basic(self):
response = "key1:value1\nkey2:123\nkey3:45.6"
result = parse_response(response)
assert result == {"key1": "value1", "key2": 123, "key3": 45.6}
def test_parse_response_with_comments(self):
response = "# This is a comment\nkey1:value1\n# Another comment\nkey2:123"
result = parse_response(response)
assert result == {"key1": "value1", "key2": 123}
def test_parse_response_cmdstat_host(self):
response = "cmdstat_host:calls=1,usec=100"
result = parse_response(response)
assert "cmdstat_host" in result
def test_parse_response_raw_lines(self):
response = "key1:value1\ninvalid_line_without_colon"
result = parse_response(response)
assert result["key1"] == "value1"
assert "__raw__" in result
assert "invalid_line_without_colon" in result["__raw__"]
class TestCreateWorkbook:
def test_create_workbook(self):
wb = create_workbook()
assert wb is not None
assert wb.active.title == "ClusterData"
class TestGetCommandByArgs:
def test_get_command_by_args(self):
cmds1 = {"cmdstat_get": {"calls": 100}, "cmdstat_set": {"calls": 50}}
cmds2 = {"cmdstat_get": {"calls": 150}, "cmdstat_set": {"calls": 80}}
result = get_command_by_args(cmds1, cmds2, "get", "set")
assert result == 80 # (150-100) + (80-50)
def test_get_command_by_args_missing_command(self):
cmds1 = {"cmdstat_get": {"calls": 100}}
cmds2 = {"cmdstat_get": {"calls": 150}}
result = get_command_by_args(cmds1, cmds2, "get", "missing")
assert result == 50 # Only get command exists
class TestGetRedisClient:
@patch("osstats.redis.Redis")
def test_get_redis_client_basic(self, mock_redis):
client = get_redis_client("localhost", 6379)
mock_redis.assert_called_once()
args = mock_redis.call_args[1]
assert args["host"] == "localhost"
assert args["port"] == 6379
assert args["ssl"] is False
@patch("osstats.redis.Redis")
def test_get_redis_client_with_auth(self, mock_redis):
client = get_redis_client("localhost", 6379, password="pass", username="user")
args = mock_redis.call_args[1]
assert args["password"] == "pass"
assert args["username"] == "user"
@patch("osstats.redis.Redis")
def test_get_redis_client_with_tls(self, mock_redis):
client = get_redis_client("localhost", 6379, tls=True, ca_cert="/path/ca.crt")
args = mock_redis.call_args[1]
assert args["ssl"] is True
assert args["ssl_cert_reqs"] == "required"
assert args["ssl_ca_certs"] == "/path/ca.crt"
class TestProcessNode:
@pytest.mark.asyncio
@patch("osstats.get_redis_client")
@patch("osstats.parse_response")
@patch("osstats.sleep")
async def test_process_node(self, mock_sleep, mock_parse, mock_get_client):
# Mock configuration
config = Mock()
def mock_get(key, default=None, fallback=None):
values = {
"host": "localhost",
"port": "6379",
"password": None,
"username": None,
"ca_cert": None,
"client_cert": None,
"client_key": None,
}
return values.get(key, fallback or default)
config.get.side_effect = mock_get
config.getboolean.return_value = False
# Mock Redis client
mock_client = Mock()
mock_get_client.return_value = mock_client
# Mock Redis responses - return parsed dictionaries directly
mock_info_dict = {
"redis_version": "6.2.0",
"os": "Linux",
"total_system_memory": 8589934592,
"used_memory_peak": 1048576,
"connected_clients": 10,
"cluster_enabled": 0,
"total_commands_processed": 1000,
"db0": {"keys": 100, "expires": 0},
}
mock_info_dict2 = mock_info_dict.copy()
mock_info_dict2["total_commands_processed"] = 1200
mock_client.execute_command.side_effect = [
"cmdstat_get:calls=100,usec=1000", # First commandstats
mock_info_dict, # First info - return dict directly
"cmdstat_get:calls=150,usec=1500", # Second commandstats
mock_info_dict2, # Second info - return dict directly
]
# Mock parse_response to return proper dictionaries
mock_parse.side_effect = [
{"cmdstat_get": {"calls": 100, "usec": 1000}},
{"cmdstat_get": {"calls": 150, "usec": 1500}},
]
result = await process_node("test-section", config, "localhost:6379", True, 1)
assert result is not None
assert result["Source"] == "OSS"
assert result["ClusterId"] == "test-section"
assert result["NodeRole"] == "Master"
if __name__ == "__main__":
pytest.main([__file__])