rb125 commited on
Commit
ba9966d
·
1 Parent(s): 9ee3a0c

added tests covering core and gate

Browse files
Files changed (3) hide show
  1. tests/__init__.py +0 -0
  2. tests/test_core.py +157 -0
  3. tests/test_gate.py +73 -0
tests/__init__.py ADDED
File without changes
tests/test_core.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Tests for registry, contracts, and economy."""
2
+
3
+ import pytest
4
+ from cgae_engine.gate import RobustnessVector, Tier, GateFunction
5
+ from cgae_engine.registry import AgentRegistry, AgentStatus
6
+ from cgae_engine.contracts import ContractManager, ContractStatus, Constraint
7
+ from cgae_engine.economy import Economy, EconomyConfig
8
+ from cgae_engine.temporal import TemporalDecay
9
+
10
+
11
+ class TestRegistry:
12
+ def setup_method(self):
13
+ self.registry = AgentRegistry()
14
+
15
+ def test_register_agent(self):
16
+ record = self.registry.register("test-model", {"model": "test"}, initial_balance=1.0)
17
+ assert record.status == AgentStatus.PENDING
18
+ assert record.balance == 1.0
19
+ assert record.model_name == "test-model"
20
+
21
+ def test_certify_activates_agent(self):
22
+ record = self.registry.register("m", {})
23
+ r = RobustnessVector(cc=0.7, er=0.7, as_=0.6, ih=0.8)
24
+ self.registry.certify(record.agent_id, r)
25
+ assert record.status == AgentStatus.ACTIVE
26
+ assert record.current_tier.value >= 1
27
+
28
+ def test_low_ih_suspends(self):
29
+ record = self.registry.register("m", {})
30
+ r = RobustnessVector(cc=0.9, er=0.9, as_=0.9, ih=0.3)
31
+ self.registry.certify(record.agent_id, r)
32
+ assert record.status == AgentStatus.SUSPENDED
33
+
34
+ def test_demote(self):
35
+ record = self.registry.register("m", {})
36
+ r_high = RobustnessVector(cc=0.8, er=0.8, as_=0.7, ih=0.9)
37
+ self.registry.certify(record.agent_id, r_high)
38
+ old_tier = record.current_tier
39
+
40
+ r_low = RobustnessVector(cc=0.3, er=0.3, as_=0.3, ih=0.6)
41
+ new_tier = self.registry.demote(record.agent_id, r_low)
42
+ assert new_tier < old_tier
43
+
44
+ def test_tier_distribution(self):
45
+ for i in range(5):
46
+ rec = self.registry.register(f"m{i}", {})
47
+ r = RobustnessVector(cc=0.5, er=0.5, as_=0.5, ih=0.7)
48
+ self.registry.certify(rec.agent_id, r)
49
+ dist = self.registry.tier_distribution()
50
+ assert sum(dist.values()) == 5
51
+
52
+
53
+ class TestContracts:
54
+ def setup_method(self):
55
+ self.cm = ContractManager()
56
+
57
+ def test_create_contract(self):
58
+ c = self.cm.create_contract(
59
+ "test", [Constraint("c1", "test", lambda x: True)],
60
+ Tier.T1, reward=0.1, penalty=0.05, issuer_id="sys", deadline=100.0,
61
+ )
62
+ assert c.status == ContractStatus.OPEN
63
+ assert c.reward == 0.1
64
+
65
+ def test_assign_enforces_tier(self):
66
+ c = self.cm.create_contract(
67
+ "test", [], Tier.T3, reward=0.1, penalty=0.05, issuer_id="sys", deadline=100.0,
68
+ )
69
+ # T1 agent can't accept T3 contract
70
+ ok = self.cm.assign_contract(c.contract_id, "agent1", Tier.T1)
71
+ assert ok is False
72
+
73
+ def test_assign_enforces_budget_ceiling(self):
74
+ # Create many contracts to exceed T1 budget ceiling (0.01)
75
+ c = self.cm.create_contract(
76
+ "test", [], Tier.T1, reward=0.1, penalty=0.02, issuer_id="sys", deadline=100.0,
77
+ )
78
+ ok = self.cm.assign_contract(c.contract_id, "agent1", Tier.T1)
79
+ assert ok is False # penalty 0.02 > T1 ceiling 0.01
80
+
81
+ def test_settle_success(self):
82
+ c = self.cm.create_contract(
83
+ "test", [Constraint("c1", "test", lambda x: True)],
84
+ Tier.T1, reward=0.01, penalty=0.005, issuer_id="sys", deadline=100.0,
85
+ )
86
+ self.cm.assign_contract(c.contract_id, "agent1", Tier.T2)
87
+ self.cm.submit_output(c.contract_id, "output")
88
+ settlement = self.cm.settle_contract(c.contract_id)
89
+ assert settlement["outcome"] == "success"
90
+
91
+ def test_settle_failure(self):
92
+ c = self.cm.create_contract(
93
+ "test", [Constraint("c1", "test", lambda x: False)],
94
+ Tier.T1, reward=0.01, penalty=0.005, issuer_id="sys", deadline=100.0,
95
+ )
96
+ self.cm.assign_contract(c.contract_id, "agent1", Tier.T2)
97
+ self.cm.submit_output(c.contract_id, "output")
98
+ settlement = self.cm.settle_contract(c.contract_id)
99
+ assert settlement["outcome"] == "failure"
100
+
101
+
102
+ class TestEconomy:
103
+ def setup_method(self):
104
+ self.econ = Economy(config=EconomyConfig(initial_balance=0.5))
105
+
106
+ def test_register_and_audit(self):
107
+ record = self.econ.register_agent("test", {"model": "test"})
108
+ assert record.balance == 0.5
109
+ r = RobustnessVector(cc=0.7, er=0.7, as_=0.6, ih=0.8)
110
+ self.econ.audit_agent(record.agent_id, r)
111
+ assert record.current_tier.value >= 1
112
+ assert record.balance < 0.5 # audit cost deducted
113
+
114
+ def test_full_contract_lifecycle(self):
115
+ record = self.econ.register_agent("test", {"model": "test"})
116
+ r = RobustnessVector(cc=0.7, er=0.7, as_=0.6, ih=0.8)
117
+ self.econ.audit_agent(record.agent_id, r)
118
+
119
+ contract = self.econ.post_contract(
120
+ "do something", [Constraint("c", "test", lambda x: True)],
121
+ min_tier=Tier.T1, reward=0.05, penalty=0.01,
122
+ )
123
+ ok = self.econ.accept_contract(contract.contract_id, record.agent_id)
124
+ assert ok is True
125
+
126
+ settlement = self.econ.complete_contract(contract.contract_id, "output")
127
+ assert settlement["outcome"] == "success"
128
+ assert record.contracts_completed == 1
129
+
130
+ def test_aggregate_safety(self):
131
+ record = self.econ.register_agent("test", {"model": "test"})
132
+ r = RobustnessVector(cc=0.7, er=0.7, as_=0.6, ih=0.8)
133
+ self.econ.audit_agent(record.agent_id, r)
134
+ safety = self.econ.aggregate_safety()
135
+ assert 0.0 <= safety <= 1.0
136
+
137
+
138
+ class TestTemporalDecay:
139
+ def test_no_decay_at_zero(self):
140
+ decay = TemporalDecay(decay_rate=0.01)
141
+ r = RobustnessVector(cc=0.8, er=0.7, as_=0.6, ih=0.9)
142
+ r_eff = decay.effective_robustness(r, 0)
143
+ assert r_eff.cc == r.cc
144
+
145
+ def test_decay_reduces_scores(self):
146
+ decay = TemporalDecay(decay_rate=0.01)
147
+ r = RobustnessVector(cc=0.8, er=0.7, as_=0.6, ih=0.9)
148
+ r_eff = decay.effective_robustness(r, 50)
149
+ assert r_eff.cc < r.cc
150
+ assert r_eff.er < r.er
151
+
152
+ def test_decay_stays_in_bounds(self):
153
+ decay = TemporalDecay(decay_rate=0.1)
154
+ r = RobustnessVector(cc=0.5, er=0.5, as_=0.5, ih=0.5)
155
+ r_eff = decay.effective_robustness(r, 1000)
156
+ assert r_eff.cc >= 0.0
157
+ assert r_eff.cc <= 1.0
tests/test_gate.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Tests for the CGAE core engine."""
2
+
3
+ import pytest
4
+ from cgae_engine.gate import GateFunction, RobustnessVector, Tier, TierThresholds
5
+
6
+
7
+ class TestRobustnessVector:
8
+ def test_valid_vector(self):
9
+ r = RobustnessVector(cc=0.5, er=0.6, as_=0.7, ih=0.8)
10
+ assert r.cc == 0.5
11
+ assert r.weakest == 0.5
12
+
13
+ def test_out_of_range_raises(self):
14
+ with pytest.raises(ValueError):
15
+ RobustnessVector(cc=1.5, er=0.5, as_=0.5, ih=0.5)
16
+
17
+ def test_primary_dimensions(self):
18
+ r = RobustnessVector(cc=0.3, er=0.5, as_=0.4, ih=0.9)
19
+ assert r.primary == (0.3, 0.5, 0.4)
20
+ assert r.weakest == 0.3
21
+
22
+
23
+ class TestGateFunction:
24
+ def setup_method(self):
25
+ self.gate = GateFunction()
26
+
27
+ def test_zero_robustness_gives_t0(self):
28
+ r = RobustnessVector(cc=0.0, er=0.0, as_=0.0, ih=0.0)
29
+ assert self.gate.evaluate(r) == Tier.T0
30
+
31
+ def test_low_ih_forces_t0(self):
32
+ r = RobustnessVector(cc=0.9, er=0.9, as_=0.9, ih=0.3)
33
+ assert self.gate.evaluate(r) == Tier.T0
34
+
35
+ def test_weakest_link(self):
36
+ # High CC and ER but low AS should be gated by AS
37
+ r = RobustnessVector(cc=0.9, er=0.9, as_=0.3, ih=0.9)
38
+ tier = self.gate.evaluate(r)
39
+ assert tier == Tier.T1 # AS=0.3 >= 0.25 (T1 threshold)
40
+
41
+ def test_t5_requires_all_high(self):
42
+ r = RobustnessVector(cc=0.95, er=0.95, as_=0.90, ih=0.95)
43
+ assert self.gate.evaluate(r) == Tier.T5
44
+
45
+ def test_evaluate_with_detail(self):
46
+ r = RobustnessVector(cc=0.72, er=0.68, as_=0.55, ih=0.82)
47
+ d = self.gate.evaluate_with_detail(r)
48
+ assert "tier" in d
49
+ assert "binding_dimension" in d
50
+ assert d["ih_pass"] is True
51
+
52
+ def test_chain_tier(self):
53
+ r1 = RobustnessVector(cc=0.9, er=0.9, as_=0.9, ih=0.9)
54
+ r2 = RobustnessVector(cc=0.4, er=0.4, as_=0.3, ih=0.6)
55
+ chain = self.gate.chain_tier([r1, r2])
56
+ assert chain <= self.gate.evaluate(r1)
57
+ assert chain == self.gate.evaluate(r2)
58
+
59
+ def test_budget_ceiling_increases_with_tier(self):
60
+ ceilings = [self.gate.budget_ceiling(Tier(i)) for i in range(6)]
61
+ for i in range(1, 6):
62
+ assert ceilings[i] > ceilings[i - 1]
63
+
64
+
65
+ class TestTierThresholds:
66
+ def test_default_thresholds_valid(self):
67
+ t = TierThresholds()
68
+ assert len(t.cc) == 6
69
+ assert t.cc[0] == 0.0
70
+
71
+ def test_non_increasing_raises(self):
72
+ with pytest.raises(ValueError):
73
+ TierThresholds(cc=[0.0, 0.5, 0.4, 0.6, 0.8, 0.9])