from types import SimpleNamespace

import pytest

from scripts.msvc_harness.models import (
    CommandSpec,
    ProjectKind,
    ResultCheck,
    ResultCheckKind,
    ValidationPlan,
    ValidationStep,
)
from scripts.msvc_harness.process import ValidationFailure, execute_plan


def _ctest_plan(root):
    command = CommandSpec(
        ("ctest", "--show-only=json-v1"),
        root,
        "CTest discovery",
    )
    check = ResultCheck(ResultCheckKind.CTEST_HAS_TESTS)
    return ValidationPlan(
        ProjectKind.CMAKE,
        (ValidationStep(command, (check,)),),
    )


def test_execute_plan_rejects_ctest_json_with_no_tests(tmp_path):
    def fake_run(*args, **kwargs):
        return SimpleNamespace(returncode=0, stdout='{"tests": []}', stderr="")

    with pytest.raises(ValidationFailure, match="CTest discovered no tests"):
        execute_plan(
            _ctest_plan(tmp_path),
            tmp_path,
            deadline=10,
            run=fake_run,
            clock=lambda: 0,
        )


def test_execute_plan_accepts_ctest_json_with_tests_without_shell(tmp_path):
    calls = []

    def fake_run(*args, **kwargs):
        calls.append((args, kwargs))
        return SimpleNamespace(
            returncode=0,
            stdout='{"tests": [{"name": "unit"}]}',
            stderr="",
        )

    results = execute_plan(
        _ctest_plan(tmp_path),
        tmp_path,
        deadline=10,
        run=fake_run,
        clock=lambda: 0,
    )

    assert len(results) == 1
    assert calls == [
        (
            (["ctest", "--show-only=json-v1"],),
            {
                "cwd": tmp_path.resolve(),
                "env": None,
                "capture_output": True,
                "shell": False,
                "timeout": 10,
            },
        )
    ]
