Files
Radosław Cybulski 9a6aed721b alternator: add streams with tablets tests
Add tests for Streams, when table uses tablets underneath.
One test verifies filtering using CHILD_SHARDS feature.
Other one makes sure we get read all data while the table
undergoes tablet count change.

Add `--tablet-load-stats-refresh-interval-in-seconds=1`
to `alternator/run` script, as otherwise newly added tests will fail.
The setting changes how often scylla refreshes tablet metadata.
This can't be done using `scylla_config_temporary`, as
1) default is 60 seconds
2) scylla will wait full timeout (60s) to read configuration variable again.
2026-04-17 18:58:27 +02:00

190 lines
8.1 KiB
Python
Executable File

#!/usr/bin/env python3
# Use the run.py library from ../cqlpy:
import sys
sys.path.insert(1, sys.path[0] + '/../cqlpy')
import run
import os
import requests
import glob
# When tests are to be run against AWS (the "--aws" option), it is not
# necessary to start Scylla at all. All we need to do is to run pytest.
if '--aws' in sys.argv:
success = run.run_pytest(sys.path[0], ['-o', 'xfail_strict=false'] + sys.argv[1:])
exit(0 if success else 1)
# check_alternator() below uses verify=False to accept self-signed SSL
# certificates but then we get scary warnings. This trick disables them:
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# If the first option is "--release", download that release (see
# fetch_scylla.py for supported release numbers), and use that.
# The downloaded Scylla will be cached in the directory build/<release>,
# where <release> is the specific release downloaded - E.g., if the user
# asks "--release 2022.1" and the downloaded release is 2022.1.9, it
# will be stored in build/2022.1.9.
if len(sys.argv) > 1 and sys.argv[1] == '--release':
release = sys.argv[2]
exe = run.download_precompiled_scylla(release)
run_scylla_cmd = lambda pid, dir: run.run_precompiled_scylla_cmd(exe, pid, dir)
sys.argv = sys.argv[0:1] + sys.argv[3:]
os.environ['SCYLLA'] = exe # so find_scylla() prints the right one
else:
run_scylla_cmd = run.run_scylla_cmd
print('Scylla is: ' + run.find_scylla() + '.')
extra_scylla_options = []
remove_scylla_options = []
# If the "--vnodes" option is given, drop the "tablets" experimental
# feature (turned on in run.py) so that all tests will be run with the
# old vnode-based replication instead of tablets. This option only has
# temporary usefulness, and should eventually be removed.
if '--vnodes' in sys.argv:
sys.argv.remove('--vnodes')
remove_scylla_options.append('--enable-tablets=true')
# Tablets are now enabled by default on some releases, it is not enough to remove the enable above.
extra_scylla_options.append('--enable-tablets=false')
if "-h" in sys.argv or "--help" in sys.argv:
run.run_pytest(sys.path[0], sys.argv)
exit(0)
# run_alternator_cmd runs the same as run_scylla_cmd with *additional*
# parameters, so in particular both CQL and Alternator will be enabled.
# This is useful for us because we need CQL to setup authentication.
def run_alternator_cmd(pid, dir):
(cmd, env) = run_scylla_cmd(pid, dir)
ip = run.pid_to_ip(pid)
cmd += [
'--alternator-address', ip,
'--alternator-enforce-authorization', '1',
'--alternator-write-isolation', 'only_rmw_uses_lwt',
'--alternator-streams-time-window-s', '0',
'--alternator-timeout-in-ms', '30000',
# no longer needed here because it's defined in test/cqlpy/run.py
# now that this parameter is used also by CQL's per-row TTL.
#'--alternator-ttl-period-in-seconds', '0.5',
'--alternator-allow-system-table-write=1',
# Allow testing experimental features. Following issue #9467, we need
# to add here specific experimental features as they are introduced.
# We only list here Alternator-specific experimental features - CQL
# ones are listed in test/cqlpy/run.py.
'--experimental-features=alternator-streams',
# this is required by test_streams.py test_parent_filtering and test_get_records_with_alternating_tablets_count
# setting the value using scylla_config_temporary won't work, because the value is read
# at the start and then periodically with `tablet-load-stats-refresh-interval-in-seconds`
# interval, which by default is 60 seconds.
'--tablet-load-stats-refresh-interval-in-seconds=1',
]
if '--https' in sys.argv:
run.setup_ssl_certificate(dir)
cmd += ['--alternator-https-port', '8043',
'--alternator-encryption-options', f'keyfile={dir}/scylla.key',
'--alternator-encryption-options', f'certificate={dir}/scylla.crt',
]
else:
cmd += ['--alternator-port', '8000']
if '--vs' in sys.argv:
cmd += ['--vector-store-primary-uri', f'http://{ip}:6080']
cmd += extra_scylla_options
for i in remove_scylla_options:
cmd.remove(i)
# Unfortunately, earlier Scylla versions required different command line
# options to run, so for some old versions we need to drop some of the
# command line options added above, or add more options. In cqlpy/run.py's
# run_precompiled_scylla_cmd we already do this for most Scylla options,
# but here we just need to take care of the Alternator-specific options
# that we added here and were different in older versions.
if 'release' in globals():
version = release.split('~')[0].split('.')
major = [int(version[0]), int(version[1])]
print(major)
if major < [2025,4]:
cmd.remove('--alternator-allow-system-table-write=1')
return (cmd, env)
pid = run.run_with_temporary_dir(run_alternator_cmd)
ip = run.pid_to_ip(pid)
if '--https' in sys.argv:
alternator_url=f"https://{ip}:8043"
else:
alternator_url=f"http://{ip}:8000"
# If the "--vs" option is given, also run the vector store process.
# The vector store is run in its own temporary directory, but runs
# on the same IP address as Scylla (otherwise, the first of the two
# which we will run will not know where to find the second).
def run_vector_store_cmd(pid, dir):
global ip # same IP as Scylla, see comment above
print('Booting Vector Store on ' + ip + ' in ' + dir + '...')
with open(f'{dir}/.password', 'w') as f:
print('cassandra', file=f)
env = {
'VECTOR_STORE_URI': f'{ip}:6080',
'VECTOR_STORE_SCYLLADB_URI': f'{ip}:9042',
'VECTOR_STORE_SCYLLADB_USERNAME': 'cassandra',
'VECTOR_STORE_SCYLLADB_PASSWORD_FILE': f'{dir}/.password',
}
global vector_store_executable # set by the code below
cmd = [
vector_store_executable
]
return (cmd, env)
if '--vs' in sys.argv:
sys.argv.remove('--vs')
# Find the vector-store executable. We look for it in the vector-store/
# directory next to the Scylla working directory taking the newest built
# executable, but it can also be specified by the user by setting the
# VECTOR_STORE environment variable to the path of if os.getenv('SCYLLA'):
global vector_store_executable
if os.getenv('VECTOR_STORE'):
vector_store_executable = os.path.abspath(os.getenv('VECTOR_STORE'))
else:
vector_store_dir = os.path.join(os.path.dirname(run.source_path), 'vector-store')
vector_stores = glob.glob(os.path.join(vector_store_dir, 'target/*/vector-store'))
if not vector_stores:
print(f"Can't find a compiled Vector Store in {vector_store_dir}.\nPlease build Vector Store or set VECTOR_STORE to the path of a Vector Store executable.")
exit(1)
vector_store_executable = max(vector_stores, key=os.path.getmtime)
if not os.access(vector_store_executable, os.X_OK):
print(f"Cannot execute '{vector_store_executable}'.\nPlease set VECTOR_STORE to the path of a Vector Store executable.")
exit(1)
print(f"Vector Store is: {vector_store_executable}.")
run.run_with_temporary_dir(run_vector_store_cmd)
# Wait for both CQL and Alternator APIs to become responsive. We obviously
# need the Alternator API to test Alternator, but currently we also need
# CQL for setting up authentication.
def check_alternator(url):
try:
requests.get(url, verify=False)
except requests.ConnectionError:
raise run.NotYetUp
# Any other exception may indicate a problem, and is passed to the caller.
run.wait_for_services(pid, [
lambda: run.check_cql(ip),
lambda: check_alternator(alternator_url),
])
# Finally run pytest:
success = run.run_pytest(sys.path[0], ['--url', alternator_url] + sys.argv[1:])
run.summary = 'Alternator tests pass' if success else 'Alternator tests failure'
exit(0 if success else 1)
# Note that the run.cleanup_all() function runs now, just like on any exit
# for any reason in this script. It will delete the temporary files and
# announce the failure or success of the test (printing run.summary).