Merge 'Fix tests in test/cql-pytest/ that fail on Cassandra' from Nadav Har'El
As a general rule, tests in test/cql-pytest shouldn't just pass on Scylla - they also should not fail on Cassandra; A test that fails on Cassandra may indicate that the test is wrong, or that Scylla's behavior is wrong and the test just enshrines that wrong behavior. Each time we see a test fail on Cassandra we need to check if this is not the case. We also have special markers scylla_only and cassandra_bug to put on tests that we know _should_ fail on Cassandra because it is missing some Scylla-only feature or there is a bug in Cassandra, respectively. Such tests will be xfailed/skipped when running on Cassandra, and not report failures. Unfortunately, over time more several tests got into our suite in that did not pass on Cassandra. In this series I went over all of them, and fixed each to pass - or be skipped - on Cassandra, in a way that each patch explains. Fixes #16027 Closes scylladb/scylladb#16033 * github.com:scylladb/scylladb: test/cql-pytest: fix test_describe.py to not fail on Cassandra test/cql-pytest: fix select_single_column_relation_test.py to not fail on Cassandra test/cql-pytest: fix compact_storage_test.py to not fail on Cassandra test/cql-pytest: fix test_secondary_index.py to not fail on Cassandra test/cql-pytest: fix test_materialized_view.py to not fail on Cassandra test/cql-pytest: fix test_keyspace.py to not fail on Cassandra test/cql-pytest: test_guardrail_replication_strategy.py is Scylla-only test/cql-pytest: partial fix for test_compaction_strategy_validation.py on Cassandra test/cql-pytest: fix test_filtering.py to not fail on Cassandra
This commit is contained in:
@@ -1046,7 +1046,7 @@ def testDeleteWithOneClusteringColumns(cql, test_keyspace, forceFlush):
|
||||
assertInvalidMessage(cql, table, "Only EQ and IN relation are supported on the partition key",
|
||||
"DELETE FROM %s WHERE partitionKey > ? AND clustering = ?", 0, 1)
|
||||
|
||||
assertInvalidMessage(cql, table, "Cannot use CONTAINS on non-collection column",
|
||||
assertInvalidMessageRE(cql, table, "Cannot use CONTAINS on non-collection column|Cannot use DELETE with CONTAINS",
|
||||
"DELETE FROM %s WHERE partitionKey CONTAINS ? AND clustering = ?", 0, 1)
|
||||
|
||||
# Non primary key in the where clause
|
||||
@@ -3965,7 +3965,7 @@ def testUpdate(cql, test_keyspace, forceFlush):
|
||||
assertInvalidMessage(cql, table, "Only EQ and IN relation are supported on the partition key",
|
||||
"UPDATE %s SET value = ? WHERE partitionKey > ? AND clustering_1 = ?", 7, 0, 1)
|
||||
|
||||
assertInvalidMessage(cql, table, "Cannot use CONTAINS on non-collection column",
|
||||
assertInvalidMessageRE(cql, table, "Cannot use CONTAINS on non-collection column|Cannot use UPDATE with CONTAINS",
|
||||
"UPDATE %s SET value = ? WHERE partitionKey CONTAINS ? AND clustering_1 = ?", 7, 0, 1)
|
||||
|
||||
assertInvalidMessage(cql, table, "value",
|
||||
@@ -4095,7 +4095,7 @@ def testUpdateWithTwoClusteringColumns(cql, test_keyspace, forceFlush):
|
||||
assertInvalidMessage(cql, table, "Only EQ and IN relation are supported on the partition key",
|
||||
"UPDATE %s SET value = ? WHERE partitionKey > ? AND clustering_1 = ? AND clustering_2 = ?", 7, 0, 1, 1)
|
||||
|
||||
assertInvalidMessage(cql, table, "Cannot use CONTAINS on non-collection column",
|
||||
assertInvalidMessageRE(cql, table, "Cannot use CONTAINS on non-collection column|Cannot use UPDATE with CONTAINS",
|
||||
"UPDATE %s SET value = ? WHERE partitionKey CONTAINS ? AND clustering_1 = ? AND clustering_2 = ?", 7, 0, 1, 1)
|
||||
|
||||
assertInvalid(cql, table,
|
||||
|
||||
@@ -89,7 +89,10 @@ def testClusteringColumnRelations(cql, test_keyspace):
|
||||
["first", 2, 6, 2],
|
||||
["first", 3, 7, 3])
|
||||
|
||||
assert_empty(execute(cql, table, "select * from %s where a = ? and b in ? and c in ?", "first", None, [7, 6]))
|
||||
# Scylla does allow IN NULL (see commit 52bbc1065c8) so this test
|
||||
# is commented out
|
||||
#assert_invalid_message(cql, table, "Invalid null value for column b",
|
||||
# "select * from %s where a = ? and b in ? and c in ?", "first", None, [7, 6])
|
||||
|
||||
assert_rows(execute(cql, table, "select * from %s where a = ? and c >= ? and b in (?, ?)", "first", 6, 3, 2),
|
||||
["first", 2, 6, 2],
|
||||
|
||||
@@ -6,38 +6,48 @@
|
||||
# Tests for compaction strategy validation
|
||||
#############################################################################
|
||||
|
||||
from cassandra_tests.porting import create_keyspace, create_table, execute, assert_invalid_throw_message, ConfigurationException
|
||||
import pytest
|
||||
from util import new_test_table
|
||||
from cassandra.protocol import ConfigurationException
|
||||
|
||||
def assert_throws(cql, msg, cmd):
|
||||
with create_keyspace(cql, "replication={ 'class' : 'SimpleStrategy', 'replication_factor' : 1 }") as ks:
|
||||
with create_table(cql, ks, "(a int PRIMARY KEY, b int) WITH compaction = { 'class' : 'SizeTieredCompactionStrategy' }") as table:
|
||||
assert_invalid_throw_message(cql, table, msg, ConfigurationException, cmd)
|
||||
@pytest.fixture(scope="module")
|
||||
def table1(cql, test_keyspace):
|
||||
with new_test_table(cql, test_keyspace, "a int PRIMARY KEY, b int", "WITH compaction = { 'class' : 'SizeTieredCompactionStrategy' }") as table:
|
||||
yield table
|
||||
|
||||
def test_common_options(cql):
|
||||
assert_throws(cql, "tombstone_threshold value (-0.4) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'tombstone_threshold' : -0.4 }")
|
||||
assert_throws(cql, "tombstone_threshold value (5.5) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'tombstone_threshold' : 5.5 }")
|
||||
assert_throws(cql, "tombstone_compaction_interval value (-7000ms) must be positive", "ALTER TABLE %s WITH compaction = { 'class' : 'LeveledCompactionStrategy', 'tombstone_compaction_interval' : -7 }")
|
||||
# NOTE: The following tests which use this assert_throws() all try to
|
||||
# check the specific wording of the error text, and it sometimes differs
|
||||
# between Scylla and Cassandra - so we need to allow both: msg is a regular
|
||||
# expression, so you can use the "|" character to allow two options.
|
||||
def assert_throws(cql, table1, msg, cmd):
|
||||
with pytest.raises(ConfigurationException, match=msg):
|
||||
cql.execute(cmd.replace('%s', table1))
|
||||
|
||||
def test_size_tiered_compaction_strategy_options(cql):
|
||||
assert_throws(cql, "min_sstable_size value (-1) must be non negative", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'min_sstable_size' : -1 }")
|
||||
assert_throws(cql, "bucket_low value (0) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'bucket_low' : 0.0 }")
|
||||
assert_throws(cql, "bucket_low value (1.3) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'bucket_low' : 1.3 }")
|
||||
assert_throws(cql, "bucket_high value (0.7) must be greater than 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'bucket_high' : 0.7 }")
|
||||
assert_throws(cql, "cold_reads_to_omit value (-8.1) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'cold_reads_to_omit' : -8.1 }")
|
||||
assert_throws(cql, "cold_reads_to_omit value (3.5) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'cold_reads_to_omit' : 3.5 }")
|
||||
assert_throws(cql, "min_threshold value (1) must be bigger or equal to 2", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'min_threshold' : 1 }")
|
||||
def test_common_options(cql, table1):
|
||||
assert_throws(cql, table1, r"tombstone_threshold value \(-0.4\) must be between 0.0 and 1.0|tombstone_threshold must be greater than 0, but was -0.400000", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'tombstone_threshold' : -0.4 }")
|
||||
assert_throws(cql, table1, r"tombstone_threshold value \(5.5\) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'tombstone_threshold' : 5.5 }")
|
||||
assert_throws(cql, table1, r"tombstone_compaction_interval value \(-7000ms\) must be positive", "ALTER TABLE %s WITH compaction = { 'class' : 'LeveledCompactionStrategy', 'tombstone_compaction_interval' : -7 }")
|
||||
|
||||
def test_time_window_compaction_strategy_options(cql):
|
||||
assert_throws(cql, "Invalid window unit SECONDS for compaction_window_unit", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'compaction_window_unit' : 'SECONDS' }")
|
||||
assert_throws(cql, "compaction_window_size value (-8) must be greater than 1", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'compaction_window_size' : -8 }")
|
||||
assert_throws(cql, "Invalid timestamp resolution SECONDS for timestamp_resolution", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'timestamp_resolution' : 'SECONDS' }")
|
||||
assert_throws(cql, "enable_optimized_twcs_queries value (no) must be \"true\" or \"false\"", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'enable_optimized_twcs_queries' : 'no' }")
|
||||
assert_throws(cql, "max_threshold value (1) must be bigger or equal to 2", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'max_threshold' : 1 }")
|
||||
def test_size_tiered_compaction_strategy_options(cql, table1):
|
||||
assert_throws(cql, table1, r"min_sstable_size value \(-1\) must be non negative|min_sstable_size must be non negative: -1", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'min_sstable_size' : -1 }")
|
||||
assert_throws(cql, table1, r"bucket_low value \(0\) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'bucket_low' : 0.0 }")
|
||||
assert_throws(cql, table1, r"bucket_low value \(1.3\) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'bucket_low' : 1.3 }")
|
||||
assert_throws(cql, table1, r"bucket_high value \(0.7\) must be greater than 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'bucket_high' : 0.7 }")
|
||||
assert_throws(cql, table1, r"cold_reads_to_omit value \(-8.1\) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'cold_reads_to_omit' : -8.1 }")
|
||||
assert_throws(cql, table1, r"cold_reads_to_omit value \(3.5\) must be between 0.0 and 1.0", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'cold_reads_to_omit' : 3.5 }")
|
||||
assert_throws(cql, table1, r"min_threshold value \(1\) must be bigger or equal to 2", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'min_threshold' : 1 }")
|
||||
|
||||
def test_leveled_compaction_strategy_options(cql):
|
||||
assert_throws(cql, "sstable_size_in_mb value (-5) must be positive", "ALTER TABLE %s WITH compaction = { 'class' : 'LeveledCompactionStrategy', 'sstable_size_in_mb' : -5 }")
|
||||
def test_time_window_compaction_strategy_options(cql, table1):
|
||||
assert_throws(cql, table1, "Invalid window unit SECONDS for compaction_window_unit|SECONDS is not valid for compaction_window_unit", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'compaction_window_unit' : 'SECONDS' }")
|
||||
assert_throws(cql, table1, r"compaction_window_size value \(-8\) must be greater than 1|-8 must be greater than 1 for compaction_window_size", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'compaction_window_size' : -8 }")
|
||||
assert_throws(cql, table1, "Invalid timestamp resolution SECONDS for timestamp_resolution", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'timestamp_resolution' : 'SECONDS' }")
|
||||
assert_throws(cql, table1, r"enable_optimized_twcs_queries value \(no\) must be \"true\" or \"false\"", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'enable_optimized_twcs_queries' : 'no' }")
|
||||
assert_throws(cql, table1, r"max_threshold value \(1\) must be bigger or equal to 2", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'max_threshold' : 1 }")
|
||||
|
||||
def test_not_allowed_options(cql):
|
||||
assert_throws(cql, "Invalid compaction strategy options {{abc, -54.54}} for chosen strategy type", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'abc' : -54.54 }")
|
||||
assert_throws(cql, "Invalid compaction strategy options {{dog, 3}} for chosen strategy type", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'dog' : 3 }")
|
||||
assert_throws(cql, "Invalid compaction strategy options {{compaction_window_size, 4}} for chosen strategy type", "ALTER TABLE %s WITH compaction = { 'class' : 'LeveledCompactionStrategy', 'compaction_window_size' : 4 }")
|
||||
def test_leveled_compaction_strategy_options(cql, table1):
|
||||
assert_throws(cql, table1, r"sstable_size_in_mb value \(-5\) must be positive|sstable_size_in_mb must be larger than 0, but was -5", "ALTER TABLE %s WITH compaction = { 'class' : 'LeveledCompactionStrategy', 'sstable_size_in_mb' : -5 }")
|
||||
|
||||
def test_not_allowed_options(cql, table1):
|
||||
assert_throws(cql, table1, r"Invalid compaction strategy options {{abc, -54.54}} for chosen strategy type|Properties specified \[abc\] are not understood by SizeTieredCompactionStrategy", "ALTER TABLE %s WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'abc' : -54.54 }")
|
||||
assert_throws(cql, table1, r"Invalid compaction strategy options {{dog, 3}} for chosen strategy type|Properties specified \[dog\] are not understood by TimeWindowCompactionStrategy", "ALTER TABLE %s WITH compaction = { 'class' : 'TimeWindowCompactionStrategy', 'dog' : 3 }")
|
||||
assert_throws(cql, table1, r"Invalid compaction strategy options {{compaction_window_size, 4}} for chosen strategy type|Properties specified \[compaction_window_size\] are not understood by LeveledCompactionStrategy", "ALTER TABLE %s WITH compaction = { 'class' : 'LeveledCompactionStrategy', 'compaction_window_size' : 4 }")
|
||||
|
||||
@@ -402,43 +402,68 @@ def test_desc_cluster(scylla_only, cql, test_keyspace):
|
||||
|
||||
assert sorted(desc_endpoints) == sorted(ring_endpoints)
|
||||
|
||||
def is_scylla(cql):
|
||||
return any('scylla' in name for name in [row.table_name for row in cql.execute("SELECT * FROM system_schema.tables WHERE keyspace_name = 'system'")])
|
||||
|
||||
# Test that 'DESC INDEX' contains create statement od index
|
||||
def test_desc_index(cql, test_keyspace):
|
||||
with new_test_table(cql, test_keyspace, "a int primary key, b int, c int") as tbl:
|
||||
tbl_name = get_name(tbl)
|
||||
create_idx_b = f"CREATE INDEX ON {tbl}(b)"
|
||||
create_idx_c = f"CREATE INDEX named_index ON {tbl}(c)"
|
||||
create_idx_ab = f"CREATE INDEX ON {tbl}((a), b)"
|
||||
# Only Scylla supports local indexes
|
||||
has_local = is_scylla(cql)
|
||||
if has_local:
|
||||
create_idx_ab = f"CREATE INDEX ON {tbl}((a), b)"
|
||||
|
||||
cql.execute(create_idx_b)
|
||||
cql.execute(create_idx_c)
|
||||
cql.execute(create_idx_ab)
|
||||
if has_local:
|
||||
cql.execute(create_idx_ab)
|
||||
|
||||
b_desc = cql.execute(f"DESC INDEX {test_keyspace}.{tbl_name}_b_idx").one().create_statement
|
||||
ab_desc = cql.execute(f"DESC INDEX {test_keyspace}.{tbl_name}_b_idx_1").one().create_statement
|
||||
if has_local:
|
||||
ab_desc = cql.execute(f"DESC INDEX {test_keyspace}.{tbl_name}_b_idx_1").one().create_statement
|
||||
c_desc = cql.execute(f"DESC INDEX {test_keyspace}.named_index").one().create_statement
|
||||
|
||||
assert f"CREATE INDEX {tbl_name}_b_idx ON {tbl}(b)" in b_desc
|
||||
assert f"CREATE INDEX {tbl_name}_b_idx_1 ON {tbl}((a), b)" in ab_desc
|
||||
assert create_idx_c in c_desc
|
||||
# Cassandra inserts a space between the table name and parantheses,
|
||||
# Scylla doesn't. This difference doesn't matter because both are
|
||||
# valid CQL commands
|
||||
if is_scylla(cql):
|
||||
maybe_space = ''
|
||||
else:
|
||||
maybe_space = ' '
|
||||
assert f"CREATE INDEX {tbl_name}_b_idx ON {tbl}{maybe_space}(b)" in b_desc
|
||||
if has_local:
|
||||
assert f"CREATE INDEX {tbl_name}_b_idx_1 ON {tbl}((a), b)" in ab_desc
|
||||
|
||||
assert f"CREATE INDEX named_index ON {tbl}{maybe_space}(c)" in c_desc
|
||||
|
||||
# Test that 'DESC TABLE' contains description of indexes
|
||||
def test_index_desc_in_table_desc(cql, test_keyspace):
|
||||
with new_test_table(cql, test_keyspace, "a int primary key, b int, c int") as tbl:
|
||||
create_idx_b = f"CREATE INDEX ON {tbl}(b)"
|
||||
create_idx_c = f"CREATE INDEX named_index ON {tbl}(c)"
|
||||
create_idx_ab = f"CREATE INDEX ON {tbl}((a), b)"
|
||||
has_local = is_scylla(cql)
|
||||
if is_scylla(cql):
|
||||
maybe_space = ''
|
||||
else:
|
||||
maybe_space = ' '
|
||||
if has_local:
|
||||
create_idx_ab = f"CREATE INDEX ON {tbl}((a), b)"
|
||||
|
||||
cql.execute(create_idx_b)
|
||||
cql.execute(create_idx_c)
|
||||
cql.execute(create_idx_ab)
|
||||
if has_local:
|
||||
cql.execute(create_idx_ab)
|
||||
|
||||
tbl_name = get_name(tbl)
|
||||
desc = "\n".join([d.create_statement for d in cql.execute(f"DESC TABLE {tbl}")])
|
||||
|
||||
assert f"CREATE INDEX {tbl_name}_b_idx ON {tbl}(b)" in desc
|
||||
assert create_idx_c in desc
|
||||
assert f"CREATE INDEX {tbl_name}_b_idx_1 ON {tbl}((a), b)" in desc
|
||||
assert f"CREATE INDEX {tbl_name}_b_idx ON {tbl}{maybe_space}(b)" in desc
|
||||
assert f"CREATE INDEX named_index ON {tbl}{maybe_space}(c)" in desc
|
||||
if has_local:
|
||||
assert f"CREATE INDEX {tbl_name}_b_idx_1 ON {tbl}((a), b)" in desc
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# "Generic describe" is a describe statement without specifying what kind of object
|
||||
@@ -492,7 +517,8 @@ def test_generic_desc_user_defined(scylla_only, cql, test_keyspace):
|
||||
|
||||
|
||||
# Test that 'DESC FUNCTION'/'DESC AGGREGATE' doesn't show UDA/UDF and doesn't crash Scylla
|
||||
def test_desc_udf_uda(cql, test_keyspace):
|
||||
# The test is marked scylla_only because it uses Lua as UDF language.
|
||||
def test_desc_udf_uda(cql, test_keyspace, scylla_only):
|
||||
with new_function(cql, test_keyspace, "(a int, b int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE LUA AS 'return a+b'") as fn:
|
||||
with new_aggregate(cql, test_keyspace, f"(int) SFUNC {fn} STYPE int") as aggr:
|
||||
|
||||
@@ -507,7 +533,8 @@ def test_desc_udf_uda(cql, test_keyspace):
|
||||
# The new server-side describe was missing it.
|
||||
# Example: caching = {'keys': 'ALL', 'rows_per_partition': 'ALL'}
|
||||
# Reproduces #14895
|
||||
def test_whitespaces_in_table_options(cql, test_keyspace):
|
||||
# The test is marked scylla_only because it uses a Scylla-only property "cdc".
|
||||
def test_whitespaces_in_table_options(cql, test_keyspace, scylla_only):
|
||||
regex = "\\{[^}]*[:,][^\\s][^}]*\\}" # looks for any colon or comma without space after it inside a { }
|
||||
|
||||
with new_test_table(cql, test_keyspace, "a int primary key", "WITH cdc = {'enabled': true}") as tbl:
|
||||
@@ -591,6 +618,8 @@ def test_type_quoting(cql):
|
||||
assert f"CREATE TYPE \"{ks_name}\".\"{name}\"" in desc
|
||||
assert f"CREATE TYPE \"{ks_name}\".{name}" not in desc
|
||||
assert f"CREATE TYPE {ks_name}.\"{name}\"" not in desc
|
||||
# The following used to be buggy in Cassandra, but fixed in
|
||||
# CASSANDRA-17918 (in Cassandra 4.1.2):
|
||||
assert f"\"{field_name}\" text" in desc
|
||||
assert f"{field_name} text" not in desc
|
||||
|
||||
@@ -873,9 +902,11 @@ def new_random_table(cql, keyspace, udts=[]):
|
||||
extras["min_index_interval"] = min_idx_interval
|
||||
extras["max_index_interval"] = random.randrange(min_idx_interval, 10000)
|
||||
extras["memtable_flush_period_in_ms"] = random.randrange(0, 10000)
|
||||
extras["paxos_grace_seconds"] = random.randrange(1000, 100000)
|
||||
|
||||
extras["tombstone_gc"] = f"{{'mode': 'timeout', 'propagation_delay_in_seconds': '{random.randrange(100, 100000)}'}}"
|
||||
if is_scylla(cql):
|
||||
# Extra properties which ScyllaDB supports but Cassandra doesn't
|
||||
extras["paxos_grace_seconds"] = random.randrange(1000, 100000)
|
||||
extras["tombstone_gc"] = f"{{'mode': 'timeout', 'propagation_delay_in_seconds': '{random.randrange(100, 100000)}'}}"
|
||||
|
||||
extra_options = [f"{k} = {v}" for (k, v) in extras.items()]
|
||||
extra_str = " AND ".join(extra_options)
|
||||
|
||||
@@ -399,17 +399,29 @@ def test_filter_and_fetch_size(cql, test_keyspace, use_index, driver_bug_1):
|
||||
# Reproduces #13468
|
||||
def test_filter_token(cql, test_keyspace):
|
||||
with new_test_table(cql, test_keyspace, 'pk int, ck int, x int, PRIMARY KEY (pk, ck)') as table:
|
||||
with pytest.raises(InvalidRequest, match='Invalid number of arguments'):
|
||||
# In this case token() expects just a single argument, if we pass
|
||||
# it the same one twice we get different errors in ScyllaDB and
|
||||
# Cassandra - in ScyllaDB we get "Invalid number of arguments",
|
||||
# Cassandra complains that the two arguments are the same - "The
|
||||
# token() function contains duplicate partition key components":
|
||||
with pytest.raises(InvalidRequest, match='Invalid number of arguments|duplicate partition key'):
|
||||
cql.execute(f'SELECT pk FROM {table} WHERE token(pk, pk) = 0')
|
||||
with new_test_table(cql, test_keyspace, 'pk int, ck int, x int, PRIMARY KEY ((pk, ck))') as table:
|
||||
with pytest.raises(InvalidRequest, match='duplicate partition key'):
|
||||
cql.execute(f'SELECT pk FROM {table} WHERE token(pk, pk) = 0')
|
||||
with pytest.raises(InvalidRequest, match='Invalid number of arguments'):
|
||||
cql.execute(f'SELECT pk FROM {table} WHERE token(x) = 0')
|
||||
with pytest.raises(InvalidRequest, match='Invalid number of arguments'):
|
||||
cql.execute(f'SELECT pk FROM {table} WHERE token(pk) = 0')
|
||||
with new_test_table(cql, test_keyspace, 'pk1 int, pk2 int, x int, PRIMARY KEY ((pk1, pk2))') as table:
|
||||
# In the following cases, token() expects two arguments but they
|
||||
# should be the two partition key columns, not something else like
|
||||
# fewer columns or the same column twice. ScyllaDB and Cassandra
|
||||
# print different error messages: ScyllaDB complains about the
|
||||
# specific problem in the request (e.g., duplicate pk1) while
|
||||
# Cassandra makes a general complaint about the that token() "must
|
||||
# be applied to all partition key components or none of them".
|
||||
with pytest.raises(InvalidRequest, match='duplicate partition key|must be applied to all partition key components or none of them'):
|
||||
cql.execute(f'SELECT pk1 FROM {table} WHERE token(pk1, pk1) = 0')
|
||||
with pytest.raises(InvalidRequest, match='Invalid number of arguments|must be applied to all partition key components or none of them'):
|
||||
cql.execute(f'SELECT pk1 FROM {table} WHERE token(x) = 0')
|
||||
with pytest.raises(InvalidRequest, match='Invalid number of arguments|must be applied to all partition key components or none of them'):
|
||||
cql.execute(f'SELECT pk1 FROM {table} WHERE token(pk1) = 0')
|
||||
with pytest.raises(InvalidRequest, match='partition key order'):
|
||||
cql.execute(f'SELECT pk FROM {table} WHERE token(ck, pk) = 0')
|
||||
cql.execute(f'SELECT pk1 FROM {table} WHERE token(pk2, pk1) = 0')
|
||||
|
||||
|
||||
# In a query with a token restriction the name assigned to the bind marker should be "partition key token".
|
||||
|
||||
@@ -3,6 +3,12 @@ from contextlib import ExitStack
|
||||
from util import unique_name, config_value_context, new_test_keyspace
|
||||
from cassandra.protocol import ConfigurationException
|
||||
|
||||
# Tests for the replication_strategy_{warn,fail}_list guardrail. Because
|
||||
# this feature does not exist in Cassandra , *all* tests in this file are
|
||||
# Scylla-only. Let's mark them all scylla_only with an autouse fixture:
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def all_tests_are_scylla_only(scylla_only):
|
||||
pass
|
||||
|
||||
def create_ks_and_assert_warnings_and_errors(cql, ks_opts, warnings_count=0, fails_count=0):
|
||||
if fails_count:
|
||||
|
||||
@@ -106,10 +106,21 @@ def test_alter_keyspace_invalid(cql, this_dc):
|
||||
with new_test_keyspace(cql, "WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', '" + this_dc + "' : 1 }") as keyspace:
|
||||
with pytest.raises(ConfigurationException):
|
||||
cql.execute(f"ALTER KEYSPACE {keyspace} WITH REPLICATION = {{ 'class' : 'NoSuchStrategy' }}")
|
||||
|
||||
# Continuing test_alter_keyspace_invalid, this is another invalid alter
|
||||
# keyspace: SimpleStrategy, if not outright forbidden, requires a
|
||||
# replication_factor option. However, this is only true in Scylla - in
|
||||
# Cassandra 4.1 and above, a missing replication_factor *is* allowed,
|
||||
# because there is a default_keyspace_rf configuration. See issue #16028.
|
||||
def test_alter_keyspace_missing_rf(cql, this_dc, scylla_only):
|
||||
with new_test_keyspace(cql, "WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', '" + this_dc + "' : 1 }") as keyspace:
|
||||
# SimpleStrategy, if not outright forbidden, requires a
|
||||
# replication_factor option.
|
||||
with pytest.raises(ConfigurationException):
|
||||
cql.execute(f"ALTER KEYSPACE {keyspace} WITH REPLICATION = {{ 'class' : 'SimpleStrategy' }}")
|
||||
# Strangely, Cassandra doesn't raise here - it allows garbage
|
||||
# replication_factor (and probably uses the default instead).
|
||||
# this should probably be considered a Cassandra bug.
|
||||
with pytest.raises(ConfigurationException):
|
||||
cql.execute(f"ALTER KEYSPACE {keyspace} WITH REPLICATION = {{ 'class' : 'NetworkTopologyStrategy', 'replication_factor' : 'foo' }}")
|
||||
|
||||
|
||||
@@ -290,7 +290,9 @@ def test_is_not_null_forbidden_in_filter(cql, test_keyspace, cassandra_bug):
|
||||
|
||||
# Test that a view can be altered with synchronous_updates property and that
|
||||
# the synchronous updates code path is then reached for such view.
|
||||
def test_mv_synchronous_updates(cql, test_keyspace):
|
||||
# The synchronous_updates feature is a ScyllaDB extension, so this is a
|
||||
# scylla_only test.
|
||||
def test_mv_synchronous_updates(cql, test_keyspace, scylla_only):
|
||||
schema = 'p int, v text, primary key (p)'
|
||||
with new_test_table(cql, test_keyspace, schema) as table:
|
||||
with new_materialized_view(cql, table, '*', 'v, p', 'v is not null and p is not null') as sync_mv, \
|
||||
|
||||
@@ -1412,9 +1412,17 @@ def test_static_column_index_build(cql, test_keyspace):
|
||||
start_time = time.time()
|
||||
rows = None
|
||||
while time.time() < start_time + 30:
|
||||
rows = sorted(cql.execute(f'SELECT pk FROM {table} WHERE s = 0'))
|
||||
if len(rows) == 3:
|
||||
break
|
||||
try:
|
||||
rows = sorted(cql.execute(f'SELECT pk FROM {table} WHERE s = 0'))
|
||||
if len(rows) == 3:
|
||||
break
|
||||
except:
|
||||
# In Cassandra, the SELECT can also fail for a short while
|
||||
# instead of returning nothing - as the index is not yet
|
||||
# set up properly. Let's ignore this failure and try again
|
||||
# until the index is ready.
|
||||
pass
|
||||
time.sleep(0.1)
|
||||
|
||||
assert [(0,),(1,),(2,)] == rows
|
||||
|
||||
@@ -1670,7 +1678,9 @@ def test_7659_global(cql, test_keyspace):
|
||||
# With issue #7659, this generated an exception and failed request:
|
||||
assert [(1,),(2,),(3,)] == sorted(list(cql.execute(f"SELECT a FROM {table} WHERE d=0 AND f>0 ALLOW FILTERING")))
|
||||
|
||||
def test_7659_local(cql, test_keyspace):
|
||||
# the version of this test for local index is scylla_only, because LSI is
|
||||
# a Scylla extension that doesn't exist in Cassandra.
|
||||
def test_7659_local(cql, test_keyspace, scylla_only):
|
||||
with new_test_table(cql, test_keyspace, 'a int, b int, c int, d int, e int, f int, PRIMARY KEY ((a, b), c, d)') as table:
|
||||
cql.execute(f'CREATE INDEX ON {table}((a, b), f)')
|
||||
cql.execute(f'CREATE INDEX ON {table}(d)')
|
||||
|
||||
Reference in New Issue
Block a user