Cai
10 days ago 8ba0fed3892bdf175cc7ae5279cc95f344316e3f
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
from __future__ import annotations
 
from pathlib import Path
from datetime import datetime, timezone
import tempfile
import unittest
 
from hibor_fast_collection.budget import Budget, BudgetExpired
from hibor_fast_collection.models import (
    ContractError, ErrorCode, EvidenceState, PackageState, TaskSpec, TerminalReceipt,
)
from helpers import task_spec
 
 
class FakeClock:
    def __init__(self): self.value = 0.0
    def __call__(self): return self.value
 
 
class ModelsBudgetTests(unittest.TestCase):
    def test_task_spec_exact_and_batch_budget(self):
        with tempfile.TemporaryDirectory() as tmp:
            spec = TaskSpec.from_mapping(task_spec(Path(tmp), quantity=3))
            self.assertEqual(spec.total_budget_ms, 1_080_000)
            bad = task_spec(Path(tmp))
            bad["package_name"] = "other"
            with self.assertRaises(ContractError): TaskSpec.from_mapping(bad)
 
    def test_key_order_rejected(self):
        with tempfile.TemporaryDirectory() as tmp:
            value = task_spec(Path(tmp))
            first = value.pop("schema_version")
            value["schema_version"] = first
            with self.assertRaises(ContractError): TaskSpec.from_mapping(value)
 
    def test_budget_work_and_close_deadline(self):
        clock = FakeClock()
        budget = Budget(10_000, 2_000, clock=clock)
        self.assertEqual(budget.require("x", "y", 9_000), 8_000)
        clock.value = 8.001
        with self.assertRaises(BudgetExpired): budget.require("x", "y", 1_000)
        self.assertGreater(budget.require("close", "z", 1_000, close=True), 0)
        clock.value = 10.1
        with self.assertRaises(BudgetExpired): budget.require("close", "z", 1_000, close=True)
 
    def test_observed_deadline_and_batch_increment(self):
        fresh_clock = FakeClock()
        fresh = Budget(840_000, 30_000, batch_increment_ms=240_000,
                       clock=fresh_clock)
        fresh.begin_item(1)
        self.assertEqual((fresh.remaining_ms(), fresh.remaining_ms(close=True),
                          fresh.remaining_ms(batch_close=True)),
                         (570_000, 600_000, 840_000))
 
        clock = FakeClock()
        wall = lambda: datetime(2026, 7, 29, 0, 5, tzinfo=timezone.utc)
        budget = Budget(840_000, 30_000, observed_at_utc="2026-07-29T00:00:00Z",
                        batch_increment_ms=240_000, clock=clock, utc_now=wall)
        budget.begin_item(1)
        self.assertEqual(budget.remaining_ms(), 270_000)
        self.assertEqual(budget.remaining_ms(close=True), 300_000)
        self.assertEqual(budget.remaining_ms(batch_close=True), 540_000)
        with self.assertRaises(ValueError):
            budget.begin_item(2)
        clock.value = 299.0
        self.assertTrue(budget.complete_item(1))
        budget.begin_item(2)
        self.assertEqual(budget.remaining_ms(), 210_000)
        self.assertEqual(budget.remaining_ms(close=True), 240_000)
        clock.value = 509.1
        with self.assertRaises(BudgetExpired): budget.checkpoint("item_2", "terminal")
        self.assertGreater(budget.remaining_ms(close=True), 0)
        clock.value = 539.1
        self.assertFalse(budget.complete_item(2))
 
    def test_terminal_receipt_cross_fields(self):
        target = Path("terminal.json")
        valid = TerminalReceipt(target, target, True, True, EvidenceState.V, True, False, True,
                                10, "a"*64, None, PackageState.P09_TIMING)
        valid.validate()
        file_u = TerminalReceipt(target, None, True, None, EvidenceState.U, True, False, True,
                                 None, None, ErrorCode.RECOVERY_UNKNOWN, PackageState.P09_TIMING)
        file_u.validate()
        live_u = TerminalReceipt(target, None, True, None, EvidenceState.U, None, True, True,
                                 None, None, ErrorCode.PROCESS_LIVENESS_UNKNOWN, PackageState.P09_TIMING)
        live_u.validate()
        with self.assertRaises(ContractError):
            TerminalReceipt(target, None, False, False, EvidenceState.U, False, False, True,
                            None, None, ErrorCode.RECOVERY_UNKNOWN, PackageState.P09_TIMING).validate()
 
 
if __name__ == "__main__": unittest.main()