Some checks failed
CI / test (pull_request) Has been cancelled
- #210: init_db()에 WAL 저널 모드 적용 (파일 DB에만, :memory: 제외) - 대시보드(READ)와 거래루프(WRITE) 동시 접근 시 SQLite 락 오류 방지 - busy_timeout=5000ms 설정 - #213: RATE_LIMIT_RPS 기본값 2.0으로 통일 (.env.example이 5.0으로 잘못 표기됨) - #216: .env.example 중요 변수 추가 및 정리 - KIS_BASE_URL 모의/실전 URL 주석 명시 (포트 29443 수정 포함) - MODE, TRADE_MODE, ENABLED_MARKETS, PAPER_OVERSEAS_CASH 추가 - GEMINI_MODEL 업데이트 (gemini-pro → gemini-2.0-flash-exp) - DASHBOARD 설정 섹션 추가 테스트 2개 추가 (WAL 파일 DB 적용, 메모리 DB 미적용 검증) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
98 lines
2.7 KiB
Python
98 lines
2.7 KiB
Python
"""Tests for database helper functions."""
|
|
|
|
import tempfile
|
|
import os
|
|
|
|
from src.db import get_open_position, init_db, log_trade
|
|
|
|
|
|
def test_get_open_position_returns_latest_buy() -> None:
|
|
conn = init_db(":memory:")
|
|
log_trade(
|
|
conn=conn,
|
|
stock_code="005930",
|
|
action="BUY",
|
|
confidence=90,
|
|
rationale="entry",
|
|
quantity=2,
|
|
price=70000.0,
|
|
market="KR",
|
|
exchange_code="KRX",
|
|
decision_id="d-buy-1",
|
|
)
|
|
|
|
position = get_open_position(conn, "005930", "KR")
|
|
assert position is not None
|
|
assert position["decision_id"] == "d-buy-1"
|
|
assert position["price"] == 70000.0
|
|
assert position["quantity"] == 2
|
|
|
|
|
|
def test_get_open_position_returns_none_when_latest_is_sell() -> None:
|
|
conn = init_db(":memory:")
|
|
log_trade(
|
|
conn=conn,
|
|
stock_code="005930",
|
|
action="BUY",
|
|
confidence=90,
|
|
rationale="entry",
|
|
quantity=1,
|
|
price=70000.0,
|
|
market="KR",
|
|
exchange_code="KRX",
|
|
decision_id="d-buy-1",
|
|
)
|
|
log_trade(
|
|
conn=conn,
|
|
stock_code="005930",
|
|
action="SELL",
|
|
confidence=95,
|
|
rationale="exit",
|
|
quantity=1,
|
|
price=71000.0,
|
|
market="KR",
|
|
exchange_code="KRX",
|
|
decision_id="d-sell-1",
|
|
)
|
|
|
|
assert get_open_position(conn, "005930", "KR") is None
|
|
|
|
|
|
def test_get_open_position_returns_none_when_no_trades() -> None:
|
|
conn = init_db(":memory:")
|
|
assert get_open_position(conn, "AAPL", "US_NASDAQ") is None
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# WAL mode tests (issue #210)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_wal_mode_applied_to_file_db() -> None:
|
|
"""File-based DB must use WAL journal mode for dashboard concurrent reads."""
|
|
with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f:
|
|
db_path = f.name
|
|
try:
|
|
conn = init_db(db_path)
|
|
cursor = conn.execute("PRAGMA journal_mode")
|
|
mode = cursor.fetchone()[0]
|
|
assert mode == "wal", f"Expected WAL mode, got {mode}"
|
|
conn.close()
|
|
finally:
|
|
os.unlink(db_path)
|
|
# Clean up WAL auxiliary files if they exist
|
|
for ext in ("-wal", "-shm"):
|
|
path = db_path + ext
|
|
if os.path.exists(path):
|
|
os.unlink(path)
|
|
|
|
|
|
def test_wal_mode_not_applied_to_memory_db() -> None:
|
|
""":memory: DB must not apply WAL (SQLite does not support WAL for in-memory)."""
|
|
conn = init_db(":memory:")
|
|
cursor = conn.execute("PRAGMA journal_mode")
|
|
mode = cursor.fetchone()[0]
|
|
# In-memory DBs default to 'memory' journal mode
|
|
assert mode != "wal", "WAL should not be set on in-memory database"
|
|
conn.close()
|