Some checks failed
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a1468b-63fa-7710-85dc-8f2e16b3ebfa
231 lines
12 KiB
Python
231 lines
12 KiB
Python
"""Binding, CAS and ambiguous-commit refusal tests; native SQL proof is separate."""
|
|
from dataclasses import replace
|
|
import json
|
|
from unittest.mock import Mock
|
|
import unittest
|
|
|
|
from group_provenance import GroupProvenanceUnavailable
|
|
from group_provenance_postgres import GroupJournalBinding, PostgresGroupProvenance
|
|
from server import configured_group_provenance
|
|
from unittest.mock import patch
|
|
import os
|
|
|
|
EPOCH = '41fbb0ed-ea3a-4682-996b-e9c94a6aa9c6'
|
|
BINDING = GroupJournalBinding('tenant:fixture:one', 'synthetic-directory', 'sha256:' + '1' * 64,
|
|
'sha256:' + '2' * 64, 'synthetic-owner', EPOCH)
|
|
REQUEST = '3' * 64
|
|
HEAD_DIGEST = 'a' * 64
|
|
META = (EPOCH, 'synthetic-directory', 7, HEAD_DIGEST, False)
|
|
|
|
|
|
def fixture(rows=(), rowcount=1, commit_error=None):
|
|
cursor = Mock()
|
|
cursor.__enter__ = Mock(return_value=cursor)
|
|
cursor.__exit__ = Mock(return_value=False)
|
|
cursor.fetchone.side_effect = rows
|
|
cursor.rowcount = rowcount
|
|
connection = Mock()
|
|
connection.__enter__ = Mock(return_value=connection)
|
|
connection.__exit__ = Mock(return_value=False, side_effect=commit_error)
|
|
connection.cursor.return_value = cursor
|
|
connector = Mock(return_value=connection)
|
|
continuity = Mock()
|
|
continuity.check.return_value = True
|
|
continuity.advance.return_value = True
|
|
store = PostgresGroupProvenance(connect=connector, binding=BINDING, continuity=continuity)
|
|
return store, connector, connection, cursor, continuity
|
|
|
|
|
|
def receipt(version=4):
|
|
return {'key': 'synthetic-operation-key', 'binding': REQUEST, 'state': 'pending', 'intent': None,
|
|
'groups': {}, 'created_groups': [], 'created_memberships': [],
|
|
'_pg_version': version, '_pg_context': BINDING.digest}
|
|
|
|
|
|
class PostgresSourceTests(unittest.TestCase):
|
|
def test_explicit_binding_and_continuity_required_without_connecting(self):
|
|
connector = Mock()
|
|
for binding, continuity in ((None, Mock()), (BINDING, None), ({'tenant_scope': 'caller-json'}, Mock())):
|
|
with self.assertRaises(ValueError):
|
|
PostgresGroupProvenance(connect=connector, binding=binding, continuity=continuity)
|
|
connector.assert_not_called()
|
|
for change in ({'tenant_scope': ''}, {'principal': ''}, {'case_digest': 'unsigned'}, {'epoch': 'default'}):
|
|
with self.assertRaises(ValueError):
|
|
replace(BINDING, **change)
|
|
self.assertNotEqual(BINDING.digest, replace(BINDING, principal='another-owner').digest)
|
|
self.assertNotEqual(BINDING.digest, replace(BINDING, tenant_scope='another-explicit-scope').digest)
|
|
|
|
def test_missing_environment_callback_path_keeps_production_disabled(self):
|
|
with patch.dict(os.environ, {'GROUP_POSTGRES_DSN': 'synthetic-only', 'GROUP_PROVENANCE_POSTGRES': 'true'}, clear=True):
|
|
self.assertIsNone(configured_group_provenance())
|
|
|
|
def test_checkpoint_mismatch_poisoned_without_receipt_query_or_effect(self):
|
|
store, connect, _, cursor, checkpoint = fixture([META])
|
|
checkpoint.check.return_value = False
|
|
with self.assertRaises(GroupProvenanceUnavailable):
|
|
store.reserve('synthetic-operation-key', REQUEST)
|
|
self.assertFalse(any('group_receipts' in c.args[0] for c in cursor.execute.call_args_list))
|
|
with self.assertRaises(GroupProvenanceUnavailable):
|
|
store.check()
|
|
self.assertEqual(1, connect.call_count)
|
|
checkpoint.advance.assert_not_called()
|
|
|
|
def test_restored_epoch_or_quarantine_refused(self):
|
|
for meta in ((EPOCH, 'other-directory', 7, HEAD_DIGEST, False), (EPOCH, 'synthetic-directory', 7, HEAD_DIGEST, True),
|
|
('98aa2b6d-a32a-44a5-a89f-b2480befc00e', 'synthetic-directory', 7, HEAD_DIGEST, False), None):
|
|
store, _, _, _, checkpoint = fixture([meta])
|
|
with self.assertRaises(GroupProvenanceUnavailable):
|
|
store.check()
|
|
checkpoint.check.assert_not_called()
|
|
|
|
def test_exactly_one_version_update_required_before_checkpoint_advance(self):
|
|
store, _, _, cursor, checkpoint = fixture([META], rowcount=0)
|
|
original = receipt()
|
|
with self.assertRaises(GroupProvenanceUnavailable):
|
|
store.save(original)
|
|
query, params = next(c.args for c in cursor.execute.call_args_list if c.args[0].startswith('UPDATE identity_provisioner.group_receipts'))
|
|
self.assertIn('AND version = %s', query)
|
|
self.assertEqual(4, params[-1])
|
|
self.assertEqual(4, original['_pg_version'])
|
|
checkpoint.advance.assert_not_called()
|
|
|
|
def test_success_acknowledges_commit_and_updates_receipt_version(self):
|
|
store, _, connection, _, checkpoint = fixture([META])
|
|
original = receipt()
|
|
store.save(original)
|
|
self.assertEqual(5, original['_pg_version'])
|
|
connection.__exit__.assert_called_once()
|
|
args = checkpoint.advance.call_args.args
|
|
self.assertEqual((EPOCH, 'synthetic-directory', 7, HEAD_DIGEST, 8), args[:5])
|
|
self.assertRegex(args[5], r'^[0-9a-f]{64}$')
|
|
self.assertNotEqual(HEAD_DIGEST, args[5])
|
|
connection.close.assert_called_once()
|
|
|
|
def test_save_preserves_nested_receipt_references_held_by_provisioner(self):
|
|
store, *_ = fixture([META])
|
|
original = receipt()
|
|
original['groups']['forge-coulomb-owners'] = {'id': None, 'before': [], 'after': ['tegwick']}
|
|
state = original['groups']['forge-coulomb-owners']
|
|
groups, created, memberships = original['groups'], original['created_groups'], original['created_memberships']
|
|
original['intent'] = {'operation': 'create_group', 'name': 'forge-coulomb-owners'}
|
|
store.save(original)
|
|
self.assertIs(groups, original['groups'])
|
|
self.assertIs(state, original['groups']['forge-coulomb-owners'])
|
|
self.assertIs(created, original['created_groups'])
|
|
self.assertIs(memberships, original['created_memberships'])
|
|
state['id'] = 4
|
|
self.assertEqual(4, original['groups']['forge-coulomb-owners']['id'])
|
|
self.assertEqual(5, original['_pg_version'])
|
|
|
|
def test_actual_provisioner_ensure_with_postgres_save_retains_created_ids(self):
|
|
from test_service_groups import Directory, req
|
|
directory = Directory()
|
|
directory.members[3].add('tegwick')
|
|
store, _, _, cursor, _ = fixture([META] * 32)
|
|
original = receipt(version=1)
|
|
payload = req()
|
|
original['key'] = payload['idempotency_key']
|
|
original['binding'] = directory._group_binding(payload['groups'], payload['members'], payload['correlation_id'])
|
|
# Reservation input is already covered by SQL unit/native oracles. Keep
|
|
# real save/_write/transaction and the real provisioner creation path.
|
|
store.reserve = Mock(return_value=(original, True))
|
|
directory.group_provenance = store
|
|
result = directory.ensure_service_groups(payload)
|
|
self.assertEqual('groups_ensured', result.status)
|
|
self.assertEqual({'forge-coulomb-owners', 'forge-coulomb-readers'}, {g['name'] for g in result.created_groups})
|
|
self.assertEqual(1, len(result.created_memberships))
|
|
self.assertEqual({'tegwick'}, directory.members[3])
|
|
bodies = [json.loads(c.args[1][2]) for c in cursor.execute.call_args_list
|
|
if c.args[0].startswith('UPDATE identity_provisioner.group_receipts')]
|
|
self.assertTrue(all(g['id'] is not None for g in bodies[-1]['groups'].values()))
|
|
self.assertEqual('ensured', bodies[-1]['state'])
|
|
|
|
def test_connection_close_failure_is_sanitized_and_stops_continuation(self):
|
|
store, _, connection, _, _ = fixture([META])
|
|
connection.close.side_effect = OSError('synthetic-private-diagnostic')
|
|
with self.assertRaisesRegex(GroupProvenanceUnavailable, '^group_provenance_unavailable$'):
|
|
store.check()
|
|
self.assertTrue(store._poisoned)
|
|
|
|
def test_commit_failure_never_advances_owner_checkpoint_or_receipt(self):
|
|
store, _, _, _, checkpoint = fixture([META], commit_error=OSError('synthetic-secret-diagnostic'))
|
|
original = receipt()
|
|
with self.assertRaisesRegex(GroupProvenanceUnavailable, '^group_provenance_unavailable$'):
|
|
store.save(original)
|
|
self.assertEqual(4, original['_pg_version'])
|
|
checkpoint.advance.assert_not_called()
|
|
|
|
def test_lost_checkpoint_acknowledgment_refuses_then_poisoned(self):
|
|
store, connect, _, _, checkpoint = fixture([META])
|
|
checkpoint.advance.side_effect = OSError('synthetic-secret-diagnostic')
|
|
original = receipt()
|
|
with self.assertRaisesRegex(GroupProvenanceUnavailable, '^group_provenance_unavailable$'):
|
|
store.save(original)
|
|
self.assertEqual(4, original['_pg_version'])
|
|
with self.assertRaises(GroupProvenanceUnavailable):
|
|
store.save(original)
|
|
self.assertEqual(1, connect.call_count)
|
|
|
|
def test_cross_case_body_or_version_cannot_be_imported(self):
|
|
for body in (dict(receipt(), _pg_context='0' * 64), dict(receipt(), _pg_version=6)):
|
|
store, _, _, _, _ = fixture([META, (REQUEST, 4, json.dumps(body), json.dumps(BINDING.__dict__, sort_keys=True))])
|
|
with self.assertRaises(GroupProvenanceUnavailable):
|
|
store.get('synthetic-operation-key', REQUEST)
|
|
|
|
def test_same_counter_divergent_body_or_context_yields_distinct_marker(self):
|
|
store, *_ = fixture()
|
|
markers = []
|
|
for change in ({}, {'intent': {'operation': 'different'}}, {'key': 'another-exact-key'}, {'_pg_version': 5}):
|
|
tx = {'head': 7, 'digest': HEAD_DIGEST}
|
|
store._transition(tx, dict(receipt(), **change), 'save')
|
|
markers.append(tx['next_digest'])
|
|
self.assertEqual(4, len(set(markers)))
|
|
tx = {'head': 7, 'digest': 'b' * 64}
|
|
store._transition(tx, receipt(), 'save')
|
|
self.assertNotIn(tx['next_digest'], markers)
|
|
foreign, *_ = fixture()
|
|
foreign.binding = replace(BINDING, principal='another-owner')
|
|
tx = {'head': 7, 'digest': HEAD_DIGEST}
|
|
foreign._transition(tx, receipt(), 'save')
|
|
self.assertNotIn(tx['next_digest'], markers)
|
|
|
|
def test_reopened_loser_clone_at_same_head_refuses_different_marker(self):
|
|
# Both DBs report head8. The independent callback accepts only winner
|
|
# digest; loser must be refused before loading any receipt or effect.
|
|
loser_digest = 'b' * 64
|
|
store, _, _, cursor, checkpoint = fixture([(EPOCH, 'synthetic-directory', 8, loser_digest, False)])
|
|
checkpoint.check.side_effect = lambda epoch, directory, head, digest: (head, digest) == (8, 'c' * 64)
|
|
with self.assertRaises(GroupProvenanceUnavailable):
|
|
store.check()
|
|
checkpoint.check.assert_called_once_with(EPOCH, 'synthetic-directory', 8, loser_digest)
|
|
self.assertFalse(any('group_receipts' in c.args[0] for c in cursor.execute.call_args_list))
|
|
|
|
def test_existing_request_mismatch_is_refused_not_rebound(self):
|
|
store, _, _, _, checkpoint = fixture([META, ('0' * 64, 4, '{}', '{}')])
|
|
with self.assertRaisesRegex(ValueError, 'binding mismatch'):
|
|
store.get('synthetic-operation-key', REQUEST)
|
|
checkpoint.advance.assert_not_called()
|
|
self.assertFalse(store._poisoned)
|
|
|
|
def test_active_fence_capacity_refusal_and_no_insert(self):
|
|
for rows in ([META, None, (1,)], [META, None, None, (256,)]):
|
|
store, _, _, cursor, checkpoint = fixture(rows)
|
|
with self.assertRaises(GroupProvenanceUnavailable):
|
|
store.reserve('synthetic-operation-key', REQUEST)
|
|
self.assertFalse(any('INSERT' in c.args[0] for c in cursor.execute.call_args_list))
|
|
checkpoint.advance.assert_not_called()
|
|
|
|
def test_new_reservation_retains_bound_context_and_write_intent(self):
|
|
store, _, _, cursor, checkpoint = fixture([META, None, None, (0,)])
|
|
created, fresh = store.reserve('synthetic-operation-key', REQUEST)
|
|
self.assertTrue(fresh)
|
|
self.assertEqual('pending', created['state'])
|
|
self.assertEqual(BINDING.digest, created['_pg_context'])
|
|
insert = next(c for c in cursor.execute.call_args_list if c.args[0].startswith('INSERT'))
|
|
self.assertIn('context_json', insert.args[0])
|
|
self.assertEqual(BINDING.tenant_scope, json.loads(insert.args[1][1])['tenant_scope'])
|
|
checkpoint.advance.assert_called_once()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|