diff --git a/tests/test_all.nim b/tests/test_all.nim index 750dccd..e39021b 100644 --- a/tests/test_all.nim +++ b/tests/test_all.nim @@ -55,170 +55,6 @@ import barabadb/protocol/scram import barabadb/protocol/ratelimit import barabadb/schema/schema as schema -suite "Row-Level Security": - test "Parse CREATE USER": - let ast = parse("CREATE USER admin WITH PASSWORD 'secret' SUPERUSER") - check ast.stmts.len == 1 - check ast.stmts[0].kind == nkCreateUser - check ast.stmts[0].cuName == "admin" - check ast.stmts[0].cuPassword == "secret" - check ast.stmts[0].cuSuperuser == true - - test "Parse CREATE USER without superuser": - let ast = parse("CREATE USER reader WITH PASSWORD 'reader123'") - check ast.stmts[0].kind == nkCreateUser - check ast.stmts[0].cuName == "reader" - check ast.stmts[0].cuPassword == "reader123" - check ast.stmts[0].cuSuperuser == false - - test "Parse DROP USER": - let ast = parse("DROP USER admin") - check ast.stmts[0].kind == nkDropUser - check ast.stmts[0].duName == "admin" - - test "Parse CREATE POLICY": - let ast = parse("CREATE POLICY user_isolation ON accounts FOR SELECT USING (user_id = current_user)") - check ast.stmts[0].kind == nkCreatePolicy - check ast.stmts[0].cpName == "user_isolation" - check ast.stmts[0].cpTable == "accounts" - check ast.stmts[0].cpCommand == "SELECT" - - test "Parse CREATE POLICY with WITH CHECK": - let ast = parse("CREATE POLICY insert_check ON accounts FOR INSERT WITH CHECK (amount > 0)") - check ast.stmts[0].kind == nkCreatePolicy - check ast.stmts[0].cpCommand == "INSERT" - - test "Parse DROP POLICY": - let ast = parse("DROP POLICY user_isolation ON accounts") - check ast.stmts[0].kind == nkDropPolicy - check ast.stmts[0].dpName == "user_isolation" - check ast.stmts[0].dpTable == "accounts" - - test "Parse GRANT": - let ast = parse("GRANT SELECT ON accounts TO reader") - check ast.stmts[0].kind == nkGrant - check ast.stmts[0].grPrivilege == "SELECT" - check ast.stmts[0].grTable == "accounts" - check ast.stmts[0].grGrantee == "reader" - - test "Parse REVOKE": - let ast = parse("REVOKE INSERT ON accounts FROM reader") - check ast.stmts[0].kind == nkRevoke - check ast.stmts[0].rvPrivilege == "INSERT" - check ast.stmts[0].rvTable == "accounts" - check ast.stmts[0].rvGrantee == "reader" - - test "Parse ENABLE ROW LEVEL SECURITY": - let ast = parse("ALTER TABLE accounts ENABLE ROW LEVEL SECURITY") - check ast.stmts[0].kind == nkEnableRLS - check ast.stmts[0].erlsTable == "accounts" - - test "Parse DISABLE ROW LEVEL SECURITY": - let ast = parse("ALTER TABLE accounts DISABLE ROW LEVEL SECURITY") - check ast.stmts[0].kind == nkDisableRLS - check ast.stmts[0].drlsTable == "accounts" - - test "RLS filter on SELECT": - var testDir = getTempDir() / "baradb_rls_test_" & $getCurrentProcessId() & "_" & $getMonoTime().ticks - createDir(testDir) - var db = newLSMTree(testDir) - var ctx = qexec.newExecutionContext(db) - # Create table and insert data - discard qexec.executeQuery(ctx, parse("CREATE TABLE docs (id INTEGER, owner TEXT)")) - discard qexec.executeQuery(ctx, parse("INSERT INTO docs (id, owner) VALUES (1, 'alice'), (2, 'bob')")) - # Create user and policy - ctx.currentUser = "alice" - ctx.users["alice"] = qexec.UserDef(name: "alice", passwordHash: "", isSuperuser: false, roles: @[]) - ctx.policies["docs"] = @[ - qexec.PolicyDef(name: "owner_only", tableName: "docs", command: "SELECT", - usingExpr: Node(kind: nkBinOp, binOp: bkEq, - binLeft: Node(kind: nkIdent, identName: "owner"), - binRight: Node(kind: nkStringLit, strVal: "alice")), - withCheckExpr: nil) - ] - # Query should only return alice's row - let res = qexec.executeQuery(ctx, parse("SELECT id, owner FROM docs")) - check res.success - check res.rows.len == 1 - check res.rows[0]["owner"] == "alice" - - test "RLS superuser bypass": - var testDir = getTempDir() / "baradb_rls_test_" & $getCurrentProcessId() & "_" & $getMonoTime().ticks - createDir(testDir) - var db = newLSMTree(testDir) - var ctx = qexec.newExecutionContext(db) - discard qexec.executeQuery(ctx, parse("CREATE TABLE docs (id INTEGER, owner TEXT)")) - discard qexec.executeQuery(ctx, parse("INSERT INTO docs (id, owner) VALUES (1, 'alice')")) - ctx.currentUser = "admin" - ctx.users["admin"] = qexec.UserDef(name: "admin", passwordHash: "", isSuperuser: true, roles: @[]) - ctx.policies["docs"] = @[ - qexec.PolicyDef(name: "owner_only", tableName: "docs", command: "SELECT", - usingExpr: Node(kind: nkBinOp, binOp: bkEq, - binLeft: Node(kind: nkIdent, identName: "owner"), - binRight: Node(kind: nkStringLit, strVal: "alice")), - withCheckExpr: nil) - ] - let res = qexec.executeQuery(ctx, parse("SELECT id, owner FROM docs")) - check res.success - check res.rows.len == 1 # superuser sees all (only 1 row exists) - -suite "UTF-8 Support": - test "Tokenize UTF-8 identifiers": - let tokens = lex.tokenize("SELECT имя FROM потребители") - check tokens[1].kind == tkIdent - check tokens[1].value == "имя" - check tokens[3].kind == tkIdent - check tokens[3].value == "потребители" - - test "Parse UTF-8 table and column names": - let ast = parse("SELECT имя, възраст FROM потребители WHERE град = 'София'") - check ast.stmts[0].kind == nkSelect - check ast.stmts[0].selFrom.fromTable == "потребители" - check ast.stmts[0].selResult[0].identName == "имя" - check ast.stmts[0].selWhere.whereExpr.binRight.strVal == "София" - - test "Execute query with UTF-8 data": - var db = newLSMTree("") - var ctx = qexec.newExecutionContext(db) - discard qexec.executeQuery(ctx, parse("CREATE TABLE потребители (имя TEXT, град TEXT)")) - discard qexec.executeQuery(ctx, parse("INSERT INTO потребители (имя, град) VALUES ('Иван', 'София'), ('Мария', 'Пловдив')")) - let res = qexec.executeQuery(ctx, parse("SELECT имя, град FROM потребители WHERE град = 'София'")) - check res.success - check res.rows.len == 1 - check res.rows[0]["имя"] == "Иван" - check res.rows[0]["град"] == "София" - -suite "B-Tree Range Scan": - test "BETWEEN uses index range scan": - var db = newLSMTree("") - var ctx = qexec.newExecutionContext(db) - discard qexec.executeQuery(ctx, parse("CREATE TABLE products (id INTEGER, name TEXT)")) - discard qexec.executeQuery(ctx, parse("INSERT INTO products (id, name) VALUES (1, 'apple'), (2, 'banana'), (3, 'cherry'), (4, 'date'), (5, 'elderberry')")) - discard qexec.executeQuery(ctx, parse("CREATE INDEX idx_products_name ON products(name)")) - let res = qexec.executeQuery(ctx, parse("SELECT name FROM products WHERE name BETWEEN 'banana' AND 'date'")) - check res.success - check res.rows.len == 3 - - test "Greater than uses index range scan": - var db = newLSMTree("") - var ctx = qexec.newExecutionContext(db) - discard qexec.executeQuery(ctx, parse("CREATE TABLE nums (id INTEGER, val TEXT)")) - discard qexec.executeQuery(ctx, parse("INSERT INTO nums (id, val) VALUES (1, '10'), (2, '20'), (3, '30'), (4, '40'), (5, '50')")) - discard qexec.executeQuery(ctx, parse("CREATE INDEX idx_nums_val ON nums(val)")) - let res = qexec.executeQuery(ctx, parse("SELECT val FROM nums WHERE val > '20'")) - check res.success - check res.rows.len == 3 - - test "Less than or equal uses index range scan": - var db = newLSMTree("") - var ctx = qexec.newExecutionContext(db) - discard qexec.executeQuery(ctx, parse("CREATE TABLE nums2 (id INTEGER, val TEXT)")) - discard qexec.executeQuery(ctx, parse("INSERT INTO nums2 (id, val) VALUES (1, '10'), (2, '20'), (3, '30'), (4, '40'), (5, '50')")) - discard qexec.executeQuery(ctx, parse("CREATE INDEX idx_nums2_val ON nums2(val)")) - let res = qexec.executeQuery(ctx, parse("SELECT val FROM nums2 WHERE val <= '30'")) - check res.success - check res.rows.len == 3 - suite "Enhanced Migrations": test "Parse CREATE MIGRATION with UP/DOWN": let ast = parse("CREATE MIGRATION add_users { UP: CREATE TABLE users (id INTEGER PRIMARY KEY); DOWN: DROP TABLE users; }")