#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/syscall.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <sys/types.h>

// 兼容性处理：获取 SYS_rt_sigtimedwait 宏
#ifndef SYS_rt_sigtimedwait
#  ifdef __NR_rt_sigtimedwait
#    define SYS_rt_sigtimedwait __NR_rt_sigtimedwait
#  else
#    error "SYS_rt_sigtimedwait 未定义，无法直接进行系统调用测试"
#  endif
#endif

// libc 包装：优先使用 sigtimedwait，保证在不同libc/内核下参数兼容
static int rt_sigtimedwait_libc(const sigset_t *set, siginfo_t *info, const struct timespec *timeout) {
    return sigtimedwait(set, info, timeout);
}

// 原始syscall：用于特定场景（如测试非法sigsetsize）
static int sys_rt_sigtimedwait_raw(const sigset_t *set, siginfo_t *info, const struct timespec *timeout, size_t sigsetsize) {
    return (int)syscall(SYS_rt_sigtimedwait, set, info, timeout, sigsetsize);
}

// 测试统计
static int total_tests = 0;
static int passed_tests = 0;
static int failed_tests = 0;
static char failed_test_names[200][256];
static int failed_test_count = 0;

#define TEST_ASSERT(condition, test_name) do { \
    total_tests++; \
    if (condition) { \
        passed_tests++; \
        printf("PASS - %s\n", test_name); \
    } else { \
        failed_tests++; \
        if (failed_test_count < 200) { \
            snprintf(failed_test_names[failed_test_count], sizeof(failed_test_names[failed_test_count]), "%s", test_name); \
            failed_test_count++; \
        } \
        printf("FAIL - %s (errno=%d: %s)\n", test_name, errno, strerror(errno)); \
    } \
} while(0)

// 工具函数：阻塞/解除阻塞 指定信号
static int block_signal(int sig, sigset_t *oldset) {
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, sig);
    return pthread_sigmask(SIG_BLOCK, &set, oldset);
}

static int unblock_signal(int sig, const sigset_t *oldset) {
    (void)sig; // 未使用，仅保持接口对称
    return pthread_sigmask(SIG_SETMASK, oldset, NULL);
}

// 工具函数：使用rt_sigtimedwait带0超时轮询一次并(如存在)清理信号
static int poll_and_consume_signal_once(int sig) {
    sigset_t set;
    siginfo_t info;
    struct timespec ts = {0, 0};
    sigemptyset(&set);
    sigaddset(&set, sig);
    int r = rt_sigtimedwait_libc(&set, &info, &ts);
    return r; // =sig 表示读到并消费；-1 且 errno=EAGAIN 表示无；其它为异常
}

// 用于线程延迟发送信号
typedef struct {
    pid_t pid;
    int sig;
    int delay_ms;
} sender_args_t;

static void *delayed_kill_sender(void *arg) {
    sender_args_t *a = (sender_args_t *)arg;
    // 确保该线程不接收要发送的信号：阻塞之，让信号成为进程待处理，供主线程 sigtimedwait 消费
    sigset_t set, oldset;
    sigemptyset(&set);
    sigaddset(&set, a->sig);
    pthread_sigmask(SIG_BLOCK, &set, &oldset);

    struct timespec ts;
    ts.tv_sec = a->delay_ms / 1000;
    ts.tv_nsec = (long)(a->delay_ms % 1000) * 1000000L;
    nanosleep(&ts, NULL);

    printf("[TEST_DEBUG]:delayed_kill_sender to kill %d sig %d\n", a->pid, a->sig);
    // 进程定向发送
    kill(a->pid, a->sig);
    printf("[TEST_DEBUG]:delayed_kill_sender killed %d sig %d\n", a->pid, a->sig);
    // 还原该线程掩码
    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
    printf("[TEST_DEBUG]:delayed_kill_sender unblocked %d sig %d\n", a->pid, a->sig);
    return NULL;
}

// 基础功能：阻塞SIGUSR1 -> 自发 -> rt_sigtimedwait应立即返回该信号
static void test_rt_sigtimedwait_basic_self_kill_SIGUSR1() {
    printf("=== 测试: 基础 - 阻塞SIGUSR1后自发并等待 ===\n");

    sigset_t oldset;
    int rc = block_signal(SIGUSR1, &oldset);
    TEST_ASSERT(rc == 0, "阻塞SIGUSR1");

    // 确保没有遗留的待处理SIGUSR1
    while (poll_and_consume_signal_once(SIGUSR1) == SIGUSR1) {}

    // 发送到自身
    pid_t me = getpid();
    rc = kill(me, SIGUSR1);
    TEST_ASSERT(rc == 0, "向自身发送SIGUSR1");

    sigset_t waitset;
    sigemptyset(&waitset);
    sigaddset(&waitset, SIGUSR1);

    siginfo_t info;
    struct timespec timeout = {2, 0}; // 2秒超时，正常应很快返回
    int ret = rt_sigtimedwait_libc(&waitset, &info, &timeout);
    TEST_ASSERT(ret == SIGUSR1, "rt_sigtimedwait 返回SIGUSR1");
    if (ret == SIGUSR1) {
        TEST_ASSERT(info.si_signo == SIGUSR1, "info.si_signo == SIGUSR1");
        // kill() 产生的应为 SI_USER
        TEST_ASSERT(info.si_code == SI_USER, "info.si_code == SI_USER");
        TEST_ASSERT(info.si_pid == me, "info.si_pid 为当前进程");
        TEST_ASSERT(info.si_uid == getuid(), "info.si_uid 为当前用户");
    }

    rc = unblock_signal(SIGUSR1, &oldset);
    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
}

// 超时：等待一个未发送的被阻塞信号，短超时应返回EAGAIN
static void test_rt_sigtimedwait_timeout() {
    printf("\n=== 测试: 超时 - 无信号到达时返回EAGAIN ===\n");

    const int sig = SIGUSR2;
    sigset_t oldset;
    int rc = block_signal(sig, &oldset);
    TEST_ASSERT(rc == 0, "阻塞SIGUSR2");

    // 清理可能的遗留
    while (poll_and_consume_signal_once(sig) == sig) {}

    sigset_t waitset;
    sigemptyset(&waitset);
    sigaddset(&waitset, sig);

    siginfo_t info;
    struct timespec timeout = {0, 100 * 1000 * 1000}; // 100ms
    int ret = rt_sigtimedwait_libc(&waitset, &info, &timeout);
    TEST_ASSERT(ret == -1 && errno == EAGAIN, "无信号到达时超时返回EAGAIN");

    rc = unblock_signal(sig, &oldset);
    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
}

// 非法timespec：tv_nsec越界应返回EINVAL
static void test_rt_sigtimedwait_invalid_timespec() {
    printf("\n=== 测试: 参数校验 - 非法timespec返回EINVAL ===\n");

    const int sig = SIGUSR1;
    sigset_t oldset;
    int rc = block_signal(sig, &oldset);
    TEST_ASSERT(rc == 0, "阻塞SIGUSR1");

    sigset_t waitset;
    sigemptyset(&waitset);
    sigaddset(&waitset, sig);

    siginfo_t info;
    struct timespec bad = { .tv_sec = 0, .tv_nsec = 2000000000L }; // > 1e9-1
    int ret = rt_sigtimedwait_libc(&waitset, &info, &bad);
    TEST_ASSERT(ret == -1 && errno == EINVAL, "tv_nsec越界 -> EINVAL");

    rc = unblock_signal(sig, &oldset);
    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
}

// 延迟发送：NULL超时指针(无限等待) + 后台线程延迟发送实时信号，调用应被唤醒并返回
static void test_rt_sigtimedwait_null_timeout_with_delayed_rt_signal() {
    printf("\n=== 测试: NULL超时 + 延迟发送SIGRTMIN+1 ===\n");

    int rtsig = SIGRTMIN + 1;
    sigset_t oldset;
    int rc = block_signal(rtsig, &oldset);
    TEST_ASSERT(rc == 0, "阻塞SIGRTMIN+1");

    // 线程延迟发送
    pthread_t th;
    sender_args_t args = { .pid = getpid(), .sig = rtsig, .delay_ms = 100 };
    rc = pthread_create(&th, NULL, delayed_kill_sender, &args);
    TEST_ASSERT(rc == 0, "创建延迟发送线程");

    sigset_t waitset;
    sigemptyset(&waitset);
    sigaddset(&waitset, rtsig);
    siginfo_t info;
    printf("[TEST_DEBUG]: to call rt_sigtimedwait_libc\n");
    // NULL超时：按规范为无限等待，但我们确保100ms内会到信号
    int ret = rt_sigtimedwait_libc(&waitset, &info, NULL);
    printf("[TEST_DEBUG]: rt_sigtimedwait_libc returned %d\n", ret);
    TEST_ASSERT(ret == rtsig, "rt_sigtimedwait(NULL) 收到实时信号");
    if (ret == rtsig) {
        TEST_ASSERT(info.si_signo == rtsig, "info.si_signo == 发送的实时信号");
        TEST_ASSERT((info.si_code == SI_USER) || (info.si_code == SI_TKILL) || (info.si_code == SI_QUEUE), "info.si_code 合理");
        TEST_ASSERT(info.si_pid == getpid(), "info.si_pid 为当前进程");
    }
    printf("[TEST_DEBUG]: to join thread\n");
    if (rc == 0) {
        pthread_join(th, NULL);
    }
    printf("[TEST_DEBUG]: to unblock signal\n");
    rc = unblock_signal(rtsig, &oldset);
    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
}

// 零超时轮询：ts={0,0} 未有信号立刻返回EAGAIN
static void test_rt_sigtimedwait_zero_timeout_poll() {
    printf("\n=== 测试: 轮询模式 - 零超时无信号返回EAGAIN ===\n");

    const int sig = SIGUSR1;
    sigset_t oldset;
    int rc = block_signal(sig, &oldset);
    TEST_ASSERT(rc == 0, "阻塞SIGUSR1");

    // 清空待处理
    while (poll_and_consume_signal_once(sig) == sig) {}

    sigset_t waitset;
    sigemptyset(&waitset);
    sigaddset(&waitset, sig);

    siginfo_t info;
    struct timespec ts = {0, 0};
    int ret = rt_sigtimedwait_libc(&waitset, &info, &ts);
    TEST_ASSERT(ret == -1 && errno == EAGAIN, "零超时无信号 -> EAGAIN");

    rc = unblock_signal(sig, &oldset);
    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
}

// 非法sigsetsize：传0期望返回EINVAL（具体行为依赖内核，这里按Linux常见实现）
static void test_rt_sigtimedwait_invalid_sigsetsize() {
    printf("\n=== 测试: 参数校验 - 非法sigsetsize返回EINVAL ===\n");

    const int sig = SIGUSR1;
    sigset_t oldset;
    int rc = block_signal(sig, &oldset);
    TEST_ASSERT(rc == 0, "阻塞SIGUSR1");

    sigset_t waitset;
    sigemptyset(&waitset);
    sigaddset(&waitset, sig);

    siginfo_t info;
    struct timespec ts = {0, 0};
    int ret = sys_rt_sigtimedwait_raw(&waitset, &info, &ts, 0 /* 非法大小 */);
    TEST_ASSERT(ret == -1 && errno == EINVAL, "sigsetsize=0 -> EINVAL");

    rc = unblock_signal(sig, &oldset);
    TEST_ASSERT(rc == 0, "恢复原有信号屏蔽集");
}

int main() {
    printf("开始 rt_sigtimedwait 系统调用测试\n");
    printf("当前进程 PID=%d\n", getpid());

    test_rt_sigtimedwait_basic_self_kill_SIGUSR1();
    test_rt_sigtimedwait_timeout();
    test_rt_sigtimedwait_invalid_timespec();
    test_rt_sigtimedwait_null_timeout_with_delayed_rt_signal();
    test_rt_sigtimedwait_zero_timeout_poll();
    test_rt_sigtimedwait_invalid_sigsetsize();

    printf("\n=== rt_sigtimedwait 测试完成 ===\n");
    printf("\n=== 测试结果总结 ===\n");
    printf("总测试数: %d\n", total_tests);
    printf("通过: %d\n", passed_tests);
    printf("失败: %d\n", failed_tests);
    printf("成功率: %.1f%%\n", total_tests > 0 ? (float)passed_tests / total_tests * 100 : 0);

    if (failed_tests > 0) {
        printf("\n失败的测试用例:\n");
        for (int i = 0; i < failed_test_count; i++) {
            printf("  - %s\n", failed_test_names[i]);
        }
    } else {
        printf("\n所有测试用例都通过了！\n");
    }

    return failed_tests > 0 ? 1 : 0;
}
