#include "linux_rawio.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static int create_status(char *path, size_t path_size, const char *cap_eff) {
    int fd;
    FILE *f;

    if (path_size < sizeof("/tmp/friidump-rawio-XXXXXX"))
        return 0;

    snprintf(path, path_size, "/tmp/friidump-rawio-XXXXXX");
    fd = mkstemp(path);
    if (fd < 0)
        return 0;

    f = fdopen(fd, "wb");
    if (!f) {
        close(fd);
        remove(path);
        return 0;
    }

    fprintf(f, "Name:\ttest\nCapInh:\t0000000000000000\nCapEff:\t%s\n", cap_eff);
    fclose(f);
    return 1;
}

static int expect_state(
    const char *label,
    const char *path,
    friidump_linux_rawio_state expected,
    unsigned long long expected_mask) {
    unsigned long long mask = 0;
    friidump_linux_rawio_state actual =
        friidump_linux_rawio_state_from_status_file(path, &mask);

    if (actual != expected || mask != expected_mask) {
        fprintf(stderr,
            "FAIL: %s state=%d expected=%d mask=0x%llx expected=0x%llx\n",
            label, (int) actual, (int) expected,
            mask, expected_mask);
        return 0;
    }

    printf("PASS: %s\n", label);
    return 1;
}

int main(void) {
    char present_path[64];
    char missing_path[64];
    char malformed_path[64];
    unsigned long long rawio_mask = 1ULL << FRIIDUMP_LINUX_CAP_SYS_RAWIO;
    char present_value[32];
    int ok = 1;

    snprintf(present_value, sizeof(present_value), "%016llx", rawio_mask);

    ok &= create_status(present_path, sizeof(present_path), present_value);
    ok &= create_status(missing_path, sizeof(missing_path), "0000000000000000");
    ok &= create_status(malformed_path, sizeof(malformed_path), "not-hex");

    if (!ok) {
        fprintf(stderr, "FAIL: fixture creation\n");
        return 1;
    }

    ok &= expect_state(
        "CAP_SYS_RAWIO present",
        present_path,
        FRIIDUMP_LINUX_RAWIO_PRESENT,
        rawio_mask);
    ok &= expect_state(
        "CAP_SYS_RAWIO missing",
        missing_path,
        FRIIDUMP_LINUX_RAWIO_MISSING,
        0);
    ok &= expect_state(
        "malformed CapEff",
        malformed_path,
        FRIIDUMP_LINUX_RAWIO_UNKNOWN,
        0);
    ok &= expect_state(
        "missing status file",
        "/definitely/not/a/real/status/file",
        FRIIDUMP_LINUX_RAWIO_UNKNOWN,
        0);

    remove(present_path);
    remove(missing_path);
    remove(malformed_path);

    if (!ok)
        return 1;

    printf("LINUX RAW-I/O CAPABILITY PARSER: PASS\n");
    return 0;
}
