############################################################################
# Copyright (C) SchedMD LLC.
############################################################################
import re

# import os
import pytest

import atf

total_cpus = 0
total_cores = 0
available_cores = 0


# Setup
@pytest.fixture(scope="module", autouse=True)
def setup():
    atf.require_auto_config(
        "needs nodes with and specific number of Cores and CoreSpecCount"
    )
    atf.require_accounting(modify=False)
    atf.require_config_parameter("SelectType", "select/cons_tres")
    atf.require_config_parameter("SelectTypeParameters", "CR_CPU")
    atf.require_config_parameter("TaskPlugin", "task/cgroup")
    atf.require_config_parameter("AllowSpecResourcesUsage", "1")
    atf.require_nodes(2, [("Cores", 3)])
    atf.require_config_parameter("ConstrainCores", "yes", source="cgroup")
    atf.require_slurm_running()


@pytest.fixture(scope="module")
def node_names():
    global total_cpus, total_cores, available_cores

    # Grab our 2 nodes with 2 Cores each
    nodes = atf.run_job_nodes("--cpu-bind=core --ntasks-per-node=2 -N2 true")

    # Reserve 1 spec core on the first, 2 on the second
    for idx, node in enumerate(nodes):
        atf.set_node_parameter(node, "CoreSpecCount", idx + 1)
        cores = atf.get_node_parameter(node, "cores")
        threads = atf.get_node_parameter(node, "threads")
        total_cores += cores
        total_cpus += cores * threads

    available_cores = total_cores - 3
    return ",".join(nodes)


def test_job_submit(node_names):
    """Verify a properly formed job submits with CoreSpecCount plugin enabled"""

    exit_code = atf.run_job_exit(f"-w {node_names} -N2 -n{available_cores} true")
    assert exit_code == 0


def test_job_denied(node_names):
    """Verify a malformed job is rejected with CoreSpecCount plugin enabled"""

    exit_code = atf.run_job_exit(
        f"-w {node_names} -N2 -n{total_cores} true", xfail=True
    )
    assert exit_code != 0


def test_node_state(node_names):
    """Verify that sinfo state is returned as 'alloc' when using all cpus except specialized cores"""

    job_id = atf.submit_job_sbatch(
        f"-w {node_names} -n{available_cores} --wrap='srun sleep 60'"
    )
    atf.wait_for_job_state(job_id, "RUNNING")

    assert (
        len(
            re.findall(
                r"alloc", atf.run_command_output(f"sinfo -n {node_names} -h -N -o%t")
            )
        )
        == 2
    ), "node states in sinfo should be both 'alloc'"

    atf.cancel_all_jobs(quiet=True)

    job_id = atf.submit_job_sbatch(f"-w {node_names} -n2 --wrap='srun sleep 60'")
    atf.wait_for_job_state(job_id, "RUNNING")

    assert (
        len(
            re.findall(
                r"alloc", atf.run_command_output(f"sinfo -n {node_names} -h -N -o%t")
            )
        )
        == 1
    ), "one node state in sinfo should be 'alloc'"
    assert (
        len(
            re.findall(
                r"mix", atf.run_command_output(f"sinfo -n {node_names} -h -N -o%t")
            )
        )
        == 1
    ), "one node state in sinfo should be 'mix'"


def test_core_spec_override(node_names):
    """Verify that if you use the --core-spec option with less than the configured amount when you submit
    a job, you should be able to use the extra cores.
    """

    job_id = atf.submit_job_sbatch(
        f"-w {node_names} --core-spec=0 -n{total_cores} --wrap='srun true'"
    )
    atf.wait_for_job_state(job_id, "DONE")
    atf.wait_for_step_accounted(job_id, 0)

    output = int(
        re.findall(
            rf"{job_id}\.0\s+(\d+)",
            atf.run_command_output(f"sacct -j {job_id} -o jobid%20,alloccpus"),
        )[0]
    )

    assert output == total_cores, f"--core-spec=0 should allow {total_cores} cores"

    job_id = atf.submit_job_sbatch(f"-w {node_names} --core-spec=0 --wrap='srun true'")
    atf.wait_for_job_state(job_id, "DONE")
    atf.wait_for_step_accounted(job_id, 0)

    output = int(
        re.findall(
            rf"{job_id}\.0\s+(\d+)",
            atf.run_command_output(f"sacct -j {job_id} -o jobid%20,alloccpus"),
        )[0]
    )

    assert (
        output == total_cores
    ), "Using --core-spec should imply --exclusive and using all cores"

    job_id = atf.submit_job_sbatch(
        f"-w {node_names} --core-spec=1 -n{total_cores - 2} --wrap='srun true'"
    )
    atf.wait_for_job_state(job_id, "DONE")
    atf.wait_for_step_accounted(job_id, 0)

    output = int(
        re.findall(
            rf"{job_id}\.0\s+(\d+)",
            atf.run_command_output(f"sacct -j {job_id} -o jobid%20,alloccpus"),
        )[0]
    )

    assert (
        output == total_cores - 2
    ), "--core-spec=1 should allocate all cores except 1 per node"

    job_id = atf.submit_job_sbatch(
        f"-w {node_names} --core-spec=2 -n{total_cores - 4} --wrap='srun true'"
    )
    atf.wait_for_job_state(job_id, "DONE")
    atf.wait_for_step_accounted(job_id, 0)

    output = int(
        re.findall(
            rf"{job_id}\.0\s+(\d+)",
            atf.run_command_output(f"sacct -j {job_id} -o jobid%20,alloccpus"),
        )[0]
    )

    assert (
        output == total_cores - 4
    ), "--core-spec=2 should allocate all cores except 2 per node"

    exit_code = atf.run_job_exit(
        f" -w {node_names} -N2 --core-spec=2 -n{available_cores} true", xfail=True
    )
    assert exit_code != 0, "--core-spec limits the available cores in nodes"


def test_thread_spec_override(node_names):
    """Verify that if you use the --thread-spec option with less than the configured amount when you submit
    a job, you should be able to use the extra threads.
    """

    job_id = atf.submit_job_sbatch(
        f"-w {node_names} --thread-spec=1 --wrap='srun true'"
    )
    atf.wait_for_job_state(job_id, "DONE")
    atf.wait_for_step_accounted(job_id, 0)

    output = int(
        re.findall(
            rf"{job_id}\.0\s+(\d+)",
            atf.run_command_output(f"sacct -j {job_id} -o jobid%20,alloccpus"),
        )[0]
    )

    assert output == (
        total_cpus - 2
    ), "--thread-spec=1 should override and reserve 1 cpu per node (2 total) for the batch step"
