Files
sanguo_vnpy_v2/tests/data_platform/test_merge_increment.py
T

75 lines
3.1 KiB
Python

# -*- coding: utf-8 -*-
"""merge_increment.py 计数契约: inserted 只计本连接写入(total_changes)。
2026-08-25 实锤: 03:00 合并窗口 bs_5m 并发写主库, after-before 把 5m 插的行
记成自己的 inserted → skipped(dup) 被挤成负数(-4881)。total_changes 只计本
连接 INSERT 生效行, 对并发写者天然免疫; skipped=inc-inserted 恢复真实含义。
"""
import importlib.util
import sqlite3
import sys
from pathlib import Path
SCRIPT = Path(__file__).resolve().parents[2] / "scripts" / "nas_sync" / "merge_increment.py"
SCHEMA = (
"CREATE TABLE dbbardata(id INTEGER PRIMARY KEY AUTOINCREMENT, "
"symbol TEXT, exchange TEXT, datetime TEXT, interval TEXT, "
"volume REAL, turnover REAL, open_interest REAL, "
"open_price REAL, high_price REAL, low_price REAL, close_price REAL)")
def _run(monkeypatch, capsys, main_db, inc_db):
monkeypatch.setattr(sys, "argv", [
"merge_increment.py", "--db", str(main_db), "--inc", str(inc_db)])
spec = importlib.util.spec_from_file_location("merge_increment_mod", SCRIPT)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
mod.main()
return capsys.readouterr().out
def _mk_inc(path, rows):
c = sqlite3.connect(path)
c.execute(SCHEMA)
c.executemany(
"INSERT INTO dbbardata(symbol,exchange,datetime,interval,close_price) "
"VALUES(?,?,?,?,?)", rows)
c.commit()
c.close()
def test_merge_accounting_new_then_dup(tmp_path, monkeypatch, capsys):
main_db = tmp_path / "main.db"
inc1 = tmp_path / "inc1.db"
_mk_inc(inc1, [("600000", "SSE", "2026-08-21", "d", 10.0),
("600000", "SSE", "2026-08-22", "d", 11.0)])
out = _run(monkeypatch, capsys, main_db, inc1)
assert "inc=2 inserted=2 skipped(dup)=0" in out
# 同增量重跑: 全 dup, inserted=0(OR IGNORE 计数路径)
out = _run(monkeypatch, capsys, main_db, inc1)
assert "inc=2 inserted=0 skipped(dup)=2" in out
def test_merge_accounting_mixed_and_other_writer_rows(tmp_path, monkeypatch, capsys):
"""部分 dup 精确计数; 主库他源行(=bs_5m 并发写)不进 inserted/skipped。"""
main_db = tmp_path / "main.db"
inc1 = tmp_path / "inc1.db"
_mk_inc(inc1, [("600000", "SSE", "2026-08-21", "d", 10.0)])
_run(monkeypatch, capsys, main_db, inc1) # 建 schema + 首灌
# 模拟并发写者(另一连接)直接向主库插 3 行 —— 任何时刻都不该被算进 merge 计数
c = sqlite3.connect(main_db)
c.executemany(
"INSERT INTO dbbardata(symbol,exchange,datetime,interval,close_price) "
"VALUES(?,?,?,?,?)",
[("000001", "SZSE", "2026-08-22", "5m", 1.0),
("000001", "SZSE", "2026-08-22 09:35:00", "5m", 1.0),
("000002", "SZSE", "2026-08-22", "5m", 1.0)])
c.commit()
c.close()
inc2 = tmp_path / "inc2.db"
_mk_inc(inc2, [("600000", "SSE", "2026-08-21", "d", 10.0), # dup
("600000", "SSE", "2026-08-22", "d", 11.0)]) # 新
out = _run(monkeypatch, capsys, main_db, inc2)
assert "inc=2 inserted=1 skipped(dup)=1" in out