def test_validation_utf8_from_lua(scylla_only, cql, test_keyspace, table1): # Create one row that the Lua functions below will run on cql.execute(f"INSERT INTO {table1} (k, a) VALUES (1, 'hello')") # This test is significantly slower than the rest, because we run the # CREATE FUNCTION operation separately for each tested string, and it is # very slow. So we only try a random sample of the good and bad strings. # TODO: can we have a faster Lua test, which uses a single function only # with different parameters, instead of multiple functions? for b in random.sample(good_utf8, 3): fname = unique_name() # translate byte 0xAB into the string "\xAB" b_lua = ''.join([('\\x%02x' % c) for c in b]) print(b_lua) cql.execute(f"CREATE FUNCTION {test_keyspace}.{fname}(k int) CALLED ON NULL INPUT RETURNS text LANGUAGE Lua AS 'return \"{b_lua}\"';") results = list(cql.execute(f"SELECT {fname}(k) FROM {table1} WHERE k=1")) assert len(results) == 1 assert len(results[0]) == 1 assert results[0][0].encode('utf-8') == b cql.execute(f"DROP FUNCTION {test_keyspace}.{fname}") for b in random.sample(bad_utf8, 3): fname = unique_name() b_lua = ''.join([('\\x%02x' % c) for c in b]) print(b_lua) cql.execute(f"CREATE FUNCTION {test_keyspace}.{fname}(k int) CALLED ON NULL INPUT RETURNS text LANGUAGE Lua AS 'return \"{b_lua}\"';") with pytest.raises(InvalidRequest, match='value is not valid utf8'): cql.execute(f"SELECT {fname}(k) FROM {table1} WHERE k=1") cql.execute(f"DROP FUNCTION {test_keyspace}.{fname}")
def test_validate_params(cql, test_keyspace, table1, scylla_with_wasm_only): table = table1 inc_float_name = "inc_float_" + unique_name() inc_float_source = f""" (module (type (;0;) (func (param f32) (result f32))) (func ${inc_float_name} (type 0) (param f32) (result f32) local.get 0 f32.const 0x1p+0 (;=1;) f32.add) (table (;0;) 1 1 funcref) (table (;1;) 32 externref) (memory (;0;) 17) (export "memory" (memory 0)) (export "{inc_float_name}" (func ${inc_float_name})) (elem (;0;) (i32.const 0) func)) """ src = f"(input int) RETURNS NULL ON NULL INPUT RETURNS float LANGUAGE xwasm AS '{inc_float_source}'" with new_function(cql, test_keyspace, src, inc_float_name): cql.execute(f"INSERT INTO {table} (p, i, f, txt) VALUES (700, 7, 7., 'oi')") with pytest.raises(InvalidRequest, match="type mismatch"): cql.execute(f"SELECT {test_keyspace}.{inc_float_name}(i) AS result FROM {table} WHERE p = 700") src = f"(input text) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE xwasm AS '{inc_float_source}'" with new_function(cql, test_keyspace, src, inc_float_name): with pytest.raises(InvalidRequest, match="failed"): cql.execute(f"SELECT {test_keyspace}.{inc_float_name}(txt) AS result FROM {table} WHERE p = 700") src = f"(input float) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE xwasm AS '{inc_float_source}'" with new_function(cql, test_keyspace, src, inc_float_name): with pytest.raises(InvalidRequest, match="Expected i32, got f32"): cql.execute(f"SELECT {test_keyspace}.{inc_float_name}(f) AS result FROM {table} WHERE p = 700") with pytest.raises(InvalidRequest, match="number.*arguments"): cql.execute(f"SELECT {test_keyspace}.{inc_float_name}(i, f) AS result FROM {table} WHERE p = 700")
def test_short_ints(cql, test_keyspace, table1, scylla_with_wasm_only): table = table1 plus_name = "plus_" + unique_name() plus_source = f""" (module (type (;0;) (func (param i32 i32) (result i32))) (func ${plus_name} (type 0) (param i32 i32) (result i32) local.get 1 local.get 0 i32.add) (table (;0;) 1 1 funcref) (table (;1;) 32 externref) (memory (;0;) 17) (export "{plus_name}" (func ${plus_name})) (elem (;0;) (i32.const 0) func)) """ src = f"(input tinyint, input2 tinyint) RETURNS NULL ON NULL INPUT RETURNS tinyint LANGUAGE xwasm AS '{plus_source}'" with new_function(cql, test_keyspace, src, plus_name): cql.execute(f"INSERT INTO {table} (p, t, t2, s, s2) VALUES (42, 42, 24, 33, 55)") cql.execute(f"INSERT INTO {table} (p, t, t2, s, s2) VALUES (43, 120, 112, 32000, 24001)") res = [row for row in cql.execute(f"SELECT {test_keyspace}.{plus_name}(t, t2) AS result FROM {table} WHERE p = 42")] assert len(res) == 1 and res[0].result == 66 # Overflow is fine res = [row for row in cql.execute(f"SELECT {test_keyspace}.{plus_name}(t, t2) AS result FROM {table} WHERE p = 43")] assert len(res) == 1 and res[0].result == -24 # A similar run for 16bit ints - note that the exact same source code is used src = f"(input smallint, input2 smallint) RETURNS NULL ON NULL INPUT RETURNS smallint LANGUAGE xwasm AS '{plus_source}'" with new_function(cql, test_keyspace, src, plus_name): res = [row for row in cql.execute(f"SELECT {test_keyspace}.{plus_name}(s, s2) AS result FROM {table} WHERE p = 42")] assert len(res) == 1 and res[0].result == 88 # Overflow is fine res = [row for row in cql.execute(f"SELECT {test_keyspace}.{plus_name}(s, s2) AS result FROM {table} WHERE p = 43")] assert len(res) == 1 and res[0].result == -9535
def table1(cql, test_keyspace): table = test_keyspace + "." + unique_name() cql.execute( f"CREATE TABLE {table} (p int PRIMARY KEY, v int, a ascii, b boolean, vi varint, mai map<ascii, int>, tup frozen<tuple<text, int>>, l list<text>, d double)" ) yield table cql.execute("DROP TABLE " + table)
def test_mv_select_stmt_bound_values(cql, test_keyspace): schema = 'p int PRIMARY KEY' mv = unique_name() with new_test_table(cql, test_keyspace, schema) as table: with pytest.raises(InvalidRequest): cql.execute(f"CREATE MATERIALIZED VIEW {test_keyspace}.{mv} AS SELECT * FROM {table} WHERE p = ? PRIMARY KEY (p)") cql.execute(f"DROP MATERIALIZED VIEW IF EXISTS {test_keyspace}.{mv}")
def table1(cql, test_keyspace): table = test_keyspace + "." + unique_name() cql.execute( f"CREATE TABLE {table} (p int primary key, t1 text, t2 text, t3 text, t4 text, t5 text, t6 text)" ) yield table cql.execute("DROP TABLE " + table)
def table1(cql, test_keyspace): table = test_keyspace + "." + unique_name() cql.execute( f"CREATE TABLE {table} (p text primary key, a ascii, b blob, t text, v varchar)" ) yield table cql.execute("DROP TABLE " + table)
def create_type(cql, keyspace, cmd): type_name = keyspace + "." + unique_name() cql.execute("CREATE TYPE " + type_name + " " + cmd) try: yield type_name finally: cql.execute("DROP TYPE " + type_name)
def create_keyspace(cql, arg): ks_name = unique_name() cql.execute("CREATE KEYSPACE " + ks_name + " WITH " + arg) try: yield ks_name finally: cql.execute("DROP KEYSPACE " + ks_name)
def login(self, e=None): """Processes submitting the login form""" name = self.name.get() # Need to have an ID to look up in the db if not name.isnumeric(): member_id = util.find_by_name(name) else: member_id = int(name) if member_id in data.members: member = data.members[member_id] if can_login(member_id, self.password.get()): self.callback(member) tkinter.messagebox.showinfo( "Login Successful", "You are now logged in as {}, member ID {}".format( util.unique_name(member), member["member_id"])) # A successful login clears the name field self.name.delete(0, END) else: tkinter.messagebox.showerror( "Login failed", "Invalid password for {first_name} {last_name}.".format( **member)) else: tkinter.messagebox.showerror( "Login failed", "Member \"{}\" not found.".format(self.name.get())) # Both successful and unsuccessful logins clear the password field self.password.delete(0, END)
def create_materialized_view(cql, keyspace, arg): mv_name = keyspace + "." + unique_name() cql.execute("CREATE MATERIALIZED VIEW " + mv_name + " " + arg) try: yield mv_name finally: cql.execute("DROP MATERIALIZED VIEW " + mv_name)
def test_f32_param(cql, test_keyspace, table1, scylla_with_wasm_only): table = table1 inc_float_name = "inc_float_" + unique_name() inc_float_source = f""" (module (type (;0;) (func (param f32) (result f32))) (func ${inc_float_name} (type 0) (param f32) (result f32) local.get 0 f32.const 0x1p+0 (;=1;) f32.add) (table (;0;) 1 1 funcref) (table (;1;) 32 externref) (memory (;0;) 17) (export "{inc_float_name}" (func ${inc_float_name})) (elem (;0;) (i32.const 0) func) (global (;0;) i32 (i32.const 1024)) (export "_scylla_abi" (global 0)) (data $.rodata (i32.const 1024) "\\01")) """ src = f"(input float) RETURNS NULL ON NULL INPUT RETURNS float LANGUAGE xwasm AS '{inc_float_source}'" with new_function(cql, test_keyspace, src, inc_float_name): cql.execute(f"INSERT INTO {table} (p, f) VALUES (121, 121.00390625)") res = [ row for row in cql.execute( f"SELECT {test_keyspace}.{inc_float_name}(f) AS result FROM {table} WHERE p = 121" ) ] assert len(res) == 1 and res[0].result == 122.00390625
def test_bool_negate(cql, test_keyspace, table1, scylla_with_wasm_only): table = table1 negate_name = "negate_" + unique_name() negate_source = f""" (module (type (;0;) (func (param i32) (result i32))) (func ${negate_name} (type 0) (param i32) (result i32) local.get 0 i32.eqz) (table (;0;) 1 1 funcref) (table (;1;) 32 externref) (memory (;0;) 17) (export "{negate_name}" (func ${negate_name})) (elem (;0;) (i32.const 0) func) (global (;0;) i32 (i32.const 1024)) (export "_scylla_abi" (global 0)) (data $.rodata (i32.const 1024) "\\01")) """ src = f"(input boolean) RETURNS NULL ON NULL INPUT RETURNS boolean LANGUAGE xwasm AS '{negate_source}'" with new_function(cql, test_keyspace, src, negate_name): cql.execute(f"INSERT INTO {table} (p, bl) VALUES (19, true)") cql.execute(f"INSERT INTO {table} (p, bl) VALUES (21, false)") res = [ row for row in cql.execute( f"SELECT {test_keyspace}.{negate_name}(bl) AS result FROM {table} WHERE p = 19" ) ] assert len(res) == 1 and res[0].result == False res = [ row for row in cql.execute( f"SELECT {test_keyspace}.{negate_name}(bl) AS result FROM {table} WHERE p = 21" ) ] assert len(res) == 1 and res[0].result == True
def test_f64_param(cql, test_keyspace, table1, scylla_with_wasm_only): table = table1 dec_double_name = "dec_double_" + unique_name() dec_double_source = f""" (module (type (;0;) (func (param f64) (result f64))) (func ${dec_double_name} (type 0) (param f64) (result f64) local.get 0 f64.const -0x1p+0 (;=-1;) f64.add) (table (;0;) 1 1 funcref) (table (;1;) 32 externref) (memory (;0;) 17) (export "{dec_double_name}" (func ${dec_double_name})) (elem (;0;) (i32.const 0) func) (global (;0;) i32 (i32.const 1024)) (export "_scylla_abi" (global 0)) (data $.rodata (i32.const 1024) "\\01")) """ src = f"(input double) RETURNS NULL ON NULL INPUT RETURNS double LANGUAGE xwasm AS '{dec_double_source}'" with new_function(cql, test_keyspace, src, dec_double_name): cql.execute(f"INSERT INTO {table} (p,d) VALUES (17,17.015625)") res = [ row for row in cql.execute( f"SELECT {test_keyspace}.{dec_double_name}(d) AS result FROM {table} WHERE p = 17" ) ] assert len(res) == 1 and res[0].result == 16.015625
def test_infinite_loop(cql, test_keyspace, table1, scylla_with_wasm_only): table = table1 inf_loop_name = "inf_loop_" + unique_name() inf_loop_source = f""" (module (type (;0;) (func (param i32) (result i32))) (func ${inf_loop_name} (type 0) (param i32) (result i32) loop (result i32) ;; label = @1 br 0 (;@1;) end) (table (;0;) 1 1 funcref) (table (;1;) 32 externref) (memory (;0;) 17) (export "{inf_loop_name}" (func ${inf_loop_name})) (elem (;0;) (i32.const 0) func) (global (;0;) i32 (i32.const 1024)) (export "_scylla_abi" (global 0)) (data $.rodata (i32.const 1024) "\\01")) """ src = f"(input int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE xwasm AS '{inf_loop_source}'" with new_function(cql, test_keyspace, src, inf_loop_name): cql.execute(f"INSERT INTO {table} (p,i) VALUES (10, 10)") import time start = time.monotonic() with pytest.raises(InvalidRequest, match="fuel consumed"): cql.execute( f"SELECT {test_keyspace}.{inf_loop_name}(i) AS result FROM {table} WHERE p = 10" ) elapsed_s = time.monotonic() - start print(f"Breaking the loop took {elapsed_s*1000:.2f}ms")
def create_function(cql, keyspace, arg): function_name = keyspace + "." + unique_name() cql.execute("CREATE FUNCTION " + function_name + " " + arg) try: yield function_name finally: cql.execute("DROP FUNCTION " + function_name)
def test_keyspace(cql, this_dc): name = unique_name() cql.execute( "CREATE KEYSPACE " + name + " WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', '" + this_dc + "' : 1 }") yield name cql.execute("DROP KEYSPACE " + name)
def create_new_object(self, key): match = RE_METHOD.search(key) if match and hasattr(self.app.objects[match.group(1)].__class__, match.group(2)): obj_class = self.app.objects[match.group(1)].__class__ obj = getattr(obj_class, match.group(2)) if not callable(obj): obj = getattr(self.app.objects[match.group(1)], match.group(2)) name = unique_name(self.app, match.group(1) + "_" + match.group(2)) else: name = unique_name(self.app, obj_class.__name__ + "_" + obj.__name__) self.app.objects[name] = obj return name
def test_keyspace(cql): name = unique_name() cql.execute( "CREATE KEYSPACE " + name + " WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }" ) yield name cql.execute("DROP KEYSPACE " + name)
def table1(cql, test_keyspace): table = test_keyspace + "." + unique_name() cql.execute( "CREATE TABLE " + table + "(p bigint PRIMARY KEY, p2 bigint, i int, i2 int, s smallint, s2 smallint, t tinyint, t2 tinyint, d double, f float, bl boolean, txt text)" ) yield table cql.execute("DROP TABLE " + table)
def _on_item_method(self, item, attr): result = attr() item.set_value(item.value) if isinstance(result, bool): self.log.show(str(result)) elif result: name = unique_name(self.app, item.name + "_" + attr.__name__) self.app.objects[name] = result
def scylla_with_wasm_only(scylla_only, cql, test_keyspace): try: f42 = unique_name() f42_body = f'(module(func ${f42} (param $n i64) (result i64)(return i64.const 42))(export "{f42}" (func ${f42})))' res = cql.execute(f"CREATE FUNCTION {test_keyspace}.{f42} (input int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE xwasm AS '{f42_body}'") cql.execute(f"DROP FUNCTION {test_keyspace}.{f42}") except NoHostAvailable as err: if "not enabled" in str(err): pytest.skip("WASM support was not enabled in Scylla, skipping") yield
def table1(cql, test_keyspace): table = test_keyspace + "." + unique_name() cql.execute("CREATE TABLE " + table + "(k int, c int, v int, PRIMARY KEY (k,c))") for i in range(0, 3): for j in range(0, 3): cql.execute(f'INSERT INTO {table} (k, c, v) VALUES ({i}, {j}, {j})') everything = list(cql.execute('SELECT * FROM ' + table)) yield (table, everything) cql.execute("DROP TABLE " + table)
def create_table(cql, keyspace, schema): global previously_used_table_names if not previously_used_table_names: previously_used_table_names.append(unique_name()) table_name = previously_used_table_names.pop() table = keyspace + "." + table_name cql.execute("CREATE TABLE " + table + " " + schema) yield table cql.execute("DROP TABLE " + table) previously_used_table_names.append(table_name)
def table4(cql, test_keyspace): table = test_keyspace + "." + unique_name() cql.execute(f"CREATE TABLE {table} (k int, c1 int, c2 int, PRIMARY KEY (k,c1,c2))") cql.execute(f"CREATE INDEX ON {table} (c2)") cql.execute(f"INSERT INTO {table} (k, c1, c2) VALUES (0, 0, 1)") cql.execute(f"INSERT INTO {table} (k, c1, c2) VALUES (0, 1, 1)") everything = list(cql.execute(f"SELECT * FROM {table}")) wait_for_index(cql, table, 'c2', everything) yield (table, everything) cql.execute(f"DROP TABLE {table}")
def test_create_index_if_not_exists2(cql, test_keyspace, cassandra_bug): with new_test_table(cql, test_keyspace, 'p int primary key, v1 int, v2 int') as table: index_name = unique_name() cql.execute(f"CREATE INDEX {index_name} ON {table}(v1)") # Obviously can't create a different index with the same name: with pytest.raises(InvalidRequest, match="already exists"): cql.execute(f"CREATE INDEX {index_name} ON {table}(v2)") # Even with "IF NOT EXISTS" we still get a failure. An index for # {table}(v2) does not yet exist, so the index creation is attempted. with pytest.raises(InvalidRequest, match="already exists"): cql.execute(f"CREATE INDEX IF NOT EXISTS {index_name} ON {table}(v2)")
def test_is_not_operator_must_be_null(cql, test_keyspace): schema = 'p int PRIMARY KEY' mv = unique_name() with new_test_table(cql, test_keyspace, schema) as table: try: with pytest.raises(SyntaxException, match="NULL"): cql.execute( f"CREATE MATERIALIZED VIEW {test_keyspace}.{mv} AS SELECT * FROM {table} WHERE p IS NOT 42 PRIMARY KEY (p)" ) finally: cql.execute( f"DROP MATERIALIZED VIEW IF EXISTS {test_keyspace}.{mv}")
def table2(cql, test_keyspace): table = test_keyspace + "." + unique_name() cql.execute("CREATE TABLE " + table + "(k int, a int, b int, PRIMARY KEY (k))") cql.execute("CREATE INDEX ON " + table + "(a)") for i in range(0, 5): cql.execute("INSERT INTO {} (k, a, b) VALUES ({}, {}, {})".format( table, i, i*10, i*100)) everything = list(cql.execute('SELECT * FROM ' + table)) wait_for_index(cql, table, 'a', everything) yield (table, everything) cql.execute("DROP TABLE " + table)
def test_update_view_with_large_row(cql, test_keyspace): schema = 'p int, c int, v text, primary key (p,c)' mv = unique_name() with new_test_table(cql, test_keyspace, schema) as table: cql.execute(f"CREATE MATERIALIZED VIEW {test_keyspace}.{mv} AS SELECT * FROM {table} WHERE p IS NOT NULL AND c IS NOT NULL PRIMARY KEY (c,p)") try: big = 'x'*11*1024*1024 cql.execute(f"INSERT INTO {table}(p,c,v) VALUES (1,1,'{big}')") res = [row for row in cql.execute(f"SELECT * FROM {test_keyspace}.{mv}")] assert len(res) == 1 and res[0].v == big finally: cql.execute(f"DROP MATERIALIZED VIEW {test_keyspace}.{mv}")
def test_create_named_index_when_its_name_is_taken(scylla_only, cql, test_keyspace): schema = 'p int primary key, v int' with new_test_table(cql, test_keyspace, schema) as table: index_name = unique_name() try: cql.execute(f"CREATE TABLE {test_keyspace}.{index_name}_index (i_do_not_exist_in_the_base_table int primary key)") # Creating an index should fail, because it's impossible to create # its underlying materialized view, because its name is taken by a regular table with pytest.raises(InvalidRequest, match="already exists"): cql.execute(f"CREATE INDEX {index_name} ON {table}(v)") finally: cql.execute(f"DROP TABLE {test_keyspace}.{index_name}_index")