# -*- coding: utf-8 -*- """init_db:幂等创建元数据表与本技能业务表。""" from __future__ import annotations import unittest from _support import IsolatedDataRoot _BUSINESS_TABLES = {"fund_projects", "progress_reports", "alert_rules"} class TestDbSmoke(unittest.TestCase): def test_init_db_idempotent_metadata_only(self) -> None: with IsolatedDataRoot(): from db.connection import get_conn, init_db from db.display_metadata import METADATA_TABLES, iter_user_tables init_db() init_db() conn = get_conn() try: cur = conn.cursor() cur.execute( "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'" ) tables = {str(row[0]) for row in cur.fetchall()} self.assertIn("_jiangchang_tables", tables) self.assertIn("_jiangchang_columns", tables) self.assertNotIn("task_logs", tables) self.assertEqual( sorted(iter_user_tables(cur)), sorted(_BUSINESS_TABLES), ) leftover = tables - METADATA_TABLES - _BUSINESS_TABLES self.assertEqual(leftover, set()) finally: conn.close() def test_init_db_migrates_legacy_progress_reports(self) -> None: """v1.0.1 旧库(无 items_json/updated_at)→ init_db 重建迁移且数据不丢。""" with IsolatedDataRoot(): from db.connection import get_conn, init_db conn = get_conn() try: conn.execute( """ CREATE TABLE progress_reports ( id INTEGER PRIMARY KEY AUTOINCREMENT, batch_no TEXT NOT NULL, project_id INTEGER, project_no TEXT, project_name TEXT, pi_name TEXT, as_of TEXT, spend_rate REAL, time_progress REAL, deviation REAL, status_tag TEXT NOT NULL, summary TEXT, suggestions_json TEXT, report_file TEXT, created_at INTEGER NOT NULL DEFAULT (unixepoch()) ) """ ) conn.execute( "INSERT INTO progress_reports (batch_no, project_no, status_tag) VALUES (?, ?, ?)", ("legacy-batch", "OLD001", "严重滞后"), ) conn.commit() finally: conn.close() init_db() conn = get_conn() try: cur = conn.cursor() cur.execute("PRAGMA table_info(progress_reports)") cols = [str(row[1]) for row in cur.fetchall()] self.assertIn("items_json", cols) self.assertIn("updated_at", cols) row = cur.execute( "SELECT project_no, status_tag FROM progress_reports WHERE batch_no = ?", ("legacy-batch",), ).fetchone() self.assertEqual(row, ("OLD001", "严重滞后")) leftovers = cur.execute( "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '_progress%'" ).fetchall() self.assertEqual(leftovers, []) triggers = cur.execute( "SELECT name FROM sqlite_master WHERE type='trigger' AND tbl_name='progress_reports'" ).fetchall() self.assertTrue(any("set_updated_at" in str(t[0]) for t in triggers)) finally: conn.close() if __name__ == "__main__": unittest.main()