98 lines
4.7 KiB
Python
98 lines
4.7 KiB
Python
"""Handoff records remain durable evidence, not a delivery confirmation."""
|
|
import json
|
|
from pathlib import Path
|
|
import tempfile
|
|
import unittest
|
|
from unittest import mock
|
|
|
|
from gui_runtime import handoff_pending_reply_file
|
|
|
|
|
|
class OfflineEvidenceTests(unittest.TestCase):
|
|
def test_legacy_visual_queue_upgrades_to_envelope_and_retains_full_evidence(self):
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
root=Path(tmp)
|
|
path=root/'pending_replies.json'
|
|
state={'stage':'receipt_check','send_state':'sent_uncommitted','reply_text':'合成发送正文','send_dispatched_at':123.0}
|
|
path.write_text(json.dumps({'task':state,'other':{'stage':'queued'}}),encoding='utf-8')
|
|
with mock.patch('queue_log.application_data_dir',return_value=root):
|
|
result=handoff_pending_reply_file(['task'],str(path),confirm_uncertain=True)
|
|
self.assertEqual(result['handed_off'],['task'])
|
|
saved=json.loads(path.read_text(encoding='utf-8'))
|
|
self.assertEqual(saved['pending'],{'other':{'stage':'queued'}})
|
|
record=saved['manual_handoffs']['task']
|
|
self.assertEqual(record['state'],state)
|
|
self.assertTrue(record['receipt_checked_by_user'])
|
|
self.assertFalse(record['delivery_confirmed'])
|
|
self.assertGreater(record['handed_off_at'],0)
|
|
|
|
def test_write_failure_preserves_original_queue_and_evidence(self):
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
root=Path(tmp)
|
|
path=root/'pending_replies.json'
|
|
original=json.dumps({'pending':{'task':{'send_state':'uncertain'}},'manual_handoffs':{'old':{'state':{}}}})
|
|
path.write_text(original,encoding='utf-8')
|
|
with mock.patch('gui_runtime.os.replace',side_effect=OSError('synthetic disk error')):
|
|
result=handoff_pending_reply_file(['task'],str(path),confirm_uncertain=True)
|
|
self.assertIn('error',result)
|
|
self.assertFalse(result['handed_off'])
|
|
self.assertEqual(path.read_text(encoding='utf-8'),original)
|
|
|
|
|
|
try:
|
|
from protocol_engine import ProtocolBot,session_key
|
|
from test_native_protocol_pipeline import Database,Sender,ACCOUNT,CONV,message
|
|
except ImportError:
|
|
ProtocolBot=None
|
|
|
|
|
|
@unittest.skipIf(ProtocolBot is None,'visual-only distribution has no protocol engine')
|
|
class ProtocolEvidenceTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.tmp=tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.tmp.cleanup)
|
|
self.root=Path(self.tmp.name)
|
|
self.db=Database();self.sender=Sender(self.db)
|
|
for patcher in (mock.patch('protocol_engine.application_data_dir',return_value=self.root),
|
|
mock.patch('queue_log.application_data_dir',return_value=self.root)):
|
|
patcher.start();self.addCleanup(patcher.stop)
|
|
self.bot=self.make_bot()
|
|
self.key=session_key(ACCOUNT,CONV)
|
|
self.state={'account':ACCOUNT,'conv_id':CONV,'stage':'receipt_check','send_state':'uncertain',
|
|
'reply_text':'可能已发送的回复','dedup_key':message()['dedup_key']}
|
|
self.bot._pending[self.key]=dict(self.state)
|
|
self.bot.needs_attention=True
|
|
self.bot._save()
|
|
|
|
def make_bot(self):
|
|
return ProtocolBot(db=self.db,sender=self.sender,identity={'accountId':ACCOUNT,'pid':1},
|
|
path=self.root/'queue.json',generate=lambda _: '合成回复',log=lambda _:None)
|
|
|
|
def test_takeover_record_survives_restart_and_poll_without_becoming_pending(self):
|
|
self.bot.handoff_pending_replies([self.key],confirm_uncertain=True)
|
|
restored=self.make_bot()
|
|
restored.poll_once()
|
|
self.assertFalse(restored._pending)
|
|
record=restored._manual_handoffs[self.key]
|
|
self.assertEqual(record['state'],self.state)
|
|
self.assertTrue(record['receipt_checked_by_user'])
|
|
self.assertFalse(record['delivery_confirmed'])
|
|
self.assertFalse(self.sender.calls)
|
|
saved=json.loads(restored.path.read_text(encoding='utf-8'))
|
|
self.assertEqual(saved['manual_handoffs'][self.key],record)
|
|
|
|
def test_failed_persist_rolls_back_memory_and_keeps_pause(self):
|
|
original=self.bot.path.read_text(encoding='utf-8')
|
|
with mock.patch.object(self.bot,'_save',side_effect=OSError('synthetic disk error')):
|
|
with self.assertRaises(OSError):
|
|
self.bot.handoff_pending_replies([self.key],confirm_uncertain=True)
|
|
self.assertEqual(self.bot._pending[self.key],self.state)
|
|
self.assertTrue(self.bot.needs_attention)
|
|
self.assertFalse(self.bot._manual_handoffs)
|
|
self.assertEqual(self.bot.path.read_text(encoding='utf-8'),original)
|
|
self.assertFalse(self.sender.calls)
|
|
|
|
|
|
if __name__=='__main__':
|
|
unittest.main()
|