# Author: Sandeep Belgavi import tempfile import unittest from pathlib import Path from pattern_09 import ApprovalStore, ProposalAdapter, demo class ApprovalTests(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory(); self.path = Path(self.tmp.name) / 'state.db' self.store = ApprovalStore(self.path); self.action = ProposalAdapter().propose() self.store.request('a', self.action, 'v1', 'reviewer', 20) def tearDown(self): self.store.close(); self.tmp.cleanup() def approve(self): return self.store.decide('a', 'reviewer', self.action, 'v1', 10) def test_wrong_identity(self): with self.assertRaises(PermissionError): self.store.decide('a', 'attacker', self.action, 'v1', 10) def test_changed_action(self): with self.assertRaises(ValueError): self.store.decide('a', 'reviewer', dict(self.action, target='other'), 'v1', 10) def test_stale_revision(self): with self.assertRaises(ValueError): self.store.decide('a', 'reviewer', self.action, 'v2', 10) def test_expiry(self): with self.assertRaises(ValueError): self.store.decide('a', 'reviewer', self.action, 'v1', 20) def test_single_consumption(self): self.approve(); self.store.consume('a', self.action, 'v1', 11) with self.assertRaises(PermissionError): self.store.consume('a', self.action, 'v1', 12) def test_rejection(self): self.store.decide('a', 'reviewer', self.action, 'v1', 10, False) with self.assertRaises(PermissionError): self.store.consume('a', self.action, 'v1', 11) def test_pending_restart(self): self.store.close(); self.store = ApprovalStore(self.path) self.assertEqual(self.approve(), 'approved') def test_expiry_after_approval(self): self.approve() with self.assertRaises(PermissionError): self.store.consume('a', self.action, 'v1', 20) def test_duplicate_decision(self): self.approve() with self.assertRaises(ValueError): self.approve() def test_demo(self): self.assertEqual(demo()['dispatch'], 'local-marker') if __name__ == '__main__': unittest.main()