1 parent
0421994fe6
commit
425ea7449b
138 files changed
+5705
-1012
No files matched your search
@@ -0,0 +1,91 @@
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SRC = ROOT / "src"
|
||||
DIALECTS = ("sqlite", "mysql", "pgsql")
|
||||
|
||||
SQL_LITERAL = re.compile(
|
||||
r'(?:r#{0,8})?"\s*(?:SELECT\s+(?:\*|[A-Za-z_(])|INSERT\s+INTO|INSERT\s+OR\s+(?:IGNORE|REPLACE)\s+INTO|UPDATE\s+[A-Za-z_]|DELETE\s+FROM|PRAGMA\s+[A-Za-z_]|WITH\s+[A-Za-z_]|CREATE\s+(?:TABLE|INDEX)|ALTER\s+TABLE|DROP\s+(?:TABLE|INDEX))',
|
||||
re.IGNORECASE | re.MULTILINE,
|
||||
)
|
||||
CONST_NAME = re.compile(r"pub const\s+([A-Z][A-Z0-9_]*)\s*:")
|
||||
MODULE = re.compile(r"^pub mod\s+([a-zA-Z0-9_]+)\s*\{", re.MULTILINE)
|
||||
|
||||
|
||||
def read(path: str) -> str:
|
||||
return (ROOT / path).read_text()
|
||||
|
||||
|
||||
def test_central_query_tree_exists():
|
||||
for dialect in DIALECTS:
|
||||
assert (ROOT / f"src/queries/{dialect}/queries.rs").is_file()
|
||||
assert (ROOT / f"src/queries/{dialect}/mod.rs").is_file()
|
||||
assert not (ROOT / "src/session_store/queries").exists()
|
||||
|
||||
|
||||
def test_session_store_uses_central_query_tree():
|
||||
db = read("src/session_store/database.rs")
|
||||
for dialect in DIALECTS:
|
||||
assert f"queries::{dialect}::queries::sessions::" in db
|
||||
|
||||
|
||||
def test_no_executable_sql_literals_outside_query_tree():
|
||||
offenders = []
|
||||
for path in SRC.rglob("*.rs"):
|
||||
if "queries" in path.parts:
|
||||
continue
|
||||
text = path.read_text()
|
||||
if SQL_LITERAL.search(text):
|
||||
offenders.append(str(path.relative_to(ROOT)))
|
||||
assert offenders == []
|
||||
|
||||
|
||||
def test_dialect_catalogs_have_same_modules_and_query_constants():
|
||||
catalogs = {d: read(f"src/queries/{d}/queries.rs") for d in DIALECTS}
|
||||
base_modules = set(MODULE.findall(catalogs["sqlite"]))
|
||||
assert "sessions" in base_modules
|
||||
for dialect in DIALECTS[1:]:
|
||||
assert set(MODULE.findall(catalogs[dialect])) == base_modules
|
||||
|
||||
# Every dialect must expose the same named query constants/templates.
|
||||
base_consts = set(CONST_NAME.findall(catalogs["sqlite"]))
|
||||
assert len(base_consts) >= 10
|
||||
for dialect in DIALECTS[1:]:
|
||||
assert set(CONST_NAME.findall(catalogs[dialect])) == base_consts
|
||||
|
||||
|
||||
def test_backend_specific_session_placeholders_are_preserved():
|
||||
sqlite = read("src/queries/sqlite/queries.rs")
|
||||
mysql = read("src/queries/mysql/queries.rs")
|
||||
pgsql = read("src/queries/pgsql/queries.rs")
|
||||
assert 'BY_TOKEN: &str = "SELECT * FROM sessions WHERE token = ?"' in sqlite
|
||||
assert 'BY_TOKEN: &str = "SELECT * FROM sessions WHERE token = ?"' in mysql
|
||||
assert 'BY_TOKEN: &str = "SELECT * FROM sessions WHERE token = $1"' in pgsql
|
||||
|
||||
|
||||
def test_dynamic_query_macros_do_not_capture_caller_locals():
|
||||
sqlite = read("src/queries/sqlite/queries.rs")
|
||||
# macro_rules identifiers are hygienic: caller-local values must arrive as metavariables.
|
||||
forbidden = [
|
||||
'WHERE id = ?{idx}',
|
||||
'ORDER BY {order_by}',
|
||||
'{where_clause}',
|
||||
'SET {set_clause}',
|
||||
'user_version = {current}',
|
||||
'user_version = {version}',
|
||||
]
|
||||
macro_section = sqlite[sqlite.index("#[macro_export]"):]
|
||||
for fragment in forbidden:
|
||||
assert fragment not in macro_section
|
||||
|
||||
calendar = read("src/db/calendar.rs")
|
||||
messages = read("src/db/messages.rs")
|
||||
notifications = read("src/db/notification_preferences.rs")
|
||||
pool = read("src/db/pool.rs")
|
||||
assert 'rustbox_query_db_calendar_004!(sets.join(", "), idx)' in calendar
|
||||
assert 'rustbox_query_db_messages_002!(&order_by)' in messages
|
||||
assert 'rustbox_query_db_messages_005!(&where_clause, param_values.len() + 1)' in messages
|
||||
assert 'rustbox_query_db_notification_preferences_001!(&set_clause, idx)' in notifications
|
||||
assert re.search(r'db_pool::set_user_version\(\s*version,?\s*\)', pool)
|
||||
assert 'refinery_schema_history' not in pool
|
||||
Reference in new issue
Block a user