"""One table, one database — proven from the servers' own logs, not from the application's side. Decision D22 says an import writes to `public.experiment_run` and to nothing else relational: no project table, no model table, no row in the predictions database. That claim is only worth making if it is checked from somewhere that sees *every* client, and there is exactly one such place. Why not the obvious alternatives: - a SQLAlchemy `before_cursor_execute` listener sees the status engine and is blind to the psycopg pool `Storage` holds — which is precisely the client that would betray the claim; - `pg_stat_statements` is aggregated, so it cannot be scoped to the window of one import. So both containers run with `log_statement=all` and the window is bracketed by a marker statement on each server. The assertions are about *which relation names appear*, not about exact statement text, because the text is the driver's business and changes with it. The predictions database is deliberately real and reachable here: `import_activities` is built with working credentials for it, so "no statement reached it" is a claim about the import's behaviour and not about a missing connection. """ from __future__ import annotations from typing import Any import pytest from temporalio.client import WorkflowFailureError from e2e.import_harness import names_no_relation, strip_literals pytestmark = [pytest.mark.import_e2e, pytest.mark.asyncio] FACTORY_PASSWORD = 'Factory1Model!Test' # Relations that exist in the predictions database and in nobody's import path. FOREIGN_RELATIONS = ( 'predictions_schema', 'laborious_data', 'transformed_data', 'predictions', ) # Tables a reader might expect an import to want, and which decision D22 says do not exist. RELATIONS_D22_DENIES = ('project', 'model_registry', 'models', 'import_run', 'model_project') class TestOneTableOneDatabase: """A full import, from claim to terminal write, watched from both servers.""" async def test_every_statement_the_import_issues_names_experiment_run( self, import_status_table: Any, import_models_collection: Any, import_bundle_factory: Any, import_upload_bundle: Any, import_insert_status_row: Any, import_build_input: Any, import_execute: Any, import_envelope: Any, import_read_status_row: Any, import_log_window: Any, ) -> None: object_key, digest = import_upload_bundle(import_bundle_factory()) import_run_id = import_insert_status_row(object_key=object_key, expected_digest=digest) with import_log_window() as captured: handle = await import_execute( import_build_input( import_run_id=import_run_id, object_key=object_key, expected_digest=digest, password_envelope=import_envelope(FACTORY_PASSWORD), ) ) await handle.result() row = import_read_status_row(import_run_id) assert row is not None assert row['status'] == 'IMPORT_SUCCESS', ( 'the window has to bracket a *working* import, or it proves nothing' ) bff_statements = captured['bff'] assert bff_statements, 'the status database logged nothing at all — the window is wrong' touching_a_relation = [ statement for statement in bff_statements if not names_no_relation(statement) ] assert touching_a_relation, 'no relational statement was logged, so nothing was checked' for statement in touching_a_relation: assert 'experiment_run' in statement, ( f'a statement naming another relation reached the status database: {statement!r}' ) # And no relation a reader might expect the feature to want appears anywhere in the window. # Literals are stripped first: the import writes the bundle's own `model_project` value into # the JSON detail, and `factory_project` is data, not a reference to a `project` table. window_text = '\n'.join(strip_literals(s) for s in bff_statements).lower() for relation in RELATIONS_D22_DENIES: assert relation not in window_text, ( f'{relation!r} appears in the import window: D22 says no such table is written' ) for relation in FOREIGN_RELATIONS: assert relation not in window_text, f'{relation!r} appears in the import window' async def test_the_predictions_database_sees_no_statement_from_an_import( self, import_status_table: Any, import_models_collection: Any, import_bundle_factory: Any, import_upload_bundle: Any, import_insert_status_row: Any, import_build_input: Any, import_execute: Any, import_envelope: Any, import_read_status_row: Any, import_log_window: Any, ) -> None: """Not "no statement against our tables" — no statement at all. The import holds a working connection to this server (`Activities` is built with one), so this is about what the import chooses to do, not about what it is able to do. """ object_key, digest = import_upload_bundle(import_bundle_factory()) import_run_id = import_insert_status_row(object_key=object_key, expected_digest=digest) with import_log_window() as captured: handle = await import_execute( import_build_input( import_run_id=import_run_id, object_key=object_key, expected_digest=digest, password_envelope=import_envelope(FACTORY_PASSWORD), ) ) await handle.result() assert import_read_status_row(import_run_id)['status'] == 'IMPORT_SUCCESS' predictions_statements = [ statement for statement in captured['predictions'] if not names_no_relation(statement) ] assert not predictions_statements, ( f'the import issued statements against the predictions database: ' f'{predictions_statements}' ) async def test_a_rejected_import_also_touches_nothing_else( self, import_status_table: Any, import_models_collection: Any, import_bundle_factory: Any, import_upload_bundle: Any, import_insert_status_row: Any, import_build_input: Any, import_execute: Any, import_envelope: Any, import_log_window: Any, ) -> None: """The failure path writes more status rows than the success path, so it is worth its own case. A rejected import runs the claim, the progress hints, cleanup and the terminal write — more statements than a success, and every one of them still has to name the same table. """ object_key, digest = import_upload_bundle(import_bundle_factory(include_metadata=False)) import_run_id = import_insert_status_row(object_key=object_key, expected_digest=digest) with import_log_window() as captured: handle = await import_execute( import_build_input( import_run_id=import_run_id, object_key=object_key, expected_digest=digest, password_envelope=import_envelope(FACTORY_PASSWORD), ) ) with pytest.raises(WorkflowFailureError): await handle.result() for statement in captured['bff']: if names_no_relation(statement): continue assert 'experiment_run' in statement, statement assert not [s for s in captured['predictions'] if not names_no_relation(s)]