"""KIN09CSV 修复测试。 覆盖: - Fix A: PARM 场景配置(missing_mode / reordered_parm / missing_ym / empty_daily) - Fix B: seed_extra_rows 大结果集注入(表头重出分支可达) """ import os import sqlite3 import sys import tempfile from pathlib import Path sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) import pytest from orchestrator_db import GixsqlOrchestrator def _make_orch(): orch = object.__new__(GixsqlOrchestrator) table = type('T', (), { 'name': 'DAILY_RECORDS', 'columns': [ type('C', (), {'name': 'EMP_ID', 'primary_key': True}), type('C', (), {'name': 'TARGET_DATE', 'primary_key': True}), type('C', (), {'name': 'TIME_IN', 'primary_key': False}), type('C', (), {'name': 'UPDATED_AT', 'primary_key': False}), ], })() orch.schema = type('S', (), {'db_tables': [table]})() return orch def _make_db(path: Path): conn = sqlite3.connect(str(path)) conn.execute('CREATE TABLE [DAILY_RECORDS] (' '[EMP_ID] CHAR(8), [TARGET_DATE] CHAR(8), ' '[TIME_IN] CHAR(4), [UPDATED_AT] TIMESTAMP, ' 'PRIMARY KEY ([EMP_ID], [TARGET_DATE]))') conn.execute("INSERT INTO [DAILY_RECORDS] VALUES ('Y0000001', '20260701', '0900', '2026-07-01')") conn.commit() conn.close() def test_seed_extra_rows_injects_rows(): """seed_extra_rows 应从 seed 行推导月份并注入唯一 (EMP, 日期) 行。""" orch = _make_orch() tmp = Path(tempfile.mkdtemp()) db = tmp / 'kin.db' _make_db(db) scenario = type('S', (), {'seed_extra_rows': {'DAILY_RECORDS': 10}})() orch._inject_extra_seed_rows(db, scenario) conn = sqlite3.connect(str(db)) rows = conn.execute('SELECT EMP_ID, TARGET_DATE FROM [DAILY_RECORDS]').fetchall() conn.close() emps = {r[0] for r in rows} assert len(rows) >= 11, f'应注入 10 条额外行, 实际 {len(rows)}' assert 'SEED0001' in emps and 'SEED0010' in emps, f'应含 SEED 行, 实际 {emps}' # 注入行日期应在查询月份内 seed_dates = {r[1] for r in rows if r[0].startswith('SEED')} assert seed_dates == {'20260701'}, f'注入日期应为 20260701, 实际 {seed_dates}' def test_seed_extra_rows_noop_when_not_configured(): """seed_extra_rows 未配置时不应注入。""" orch = _make_orch() tmp = Path(tempfile.mkdtemp()) db = tmp / 'kin.db' _make_db(db) scenario = type('S', (), {'seed_extra_rows': {}})() orch._inject_extra_seed_rows(db, scenario) conn = sqlite3.connect(str(db)) n = conn.execute('SELECT COUNT(*) FROM [DAILY_RECORDS]').fetchone()[0] conn.close() assert n == 1, f'不应注入额外行, 实际 {n}' def test_kin09csv_scenarios_parse(): """KIN09CSV.yaml 场景(含 seed_extra_rows)应正确解析。""" from config.program_schema import load_schema schema = load_schema('KIN09CSV', [str(Path(__file__).parent.parent / 'config' / 'programs')]) by_id = {r.id: r for r in schema.runs} assert 'missing_mode' in by_id, f'应含 missing_mode 场景: {list(by_id)}' assert 'reordered_parm' in by_id assert 'missing_ym' in by_id assert 'empty_daily' in by_id assert by_id['missing_mode'].command_line == 'YEARMONTH=202607' assert by_id['reordered_parm'].command_line == 'MODE=FULL,YEARMONTH=202607' assert by_id['missing_ym'].command_line == 'MODE=FULL' assert by_id['empty_daily'].drop_tables == ['DAILY_RECORDS'], \ f'empty_daily 应 drop DAILY_RECORDS, 实际 {by_id["empty_daily"].drop_tables}' full = by_id['FULL'] assert full.seed_extra_rows.get('DAILY_RECORDS') == 100, \ f'FULL 场景 seed_extra_rows 应为 100, 实际 {full.seed_extra_rows}'