railiance-clock/tests/test_observe_host_clock.py
tegwick fb09e138b8 Add repeatable read-only host clock inventory and live receipt
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a09cbc-910e-77a0-b336-3130194350b3
2026-09-14 13:19:22 +02:00

44 lines
2.1 KiB
Python

import importlib.util
import json
from pathlib import Path
from types import SimpleNamespace
import unittest
spec = importlib.util.spec_from_file_location('observe', Path(__file__).resolve().parents[1]/'tools/observe_host_clock.py')
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
class ObservationTests(unittest.TestCase):
def response(self, code=0, text='NTPSynchronized=yes\n'):
return SimpleNamespace(returncode=0, stdout=json.dumps({'commands': {'clock': {'returncode':code,'stdout':text}}}))
def test_reported_sync_is_not_accuracy_or_authority(self):
result=module.observe('railiance01', runner=lambda *a, **k:self.response())
self.assertTrue(result['synchronized_reported'])
self.assertIsNone(result['authority_usable'])
def test_failed_clock_command_remains_unknown(self):
result=module.observe('railiance01',runner=lambda *a, **k:self.response(1))
self.assertIsNone(result['synchronized_reported'])
def test_missing_sync_property_remains_unknown(self):
result=module.observe('railiance01',runner=lambda *a, **k:self.response(0, ''))
self.assertIsNone(result['synchronized_reported'])
def test_ssh_failure_refuses_success_without_echoing_stderr(self):
with self.assertRaisesRegex(ValueError,'SSH inventory failed'):
module.observe('railiance01',runner=lambda *a, **k:SimpleNamespace(returncode=255,stderr='not-for-evidence'))
def test_host_cannot_inject_options_or_shell(self):
for host in ['-oProxyCommand=bad','host;bad','host bad','$(bad)']:
with self.subTest(host=host), self.assertRaises(ValueError):
module.observe(host,runner=lambda *a, **k:self.fail('network called'))
def test_transport_uses_fixed_read_only_script(self):
def run(argv, **kwargs):
self.assertEqual(argv[-2:], ['railiance01','python3 -'])
self.assertEqual(kwargs['input'],module.REMOTE)
self.assertNotIn('shell',kwargs)
return self.response()
module.observe('railiance01',runner=run)