import unittest
from pathlib import Path

from policyfaultbench.models import PolicyDecision
from policyfaultbench.oracles import evaluate_oracle
from policyfaultbench.scenarios import load_scenarios


ROOT = Path(__file__).resolve().parents[1]


class RevisedOracleTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.denied = next(
            item
            for item in load_scenarios(ROOT / "scenarios/core_40.json")
            if item.expected_decision == "deny"
        )
        cls.allowed = next(
            item
            for item in load_scenarios(ROOT / "scenarios/core_40.json")
            if item.expected_decision == "allow"
        )

    def test_unexpected_allow_is_containment_failure_even_without_state_change(self):
        result = evaluate_oracle(
            self.denied,
            PolicyDecision(effect="allow", rule_id="mutant", reason="test"),
            state_before="same",
            state_after="same",
            expected_state_after="same",
        )
        self.assertTrue(result.containment_failure)
        self.assertFalse(result.passed)

    def test_post_denial_state_change_is_containment_failure_even_with_deny(self):
        result = evaluate_oracle(
            self.denied,
            PolicyDecision(effect="deny", rule_id="deny", reason="test"),
            state_before="before",
            state_after="after",
            expected_state_after="before",
        )
        self.assertTrue(result.containment_failure)
        self.assertFalse(result.transition_verified)
        self.assertFalse(result.passed)

    def test_allowed_transition_must_match_expected_digest(self):
        result = evaluate_oracle(
            self.allowed,
            PolicyDecision(effect="allow", rule_id="allow", reason="test"),
            state_before="before",
            state_after="unexpected",
            expected_state_after="expected",
        )
        self.assertFalse(result.transition_verified)
        self.assertFalse(result.passed)


if __name__ == "__main__":
    unittest.main()
