119 lines
4.1 KiB
Python
119 lines
4.1 KiB
Python
"""state 模块行为测试 (SQLite 真实读写, 非 mock)
|
|
|
|
运行: cd /home/lou/文档/7z-encrypt && .venv/bin/python -m unittest discover -s tests -v
|
|
"""
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from datetime import datetime, timedelta
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from state import (
|
|
CHUNK_FAILED,
|
|
CHUNK_UPLOADED,
|
|
STATUS_DONE,
|
|
STATUS_FAILED,
|
|
STATUS_UPLOADING,
|
|
TaskStore,
|
|
)
|
|
|
|
|
|
class TaskStoreBase(unittest.TestCase):
|
|
def setUp(self):
|
|
self._td = tempfile.TemporaryDirectory(prefix='hermes-test-')
|
|
self.addCleanup(self._td.cleanup)
|
|
self.store = TaskStore(os.path.join(self._td.name, 'tasks.db'))
|
|
self.store.create_task('T1', 'a.mp4', 100, 3)
|
|
self.store.create_task('T2', 'b.mp4', 200, 2)
|
|
|
|
|
|
class TestCreate(TaskStoreBase):
|
|
def test_create_and_get(self):
|
|
t = self.store.get_task('T1')
|
|
self.assertEqual(t['file_name'], 'a.mp4')
|
|
self.assertEqual(t['file_size'], 100)
|
|
self.assertEqual(t['chunk_count'], 3)
|
|
self.assertEqual(t['status'], STATUS_UPLOADING)
|
|
self.assertIsNone(self.store.get_task('NOPE'))
|
|
|
|
def test_db_file_created(self):
|
|
self.assertTrue(os.path.exists(os.path.join(self._td.name, 'tasks.db')))
|
|
|
|
def test_persist_across_reopen(self):
|
|
store2 = TaskStore(os.path.join(self._td.name, 'tasks.db'))
|
|
t = store2.get_task('T1')
|
|
assert t is not None
|
|
self.assertEqual(t['file_name'], 'a.mp4')
|
|
|
|
|
|
class TestChunkEvents(TaskStoreBase):
|
|
def test_mark_uploaded(self):
|
|
self.store.mark_chunk_uploaded('T1', 1)
|
|
self.assertEqual(self.store.get_chunk_status('T1'), {1: CHUNK_UPLOADED})
|
|
|
|
def test_mark_failed(self):
|
|
self.store.mark_chunk_failed('T1', 2)
|
|
self.assertEqual(self.store.get_chunk_status('T1'), {2: CHUNK_FAILED})
|
|
|
|
def test_upsert_overwrite(self):
|
|
self.store.mark_chunk_uploaded('T1', 1)
|
|
self.store.mark_chunk_failed('T1', 1) # 覆盖为 failed
|
|
self.assertEqual(self.store.get_chunk_status('T1'), {1: CHUNK_FAILED})
|
|
|
|
|
|
class TestPending(TaskStoreBase):
|
|
def test_pending_contains_uploading(self):
|
|
pending = {t['task_id'] for t in self.store.get_pending_tasks()}
|
|
self.assertEqual(pending, {'T1', 'T2'})
|
|
|
|
def test_uploaded_chunks_listed(self):
|
|
self.store.mark_chunk_uploaded('T1', 1)
|
|
self.store.mark_chunk_uploaded('T1', 3)
|
|
self.store.mark_chunk_failed('T1', 2)
|
|
t1 = next(t for t in self.store.get_pending_tasks() if t['task_id'] == 'T1')
|
|
self.assertEqual(t1['uploaded_chunks'], [1, 3]) # failed 卷不算已传
|
|
|
|
def test_done_not_pending(self):
|
|
self.store.mark_done('T1')
|
|
pending = {t['task_id'] for t in self.store.get_pending_tasks()}
|
|
self.assertEqual(pending, {'T2'})
|
|
|
|
def test_failed_not_pending(self):
|
|
self.store.mark_failed('T1')
|
|
pending = {t['task_id'] for t in self.store.get_pending_tasks()}
|
|
self.assertEqual(pending, {'T2'})
|
|
|
|
|
|
class TestCleanup(TaskStoreBase):
|
|
def _age_task(self, task_id: str, days: int) -> None:
|
|
"""把任务 updated_at 改老, 模拟过期"""
|
|
old = (datetime.now() - timedelta(days=days)).isoformat(timespec='seconds')
|
|
with self.store._connect() as conn:
|
|
conn.execute("UPDATE tasks SET updated_at = ? WHERE task_id = ?", (old, task_id))
|
|
|
|
def test_cleanup_removes_old_done(self):
|
|
self.store.mark_done('T1')
|
|
self._age_task('T1', days=30)
|
|
n = self.store.cleanup(days=7)
|
|
self.assertEqual(n, 1)
|
|
self.assertIsNone(self.store.get_task('T1'))
|
|
|
|
def test_cleanup_keeps_uploading(self):
|
|
self._age_task('T1', days=30) # uploading 状态不受清理
|
|
n = self.store.cleanup(days=7)
|
|
self.assertEqual(n, 0)
|
|
self.assertIsNotNone(self.store.get_task('T1'))
|
|
|
|
def test_cleanup_removes_chunks_too(self):
|
|
self.store.mark_chunk_uploaded('T1', 1)
|
|
self.store.mark_done('T1')
|
|
self._age_task('T1', days=30)
|
|
self.store.cleanup(days=7)
|
|
self.assertEqual(self.store.get_chunk_status('T1'), {})
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|