Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding tests for modules ACL and modules config changes in 8.0 #3489

Merged
merged 3 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 204 additions & 0 deletions tests/test_asyncio/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
parse_info,
)
from redis.client import EMPTY_RESPONSE, NEVER_DECODE
from redis.commands.json.path import Path
from redis.commands.search.field import TextField
from redis.commands.search.query import Query
from tests.conftest import (
assert_resp_response,
assert_resp_response_in,
Expand Down Expand Up @@ -49,6 +52,12 @@ def factory(username):
return r

yield factory
try:
current_user = await r.client_info()
petyaslavova marked this conversation as resolved.
Show resolved Hide resolved
except exceptions.NoPermissionError:
current_user = {}
if "default" != current_user.get("user"):
petyaslavova marked this conversation as resolved.
Show resolved Hide resolved
await r.auth("", "default")
for username in usernames:
await r.acl_deluser(username)

Expand Down Expand Up @@ -115,12 +124,65 @@ async def test_acl_cat_no_category(self, r: redis.Redis):
assert isinstance(categories, list)
assert "read" in categories or b"read" in categories

@pytest.mark.redismod
@skip_if_server_version_lt("7.9.0")
async def test_acl_cat_contain_modules_no_category(self, r: redis.Redis):
modules_list = [
"search",
"bloom",
"json",
"cuckoo",
"timeseries",
"cms",
"topk",
"tdigest",
]
categories = await r.acl_cat()
assert isinstance(categories, list)
for module_cat in modules_list:
assert module_cat in categories or module_cat.encode() in categories

@skip_if_server_version_lt(REDIS_6_VERSION)
async def test_acl_cat_with_category(self, r: redis.Redis):
commands = await r.acl_cat("read")
assert isinstance(commands, list)
assert "get" in commands or b"get" in commands

@pytest.mark.redismod
@skip_if_server_version_lt("7.9.0")
async def test_acl_modules_cat_with_category(self, r: redis.Redis):
search_commands = await r.acl_cat("search")
assert isinstance(search_commands, list)
assert "FT.SEARCH" in search_commands or b"FT.SEARCH" in search_commands

bloom_commands = await r.acl_cat("bloom")
assert isinstance(bloom_commands, list)
assert "bf.add" in bloom_commands or b"bf.add" in bloom_commands

json_commands = await r.acl_cat("json")
assert isinstance(json_commands, list)
assert "json.get" in json_commands or b"json.get" in json_commands

cuckoo_commands = await r.acl_cat("cuckoo")
assert isinstance(cuckoo_commands, list)
assert "cf.insert" in cuckoo_commands or b"cf.insert" in cuckoo_commands

cms_commands = await r.acl_cat("cms")
assert isinstance(cms_commands, list)
assert "cms.query" in cms_commands or b"cms.query" in cms_commands

topk_commands = await r.acl_cat("topk")
assert isinstance(topk_commands, list)
assert "topk.list" in topk_commands or b"topk.list" in topk_commands

tdigest_commands = await r.acl_cat("tdigest")
assert isinstance(tdigest_commands, list)
assert "tdigest.rank" in tdigest_commands or b"tdigest.rank" in tdigest_commands

timeseries_commands = await r.acl_cat("timeseries")
assert isinstance(timeseries_commands, list)
assert "ts.range" in timeseries_commands or b"ts.range" in timeseries_commands

@skip_if_server_version_lt(REDIS_6_VERSION)
async def test_acl_deluser(self, r_teardown):
username = "redis-py-user"
Expand Down Expand Up @@ -316,6 +378,116 @@ async def test_acl_whoami(self, r: redis.Redis):
username = await r.acl_whoami()
assert isinstance(username, (str, bytes))

@pytest.mark.redismod
@skip_if_server_version_lt("7.9.0")
async def test_acl_modules_commands(self, r_teardown):
username = "redis-py-user"
password = "pass-for-test-user"

r = r_teardown(username)
await r.flushdb()

await r.ft().create_index((TextField("txt"),))
await r.hset("doc1", mapping={"txt": "foo baz"})
await r.hset("doc2", mapping={"txt": "foo bar"})

await r.acl_setuser(
username,
enabled=True,
reset=True,
passwords=[f"+{password}"],
categories=["-all"],
commands=[
"+FT.SEARCH",
"-FT.DROPINDEX",
"+json.set",
"+json.get",
"-json.clear",
"+bf.reserve",
"-bf.info",
"+cf.reserve",
"+cms.initbydim",
"+topk.reserve",
"+tdigest.create",
"+ts.create",
"-ts.info",
],
keys=["*"],
)

await r.auth(password, username)

assert await r.ft().search(Query("foo ~bar"))
with pytest.raises(exceptions.NoPermissionError):
await r.ft().dropindex()

await r.json().set("foo", Path.root_path(), "bar")
assert await r.json().get("foo") == "bar"
with pytest.raises(exceptions.NoPermissionError):
await r.json().clear("foo")

assert await r.bf().create("bloom", 0.01, 1000)
assert await r.cf().create("cuckoo", 1000)
assert await r.cms().initbydim("cmsDim", 100, 5)
assert await r.topk().reserve("topk", 5, 100, 5, 0.9)
assert await r.tdigest().create("to-tDigest", 10)
with pytest.raises(exceptions.NoPermissionError):
await r.bf().info("bloom")

assert await r.ts().create(1, labels={"Redis": "Labs"})
with pytest.raises(exceptions.NoPermissionError):
await r.ts().info(1)

@pytest.mark.redismod
@skip_if_server_version_lt("7.9.0")
async def test_acl_modules_category_commands(self, r_teardown):
username = "redis-py-user"
password = "pass-for-test-user"

r = r_teardown(username)
await r.flushdb()

# validate modules categories acl config
await r.acl_setuser(
username,
enabled=True,
reset=True,
passwords=[f"+{password}"],
categories=[
"-all",
"+@search",
"+@json",
"+@bloom",
"+@cuckoo",
"+@topk",
"+@cms",
"+@timeseries",
"+@tdigest",
],
keys=["*"],
)
await r.ft().create_index((TextField("txt"),))
await r.hset("doc1", mapping={"txt": "foo baz"})
await r.hset("doc2", mapping={"txt": "foo bar"})

await r.auth(password, username)

assert await r.ft().search(Query("foo ~bar"))
assert await r.ft().dropindex()

assert await r.json().set("foo", Path.root_path(), "bar")
assert await r.json().get("foo") == "bar"

assert await r.bf().create("bloom", 0.01, 1000)
assert await r.bf().info("bloom")
assert await r.cf().create("cuckoo", 1000)
assert await r.cms().initbydim("cmsDim", 100, 5)
assert await r.topk().reserve("topk", 5, 100, 5, 0.9)
assert await r.tdigest().create("to-tDigest", 10)

assert await r.ts().create(1, labels={"Redis": "Labs"})
assert await r.ts().info(1)

@pytest.mark.onlynoncluster
async def test_client_list(self, r: redis.Redis):
clients = await r.client_list()
Expand Down Expand Up @@ -512,6 +684,38 @@ async def test_config_set(self, r: redis.Redis):
assert await r.config_set("timeout", 0)
assert (await r.config_get())["timeout"] == "0"

@pytest.mark.redismod
@skip_if_server_version_lt("7.9.0")
async def test_config_get_for_modules(self, r: redis.Redis):
search_module_configs = await r.config_get("search-*")
assert "search-timeout" in search_module_configs

ts_module_configs = await r.config_get("ts-*")
assert "ts-num-threads" in ts_module_configs
petyaslavova marked this conversation as resolved.
Show resolved Hide resolved

bf_module_configs = await r.config_get("bf-*")
assert "bf-initial-size" in bf_module_configs
petyaslavova marked this conversation as resolved.
Show resolved Hide resolved

cf_module_configs = await r.config_get("cf-*")
assert "cf-max-iterations" in cf_module_configs
petyaslavova marked this conversation as resolved.
Show resolved Hide resolved

@pytest.mark.redismod
@skip_if_server_version_lt("7.9.0")
async def test_config_set_for_search_module(self, r: redis.Redis):
petyaslavova marked this conversation as resolved.
Show resolved Hide resolved
search_timeout_initial = (await r.config_get())["search-timeout"]
search_timeout_new = int(search_timeout_initial) + 100

assert await r.config_set("search-timeout", search_timeout_new)
petyaslavova marked this conversation as resolved.
Show resolved Hide resolved
assert (
int((await r.config_get("search-*"))["search-timeout"])
== search_timeout_new
)
assert (
int((await r.ft().config_get("TIMEOUT"))[b"TIMEOUT"]) == search_timeout_new
)
with pytest.raises(exceptions.ResponseError):
await r.config_set("search-max-doctablesize", 2000000)

@pytest.mark.onlynoncluster
async def test_dbsize(self, r: redis.Redis):
await r.set("a", "foo")
Expand Down
Loading
Loading