"""Tests for :mod:`mgf.vm.core.security.isolation.checks.host` (MA-A3.2).

3 checks: 1 runtime-only (KSM) + 2 static (CPU pinning, swap).
"""

from __future__ import annotations

from typing import Any

from _isolation_xml import domain_with, parsed

from mgf.vm.core.security.isolation.checks.host import (
    host_cpu_pinning,
    host_ksm_disabled,
    host_swap_disabled,
)
from mgf.vm.core.security.isolation.context import AnalysisContext
from mgf.vm.core.security.isolation.types import IsolationCategory


def _ctx(*body: str, **facts: Any) -> AnalysisContext:
    return AnalysisContext(
        domain_xml=parsed(domain_with(*body)),
        vm_name="t",
        runtime_audit=bool(facts),
        host_facts=dict(facts),
    )


def _ctx_with_root(root_xml: str, **facts: Any) -> AnalysisContext:
    """Build a context using a complete <domain> XML (custom root contents)."""
    import xml.etree.ElementTree as ET

    return AnalysisContext(
        domain_xml=ET.ElementTree(ET.fromstring(root_xml)),
        vm_name="t",
        runtime_audit=bool(facts),
        host_facts=dict(facts),
    )


class TestHostKsmDisabled:
    def test_passes_when_ksm_run_zero(self) -> None:
        f = host_ksm_disabled(_ctx(**{"host.ksm_run": "0"}))
        assert f.passing is True
        assert f.category is IsolationCategory.INFO

    def test_passes_when_unreadable(self) -> None:
        # Empty fact = couldn't determine → treat as disabled (best
        # effort), not as "fail".
        f = host_ksm_disabled(_ctx())
        assert f.passing is True

    def test_fails_when_ksm_run_one(self) -> None:
        f = host_ksm_disabled(_ctx(**{"host.ksm_run": "1"}))
        assert f.passing is False
        assert "side-channel" in f.summary


class TestHostCpuPinning:
    def test_passes_when_vcpu_cpuset(self) -> None:
        xml = "<domain><name>t</name><vcpu cpuset='0-3'>4</vcpu><devices/></domain>"
        f = host_cpu_pinning(_ctx_with_root(xml))
        assert f.passing is True

    def test_passes_when_cputune_vcpupin(self) -> None:
        xml = (
            "<domain><name>t</name><vcpu>4</vcpu>"
            "<cputune>"
            "<vcpupin vcpu='0' cpuset='0'/>"
            "<vcpupin vcpu='1' cpuset='1'/>"
            "</cputune>"
            "<devices/></domain>"
        )
        f = host_cpu_pinning(_ctx_with_root(xml))
        assert f.passing is True

    def test_fails_when_no_pinning(self) -> None:
        xml = "<domain><name>t</name><vcpu>4</vcpu><devices/></domain>"
        f = host_cpu_pinning(_ctx_with_root(xml))
        assert f.passing is False
        assert "side-channel" in f.summary


class TestHostSwapDisabled:
    def test_passes_when_locked(self) -> None:
        xml = "<domain><name>t</name><memoryBacking><locked/></memoryBacking><devices/></domain>"
        f = host_swap_disabled(_ctx_with_root(xml))
        assert f.passing is True

    def test_fails_when_no_memory_backing(self) -> None:
        xml = "<domain><name>t</name><devices/></domain>"
        f = host_swap_disabled(_ctx_with_root(xml))
        assert f.passing is False
        assert "swappable" in f.summary

    def test_fails_when_memory_backing_without_locked(self) -> None:
        xml = "<domain><name>t</name><memoryBacking><hugepages/></memoryBacking><devices/></domain>"
        f = host_swap_disabled(_ctx_with_root(xml))
        assert f.passing is False
