main
py 92 lines 4.25 KB
Raw
1 from dataclasses import replace
2 from uuid import UUID
3
4 import pytest
5
6 from app.persistence import SqliteResearchPersistence, DisabledResearchPersistence
7 from app.postgres_persistence import PostgresResearchPersistence, _PostgresConnectionAdapter
8 from app.repository import ResearchRepository
9 from test_fact_precedence import fact
10 from app.fact_precedence import FactSourceTier
11 from test_shareholding import _snapshot
12 from test_structured_market_persistence import _record
13
14
15 @pytest.mark.parametrize("method", ["load_financial_facts", "load_events", "load_shareholding_snapshots",
16 "load_structured_market_snapshots", "load_market_price_observations"])
17 def test_empty_filter_never_reads_all_rows(method):
18 store = SqliteResearchPersistence()
19 queries = []
20 store._connection.set_trace_callback(queries.append)
21 assert getattr(store, method)(set()) == []
22 assert queries == []
23 assert getattr(DisabledResearchPersistence(), method)(set()) == []
24
25
26 def test_filtered_facts_snapshots_prices_and_shareholding_values():
27 store = SqliteResearchPersistence()
28 for n in [1, 2]:
29 key = UUID(int=n)
30 value = fact("pat", n, FactSourceTier.OFFICIAL_NSE)
31 store.upsert_financial_fact(replace(value, key=replace(value.key, instrument_id=key)))
32 store.upsert_shareholding_snapshot(_snapshot(key, source=f"source-{n}"))
33 store.upsert_structured_market_snapshot(_record(key))
34 queries = []
35 store._connection.set_trace_callback(queries.append)
36 ids = {UUID(int=1)}
37 assert [f.key.instrument_id for f in store.load_financial_facts(ids)] == list(ids)
38 snapshots = store.load_shareholding_snapshots(ids)
39 assert [s.instrument_id for s in snapshots] == list(ids)
40 assert len(snapshots[0].values) == 1
41 assert [s.instrument_id for s in store.load_structured_market_snapshots(ids)] == list(ids)
42 assert [p.instrument_id for p in store.load_market_price_observations(ids)] == list(ids)
43 assert all(" WHERE " in q and " IN (" in q for q in queries)
44 assert len(store.load_financial_facts()) == 2
45
46
47 @pytest.mark.asyncio
48 async def test_repository_financial_reads_pass_ids_to_persistence():
49 class FilterRequired(DisabledResearchPersistence):
50 def load_financial_facts(self, instrument_ids=None):
51 assert instrument_ids == {UUID(int=1)}
52 return []
53 repository = ResearchRepository.__new__(ResearchRepository)
54 repository._persistence = FilterRequired()
55 import threading
56 repository._persistence_worker_lock = threading.RLock()
57 assert repository.financial_facts_for(UUID(int=1)) == []
58 assert await repository.financial_facts_for_instruments({UUID(int=1)}) == {UUID(int=1): []}
59
60
61 def test_postgres_inherits_parameterized_bounded_batch_reads():
62 queries = []
63 class Connection:
64 def execute(self, sql, params):
65 queries.append((sql, params))
66 return self
67 def fetchall(self): return []
68 store = PostgresResearchPersistence.__new__(PostgresResearchPersistence)
69 store._connection = _PostgresConnectionAdapter(Connection())
70 ids = {UUID(int=n) for n in range(1, 1002)}
71 assert store.load_financial_facts(ids) == []
72 assert [len(params) for _, params in queries] == [500, 500, 1]
73 assert all("WHERE instrument_id IN (%s" in sql and "?" not in sql for sql, _ in queries)
74 assert set(p for _, params in queries for p in params) == {str(i) for i in ids}
75
76
77 def test_event_and_supporting_source_reads_are_filtered():
78 # Existing domain fixtures supply valid source documents and events.
79 repository = ResearchRepository(persistence=DisabledResearchPersistence())
80 store = SqliteResearchPersistence()
81 events = list(repository.events.values())
82 assert events
83 for document in repository.documents.values(): store.upsert_document(document)
84 for event in events: store.upsert_event(event)
85 target = events[0].instrument_id
86 queries = []
87 store._connection.set_trace_callback(queries.append)
88 loaded = store.load_events({target})
89 assert loaded and {e.instrument_id for e in loaded} == {target}
90 assert len(loaded) == sum(e.instrument_id == target for e in events)
91 assert all(" WHERE " in q and " IN (" in q for q in queries)
92 assert any("research_event_sources" in q and "event_id IN" in q for q in queries)