#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <math.h>
#include <string.h>

/* ---------- Minimal test framework ---------- */
static int tests_run = 0, tests_failed = 0;
#define REQUIRE(cond, msg) do {                       \
    tests_run++;                                      \
    if (!(cond)) {                                    \
        tests_failed++;                               \
        fprintf(stderr, "FAIL: %s (%s:%d)\n",         \
                msg, __FILE__, __LINE__);             \
        return 1;                                     \
    }                                                 \
} while (0)
#define PASS(msg) do { tests_run++; (void)msg; return 0; } while (0)

/* ---------- Device-under-test (DUT) API (example) ----------
   In a real project these would come from your production code.
   They embody software safety requirements to be verified.
*/
typedef enum { SAFE_OK=0, SAFE_FAULT=1 } safe_state_t;

/* Safety requirements (examples):
   - Speed input shall be validated to [0, 200] km/h (inclusive).
   - On sensor fault, system transitions to SAFE_FAULT and commands torque = 0.
   - Two redundant sensors must agree within tolerance.
   - Watchdog must be serviced within WDG_MAX_MS.
   - Control step must complete within DEADLINE_MS.
   - Safety CRC must validate configuration blob at startup.
*/
enum { SPEED_MAX = 200, SPEED_MIN = 0 };
enum { DEADLINE_MS = 5 };         /* unit deadline budget */
enum { WDG_MAX_MS  = 50 };        /* watchdog max interval */
enum { REDUND_TOL  = 3 };         /* units of km/h */

/* DUT state (simplified) */
static volatile safe_state_t g_state = SAFE_OK;
static volatile int g_cmd_torque = 0;

/* Pretend CRC16 for config validation */
static uint16_t crc16(const uint8_t *p, size_t n) {
    uint16_t crc = 0xFFFF;
    for (size_t i = 0; i < n; i++) {
        crc ^= (uint16_t)p[i];
        for (int b = 0; b < 8; b++)
            crc = (crc & 1) ? (crc >> 1) ^ 0xA001 : (crc >> 1);
    }
    return crc;
}

static int validate_speed_input(int kmh_in, int *kmh_out) {
    if (kmh_out == NULL) return -1;
    if (kmh_in < SPEED_MIN || kmh_in > SPEED_MAX) return -2;
    *kmh_out = kmh_in;
    return 0;
}

static void enter_safe_fault(void) {
    g_state = SAFE_FAULT;
    g_cmd_torque = 0; /* de-energize actuation */
}

static int redundant_speed_plausible(int s1, int s2) {
    return (abs(s1 - s2) <= REDUND_TOL);
}

/* Simulate control step; returns elapsed time in ms */
static long control_step(int speed_kmh) {
    clock_t t0 = clock();
    int tmp;
    if (validate_speed_input(speed_kmh, &tmp) != 0) {
        enter_safe_fault();
    } else {
        /* simple deterministic workload to emulate compute */
        volatile int acc = 0;
        for (int i = 0; i < 20000; i++) acc += i ^ tmp;
        (void)acc;
    }
    clock_t t1 = clock();
    return (long)((t1 - t0) * 1000.0 / CLOCKS_PER_SEC);
}

/* Watchdog mock */
static long ms_since(struct timespec a, struct timespec b) {
    long ds = (b.tv_sec - a.tv_sec) * 1000L;
    long dns = (b.tv_nsec - a.tv_nsec) / 1000000L;
    return ds + dns;
}
static int watchdog_ok(long interval_ms) { return interval_ms <= WDG_MAX_MS; }

/* ---------- Tests ---------- */

/* 1) Boundary-value check for input validation (Unit verification) */
static int test_speed_range_boundaries(void) {
    int out = -1;
    REQUIRE(validate_speed_input(0, &out) == 0 && out == 0,
            "speed lower bound must pass");
    REQUIRE(validate_speed_input(200, &out) == 0 && out == 200,
            "speed upper bound must pass");
    REQUIRE(validate_speed_input(-1, &out) != 0,
            "below lower bound must fail");
    REQUIRE(validate_speed_input(201, &out) != 0,
            "above upper bound must fail");
    PASS("test_speed_range_boundaries");
}

/* 2) Robustness: null pointer handling (Unit verification) */
static int test_speed_nullptr_rejected(void) {
    REQUIRE(validate_speed_input(50, NULL) != 0,
            "NULL output pointer must be rejected");
    PASS("test_speed_nullptr_rejected");
}

/* 3) Safe-state on sensor fault (Embedded-software test) */
static int test_enters_safe_state_on_invalid_input(void) {
    g_state = SAFE_OK; g_cmd_torque = 123;
    (void)control_step(-10); /* invalid -> fault */
    REQUIRE(g_state == SAFE_FAULT, "system must enter SAFE_FAULT");
    REQUIRE(g_cmd_torque == 0,    "torque must be de-energized in fault");
    PASS("test_enters_safe_state_on_invalid_input");
}

/* 4) Timing: control step meets deadline (Embedded test) */
static int test_control_step_deadline(void) {
    long elapsed = control_step(100);
    REQUIRE(elapsed <= DEADLINE_MS, "control step must meet deadline");
    PASS("test_control_step_deadline");
}

/* 5) Redundant-sensor plausibility (Integration & verification) */
static int test_redundant_sensor_agreement(void) {
    REQUIRE(redundant_speed_plausible(80, 82) == 1,
            "redundant sensors within tolerance must pass");
    REQUIRE(redundant_speed_plausible(80, 90) == 0,
            "redundant sensors outside tolerance must fail");
    PASS("test_redundant_sensor_agreement");
}

/* 6) Watchdog service interval (Integration & verification) */
static int test_watchdog_interval(void) {
    struct timespec t0, t1;
    clock_gettime(CLOCK_MONOTONIC, &t0);
    /* Simulate doing useful work */
    volatile int s = 0; for (int i = 0; i < 50000; i++) s ^= i;
    (void)s;
    clock_gettime(CLOCK_MONOTONIC, &t1);
    long dt = ms_since(t0, t1);
    REQUIRE(watchdog_ok(dt), "watchdog must be serviced within max interval");
    PASS("test_watchdog_interval");
}

/* 7) Configuration integrity via CRC (Unit/Startup test) */
static int test_configuration_crc_ok(void) {
    const uint8_t blob[] = {0x12,0x34,0x56,0x78,0x9A,0xBC};
    uint16_t expected = crc16(blob, sizeof(blob));
    REQUIRE(expected == crc16(blob, sizeof(blob)),
            "CRC must be stable/deterministic");
    /* Corrupt one byte */
    uint8_t bad[sizeof(blob)]; memcpy(bad, blob, sizeof(blob));
    ((uint8_t*)bad)[2] ^= 0xFF;
    REQUIRE(expected != crc16(bad, sizeof(bad)),
            "CRC must detect single-byte corruption");
    PASS("test_configuration_crc_ok");
}

/* ---------- Runner ---------- */
int main(void) {
    int (*tests[])(void) = {
        test_speed_range_boundaries,
        test_speed_nullptr_rejected,
        test_enters_safe_state_on_invalid_input,
        test_control_step_deadline,
        test_redundant_sensor_agreement,
        test_watchdog_interval,
        test_configuration_crc_ok,
    };
    const int N = (int)(sizeof(tests)/sizeof(tests[0]));
    for (int i = 0; i < N; i++) { tests_failed += tests[i](); }
    printf("\nTests run: %d, Failures: %d\n", tests_run, tests_failed);
    return tests_failed ? 1 : 0;
}
