-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_membrane_phase2.py
More file actions
93 lines (74 loc) · 3.9 KB
/
test_membrane_phase2.py
File metadata and controls
93 lines (74 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# Copyright 2026 Quantum Pipes Technologies, LLC
# SPDX-License-Identifier: Apache-2.0
"""Tests for Membrane Phase 2.
Covers: AdversarialVerifier, source diversity, approval budgets, anomaly detection.
"""
from __future__ import annotations
import pytest
from qp_vault.adversarial import VALID_TRANSITIONS, AdversarialVerifier
from qp_vault.enums import AdversarialStatus
# =============================================================================
# ADVERSARIAL VERIFIER TESTS
# =============================================================================
class TestAdversarialVerifier:
"""AdversarialVerifier: manage adversarial_status transitions."""
@pytest.fixture
def verifier(self):
return AdversarialVerifier()
@pytest.mark.asyncio
async def test_default_status_is_unverified(self, verifier):
status = await verifier.get_status("r1")
assert status == AdversarialStatus.UNVERIFIED
@pytest.mark.asyncio
async def test_transition_unverified_to_verified(self, verifier):
result = await verifier.set_status("r1", AdversarialStatus.VERIFIED, reason="Membrane passed")
assert result == AdversarialStatus.VERIFIED
assert await verifier.get_status("r1") == AdversarialStatus.VERIFIED
@pytest.mark.asyncio
async def test_transition_unverified_to_suspicious(self, verifier):
result = await verifier.set_status("r1", AdversarialStatus.SUSPICIOUS, reason="Flagged")
assert result == AdversarialStatus.SUSPICIOUS
@pytest.mark.asyncio
async def test_transition_suspicious_to_verified(self, verifier):
await verifier.set_status("r1", AdversarialStatus.SUSPICIOUS)
result = await verifier.set_status("r1", AdversarialStatus.VERIFIED, reason="Human cleared")
assert result == AdversarialStatus.VERIFIED
@pytest.mark.asyncio
async def test_transition_verified_to_suspicious(self, verifier):
await verifier.set_status("r1", AdversarialStatus.VERIFIED)
result = await verifier.set_status("r1", AdversarialStatus.SUSPICIOUS, reason="Re-assessed")
assert result == AdversarialStatus.SUSPICIOUS
@pytest.mark.asyncio
async def test_invalid_transition_raises(self, verifier):
await verifier.set_status("r1", AdversarialStatus.VERIFIED)
with pytest.raises(ValueError, match="Invalid transition"):
await verifier.set_status("r1", AdversarialStatus.UNVERIFIED)
@pytest.mark.asyncio
async def test_bulk_reassess(self, verifier):
await verifier.set_status("r1", AdversarialStatus.VERIFIED)
await verifier.set_status("r2", AdversarialStatus.VERIFIED)
results = await verifier.bulk_reassess(
["r1", "r2"], AdversarialStatus.SUSPICIOUS, reason="Source compromised"
)
assert results["r1"] == AdversarialStatus.SUSPICIOUS
assert results["r2"] == AdversarialStatus.SUSPICIOUS
@pytest.mark.asyncio
async def test_bulk_reassess_skips_invalid(self, verifier):
"""Bulk reassess skips invalid transitions without raising."""
await verifier.set_status("r1", AdversarialStatus.SUSPICIOUS)
# SUSPICIOUS -> UNVERIFIED is invalid
results = await verifier.bulk_reassess(
["r1"], AdversarialStatus.UNVERIFIED, reason="test"
)
assert results["r1"] == AdversarialStatus.SUSPICIOUS # unchanged
@pytest.mark.asyncio
async def test_counts(self, verifier):
await verifier.set_status("r1", AdversarialStatus.VERIFIED)
await verifier.set_status("r2", AdversarialStatus.VERIFIED)
await verifier.set_status("r3", AdversarialStatus.SUSPICIOUS)
assert await verifier.get_verified_count() == 2
assert await verifier.get_suspicious_count() == 1
def test_valid_transitions_complete(self):
"""All statuses have transition rules defined."""
for status in AdversarialStatus:
assert status in VALID_TRANSITIONS