/**
 * @file test_uapi_probe.c
 * @brief Kernel UAPI topology probe test
 *
 * Exercises /dev/mvgal0 when the module is loaded; skips gracefully otherwise.
 */

#include "mvgal/mvgal_uapi.h"

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define MVGAL_DEV_PATH "/dev/" MVGAL_DEVICE_NAME

static int tests_passed;
static int tests_failed;

#define TEST_ASSERT(cond, msg)                          \
    do {                                                \
        if (cond) {                                     \
            tests_passed++;                             \
            fprintf(stdout, "  PASS: %s\n", msg);       \
        } else {                                        \
            tests_failed++;                             \
            fprintf(stderr, "  FAIL: %s\n", msg);       \
        }                                               \
    } while (0)

int main(void)
{
    int fd;
    struct mvgal_uapi_version version;
    struct mvgal_uapi_gpu_count count;
    struct mvgal_uapi_caps caps;

    fprintf(stdout, "\n=== MVGAL UAPI Probe Test ===\n\n");

    fd = open(MVGAL_DEV_PATH, O_RDONLY | O_CLOEXEC);
    if (fd < 0) {
        fprintf(stdout, "  SKIP: %s not available (%s)\n",
                MVGAL_DEV_PATH, strerror(errno));
        fprintf(stdout, "  (Load kernel module to enable this test)\n\n");
        return EXIT_SUCCESS;
    }

    TEST_ASSERT(ioctl(fd, MVGAL_IOC_QUERY_VERSION, &version) == 0,
                "MVGAL_IOC_QUERY_VERSION");
    if (ioctl(fd, MVGAL_IOC_QUERY_VERSION, &version) == 0) {
        fprintf(stdout, "  UAPI version: %u.%u.%u\n",
                version.major, version.minor, version.patch);
    }

    TEST_ASSERT(ioctl(fd, MVGAL_IOC_GET_GPU_COUNT, &count) == 0,
                "MVGAL_IOC_GET_GPU_COUNT");
    if (ioctl(fd, MVGAL_IOC_GET_GPU_COUNT, &count) == 0) {
        fprintf(stdout, "  GPU count: %u\n", count.gpu_count);
    }

    TEST_ASSERT(ioctl(fd, MVGAL_IOC_GET_CAPS, &caps) == 0,
                "MVGAL_IOC_GET_CAPS");
    if (ioctl(fd, MVGAL_IOC_GET_CAPS, &caps) == 0) {
        TEST_ASSERT(caps.feature_flags & MVGAL_UAPI_FEATURE_ENUMERATION,
                    "enumeration feature flag set");
        fprintf(stdout, "  topology_generation: %u\n", caps.topology_generation);
    }

    if (count.gpu_count > 0) {
        struct mvgal_uapi_gpu_query query;
        memset(&query, 0, sizeof(query));
        query.index = 0;
        TEST_ASSERT(ioctl(fd, MVGAL_IOC_GET_GPU_INFO, &query) == 0,
                    "MVGAL_IOC_GET_GPU_INFO(0)");
        if (ioctl(fd, MVGAL_IOC_GET_GPU_INFO, &query) == 0) {
            TEST_ASSERT(query.info.name[0] != '\0' || query.info.vendor_id != 0,
                        "first GPU has identifying info");
            fprintf(stdout, "  GPU[0]: %s (%s)\n",
                    query.info.name[0] ? query.info.name : "unnamed",
                    query.info.bdf);
        }
    }

    close(fd);

    fprintf(stdout, "\nResults: %d passed, %d failed\n\n",
            tests_passed, tests_failed);
    return tests_failed > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
