// SPDX-FileCopyrightText: Peter Pentchev <roam@ringlet.net>
// SPDX-License-Identifier: BSD-2-Clause
//! Test some trivial aspects of the timelimit crate.

#![expect(clippy::tests_outside_test_module, reason = "integration test")]

use std::str::FromStr as _;
use std::time::Instant;

use anyhow::{Context as _, Result};

use timelimit::exitcode::WrappedReport;
use timelimit::{Config, Signal};

fn run_sleep_with_arg(
    cfg: Config,
    arg: &str,
    exitcode: u8,
    signalled: bool,
    thresh_low: u128,
    thresh_high: u128,
) {
    let before = Instant::now();
    let res = smol::block_on(timelimit::limit(cfg, &["sleep", arg]));
    let millis = before.elapsed().as_millis();

    if signalled {
        assert!(matches!(res.report(), WrappedReport::Signal(_)), "{res:?}");
    } else {
        assert!(
            matches!(res.report(), WrappedReport::Exact(rc) if *rc == exitcode),
            "{res:?}"
        );
    }
    assert_eq!(res.exitcode(), exitcode, "{res:?}");

    assert!(millis >= thresh_low, "{millis}");
    assert!(millis < thresh_high, "{millis}");
}

fn run_sleep(cfg: Config, exitcode: u8, signalled: bool, thresh_low: u128, thresh_high: u128) {
    run_sleep_with_arg(cfg, "9", exitcode, signalled, thresh_low, thresh_high);
}

#[test]
fn limit_finish_bad() {
    run_sleep_with_arg(
        Config::builder().warntime(3_f32).killtime(3_f32).build(),
        "-1",
        1_u8,
        false,
        0_u128,
        1500_u128,
    );
}

#[test]
fn limit_finish() {
    run_sleep(
        Config::builder().warntime(12_f32).killtime(3_f32).build(),
        0_u8,
        false,
        7500_u128,
        10500_u128,
    );
}

#[test]
fn limit_warn() {
    run_sleep(
        Config::builder().warntime(3_f32).killtime(6_f32).build(),
        143_u8,
        true,
        1500_u128,
        4500_u128,
    );
}

#[test]
fn limit_kill() -> Result<()> {
    run_sleep(
        Config::builder()
            .warntime(3_f32)
            .warnsig(
                Signal::from_str("SIGWINCH").context("Could not recognize the SIGWINCH signal")?,
            )
            .killtime(3_f32)
            .build(),
        137_u8,
        true,
        4500_u128,
        7500_u128,
    );
    Ok(())
}
