Skip to content

Commit 591ab10

Browse files
authored
Adding a bloom command keyspace test (#40)
Signed-off-by: zackcam <[email protected]>
1 parent 1bb7d25 commit 591ab10

4 files changed

+87
-9
lines changed

tests/test_bloom_basic.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ def test_too_large_bloom_obj(self):
8181
# is rejected.
8282
assert client.execute_command('CONFIG SET bf.bloom-memory-usage-limit 1000') == b'OK'
8383
cmds = [
84-
'BF.INSERT filter items new_item1',
85-
'BF.ADD filter new_item1',
86-
'BF.MADD filter new_item1 new_item2',
84+
'BF.INSERT filter ITEMS',
85+
'BF.ADD filter',
86+
'BF.MADD filter',
8787
]
8888
# Fill a filter to capacity.
8989
assert client.execute_command('BF.RESERVE filter 0.001 100 EXPANSION 10') == b'OK'
@@ -94,12 +94,19 @@ def test_too_large_bloom_obj(self):
9494
assert client.execute_command('BF.INFO filter FILTERS') == 1
9595
assert client.execute_command('BF.INFO filter EXPANSION') == 10
9696
# Validate that scale out is rejected with appropriate error.
97+
new_item_idx = 0
9798
for cmd in cmds:
98-
if "BF.ADD" in cmd:
99-
self.verify_error_response(self.client, cmd, obj_exceeds_size_err)
100-
else:
101-
response = client.execute_command(cmd)
102-
assert obj_exceeds_size_err in str(response[0])
99+
response = ""
100+
while obj_exceeds_size_err not in response:
101+
item = f"new_item{new_item_idx}"
102+
new_item_idx += 1
103+
if "BF.ADD" in cmd:
104+
response = self.verify_error_response(self.client,f"{cmd} {item}", obj_exceeds_size_err)
105+
else:
106+
response = str(client.execute_command(f"{cmd} {item}"))
107+
if "1" in response:
108+
assert False, f"{cmd} returned a value of 1 when it should have thrown an {obj_exceeds_size_err}"
109+
new_item_idx -= 1
103110

104111
def test_large_allocation_when_below_maxmemory(self):
105112
two_megabytes = 2 * 1024 * 1024

tests/test_bloom_keyspace.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import logging, time
2+
from valkey_bloom_test_case import ValkeyBloomTestCaseBase
3+
from valkeytests.conftest import resource_port_tracker
4+
5+
class TestKeyEventNotifications(ValkeyBloomTestCaseBase):
6+
RESERVE_KEYSPACE_MESSAGE = {'type': 'pmessage', 'pattern': b'__key*__:*', 'channel': b'__keyspace@0__:intermediate_val', 'data': b'bloom.reserve'}
7+
RESERVE_KEYEVENT_MESSAGE = {'type': 'pmessage', 'pattern': b'__key*__:*', 'channel': b'__keyevent@0__:bloom.reserve', 'data': b'intermediate_val'}
8+
ADD_KEYSPACE_MESSAGE = {'type': 'pmessage', 'pattern': b'__key*__:*', 'channel': b'__keyspace@0__:intermediate_val', 'data': b'bloom.add'}
9+
ADD_KEYEVENT_MESSAGE = {'type': 'pmessage', 'pattern': b'__key*__:*', 'channel': b'__keyevent@0__:bloom.add', 'data': b'intermediate_val'}
10+
11+
def create_expected_message_list(self, reserve_expected, add_expected, key_name):
12+
expected_messages = []
13+
self.RESERVE_KEYSPACE_MESSAGE['channel'] = f"__keyspace@0__:{key_name}".encode('utf-8')
14+
self.RESERVE_KEYEVENT_MESSAGE['data'] = f"{key_name}".encode('utf-8')
15+
self.ADD_KEYSPACE_MESSAGE['channel'] = f"__keyspace@0__:{key_name}".encode('utf-8')
16+
self.ADD_KEYEVENT_MESSAGE['data'] = f"{key_name}".encode('utf-8')
17+
if reserve_expected:
18+
expected_messages.append(self.RESERVE_KEYEVENT_MESSAGE)
19+
expected_messages.append(self.RESERVE_KEYSPACE_MESSAGE)
20+
if add_expected:
21+
expected_messages.append(self.ADD_KEYSPACE_MESSAGE)
22+
expected_messages.append(self.ADD_KEYEVENT_MESSAGE)
23+
return expected_messages
24+
25+
def check_response(self, result_messages, expected_messages):
26+
extra_message = self.keyspace_client_subscribe.get_message()
27+
if extra_message:
28+
assert False, f"Unexpected extra message returned: {extra_message}"
29+
for message in expected_messages:
30+
assert message in result_messages, f"{message} was not found in messages received"
31+
32+
def get_subscribe_client_messages(self, client, cmd, expected_message_count):
33+
client.execute_command(cmd)
34+
count = 0
35+
messages = []
36+
timeout = time.time() + 5
37+
while expected_message_count != count:
38+
message = self.keyspace_client_subscribe.get_message()
39+
if message:
40+
# Only for the first time we get messages we should skip the first message gotten
41+
if count > 0 or "BF.ADD" not in cmd:
42+
messages.append(message)
43+
count = count + 1
44+
if timeout < time.time():
45+
assert False, f"The number of expected messages failed tor eturn in time, messages received so far {messages}"
46+
return messages
47+
48+
def test_keyspace_bloom_commands(self):
49+
self.create_subscribe_clients()
50+
# The first call to get messages will return message that shows we subscribed to messages so we expect one more message than we need to check for
51+
# the first time we look at messages
52+
bloom_commands = [
53+
('BF.ADD add_test key', True, True, 5),
54+
('BF.MADD madd_test key1 key2', True, True, 4),
55+
('BF.EXISTS exists_test key', False, False, 0),
56+
('BF.INSERT insert_test ITEMS key1 key2', True, True, 4),
57+
('BF.RESERVE reserve_test 0.01 1000', True, False, 2)
58+
]
59+
60+
for command, reserve_expected, add_expected, expected_message_count in bloom_commands:
61+
expected_messages = self.create_expected_message_list(reserve_expected, add_expected, command.split()[1]) if reserve_expected else []
62+
result_messages = self.get_subscribe_client_messages(self.keyspace_client, command, expected_message_count)
63+
self.check_response(result_messages, expected_messages)
64+
65+
def create_subscribe_clients(self):
66+
self.keyspace_client = self.server.get_new_client()
67+
self.keyspace_client_subscribe = self.keyspace_client.pubsub()
68+
self.keyspace_client_subscribe.psubscribe('__key*__:*')
69+
self.keyspace_client.execute_command('CONFIG' ,'SET','notify-keyspace-events', 'KEA')
70+

tests/test_bloom_save_and_restore.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def test_restore_failed_large_bloom_filter(self):
7777
# Create a large bloom filter.
7878
# When we try to restore this on a server with the default max allowed filter size of 128MB, start up should fail.
7979
updated_max_size = 180 * 1024 * 1024
80-
original_max_size = 64 * 1024 * 1024
80+
original_max_size = int(client.execute_command('CONFIG GET bf.bloom-memory-usage-limit')[1])
8181
bf_add_result_1 = client.execute_command('CONFIG SET bf.bloom-memory-usage-limit ' + str(updated_max_size))
8282
client.execute_command('BF.RESERVE testSave 0.001 100000000')
8383
assert int(client.execute_command('BF.INFO testSave size')) > original_max_size

tests/valkey_bloom_test_case.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def verify_error_response(self, client, cmd, expected_err_reply):
3131
except ResponseError as e:
3232
assert_error_msg = f"Actual error message: '{str(e)}' is different from expected error message '{expected_err_reply}'"
3333
assert str(e) == expected_err_reply, assert_error_msg
34+
return str(e)
3435

3536
def verify_command_success_reply(self, client, cmd, expected_result):
3637
cmd_actual_result = client.execute_command(cmd)

0 commit comments

Comments
 (0)