Files
scylladb/test/cql-pytest/util.py
Nadav Har'El 068c4283b7 test/cql-pytest: add tests for some undocumented cases of string types
This patch adds tests for two undocumented (as far as I can tell) corner
cases of CQL's string types:

1. The types "text" and "varchar" are not just similar - they are in
   fact exactly the same type.

2. All CQL string and blob types ("ascii", "text" or "varchar", "blob")
   allow the null character as a valid character inside them. They are
   *not* C strings that get terminated by the first null.

These tests pass on both Cassandra and Scylla, so did not expose any
bug, but having such tests is useful to understand these (so-far)
undocumented behaviors - so we can later document them.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
Message-Id: <20210824225641.194146-1-nyh@scylladb.com>
2021-09-02 15:45:47 +03:00

96 lines
3.4 KiB
Python

# Copyright 2020-present ScyllaDB
#
# This file is part of Scylla.
#
# Scylla is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Scylla is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Scylla. If not, see <http://www.gnu.org/licenses/>.
##################################################################
# Various utility functions which are useful for multiple tests.
# Note that fixtures aren't here - they are in conftest.py.
import string
import random
import time
from contextlib import contextmanager
def random_string(length=10, chars=string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for x in range(length))
def random_bytes(length=10):
return bytearray(random.getrandbits(8) for _ in range(length))
# A function for picking a unique name for test keyspace or table.
# This name doesn't need to be quoted in CQL - it only contains
# lowercase letters, numbers, and underscores, and starts with a letter.
unique_name_prefix = 'cql_test_'
def unique_name():
current_ms = int(round(time.time() * 1000))
# If unique_name() is called twice in the same millisecond...
if unique_name.last_ms >= current_ms:
current_ms = unique_name.last_ms + 1
unique_name.last_ms = current_ms
return unique_name_prefix + str(current_ms)
unique_name.last_ms = 0
# A utility function for creating a new temporary keyspace with given options.
# It can be used in a "with", as:
# with new_test_keyspace(cql, '...') as keyspace:
# This is not a fixture - see those in conftest.py.
@contextmanager
def new_test_keyspace(cql, opts):
keyspace = unique_name()
cql.execute("CREATE KEYSPACE " + keyspace + " " + opts)
try:
yield keyspace
finally:
cql.execute("DROP KEYSPACE " + keyspace)
# A utility function for creating a new temporary table with a given schema.
# It can be used in a "with", as:
# with new_test_table(cql, keyspace, '...') as table:
# This is not a fixture - see those in conftest.py.
@contextmanager
def new_test_table(cql, keyspace, schema, extra=""):
table = keyspace + "." + unique_name()
cql.execute("CREATE TABLE " + table + "(" + schema + ")" + extra)
try:
yield table
finally:
cql.execute("DROP TABLE " + table)
# A utility function for creating a new temporary user-defined function.
@contextmanager
def new_function(cql, keyspace, body):
fun = unique_name()
cql.execute(f"CREATE FUNCTION {keyspace}.{fun} {body}")
try:
yield fun
finally:
cql.execute(f"DROP FUNCTION {keyspace}.{fun}")
# A utility function for creating a new temporary user-defined aggregate.
@contextmanager
def new_aggregate(cql, keyspace, body):
aggr = unique_name()
cql.execute(f"CREATE AGGREGATE {keyspace}.{aggr} {body}")
try:
yield aggr
finally:
cql.execute(f"DROP AGGREGATE {keyspace}.{aggr}")
def project(column_name_string, rows):
"""Returns a list of column values from each of the rows."""
return [getattr(r, column_name_string) for r in rows]