test/cql-pytest: add tests reproducing bugs in compression configuration
This patch adds some minimal tests for the "with compression = {..}" table
configuration. These tests reproduce three known bugs:
Refs #6442: Always print all schema parameters (including default values)
Scylla doesn't return the default chunk_length_in_kb, but Cassandra
does.
Refs #8948: Cassandra 3.11.10 uses "class" instead of "sstable_compression"
for compression settings by default
Cassandra switched, long ago, the "sstable_compression" attribute's
name to "class". This can break Cassandra applications that create
tables (where we won't understand the "class" parameter) and applications
that inquire about the configuration of existing tables. This patch adds
tests for both problems.
Refs #9933: ALTER TABLE with "chunk_length_kb" (compression) of 1MB caused a
core dump on all nodes
Our test for this issue hangs Scylla (or crashes, depending on the test
environment configuration), when a huge allocation is attempted during
memtable flush. So this test is marked "skip" instead of xfail.
The tests included here also uncovered a new minor/insignificant bug,
where Scylla allows floating point numbers as chunk_length_in_kb - this
number is truncated to an integer, and allowed, unlike Cassandra or
common sense.
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
Closes #14261
This commit is contained in:
committed by
Botond Dénes
parent
5fa08adc88
commit
7deba4f4a5
87
test/cql-pytest/test_sstable_compression.py
Normal file
87
test/cql-pytest/test_sstable_compression.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2023-present ScyllaDB
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
#############################################################################
|
||||
# Tests for configuration of compressed sstables
|
||||
#############################################################################
|
||||
|
||||
import pytest
|
||||
import nodetool
|
||||
from util import new_test_table
|
||||
from cassandra.protocol import ConfigurationException, SyntaxException
|
||||
|
||||
# In older Cassandra and Scylla, the name of the compression algorithm was
|
||||
# given as a "sstable_compression" attribute, but newer Cassandra switched
|
||||
# to "class". Check that we support this new name class.
|
||||
# Reproduces #8948.
|
||||
@pytest.mark.xfail(reason="#8948")
|
||||
def test_compression_class(cql, test_keyspace):
|
||||
with new_test_table(cql, test_keyspace, "p int primary key, v int", "with compression = { 'class': 'LZ4Compressor' }") as table:
|
||||
pass
|
||||
|
||||
# In the following tests, we use the older "sstable_compression" option name
|
||||
# (instead of the new "class") so we can have passing tests despite #8948.
|
||||
# When both Scylla and Cassandra support "class", we should modify this variable
|
||||
# to use it:
|
||||
sstable_compression = 'sstable_compression'
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def table_lz4(cql, test_keyspace):
|
||||
with new_test_table(cql, test_keyspace, "p int primary key, v int", "with compression = { '" + sstable_compression + "': 'LZ4Compressor' }") as table:
|
||||
yield table
|
||||
|
||||
# Test that if we have a table with lz4 compression, it has the expected
|
||||
# compression "class" in its schema table. Note that even if the older
|
||||
# "sstable_compression" attribute was used to set the compression class,
|
||||
# when reading the schema we should see "class".
|
||||
# Reproduces #8948.
|
||||
@pytest.mark.xfail(reason="#8948")
|
||||
def test_read_compression_class(cql, table_lz4):
|
||||
[ks, cf] = table_lz4.split('.')
|
||||
opts = cql.execute(f"SELECT compression FROM system_schema.tables WHERE keyspace_name='{ks}' AND table_name='{cf}'").one().compression
|
||||
assert 'class' in opts
|
||||
assert opts['class'] == 'org.apache.cassandra.io.compress.LZ4Compressor'
|
||||
|
||||
# When creating a compressed table without specifying chunk_length_in_kb
|
||||
# explicitly, some default value is nevertheless used, and its value should
|
||||
# be readable from the schema.
|
||||
# Reproduces #6442.
|
||||
@pytest.mark.xfail(reason="#6442")
|
||||
def test_read_chunk_length(cql, table_lz4):
|
||||
[ks, cf] = table_lz4.split('.')
|
||||
opts = cql.execute(f"SELECT compression FROM system_schema.tables WHERE keyspace_name='{ks}' AND table_name='{cf}'").one().compression
|
||||
assert 'chunk_length_in_kb' in opts
|
||||
|
||||
# Both Cassandra and Scylla only allow chunk_length_in_kb to be set a power
|
||||
# of two.
|
||||
def test_chunk_length_must_be_power_of_two(cql, test_keyspace):
|
||||
with pytest.raises(ConfigurationException, match='power of 2'):
|
||||
with new_test_table(cql, test_keyspace, "p int primary key, v int", "with compression = { '" + sstable_compression + "': 'LZ4Compressor', 'chunk_length_in_kb': 100 }") as table:
|
||||
pass
|
||||
|
||||
# chunk_length_in_kb cannot be zero, negative, null, or non-integer.
|
||||
# Surprisingly, Scylla allows floating-point numbers (and truncates them).
|
||||
# It shouldn't, and Cassandra doesn't, so this case is "xfail" below.
|
||||
@pytest.mark.parametrize("garbage", ["0", "-1", "null", "'dog'",
|
||||
pytest.param("1.1", marks=pytest.mark.xfail(reason='Scylla truncates float chunk length'))])
|
||||
def test_chunk_length_invalid(cql, test_keyspace, garbage):
|
||||
# The error should usually be ConfigurationException, but strangely
|
||||
# Cassandra throws a SyntaxException in the "null" case.
|
||||
with pytest.raises((ConfigurationException, SyntaxException), match='chunk_length_in_kb'):
|
||||
with new_test_table(cql, test_keyspace, "p int primary key, v int", "with compression = { '" + sstable_compression + "': 'LZ4Compressor', 'chunk_length_in_kb': " + garbage + " }") as table:
|
||||
pass
|
||||
|
||||
# If a user is allowed to specify a huge number for chunk_length_in_kb, it can
|
||||
# result in unbounded allocations and potentially crashing Scylla. Therefore,
|
||||
# there ought to be some limit for the configured chunk length. Let's check it
|
||||
# by trying a ridiculously large value, which shouldn't be legal.
|
||||
# Reproduces #9933.
|
||||
@pytest.mark.skip(reason="#9933")
|
||||
def test_huge_chunk_length(cql, test_keyspace):
|
||||
with new_test_table(cql, test_keyspace, "p int primary key, v int", "with compression = { '" + sstable_compression + "': 'LZ4Compressor', 'chunk_length_in_kb': 1048576 }") as table:
|
||||
# Write something and flush it, to have sstable compression actually
|
||||
# be used
|
||||
cql.execute(f'INSERT INTO {table} (p, v) VALUES (1, 2)')
|
||||
nodetool.flush(cql, table)
|
||||
Reference in New Issue
Block a user