Files
scylladb/test/nodetool/test_viewbuildstatus.py
Avi Kivity f3eade2f62 treewide: relicense to ScyllaDB-Source-Available-1.0
Drop the AGPL license in favor of a source-available license.
See the blog post [1] for details.

[1] https://www.scylladb.com/2024/12/18/why-were-moving-to-a-source-available-license/
2024-12-18 17:45:13 +02:00

125 lines
4.2 KiB
Python

#
# Copyright 2024-present ScyllaDB
#
# SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
#
import pytest
from subprocess import CalledProcessError
from test.nodetool.rest_api_mock import expected_request
def get_keyspace_view_from_args(args):
keyspace = None
view = None
if len(args) == 1:
keyspace_view = args[0].replace('/', '.', 1)
try:
keyspace, view = keyspace_view.split('.', 1)
except ValueError:
pass
elif len(args) == 2:
keyspace, view = args
return keyspace, view
def format_status(host, info):
return f"{host:<9} {info:<7}\n"
def format_output(keyspace, view, view_status):
table = format_status("Host", "Info")
succeed = True
for host, status in view_status.items():
if status != 'SUCCESS':
succeed = False
table += format_status(host, status)
output = ''
if succeed:
output += f"{keyspace}.{view} has finished building\n"
else:
output += f"{keyspace}.{view} has not finished building; node status is below.\n"
output += "\n"
output += table
return output
def id_from_param(param):
args, statuses, _ = param
if args:
args_fmt = ','.join(args)
else:
args_fmt = '<none>'
if statuses:
statuses_fmt = ','.join(statuses)
else:
statuses_fmt = '<none>'
return f"args({args_fmt})-statuses({statuses_fmt})"
def format_invalid_argument_error(is_scylla):
stdout = ''
stderr = ''
message = 'viewbuildstatus requires keyspace and view name arguments'
if is_scylla:
stderr += f'error processing arguments: {message}\n'
else:
progname = "nodetool"
stdout += f"{progname}: {message}\n"
stdout += f"See '{progname} help' or '{progname} help <command>'.\n"
return stdout, stderr
test_params = [
([], [], 1),
(["ks"], [], 1),
(["ks.view"], ['UNKNOWN'], 1),
(["ks.view"], ['SUCCESS'], 0),
(["ks.view"], ['STARTED', 'UNKNOWN', 'SUCCESS'], 1),
(["ks.view"], ['STARTED', 'STARTED', 'STARTED'], 1),
(["ks.view"], ['SUCCESS', 'SUCCESS', 'SUCCESS'], 0),
(["ks/view"], ['SUCCESS'], 0),
(["ks", "view"], ['SUCCESS'], 0),
(["ks", "view", "something-more"], [], 1),
]
@pytest.mark.parametrize("args,statuses,returncode", [pytest.param(*param, id=id_from_param(param))
for param in test_params])
def test_viewbuildstatus(request, nodetool, args, statuses, returncode):
keyspace, view = get_keyspace_view_from_args(args)
if keyspace is None:
expected_requests = []
else:
view_status = {f"127.0.0.{i}": status for i, status in enumerate(statuses)}
expected_requests = [
expected_request("GET", f"/storage_service/view_build_statuses/{keyspace}/{view}",
response=[{"key": host, "value": status} for host, status in view_status.items()])
]
expected_output = format_output(keyspace, view, view_status)
if returncode != 0:
is_scylla = request.config.getoption("nodetool") == "scylla"
if all(status == 'SUCCESS' for status in statuses):
# invalid argument
with pytest.raises(CalledProcessError) as exc_info:
res = nodetool("viewbuildstatus", *args, expected_requests=expected_requests)
actual_output = res.stdout
assert exc_info.type is CalledProcessError
assert exc_info.value.returncode == 1
expected_stdout, expected_stderr = format_invalid_argument_error(is_scylla)
assert exc_info.value.stdout == expected_stdout
assert expected_stderr in exc_info.value.stderr
else:
with pytest.raises(CalledProcessError) as exc_info:
res = nodetool("viewbuildstatus", *args, expected_requests=expected_requests)
actual_output = res.stdout
assert exc_info.type is CalledProcessError
assert exc_info.value.returncode == 1
assert exc_info.value.output == expected_output
else:
res = nodetool("viewbuildstatus", *args, expected_requests=expected_requests)
actual_output = res.stdout
assert actual_output == expected_output