import importlib.util import json from pathlib import Path import unittest spec = importlib.util.spec_from_file_location('timing', Path(__file__).parents[1] / 'platform_timing_summary.py') timing = importlib.util.module_from_spec(spec) spec.loader.exec_module(timing) class EvidenceTests(unittest.TestCase): def evidence(self, suspend=0): records = [] for phase in ('start', 'end'): for path, value in [('/proc/sys/kernel/osrelease', 'candidate'), ('/proc/sys/kernel/random/boot_id', 'same-boot'), ('/sys/devices/system/clocksource/clocksource0/current_clocksource', 'tsc')]: records.append(dict(kind='metadata', phase=phase, path=path, value=value, errno=0)) records.extend([ dict(kind='sample', index=0, before_ns=100, after_ns=102, end_ns=106, mono_ns=103), dict(kind='sample', index=1, before_ns=200+suspend, after_ns=202+suspend, end_ns=206+suspend, mono_ns=203), dict(kind='complete', qualified=False)]) return records def run_summary(self, records): return timing.summarize('\n'.join('TIMING ' + json.dumps(r) for r in records)) def test_suspend_interval_not_point_or_accuracy_claim(self): result = self.run_summary(self.evidence(5000)) self.assertEqual(result['suspend_offset_change_interval_ns'], [4996, 5004]) self.assertFalse(result['qualified']) self.assertIsNone(result['max_elapsed_error_ppb']) def test_reject_truncated_evidence(self): with self.assertRaises(ValueError): self.run_summary(self.evidence()[:-1]) def test_reject_changed_boot(self): records = self.evidence() records[4]['value'] = 'new-boot' with self.assertRaises(ValueError): self.run_summary(records) def test_reject_regression_and_missing_sample(self): records = self.evidence() records[-2]['before_ns'] = 50 with self.assertRaises(ValueError): self.run_summary(records) records = self.evidence() records[-2]['index'] = 2 with self.assertRaises(ValueError): self.run_summary(records) if __name__ == '__main__': unittest.main()