Refactor radar system
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
"""Settings commits retain valid files on failure and concurrent writes."""
|
||||
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
from python_app.file_io import atomic_write_json
|
||||
from python_app.orchestration.gui_session_state import GuiSessionStateStore
|
||||
|
||||
|
||||
class AtomicJsonTest(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
directory = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(directory.cleanup)
|
||||
self.path = Path(directory.name) / "settings.json"
|
||||
atomic_write_json(self.path, {"old": True})
|
||||
|
||||
def test_failed_sync_or_commit_preserves_previous_file(self) -> None:
|
||||
for operation in ('fsync', 'replace'):
|
||||
with self.subTest(operation=operation), \
|
||||
mock.patch(f'python_app.file_io.os.{operation}', side_effect=OSError('disk failure')), \
|
||||
self.assertRaises(OSError):
|
||||
atomic_write_json(self.path, {'new': True}, durable=True)
|
||||
self.assertEqual(json.loads(self.path.read_text()), {'old': True})
|
||||
self.assertEqual(list(self.path.parent.glob('*.tmp')), [])
|
||||
|
||||
def test_nonfinite_json_cannot_overwrite_settings(self) -> None:
|
||||
with self.assertRaises(ValueError):
|
||||
atomic_write_json(self.path, {'bad': float('nan')})
|
||||
self.assertEqual(json.loads(self.path.read_text()), {'old': True})
|
||||
|
||||
def test_concurrent_writers_publish_complete_json_and_leave_no_temp_files(self) -> None:
|
||||
payloads = [{'index': i, 'values': [i] * 1000} for i in range(32)]
|
||||
with ThreadPoolExecutor(max_workers=8) as executor:
|
||||
list(executor.map(lambda payload: atomic_write_json(self.path, payload), payloads))
|
||||
self.assertIn(json.loads(self.path.read_text()), payloads)
|
||||
self.assertEqual(list(self.path.parent.glob('*.tmp')), [])
|
||||
|
||||
def test_invalid_utf8_session_cache_uses_defaults(self) -> None:
|
||||
self.path.write_bytes(b'\xff')
|
||||
self.assertEqual(GuiSessionStateStore(self.path).load().last_profile_path, '')
|
||||
Reference in New Issue
Block a user