chore: establish project baseline
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
import pytest
|
||||
|
||||
import gti_discovery
|
||||
from gti_discovery.catalog import FirebirdCatalog
|
||||
from gti_discovery.collector import _approved_fixture_reader
|
||||
from gti_discovery.firebird_queries import (
|
||||
_ADAPTER_REGISTRATION_TOKEN,
|
||||
_APPROVED_ADAPTER_TYPES,
|
||||
_CATALOG_QUERIES,
|
||||
_INTERNAL_QUERIES,
|
||||
_execute_catalog,
|
||||
_register_approved_adapter,
|
||||
)
|
||||
from gti_discovery.collector import _APPROVED_FIXTURE_TYPES
|
||||
|
||||
|
||||
class RecordingAdapter:
|
||||
read_only = True
|
||||
|
||||
def __init__(self):
|
||||
self.calls = []
|
||||
|
||||
def execute(self, sql, params=()):
|
||||
self.calls.append((sql, params))
|
||||
return []
|
||||
|
||||
|
||||
_register_approved_adapter(RecordingAdapter, _ADAPTER_REGISTRATION_TOKEN)
|
||||
|
||||
|
||||
def make_structured_connection():
|
||||
return FirebirdCatalog(RecordingAdapter())
|
||||
|
||||
|
||||
def test_public_connection_has_no_sql_execute_method():
|
||||
connection = make_structured_connection()
|
||||
for name in ("execute", "query", "raw_execute", "execute_statement", "run_sql", "_run"):
|
||||
assert not hasattr(connection, name)
|
||||
assert name not in gti_discovery.__all__
|
||||
|
||||
|
||||
def test_package_exports_no_raw_sql_or_parser_authority():
|
||||
forbidden = {
|
||||
"execute", "query", "raw_execute", "execute_statement", "run_sql",
|
||||
"validate_read_only",
|
||||
}
|
||||
assert forbidden.isdisjoint(vars(gti_discovery))
|
||||
assert forbidden.isdisjoint(gti_discovery.__all__)
|
||||
|
||||
|
||||
def test_private_sql_runner_cannot_bypass_operation_boundary():
|
||||
connection = make_structured_connection()
|
||||
assert not hasattr(connection, "_run")
|
||||
assert not hasattr(connection, "_run_sql")
|
||||
|
||||
|
||||
def test_unknown_operation_key_never_reaches_driver():
|
||||
adapter = RecordingAdapter()
|
||||
with pytest.raises(ValueError):
|
||||
_execute_catalog(adapter, "SELECT * FROM X")
|
||||
assert adapter.calls == []
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"forbidden_operation",
|
||||
["execute_procedure", "select_procedure", "execute_selectable_procedure", "invoke_udf"],
|
||||
)
|
||||
def test_procedure_and_udf_operations_never_reach_driver(forbidden_operation):
|
||||
adapter = RecordingAdapter()
|
||||
|
||||
with pytest.raises(ValueError, match="unknown catalog operation"):
|
||||
_execute_catalog(adapter, forbidden_operation)
|
||||
|
||||
assert adapter.calls == []
|
||||
|
||||
|
||||
def test_procedure_api_is_metadata_only():
|
||||
adapter = RecordingAdapter()
|
||||
catalog = FirebirdCatalog(adapter)
|
||||
|
||||
assert catalog.get_procedures() == []
|
||||
assert catalog.get_procedure_parameters() == []
|
||||
assert not any("EXECUTE PROCEDURE" in sql.upper() for sql, _ in adapter.calls)
|
||||
assert not any("FROM " + name in sql.upper() for name in ("SP_RECALC", "SOME_UDF") for sql, _ in adapter.calls)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("operation_key", [None, 1, [], {}, bytearray(b"database"), str("database") + ""])
|
||||
def test_operation_key_must_be_an_exact_approved_string(operation_key):
|
||||
adapter = RecordingAdapter()
|
||||
if type(operation_key) is str:
|
||||
pytest.skip("control case is tested by the static operation tests")
|
||||
with pytest.raises(ValueError, match="operation"):
|
||||
_execute_catalog(adapter, operation_key)
|
||||
assert adapter.calls == []
|
||||
|
||||
|
||||
def test_str_subclass_is_not_an_operation_key():
|
||||
class Lookalike(str):
|
||||
pass
|
||||
|
||||
adapter = RecordingAdapter()
|
||||
with pytest.raises(ValueError, match="operation"):
|
||||
_execute_catalog(adapter, Lookalike("database"))
|
||||
assert adapter.calls == []
|
||||
|
||||
|
||||
def test_arbitrary_adapter_is_rejected_before_driver_invocation():
|
||||
class ArbitraryAdapter:
|
||||
def execute(self, sql, params=()):
|
||||
raise AssertionError("driver must not be invoked")
|
||||
|
||||
with pytest.raises(TypeError, match="approved implementation"):
|
||||
_execute_catalog(ArbitraryAdapter(), "database")
|
||||
|
||||
|
||||
def test_catalog_rejects_unregistered_read_only_adapter_before_driver_invocation():
|
||||
class LookalikeAdapter:
|
||||
read_only = True
|
||||
|
||||
def execute(self, sql, params=()):
|
||||
raise AssertionError("driver must not be invoked")
|
||||
|
||||
with pytest.raises(TypeError, match="approved implementation"):
|
||||
FirebirdCatalog(LookalikeAdapter())
|
||||
|
||||
|
||||
def test_catalog_close_cannot_act_on_unregistered_adapter():
|
||||
class LookalikeAdapter:
|
||||
read_only = True
|
||||
closed = False
|
||||
|
||||
def execute(self, sql, params=()):
|
||||
raise AssertionError("driver must not be invoked")
|
||||
|
||||
def close(self):
|
||||
self.closed = True
|
||||
|
||||
adapter = LookalikeAdapter()
|
||||
with pytest.raises(TypeError, match="approved implementation"):
|
||||
FirebirdCatalog(adapter)
|
||||
assert adapter.closed is False
|
||||
|
||||
|
||||
def test_fixture_reader_registration_requires_private_capability():
|
||||
class UntrustedReader:
|
||||
pass
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
_approved_fixture_reader(UntrustedReader)
|
||||
|
||||
|
||||
def test_catalog_queries_are_immutable_and_operation_keyed():
|
||||
with pytest.raises(TypeError):
|
||||
_CATALOG_QUERIES["new"] = "SELECT 1"
|
||||
assert set(_CATALOG_QUERIES) == {
|
||||
"database", "relations", "fields", "keys", "indexes", "foreign_keys",
|
||||
"triggers", "procedures", "procedure_parameters", "packages", "generators",
|
||||
"dependencies", "monitoring",
|
||||
}
|
||||
|
||||
|
||||
def test_private_approved_type_registries_are_immutable_snapshots():
|
||||
assert isinstance(_APPROVED_ADAPTER_TYPES, type(_CATALOG_QUERIES))
|
||||
assert isinstance(_APPROVED_FIXTURE_TYPES, type(_CATALOG_QUERIES))
|
||||
with pytest.raises(TypeError):
|
||||
_APPROVED_ADAPTER_TYPES[RecordingAdapter] = True
|
||||
with pytest.raises(TypeError):
|
||||
_APPROVED_FIXTURE_TYPES[RecordingAdapter] = True
|
||||
|
||||
|
||||
def test_registration_mutators_are_not_publicly_exported():
|
||||
for name in ("_register_approved_adapter", "_approved_fixture_reader"):
|
||||
assert name not in gti_discovery.__all__
|
||||
assert not hasattr(gti_discovery, name)
|
||||
|
||||
|
||||
def test_threat_model_documents_accidental_boundary_scope():
|
||||
from pathlib import Path
|
||||
|
||||
state = Path("docs/AI_PROJECT_STATE.md").read_text(encoding="utf-8")
|
||||
report = Path("docs/MISSION_00_REPORT.md").read_text(encoding="utf-8")
|
||||
required = (
|
||||
"implementation mistakes", "accidental unauthorized operations",
|
||||
"arbitrary SQL", "wrong database", "writes", "procedures/UDFs",
|
||||
"injection", "dependency shadowing",
|
||||
)
|
||||
for phrase in required:
|
||||
assert phrase in state
|
||||
assert phrase in report
|
||||
assert "arbitrary Python" in state
|
||||
assert "same process" in report
|
||||
|
||||
|
||||
def test_legitimate_firebird_syntax_reaches_driver_without_old_parser(monkeypatch):
|
||||
adapter = RecordingAdapter()
|
||||
query = _INTERNAL_QUERIES["expression_probe"]
|
||||
monkeypatch.setattr("gti_discovery.read_only.validate_read_only", lambda _: (_ for _ in ()).throw(AssertionError()))
|
||||
_execute_catalog(adapter, "expression_probe")
|
||||
assert adapter.calls == [(query, ())]
|
||||
Reference in New Issue
Block a user