保存今天的修改

This commit is contained in:
songxinnuo
2026-11-02 17:51:10 +08:00
parent 04f94ad665
commit eebaba8084
44 changed files with 2831 additions and 154 deletions
+92
View File
@@ -8,6 +8,9 @@ import time
import unittest
from concurrent.futures import ThreadPoolExecutor
from threading import Barrier
from unittest.mock import patch
from contextlib import closing
import sqlite3
from flask import Flask
from werkzeug.datastructures import FileStorage
@@ -115,6 +118,95 @@ class StorageTests(unittest.TestCase):
self.assertFalse(old.exists())
self.assertEqual((uploads/'new.txt').read_text(), 'new')
def test_schema_version_and_pre_migration_snapshot_are_recorded_before_upgrade(self):
connection = db.connect()
connection.execute('DROP TABLE IF EXISTS schema_meta')
connection.commit()
connection.close()
db.init_db()
connection = db.connect()
self.assertEqual(connection.execute("SELECT value FROM schema_meta WHERE key='schema_version'").fetchone()[0], str(db.SCHEMA_VERSION))
connection.close()
snapshots = list((self.root/'backups').glob('pre-migration-*.db'))
self.assertEqual(len(snapshots), 1)
self.assertEqual(db.check_database(snapshots[0]), 'ok')
with closing(sqlite3.connect(snapshots[0])) as snapshot:
self.assertIsNone(snapshot.execute("SELECT 1 FROM sqlite_master WHERE name='schema_meta'").fetchone())
def test_startup_migration_snapshots_keep_only_the_latest_five(self):
for _ in range(7):
db.init_db()
snapshots = sorted((self.root/'backups').glob('pre-migration-*.db'))
self.assertEqual(len(snapshots), 5)
self.assertTrue(all(path.is_file() for path in snapshots))
self.assertTrue(all(db.check_database(path) == 'ok' for path in snapshots))
def test_backup_failure_prevents_any_schema_changes(self):
with closing(db.connect()) as connection:
connection.execute('DROP TABLE schema_meta')
connection.commit()
with patch('logistics_chat.db.snapshot_database', side_effect=OSError('fixture disk full')):
with self.assertRaisesRegex(OSError, 'disk full'):
db.init_db()
with closing(db.connect()) as connection:
self.assertIsNone(connection.execute("SELECT 1 FROM sqlite_master WHERE name='schema_meta'").fetchone())
def test_failed_startup_snapshot_does_not_prune_previous_backups(self):
backups = self.root/'backups'
backups.mkdir()
previous = []
for index in range(6):
path = backups/f'pre-migration-20260101-00000{index}-000000-{index:08x}.db'
db.snapshot_database(self.root/'history.db', path)
previous.append(path)
with patch('logistics_chat.db.snapshot_database', side_effect=OSError('fixture disk full')):
with self.assertRaises(OSError):
db.init_db()
self.assertTrue(all(path.exists() for path in previous))
def test_failed_migration_rolls_back_schema_and_data_and_keeps_preimage(self):
with closing(db.connect()) as connection:
connection.execute('DROP TABLE schema_meta')
connection.commit()
def broken(connection):
connection.execute('CREATE TABLE partial_upgrade(value TEXT)')
connection.execute("INSERT INTO tickets(content) VALUES('must roll back')")
raise RuntimeError('fixture migration failed')
with patch('logistics_chat.db.MIGRATIONS', ((1, broken), *db.MIGRATIONS[1:])):
with self.assertRaisesRegex(RuntimeError, 'migration failed'):
db.init_db()
with closing(db.connect()) as connection:
self.assertIsNone(connection.execute("SELECT 1 FROM sqlite_master WHERE name='partial_upgrade'").fetchone())
self.assertEqual(connection.execute('SELECT COUNT(*) FROM tickets').fetchone()[0], 0)
self.assertEqual(len(list((self.root/'backups').glob('pre-migration-*.db'))), 1)
def test_newer_database_version_is_never_downgraded(self):
with closing(db.connect()) as connection:
connection.execute("UPDATE schema_meta SET value='999' WHERE key='schema_version'")
connection.commit()
with self.assertRaisesRegex(RuntimeError, 'newer'):
db.init_db()
with closing(db.connect()) as connection:
self.assertEqual(connection.execute("SELECT value FROM schema_meta WHERE key='schema_version'").fetchone()[0], '999')
def test_missing_migration_step_cannot_mark_database_as_upgraded(self):
with patch('logistics_chat.db.SCHEMA_VERSION', db.SCHEMA_VERSION + 1):
with self.assertRaisesRegex(RuntimeError, 'migration'):
db.init_db()
with closing(db.connect()) as connection:
self.assertEqual(connection.execute("SELECT value FROM schema_meta WHERE key='schema_version'").fetchone()[0], str(db.SCHEMA_VERSION))
def test_snapshot_backup_is_verified_and_restore_source_is_not_modified(self):
destination = self.root/'backups'/'manual.db'
db.snapshot_database(self.root/'history.db', destination)
self.assertEqual(db.check_database(destination), 'ok')
original = destination.read_bytes()
connection = db.connect()
connection.execute("INSERT INTO chat_history(title,ctime) VALUES('after-backup','now')")
connection.commit()
connection.close()
self.assertEqual(destination.read_bytes(), original)
def test_upload_uses_generated_name_and_configured_directory(self):
upload = FileStorage(stream=io.BytesIO(b'hello'), filename='../report.txt')
result = file_service.upload_file({'file': upload})