Spaces:
Sleeping
Sleeping
Download tests/test_safety.py from aadi-joshi/openenvhack: direct link, hf CLI and curl.
- Browser
- Download file 5.11 kB
-
https://huggingface.co/spaces/aadi-joshi/openenvhack/resolve/main/tests/test_safety.py
- Command line
-
hf download hf://spaces/aadi-joshi/openenvhack/tests/test_safety.py
-
curl -L -o test_safety.py https://huggingface.co/spaces/aadi-joshi/openenvhack/resolve/main/tests/test_safety.py
5.11 kB
| """Unit tests for server.safety -- pre/post-execution checks.""" | |
| import sqlite3 | |
| import pytest | |
| from server.safety import ( | |
| SafetyViolation, | |
| budget_cost, | |
| check_post_execution, | |
| check_pre_execution, | |
| classify_sql, | |
| ) | |
| CORE_TABLES = ["users", "products", "vendors"] | |
| # classify_sql | |
| class TestClassifySql: | |
| def test_select(self): | |
| assert classify_sql("SELECT * FROM users") == "SELECT" | |
| def test_select_cte(self): | |
| assert classify_sql("WITH cte AS (SELECT 1) SELECT * FROM cte") == "SELECT" | |
| def test_pragma(self): | |
| assert classify_sql("PRAGMA table_info(users)") == "META" | |
| def test_insert(self): | |
| assert classify_sql("INSERT INTO users VALUES (1, 'a@b.com')") == "MUTATION" | |
| def test_update(self): | |
| assert classify_sql("UPDATE users SET status='inactive' WHERE id=1") == "MUTATION" | |
| def test_delete(self): | |
| assert classify_sql("DELETE FROM users WHERE id=9") == "MUTATION" | |
| def test_alter(self): | |
| assert classify_sql("ALTER TABLE users ADD COLUMN phone TEXT") == "MUTATION" | |
| def test_create(self): | |
| assert classify_sql("CREATE TABLE foo (id INTEGER PRIMARY KEY)") == "MUTATION" | |
| def test_leading_whitespace(self): | |
| assert classify_sql(" \n SELECT id FROM users") == "SELECT" | |
| # budget_cost | |
| class TestBudgetCost: | |
| def test_select_costs_1(self): | |
| assert budget_cost("SELECT") == 1 | |
| def test_meta_costs_1(self): | |
| assert budget_cost("META") == 1 | |
| def test_mutation_costs_5(self): | |
| assert budget_cost("MUTATION") == 5 | |
| # check_pre_execution | |
| class TestPreExecution: | |
| def test_safe_select_returns_none(self): | |
| assert check_pre_execution("SELECT * FROM users", CORE_TABLES) is None | |
| def test_drop_core_table_triggers_violation(self): | |
| v = check_pre_execution("DROP TABLE users", CORE_TABLES) | |
| assert v is not None | |
| assert v.kind == "SCHEMA_DESTRUCTION" | |
| assert "users" in v.message | |
| def test_drop_non_core_table_is_allowed(self): | |
| v = check_pre_execution("DROP TABLE temp_backup", CORE_TABLES) | |
| assert v is None | |
| def test_drop_table_if_exists_core(self): | |
| v = check_pre_execution("DROP TABLE IF EXISTS products", CORE_TABLES) | |
| assert v is not None | |
| assert v.kind == "SCHEMA_DESTRUCTION" | |
| def test_delete_with_where_is_safe(self): | |
| v = check_pre_execution( | |
| "DELETE FROM users WHERE id = 9", CORE_TABLES | |
| ) | |
| assert v is None | |
| def test_delete_without_where_triggers_violation(self): | |
| v = check_pre_execution("DELETE FROM users", CORE_TABLES) | |
| assert v is not None | |
| assert v.kind == "TRUNCATION" | |
| def test_delete_from_with_newline_no_where(self): | |
| v = check_pre_execution("DELETE\nFROM\nusers", CORE_TABLES) | |
| assert v is not None | |
| assert v.kind == "TRUNCATION" | |
| def test_delete_with_subquery_where(self): | |
| sql = "DELETE FROM users WHERE id IN (SELECT id FROM temp_dups)" | |
| v = check_pre_execution(sql, CORE_TABLES) | |
| assert v is None | |
| def test_drop_core_table_case_insensitive(self): | |
| v = check_pre_execution("drop table USERS", CORE_TABLES) | |
| assert v is not None | |
| assert v.kind == "SCHEMA_DESTRUCTION" | |
| def test_pragma_is_safe(self): | |
| assert check_pre_execution("PRAGMA foreign_key_check", CORE_TABLES) is None | |
| def test_insert_is_safe(self): | |
| assert ( | |
| check_pre_execution( | |
| "INSERT INTO users VALUES (99, 'x@y.com', 'x', '2024-01-01', 'active')", | |
| CORE_TABLES, | |
| ) | |
| is None | |
| ) | |
| # check_post_execution | |
| class TestPostExecution: | |
| def _make_conn_with_users(self, n: int) -> sqlite3.Connection: | |
| conn = sqlite3.connect(":memory:") | |
| conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)") | |
| for i in range(n): | |
| conn.execute("INSERT INTO users VALUES (?, ?)", (i + 1, f"u{i}@test.com")) | |
| conn.commit() | |
| return conn | |
| def test_no_loss_returns_none(self): | |
| conn = self._make_conn_with_users(10) | |
| initial = {"users": 10} | |
| assert check_post_execution(conn, initial) is None | |
| def test_small_loss_is_ok(self): | |
| conn = self._make_conn_with_users(10) | |
| conn.execute("DELETE FROM users WHERE id = 10") | |
| conn.commit() | |
| # floor = 10 (what we must protect); 9 >= 10*0.9 = 9 - OK | |
| floor = {"users": 10} | |
| assert check_post_execution(conn, floor) is None | |
| def test_catastrophic_loss_triggers_violation(self): | |
| conn = self._make_conn_with_users(10) | |
| conn.execute("DELETE FROM users WHERE id > 2") # 8 deleted -> 2 remain (20%) | |
| conn.commit() | |
| floor = {"users": 10} | |
| v = check_post_execution(conn, floor) | |
| assert v is not None | |
| assert v.kind == "CATASTROPHIC_LOSS" | |
| assert "users" in v.message | |
| def test_zero_initial_is_ignored(self): | |
| conn = self._make_conn_with_users(0) | |
| initial = {"users": 0} | |
| assert check_post_execution(conn, initial) is None | |