2023-03-16 19:37:06 +00:00
|
|
|
import pytest
|
|
|
|
from helpers.cluster import ClickHouseCluster
|
2023-07-26 05:57:16 +00:00
|
|
|
from helpers.test_tools import TSV
|
2023-09-16 00:03:46 +00:00
|
|
|
from helpers.keeper_utils import KeeperClient, KeeperException
|
2023-03-16 19:37:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
cluster = ClickHouseCluster(__file__)
|
|
|
|
|
|
|
|
node = cluster.add_instance(
|
|
|
|
"node",
|
|
|
|
main_configs=["configs/keeper_config.xml"],
|
|
|
|
with_zookeeper=True,
|
|
|
|
stay_alive=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2023-07-28 06:09:57 +00:00
|
|
|
@pytest.fixture(scope="module", autouse=True)
|
2023-03-16 19:37:06 +00:00
|
|
|
def started_cluster():
|
|
|
|
try:
|
|
|
|
cluster.start()
|
|
|
|
yield cluster
|
|
|
|
|
|
|
|
finally:
|
|
|
|
cluster.shutdown()
|
|
|
|
|
|
|
|
|
2023-09-07 00:36:39 +00:00
|
|
|
@pytest.fixture(scope="function")
|
|
|
|
def client(started_cluster):
|
|
|
|
with KeeperClient.from_cluster(cluster, "zoo1") as keeper_client:
|
|
|
|
yield keeper_client
|
2023-07-26 15:13:53 +00:00
|
|
|
|
|
|
|
|
2023-09-07 00:36:39 +00:00
|
|
|
def test_big_family(client: KeeperClient):
|
|
|
|
client.touch("/test_big_family")
|
|
|
|
client.touch("/test_big_family/1")
|
|
|
|
client.touch("/test_big_family/1/1")
|
|
|
|
client.touch("/test_big_family/1/2")
|
|
|
|
client.touch("/test_big_family/1/3")
|
|
|
|
client.touch("/test_big_family/1/4")
|
|
|
|
client.touch("/test_big_family/1/5")
|
|
|
|
client.touch("/test_big_family/2")
|
|
|
|
client.touch("/test_big_family/2/1")
|
|
|
|
client.touch("/test_big_family/2/2")
|
|
|
|
client.touch("/test_big_family/2/3")
|
2023-03-16 19:37:06 +00:00
|
|
|
|
2023-09-07 00:36:39 +00:00
|
|
|
response = client.find_big_family("/test_big_family")
|
|
|
|
|
|
|
|
assert response == TSV(
|
2023-07-26 05:57:16 +00:00
|
|
|
[
|
2024-05-16 08:42:38 +00:00
|
|
|
["/test_big_family", "11"],
|
|
|
|
["/test_big_family/1", "6"],
|
|
|
|
["/test_big_family/2", "4"],
|
|
|
|
["/test_big_family/2/3", "1"],
|
|
|
|
["/test_big_family/2/2", "1"],
|
|
|
|
["/test_big_family/2/1", "1"],
|
|
|
|
["/test_big_family/1/5", "1"],
|
|
|
|
["/test_big_family/1/4", "1"],
|
|
|
|
["/test_big_family/1/3", "1"],
|
|
|
|
["/test_big_family/1/2", "1"],
|
2023-07-26 05:57:16 +00:00
|
|
|
]
|
|
|
|
)
|
2023-03-16 19:37:06 +00:00
|
|
|
|
2024-05-16 08:42:38 +00:00
|
|
|
response = client.find_big_family("/test_big_family", 2)
|
2023-09-07 00:36:39 +00:00
|
|
|
assert response == TSV(
|
2023-03-16 19:37:06 +00:00
|
|
|
[
|
2024-05-16 08:42:38 +00:00
|
|
|
["/test_big_family", "11"],
|
|
|
|
["/test_big_family/1", "6"],
|
2023-07-26 05:57:16 +00:00
|
|
|
]
|
2023-03-16 19:37:06 +00:00
|
|
|
)
|
|
|
|
|
2023-07-26 05:57:16 +00:00
|
|
|
|
2023-09-07 00:36:39 +00:00
|
|
|
def test_find_super_nodes(client: KeeperClient):
|
|
|
|
client.touch("/test_find_super_nodes")
|
|
|
|
client.touch("/test_find_super_nodes/1")
|
|
|
|
client.touch("/test_find_super_nodes/1/1")
|
|
|
|
client.touch("/test_find_super_nodes/1/2")
|
|
|
|
client.touch("/test_find_super_nodes/1/3")
|
|
|
|
client.touch("/test_find_super_nodes/1/4")
|
|
|
|
client.touch("/test_find_super_nodes/1/5")
|
|
|
|
client.touch("/test_find_super_nodes/2")
|
|
|
|
client.touch("/test_find_super_nodes/2/1")
|
|
|
|
client.touch("/test_find_super_nodes/2/2")
|
|
|
|
client.touch("/test_find_super_nodes/2/3")
|
|
|
|
client.touch("/test_find_super_nodes/2/4")
|
|
|
|
|
|
|
|
client.cd("/test_find_super_nodes")
|
|
|
|
|
|
|
|
response = client.find_super_nodes(4)
|
2024-05-31 08:28:46 +00:00
|
|
|
|
|
|
|
# The order of the response is not guaranteed, so we need to sort it
|
|
|
|
normalized_response = response.strip().split("\n")
|
2024-05-31 08:40:09 +00:00
|
|
|
normalized_response.sort()
|
2024-05-31 08:28:46 +00:00
|
|
|
|
|
|
|
assert TSV(normalized_response) == TSV(
|
2023-07-26 05:57:16 +00:00
|
|
|
[
|
|
|
|
["/test_find_super_nodes/1", "5"],
|
|
|
|
["/test_find_super_nodes/2", "4"],
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2023-09-07 00:36:39 +00:00
|
|
|
def test_delete_stale_backups(client: KeeperClient):
|
|
|
|
client.touch("/clickhouse")
|
|
|
|
client.touch("/clickhouse/backups")
|
|
|
|
client.touch("/clickhouse/backups/1")
|
|
|
|
client.touch("/clickhouse/backups/1/stage")
|
|
|
|
client.touch("/clickhouse/backups/1/stage/alive123")
|
|
|
|
client.touch("/clickhouse/backups/2")
|
|
|
|
client.touch("/clickhouse/backups/2/stage")
|
|
|
|
client.touch("/clickhouse/backups/2/stage/dead123")
|
|
|
|
|
|
|
|
response = client.delete_stale_backups()
|
2023-07-26 05:57:16 +00:00
|
|
|
|
2023-09-07 00:36:39 +00:00
|
|
|
assert response == (
|
2023-07-28 06:34:05 +00:00
|
|
|
'Found backup "/clickhouse/backups/1", checking if it\'s active\n'
|
|
|
|
'Backup "/clickhouse/backups/1" is active, not going to delete\n'
|
|
|
|
'Found backup "/clickhouse/backups/2", checking if it\'s active\n'
|
2023-09-07 00:36:39 +00:00
|
|
|
'Backup "/clickhouse/backups/2" is not active, deleting it'
|
2023-07-26 05:57:16 +00:00
|
|
|
)
|
|
|
|
|
2023-09-07 00:36:39 +00:00
|
|
|
assert client.ls("/clickhouse/backups") == ["1"]
|
2023-07-26 05:57:16 +00:00
|
|
|
|
|
|
|
|
2023-09-07 00:36:39 +00:00
|
|
|
def test_base_commands(client: KeeperClient):
|
|
|
|
client.create("/test_create_zk_node1", "testvalue1")
|
|
|
|
client.create("/test_create_zk_node_2", "testvalue2")
|
|
|
|
assert client.get("/test_create_zk_node1") == "testvalue1"
|
|
|
|
|
|
|
|
client.create("/123", "1=2")
|
2024-06-20 18:10:11 +00:00
|
|
|
client.create("/123/321", "foo;bar")
|
2023-09-07 00:36:39 +00:00
|
|
|
assert client.get("/123") == "1=2"
|
|
|
|
assert client.get("/123/321") == "foo;bar"
|
2023-07-26 05:57:16 +00:00
|
|
|
|
|
|
|
|
2023-09-07 00:36:39 +00:00
|
|
|
def test_four_letter_word_commands(client: KeeperClient):
|
|
|
|
assert client.execute_query("ruok") == "imok"
|
2023-09-16 00:03:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_rm_with_version(client: KeeperClient):
|
|
|
|
node_path = "/test_rm_with_version_node"
|
|
|
|
client.create(node_path, "value")
|
|
|
|
assert client.get(node_path) == "value"
|
|
|
|
|
|
|
|
with pytest.raises(KeeperException) as ex:
|
|
|
|
client.rm(node_path, 1)
|
|
|
|
|
|
|
|
ex_as_str = str(ex)
|
|
|
|
assert "Coordination error: Bad version" in ex_as_str
|
|
|
|
assert node_path in ex_as_str
|
|
|
|
assert client.get(node_path) == "value"
|
|
|
|
|
|
|
|
client.rm(node_path, 0)
|
|
|
|
|
|
|
|
with pytest.raises(KeeperException) as ex:
|
|
|
|
client.get(node_path)
|
|
|
|
|
|
|
|
ex_as_str = str(ex)
|
|
|
|
assert "node doesn't exist" in ex_as_str
|
|
|
|
assert node_path in ex_as_str
|
|
|
|
|
|
|
|
|
|
|
|
def test_rm_without_version(client: KeeperClient):
|
|
|
|
node_path = "/test_rm_with_version_node"
|
|
|
|
client.create(node_path, "value")
|
|
|
|
assert client.get(node_path) == "value"
|
|
|
|
|
|
|
|
client.rm(node_path)
|
|
|
|
|
|
|
|
with pytest.raises(KeeperException) as ex:
|
|
|
|
client.get(node_path)
|
|
|
|
|
|
|
|
ex_as_str = str(ex)
|
|
|
|
assert "node doesn't exist" in ex_as_str
|
|
|
|
assert node_path in ex_as_str
|
2023-09-16 00:07:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_set_with_version(client: KeeperClient):
|
|
|
|
node_path = "/test_set_with_version_node"
|
|
|
|
client.create(node_path, "value")
|
|
|
|
assert client.get(node_path) == "value"
|
|
|
|
|
|
|
|
client.set(node_path, "value1", 0)
|
|
|
|
assert client.get(node_path) == "value1"
|
|
|
|
|
|
|
|
with pytest.raises(KeeperException) as ex:
|
|
|
|
client.set(node_path, "value2", 2)
|
|
|
|
|
|
|
|
ex_as_str = str(ex)
|
|
|
|
assert "Coordination error: Bad version" in ex_as_str
|
|
|
|
assert node_path in ex_as_str
|
|
|
|
assert client.get(node_path) == "value1"
|
|
|
|
|
|
|
|
client.set(node_path, "value2", 1)
|
|
|
|
assert client.get(node_path) == "value2"
|
|
|
|
|
|
|
|
|
|
|
|
def test_set_without_version(client: KeeperClient):
|
|
|
|
node_path = "/test_set_without_version_node"
|
|
|
|
client.create(node_path, "value")
|
|
|
|
assert client.get(node_path) == "value"
|
|
|
|
|
|
|
|
client.set(node_path, "value1")
|
|
|
|
assert client.get(node_path) == "value1"
|
|
|
|
|
|
|
|
client.set(node_path, "value2")
|
|
|
|
assert client.get(node_path) == "value2"
|
|
|
|
|
|
|
|
|
|
|
|
def test_quoted_argument_parsing(client: KeeperClient):
|
|
|
|
node_path = "/test_quoted_argument_parsing_node"
|
|
|
|
client.create(node_path, "value")
|
|
|
|
|
|
|
|
client.execute_query(f"set '{node_path}' 'value1 with some whitespace'")
|
|
|
|
assert client.get(node_path) == "value1 with some whitespace"
|
|
|
|
|
|
|
|
client.execute_query(f"set '{node_path}' 'value2 with some whitespace' 1")
|
|
|
|
assert client.get(node_path) == "value2 with some whitespace"
|
|
|
|
|
|
|
|
client.execute_query(f"set '{node_path}' \"value3 with some whitespace\"")
|
|
|
|
assert client.get(node_path) == "value3 with some whitespace"
|
|
|
|
|
|
|
|
client.execute_query(f"set '{node_path}' \"value4 with some whitespace\" 3")
|
2023-09-16 00:32:32 +00:00
|
|
|
assert client.get(node_path) == "value4 with some whitespace"
|
2023-10-11 12:45:38 +00:00
|
|
|
|
2023-10-12 12:32:36 +00:00
|
|
|
|
2023-10-24 15:02:54 +00:00
|
|
|
def get_direct_children_number(client: KeeperClient):
|
|
|
|
client.touch("/get_direct_children_number")
|
|
|
|
client.touch("/get_direct_children_number/1")
|
|
|
|
client.touch("/get_direct_children_number/1/1")
|
|
|
|
client.touch("/get_direct_children_number/1/2")
|
|
|
|
client.touch("/get_direct_children_number/2")
|
|
|
|
client.touch("/get_direct_children_number/2/1")
|
|
|
|
client.touch("/get_direct_children_number/2/2")
|
|
|
|
|
|
|
|
assert client.get_direct_children_number("/get_direct_children_number") == "2"
|
|
|
|
|
|
|
|
|
2023-10-11 12:45:38 +00:00
|
|
|
def test_get_all_children_number(client: KeeperClient):
|
|
|
|
client.touch("/test_get_all_children_number")
|
|
|
|
client.touch("/test_get_all_children_number/1")
|
|
|
|
client.touch("/test_get_all_children_number/1/1")
|
|
|
|
client.touch("/test_get_all_children_number/1/2")
|
|
|
|
client.touch("/test_get_all_children_number/1/3")
|
|
|
|
client.touch("/test_get_all_children_number/1/4")
|
|
|
|
client.touch("/test_get_all_children_number/1/5")
|
|
|
|
client.touch("/test_get_all_children_number/2")
|
|
|
|
client.touch("/test_get_all_children_number/2/1")
|
|
|
|
client.touch("/test_get_all_children_number/2/2")
|
|
|
|
client.touch("/test_get_all_children_number/2/3")
|
|
|
|
client.touch("/test_get_all_children_number/2/4")
|
|
|
|
|
2023-10-16 02:02:31 +00:00
|
|
|
assert client.get_all_children_number("/test_get_all_children_number") == "11"
|